[PATCH 2/2] media: cedrus: Fix H264 decoding

2020-12-23 Thread Jernej Skrabec
During H264 API overhaul subtle bug was introduced Cedrus driver.
Progressive references have both, top and bottom reference flags set.
Cedrus reference list expects only bottom reference flag and only when
interlaced frames are decoded. However, due to a bug in Cedrus check,
exclusivity is not tested and that flag is set also for progressive
references. That causes "jumpy" background with many videos.

Fix that by checking that only bottom reference flag is set in control
and nothing else.

Tested-by: Andre Heider 
Fixes: cfc8c3ed533e ("media: cedrus: h264: Properly configure reference field")
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 781c84a9b1b7..de7442d4834d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -203,7 +203,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
position = cedrus_buf->codec.h264.position;
 
sram_array[i] |= position << 1;
-   if (ref_list[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
+   if (ref_list[i].fields == V4L2_H264_BOTTOM_FIELD_REF)
sram_array[i] |= BIT(0);
}
 
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/2] media: cedrus: Remove checking for required controls

2020-12-23 Thread Jernej Skrabec
According to v4l2 request api specifications, it's allowed to skip
control if its content isn't changed for performance reasons. Cedrus
driver predates that, so it has implemented mechanism to check if all
required controls are included in one request.

Conform to specifications with removing that mechanism.

Note that this mechanism with static required flag isn't very good
anyway because need for control is usually signaled in other controls.

Fixes: 50e761516f2b ("media: platform: Add Cedrus VPU decoder driver")
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.c | 49 -
 drivers/staging/media/sunxi/cedrus/cedrus.h |  1 -
 2 files changed, 50 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index ddad5d274ee8..7bd9291c8d5f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -34,56 +34,48 @@ static const struct cedrus_control cedrus_controls[] = {
.id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
},
.codec  = CEDRUS_CODEC_MPEG2,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
},
.codec  = CEDRUS_CODEC_MPEG2,
-   .required   = false,
},
{
.cfg = {
.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_STATELESS_H264_SLICE_PARAMS,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_STATELESS_H264_SPS,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_STATELESS_H264_PPS,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = false,
},
{
.cfg = {
.id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = false,
},
{
.cfg = {
@@ -92,7 +84,6 @@ static const struct cedrus_control cedrus_controls[] = {
.def= V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = false,
},
{
.cfg = {
@@ -101,7 +92,6 @@ static const struct cedrus_control cedrus_controls[] = {
.def= V4L2_STATELESS_H264_START_CODE_NONE,
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = false,
},
/*
 * We only expose supported profiles information,
@@ -120,28 +110,24 @@ static const struct cedrus_control cedrus_controls[] = {
BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED),
},
.codec  = CEDRUS_CODEC_H264,
-   .required   = false,
},
{
.cfg = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
},
.codec  = CEDRUS_CODEC_H265,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_PPS,
},
.codec  = CEDRUS_CODEC_H265,
-   .required   = true,
},
{
.cfg = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
},
.codec  = CEDRUS_CODEC_H265,
-   .required   = true,
},
{
.cfg = {
@@ -150,7 +136,6 @@ static const struct cedrus_control cedrus_controls[] = {
.def= V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED,
},
.codec  = CEDRUS_CODEC_H265,
-   .required   = false,
},
{
.cfg = {
@@ -159,14 +144,12 @@ static const struct cedrus_control cedrus_controls[] = {
.def= V4L2_MPEG_VIDEO_HEVC_START

[PATCH 0/2] media: cedrus: a couple of fixes

2020-12-23 Thread Jernej Skrabec
This short series fixes two issues:
1. conformance to v4l2 request api specifications
2. regression in h264 video decoding introduced during h264 api rework

Please take a look.

Best regards,
Jernej

Jernej Skrabec (2):
  media: cedrus: Remove checking for required controls
  media: cedrus: Fix H264 decoding

 drivers/staging/media/sunxi/cedrus/cedrus.c   | 49 ---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 -
 .../staging/media/sunxi/cedrus/cedrus_h264.c  |  2 +-
 3 files changed, 1 insertion(+), 51 deletions(-)

-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: cedrus: Make VP8 codec as capability

2020-12-02 Thread Jernej Skrabec
Commit 31d9b9ef8564 ("media: cedrus: Register all codecs as capability")
makes separate capability flags for each codec. However, VP8 codec was
merged at the same time as mentioned patch, so there is no capability
flag for it.

This patch adds capability flag for VP8 and enables it for all variants
except for V3s.

Signed-off-by: Jernej Skrabec 
---
Note: this should be merged after both of these PRs:
https://patchwork.linuxtv.org/project/linux-media/patch/8cf5021f-559c-5ea8-f1f0-250c00bc1...@xs4all.nl/
https://patchwork.linuxtv.org/project/linux-media/patch/5dbd468d-1d10-e0c8-43f0-ebe8f17ab...@xs4all.nl/

 drivers/staging/media/sunxi/cedrus/cedrus.c   | 27 ---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 +
 .../staging/media/sunxi/cedrus/cedrus_video.c |  1 +
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index dce7cbc95872..c0f226d75feb 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -495,26 +495,30 @@ static int cedrus_remove(struct platform_device *pdev)
 
 static const struct cedrus_variant sun4i_a10_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_MPEG2_DEC |
- CEDRUS_CAPABILITY_H264_DEC,
+ CEDRUS_CAPABILITY_H264_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun5i_a13_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_MPEG2_DEC |
- CEDRUS_CAPABILITY_H264_DEC,
+ CEDRUS_CAPABILITY_H264_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun7i_a20_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_MPEG2_DEC |
- CEDRUS_CAPABILITY_H264_DEC,
+ CEDRUS_CAPABILITY_H264_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun8i_a33_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_MPEG2_DEC |
- CEDRUS_CAPABILITY_H264_DEC,
+ CEDRUS_CAPABILITY_H264_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 32000,
 };
 
@@ -522,7 +526,8 @@ static const struct cedrus_variant sun8i_h3_cedrus_variant 
= {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_MPEG2_DEC |
  CEDRUS_CAPABILITY_H264_DEC |
- CEDRUS_CAPABILITY_H265_DEC,
+ CEDRUS_CAPABILITY_H265_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 40200,
 };
 
@@ -535,7 +540,8 @@ static const struct cedrus_variant sun8i_v3s_cedrus_variant 
= {
 static const struct cedrus_variant sun8i_r40_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_MPEG2_DEC |
- CEDRUS_CAPABILITY_H264_DEC,
+ CEDRUS_CAPABILITY_H264_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 29700,
 };
 
@@ -543,7 +549,8 @@ static const struct cedrus_variant 
sun50i_a64_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_MPEG2_DEC |
  CEDRUS_CAPABILITY_H264_DEC |
- CEDRUS_CAPABILITY_H265_DEC,
+ CEDRUS_CAPABILITY_H265_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 40200,
 };
 
@@ -551,7 +558,8 @@ static const struct cedrus_variant sun50i_h5_cedrus_variant 
= {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_MPEG2_DEC |
  CEDRUS_CAPABILITY_H264_DEC |
- CEDRUS_CAPABILITY_H265_DEC,
+ CEDRUS_CAPABILITY_H265_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.mod_rate   = 40200,
 };
 
@@ -559,7 +567,8 @@ static const struct cedrus_variant sun50i_h6_cedrus_variant 
= {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_MPEG2_DEC |
  CEDRUS_CAPABILITY_H264_DEC |
- CEDRUS_CAPABILITY_H265_DEC,
+ CEDRUS_CAPABILITY_H265_DEC |
+ CEDRUS_CAPABILITY_VP8_DEC,
.quirks = CEDRUS_QUIRK_NO_DMA_OFFSET,
.mod_rate   = 6,
 };
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 0b

[PATCH v3] media: cedrus: Add support for VP8 decoding

2020-11-10 Thread Jernej Skrabec
VP8 in Cedrus shares same engine as H264.

Note that it seems necessary to call bitstream parsing functions,
to parse frame header, otherwise decoded image is garbage. This is
contrary to what is driver supposed to do. However, values are not
really used, so this might be acceptable. It's possible that bitstream
parsing functions set some internal VPU state, which is later necessary
for proper decoding. Biggest suspect is "VP8 probs update" trigger.

Signed-off-by: Jernej Skrabec 
[addressed issues from reviewer]
Signed-off-by: Emmanuel Gil Peyrot 
---
Changes in v3:
- addressed comments from Ezequiel Garcia - new comments,
  using new macros from VP8 UAPI, new function for waiting
  on bit to be set
Changes in v2:
- rebased on top of current linux-media master branch

NOTE: This now depends on following patch:
https://patchwork.linuxtv.org/project/linux-media/patch/20201108202021.4187-1-linkma...@linkmauve.fr/

 drivers/staging/media/sunxi/cedrus/Makefile   |   3 +-
 drivers/staging/media/sunxi/cedrus/cedrus.c   |   8 +
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  24 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |   5 +
 .../staging/media/sunxi/cedrus/cedrus_hw.c|   2 +
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  80 ++
 .../staging/media/sunxi/cedrus/cedrus_video.c |   9 +
 .../staging/media/sunxi/cedrus/cedrus_vp8.c   | 907 ++
 8 files changed, 1037 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_vp8.c

diff --git a/drivers/staging/media/sunxi/cedrus/Makefile 
b/drivers/staging/media/sunxi/cedrus/Makefile
index 1bce49d3e7e2..a647b3690bf8 100644
--- a/drivers/staging/media/sunxi/cedrus/Makefile
+++ b/drivers/staging/media/sunxi/cedrus/Makefile
@@ -2,4 +2,5 @@
 obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
 
 sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
-cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o
+cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \
+cedrus_vp8.o
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index 9a102b7c1bb9..0b8e748ef8f1 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -142,6 +142,13 @@ static const struct cedrus_control cedrus_controls[] = {
.codec  = CEDRUS_CODEC_H265,
.required   = false,
},
+   {
+   .cfg = {
+   .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER,
+   },
+   .codec  = CEDRUS_CODEC_VP8,
+   .required   = true,
+   },
 };
 
 #define CEDRUS_CONTROLS_COUNT  ARRAY_SIZE(cedrus_controls)
@@ -393,6 +400,7 @@ static int cedrus_probe(struct platform_device *pdev)
dev->dec_ops[CEDRUS_CODEC_MPEG2] = _dec_ops_mpeg2;
dev->dec_ops[CEDRUS_CODEC_H264] = _dec_ops_h264;
dev->dec_ops[CEDRUS_CODEC_H265] = _dec_ops_h265;
+   dev->dec_ops[CEDRUS_CODEC_VP8] = _dec_ops_vp8;
 
mutex_init(>dev_mutex);
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 93c843ae14bb..fece505272b4 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -22,6 +22,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #define CEDRUS_NAME"cedrus"
@@ -35,6 +36,7 @@ enum cedrus_codec {
CEDRUS_CODEC_MPEG2,
CEDRUS_CODEC_H264,
CEDRUS_CODEC_H265,
+   CEDRUS_CODEC_VP8,
CEDRUS_CODEC_LAST,
 };
 
@@ -76,6 +78,10 @@ struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_slice_params*slice_params;
 };
 
+struct cedrus_vp8_run {
+   const struct v4l2_ctrl_vp8_frame_header *frame_params;
+};
+
 struct cedrus_run {
struct vb2_v4l2_buffer  *src;
struct vb2_v4l2_buffer  *dst;
@@ -84,6 +90,7 @@ struct cedrus_run {
struct cedrus_h264_run  h264;
struct cedrus_mpeg2_run mpeg2;
struct cedrus_h265_run  h265;
+   struct cedrus_vp8_run   vp8;
};
 };
 
@@ -135,6 +142,14 @@ struct cedrus_ctx {
void*neighbor_info_buf;
dma_addr_t  neighbor_info_buf_addr;
} h265;
+   struct {
+   unsigned intlast_frame_p_type;
+   unsigned intlast_filter_type;
+   unsigned intlast_sharpness_level;
+
+   u8  *entropy_probs_buf;
+   dma_addr_t  entropy_probs_buf_dma;
+   } vp8;
} codec;
 };
 
@@ -181,6 +196,7 @@ struct cedrus_dev {
 extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
 extern struct cedrus_dec_ops cedrus_dec_ops_h264;
 extern struct cedrus_dec_ops cedrus_dec_ops_

[PATCH] media: cedrus: h264: Fix check for presence of scaling matrix

2020-10-21 Thread Jernej Skrabec
If scaling matrix control is present, VPU should not use default matrix.
Fix that.

Fixes: b3a23db0e2f8 ("media: cedrus: Use H264_SCALING_MATRIX only when 
required")
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 28319351e909..781c84a9b1b7 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -446,7 +446,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16;
reg |= (pps->chroma_qp_index_offset & 0x3f) << 8;
reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f;
-   if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)
+   if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT;
cedrus_write(dev, VE_H264_SHS_QP, reg);
 
-- 
2.29.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 4/5] media: cedrus: Add support for R40

2020-08-25 Thread Jernej Skrabec
Video engine in R40 is very similar to that in A33 but it runs on lower
speed, at least according to OS images released by board designer.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index bc27f9430eeb..83a654a618be 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -496,6 +496,11 @@ static const struct cedrus_variant sun8i_h3_cedrus_variant 
= {
.mod_rate   = 40200,
 };
 
+static const struct cedrus_variant sun8i_r40_cedrus_variant = {
+   .capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   .mod_rate   = 29700,
+};
+
 static const struct cedrus_variant sun50i_a64_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED |
  CEDRUS_CAPABILITY_H265_DEC,
@@ -536,6 +541,10 @@ static const struct of_device_id cedrus_dt_match[] = {
.compatible = "allwinner,sun8i-h3-video-engine",
.data = _h3_cedrus_variant,
},
+   {
+   .compatible = "allwinner,sun8i-r40-video-engine",
+   .data = _r40_cedrus_variant,
+   },
{
.compatible = "allwinner,sun50i-a64-video-engine",
.data = _a64_cedrus_variant,
-- 
2.28.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 0/5] ARM: dts: sun8i: r40: Enable video decoder

2020-08-25 Thread Jernej Skrabec
Allwinner R40 SoC contains video engine very similar to that in A33.

First two patches add system controller nodes and the rest of them
add support for Cedrus VPU.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (5):
  dt-bindings: sram: allwinner,sun4i-a10-system-control: Add R40
compatibles
  ARM: dts: sun8i: r40: Add node for system controller
  dt-bindings: media: allwinner,sun4i-a10-video-engine: Add R40
compatible
  media: cedrus: Add support for R40
  ARM: dts: sun8i: r40: Add video engine node

 .../allwinner,sun4i-a10-video-engine.yaml |  1 +
 .../allwinner,sun4i-a10-system-control.yaml   |  6 
 arch/arm/boot/dts/sun8i-r40.dtsi  | 34 +++
 drivers/staging/media/sunxi/cedrus/cedrus.c   |  9 +
 4 files changed, 50 insertions(+)

-- 
2.28.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/5] ARM: dts: sun8i: r40: Add node for system controller

2020-08-25 Thread Jernej Skrabec
Allwinner R40 has system controller and SRAM C1 region similar to that
in A10.

Add nodes for them.

Signed-off-by: Jernej Skrabec 
---
 arch/arm/boot/dts/sun8i-r40.dtsi | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index dff9a3dc1fba..0c7526365896 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -190,6 +190,29 @@ mixer1_out_tcon_top: endpoint {
};
};
 
+   syscon: system-control@1c0 {
+   compatible = "allwinner,sun8i-r40-system-control",
+"allwinner,sun4i-a10-system-control";
+   reg = <0x01c0 0x30>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   sram_c: sram@1d0 {
+   compatible = "mmio-sram";
+   reg = <0x01d0 0xd>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0 0x01d0 0xd>;
+
+   ve_sram: sram-section@0 {
+   compatible = 
"allwinner,sun8i-r40-sram-c1",
+
"allwinner,sun4i-a10-sram-c1";
+   reg = <0x00 0x8>;
+   };
+   };
+   };
+
nmi_intc: interrupt-controller@1c00030 {
compatible = "allwinner,sun7i-a20-sc-nmi";
interrupt-controller;
-- 
2.28.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/5] dt-bindings: sram: allwinner, sun4i-a10-system-control: Add R40 compatibles

2020-08-25 Thread Jernej Skrabec
Allwinner R40 has system controller similar to that in A10.

Add compatibles for system controller and sram c1 region.

Signed-off-by: Jernej Skrabec 
---
 .../bindings/sram/allwinner,sun4i-a10-system-control.yaml   | 6 ++
 1 file changed, 6 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
 
b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index f5825935fd22..6ebcbc153691 100644
--- 
a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ 
b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -33,6 +33,9 @@ properties:
   - const: allwinner,sun4i-a10-system-control
   - const: allwinner,sun8i-a23-system-control
   - const: allwinner,sun8i-h3-system-control
+  - items:
+  - const: allwinner,sun8i-r40-system-control
+  - const: allwinner,sun4i-a10-system-control
   - const: allwinner,sun50i-a64-sram-controller
 deprecated: true
   - const: allwinner,sun50i-a64-system-control
@@ -86,6 +89,9 @@ patternProperties:
   - items:
   - const: allwinner,sun8i-h3-sram-c1
   - const: allwinner,sun4i-a10-sram-c1
+  - items:
+  - const: allwinner,sun8i-r40-sram-c1
+  - const: allwinner,sun4i-a10-sram-c1
   - items:
   - const: allwinner,sun50i-a64-sram-c1
   - const: allwinner,sun4i-a10-sram-c1
-- 
2.28.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 5/5] ARM: dts: sun8i: r40: Add video engine node

2020-08-25 Thread Jernej Skrabec
Allwinner R40 SoC has a video engine.

Add a node for it.

Signed-off-by: Jernej Skrabec 
---
 arch/arm/boot/dts/sun8i-r40.dtsi | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 0c7526365896..7907569e7b5c 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -273,6 +273,17 @@ csi0: csi@1c09000 {
status = "disabled";
};
 
+   video-codec@1c0e000 {
+   compatible = "allwinner,sun8i-r40-video-engine";
+   reg = <0x01c0e000 0x1000>;
+   clocks = < CLK_BUS_VE>, < CLK_VE>,
+   < CLK_DRAM_VE>;
+   clock-names = "ahb", "mod", "ram";
+   resets = < RST_BUS_VE>;
+   interrupts = ;
+   allwinner,sram = <_sram 1>;
+   };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun8i-r40-mmc",
 "allwinner,sun50i-a64-mmc";
-- 
2.28.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 3/5] dt-bindings: media: allwinner, sun4i-a10-video-engine: Add R40 compatible

2020-08-25 Thread Jernej Skrabec
Allwinner R40 SoC contains video engine. Add compatible for it.

Signed-off-by: Jernej Skrabec 
---
 .../bindings/media/allwinner,sun4i-a10-video-engine.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git 
a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml 
b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml
index 4cc1a670c986..0d58bbcd24d3 100644
--- 
a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml
+++ 
b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml
@@ -18,6 +18,7 @@ properties:
   - allwinner,sun7i-a20-video-engine
   - allwinner,sun8i-a33-video-engine
   - allwinner,sun8i-h3-video-engine
+  - allwinner,sun8i-r40-video-engine
   - allwinner,sun50i-a64-video-engine
   - allwinner,sun50i-h5-video-engine
   - allwinner,sun50i-h6-video-engine
-- 
2.28.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2] media: cedrus: Add support for VP8 decoding

2020-07-22 Thread Jernej Skrabec
VP8 in Cedrus shares same engine as H264.

Note that it seems necessary to call bitstream parsing functions,
to parse frame header, otherwise decoded image is garbage. This is
contrary to what is driver supposed to do. However, values are not
really used, so this might be acceptable. It's possible that bitstream
parsing functions set some internal VPU state, which is later necessary
for proper decoding. Biggest suspect is "VP8 probs update" trigger.

Signed-off-by: Jernej Skrabec 
---
Changes in v2:
- rebased on top of current linux-media master branch

 drivers/staging/media/sunxi/cedrus/Makefile   |   3 +-
 drivers/staging/media/sunxi/cedrus/cedrus.c   |   8 +
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  15 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |   5 +
 .../staging/media/sunxi/cedrus/cedrus_hw.c|   1 +
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  80 ++
 .../staging/media/sunxi/cedrus/cedrus_video.c |   9 +
 .../staging/media/sunxi/cedrus/cedrus_vp8.c   | 699 ++
 8 files changed, 819 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_vp8.c

diff --git a/drivers/staging/media/sunxi/cedrus/Makefile 
b/drivers/staging/media/sunxi/cedrus/Makefile
index 1bce49d3e7e2..a647b3690bf8 100644
--- a/drivers/staging/media/sunxi/cedrus/Makefile
+++ b/drivers/staging/media/sunxi/cedrus/Makefile
@@ -2,4 +2,5 @@
 obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
 
 sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
-cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o
+cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \
+cedrus_vp8.o
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index bc27f9430eeb..b2f5f03ad4a3 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -135,6 +135,13 @@ static const struct cedrus_control cedrus_controls[] = {
.codec  = CEDRUS_CODEC_H265,
.required   = false,
},
+   {
+   .cfg = {
+   .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER,
+   },
+   .codec  = CEDRUS_CODEC_VP8,
+   .required   = true,
+   },
 };
 
 #define CEDRUS_CONTROLS_COUNT  ARRAY_SIZE(cedrus_controls)
@@ -381,6 +388,7 @@ static int cedrus_probe(struct platform_device *pdev)
dev->dec_ops[CEDRUS_CODEC_MPEG2] = _dec_ops_mpeg2;
dev->dec_ops[CEDRUS_CODEC_H264] = _dec_ops_h264;
dev->dec_ops[CEDRUS_CODEC_H265] = _dec_ops_h265;
+   dev->dec_ops[CEDRUS_CODEC_VP8] = _dec_ops_vp8;
 
mutex_init(>dev_mutex);
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 9676ab8a..9f4605afa0f4 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -35,6 +35,7 @@ enum cedrus_codec {
CEDRUS_CODEC_MPEG2,
CEDRUS_CODEC_H264,
CEDRUS_CODEC_H265,
+   CEDRUS_CODEC_VP8,
CEDRUS_CODEC_LAST,
 };
 
@@ -75,6 +76,10 @@ struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_slice_params*slice_params;
 };
 
+struct cedrus_vp8_run {
+   const struct v4l2_ctrl_vp8_frame_header *slice_params;
+};
+
 struct cedrus_run {
struct vb2_v4l2_buffer  *src;
struct vb2_v4l2_buffer  *dst;
@@ -83,6 +88,7 @@ struct cedrus_run {
struct cedrus_h264_run  h264;
struct cedrus_mpeg2_run mpeg2;
struct cedrus_h265_run  h265;
+   struct cedrus_vp8_run   vp8;
};
 };
 
@@ -134,6 +140,14 @@ struct cedrus_ctx {
void*neighbor_info_buf;
dma_addr_t  neighbor_info_buf_addr;
} h265;
+   struct {
+   unsigned intlast_frame_p_type;
+   unsigned intlast_filter_type;
+   unsigned intlast_sharpness_level;
+
+   u8  *entropy_probs_buf;
+   dma_addr_t  entropy_probs_buf_dma;
+   } vp8;
} codec;
 };
 
@@ -180,6 +194,7 @@ struct cedrus_dev {
 extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
 extern struct cedrus_dec_ops cedrus_dec_ops_h264;
 extern struct cedrus_dec_ops cedrus_dec_ops_h265;
+extern struct cedrus_dec_ops cedrus_dec_ops_vp8;
 
 static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
 {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index 58c48e4fdfe9..47c079f14c74 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -68,6 +68,11 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPE

[PATCH 3/3] media: cedrus: h264: Fix frame list construction

2020-06-04 Thread Jernej Skrabec
Current frame list construction algorithm assumes that decoded image
will be output into its own buffer. That is true for progressive content
but not for interlaced where each field is decoded separately into same
buffer.

Fix that by checking if capture buffer is listed in DPB. If it is, reuse
it.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index c87717d17ec5..4f79386315ae 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -102,7 +102,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
struct cedrus_dev *dev = ctx->dev;
unsigned long used_dpbs = 0;
unsigned int position;
-   unsigned int output = 0;
+   int output = -1;
unsigned int i;
 
cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -125,6 +125,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
position = cedrus_buf->codec.h264.position;
used_dpbs |= BIT(position);
 
+   if (run->dst->vb2_buf.timestamp == dpb->reference_ts) {
+   output = position;
+   continue;
+   }
+
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
continue;
 
@@ -132,13 +137,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx 
*ctx,
dpb->top_field_order_cnt,
dpb->bottom_field_order_cnt,
_list[position]);
-
-   output = max(position, output);
}
 
-   position = find_next_zero_bit(_dpbs, CEDRUS_H264_FRAME_NUM,
- output);
-   if (position >= CEDRUS_H264_FRAME_NUM)
+   if (output >= 0)
+   position = output;
+   else
position = find_first_zero_bit(_dpbs, 
CEDRUS_H264_FRAME_NUM);
 
output_buf = vb2_to_cedrus_buffer(>dst->vb2_buf);
-- 
2.27.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/3] media: uapi: h264: update reference lists

2020-06-04 Thread Jernej Skrabec
When dealing with with interlaced frames, reference lists must tell if
each particular reference is meant for top or bottom field. This info
is currently not provided at all in the H264 related controls.

Make reference lists hold a structure which will also hold flags along
index into DPB array. Flags will tell if reference is meant for top or
bottom field.

Currently the only user of these lists is Cedrus which is just compile
fixed here. Actual usage of newly introduced flags will come in
following commit.

Signed-off-by: Jernej Skrabec 
---
 .../media/v4l/ext-ctrls-codec.rst | 40 ++-
 .../staging/media/sunxi/cedrus/cedrus_h264.c  |  6 +--
 include/media/h264-ctrls.h| 12 +-
 3 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst 
b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
index d0d506a444b1..6c36d298db20 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
@@ -1843,10 +1843,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
 * - __u32
   - ``slice_group_change_cycle``
   -
-* - __u8
+* - struct :c:type:`v4l2_h264_reference`
   - ``ref_pic_list0[32]``
   - Reference picture list after applying the per-slice modifications
-* - __u8
+* - struct :c:type:`v4l2_h264_reference`
   - ``ref_pic_list1[32]``
   - Reference picture list after applying the per-slice modifications
 * - __u32
@@ -1926,6 +1926,42 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
   - ``chroma_offset[32][2]``
   -
 
+``Picture Reference``
+
+.. c:type:: v4l2_h264_reference
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_h264_reference
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+* - __u16
+  - ``flags``
+  - See :ref:`Picture Reference Flags `
+* - __u8
+  - ``index``
+  -
+
+.. _h264_reference_flags:
+
+``Picture Reference Flags``
+
+.. cssclass:: longtable
+
+.. flat-table::
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+* - ``V4L2_H264_REFERENCE_FLAG_TOP_FIELD``
+  - 0x0001
+  -
+* - ``V4L2_H264_REFERENCE_FLAG_BOTTOM_FIELD``
+  - 0x0002
+  -
+
 ``V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (struct)``
 Specifies the decode parameters (as extracted from the bitstream)
 for the associated H264 slice data. This includes the necessary
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 54ee2aa423e2..cce527bbdf86 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -166,8 +166,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
 
 static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
   struct cedrus_run *run,
-  const u8 *ref_list, u8 num_ref,
-  enum cedrus_h264_sram_off sram)
+  const struct v4l2_h264_reference *ref_list,
+  u8 num_ref, enum cedrus_h264_sram_off sram)
 {
const struct v4l2_ctrl_h264_decode_params *decode = 
run->h264.decode_params;
struct vb2_queue *cap_q;
@@ -188,7 +188,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
int buf_idx;
u8 dpb_idx;
 
-   dpb_idx = ref_list[i];
+   dpb_idx = ref_list[i].index;
dpb = >dpb[dpb_idx];
 
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
diff --git a/include/media/h264-ctrls.h b/include/media/h264-ctrls.h
index 080fd1293c42..9b1cbc9bc38e 100644
--- a/include/media/h264-ctrls.h
+++ b/include/media/h264-ctrls.h
@@ -140,6 +140,14 @@ struct v4l2_h264_pred_weight_table {
 #define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED0x04
 #define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08
 
+#define V4L2_H264_REFERENCE_FLAG_TOP_FIELD 0x01
+#define V4L2_H264_REFERENCE_FLAG_BOTTOM_FIELD  0x02
+
+struct v4l2_h264_reference {
+   __u8 flags;
+   __u8 index;
+};
+
 struct v4l2_ctrl_h264_slice_params {
/* Size in bytes, including header */
__u32 size;
@@ -182,8 +190,8 @@ struct v4l2_ctrl_h264_slice_params {
 * Entries on each list are indices into
 * v4l2_ctrl_h264_decode_params.dpb[].
 */
-   __u8 ref_pic_list0[32];
-   __u8 ref_pic_list1[32];
+   struct v4l2_h264_reference ref_pic_list0[32];
+   struct v4l2_h264_reference ref_pic_list1[32];
 
__u32 flags;
 };
-- 
2.27.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 0/3] media: uapi: cedrus: Fix decoding interlaced H264 content

2020-06-04 Thread Jernej Skrabec
Currently H264 interlaced content it's not properly decoded on Cedrus.
There are two reasons for this:
1. slice parameters control doesn't provide enough information
2. bug in frame list construction in Cedrus driver

As described in commit message in patch 1, references stored in
reference lists should tell if reference targets top or bottom field.
However, this information is currently not provided. Patch 1 adds
it in form of flags which are set for each reference. Patch 2 then
uses those flags in Cedrus driver.

Frame list construction is fixed in patch 3.

This solution was extensively tested using Kodi on LibreELEC with A64,
H3, H5 and H6 SoCs in slightly different form (flags were transmitted
in MSB bits in index).

Note: I'm not 100% sure if flags for both, top and bottom fields are
needed. Any input here would be welcome.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (3):
  media: uapi: h264: update reference lists
  media: cedrus: h264: Properly configure reference field
  media: cedrus: h264: Fix frame list construction

 .../media/v4l/ext-ctrls-codec.rst | 40 ++-
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 27 +++--
 include/media/h264-ctrls.h| 12 +-
 3 files changed, 62 insertions(+), 17 deletions(-)

-- 
2.27.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/3] media: cedrus: h264: Properly configure reference field

2020-06-04 Thread Jernej Skrabec
When interlaced H264 content is being decoded, references must indicate
which field is being referenced. Currently this was done by checking
capture buffer flags. However, that is not correct because capture
buffer may hold both fields.

Fix this by checking newly introduced flags in reference lists.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index cce527bbdf86..c87717d17ec5 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -183,7 +183,6 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
for (i = 0; i < num_ref; i++) {
const struct v4l2_h264_dpb_entry *dpb;
const struct cedrus_buffer *cedrus_buf;
-   const struct vb2_v4l2_buffer *ref_buf;
unsigned int position;
int buf_idx;
u8 dpb_idx;
@@ -198,12 +197,11 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
if (buf_idx < 0)
continue;
 
-   ref_buf = to_vb2_v4l2_buffer(cap_q->bufs[buf_idx]);
-   cedrus_buf = vb2_v4l2_to_cedrus_buffer(ref_buf);
+   cedrus_buf = vb2_to_cedrus_buffer(cap_q->bufs[buf_idx]);
position = cedrus_buf->codec.h264.position;
 
sram_array[i] |= position << 1;
-   if (ref_buf->field == V4L2_FIELD_BOTTOM)
+   if (ref_list[i].flags & V4L2_H264_REFERENCE_FLAG_BOTTOM_FIELD)
sram_array[i] |= BIT(0);
}
 
-- 
2.27.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: cedrus: Add support for VP8 decoding

2020-05-20 Thread Jernej Skrabec
VP8 in Cedrus shares same engine as H264.

Note that it seems necessary to call bitstream parsing functions,
to parse frame header, otherwise decoded image is garbage. This is
contrary to what is driver supposed to do. However, values are not
really used, so this might be acceptable. It's possible that bitstream
parsing functions set some internal VPU state, which is later necessary
for proper decoding. Biggest suspect is "VP8 probs update" trigger.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/Makefile   |   3 +-
 drivers/staging/media/sunxi/cedrus/cedrus.c   |   8 +
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  15 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |   5 +
 .../staging/media/sunxi/cedrus/cedrus_hw.c|   1 +
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  80 ++
 .../staging/media/sunxi/cedrus/cedrus_video.c |   9 +
 .../staging/media/sunxi/cedrus/cedrus_vp8.c   | 699 ++
 8 files changed, 819 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/media/sunxi/cedrus/cedrus_vp8.c

diff --git a/drivers/staging/media/sunxi/cedrus/Makefile 
b/drivers/staging/media/sunxi/cedrus/Makefile
index 1bce49d3e7e2..a647b3690bf8 100644
--- a/drivers/staging/media/sunxi/cedrus/Makefile
+++ b/drivers/staging/media/sunxi/cedrus/Makefile
@@ -2,4 +2,5 @@
 obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
 
 sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
-cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o
+cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \
+cedrus_vp8.o
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index b320aa058f74..e6b864f05364 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -142,6 +142,13 @@ static const struct cedrus_control cedrus_controls[] = {
.codec  = CEDRUS_CODEC_H265,
.required   = false,
},
+   {
+   .cfg = {
+   .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER,
+   },
+   .codec  = CEDRUS_CODEC_VP8,
+   .required   = true,
+   },
 };
 
 #define CEDRUS_CONTROLS_COUNT  ARRAY_SIZE(cedrus_controls)
@@ -388,6 +395,7 @@ static int cedrus_probe(struct platform_device *pdev)
dev->dec_ops[CEDRUS_CODEC_MPEG2] = _dec_ops_mpeg2;
dev->dec_ops[CEDRUS_CODEC_H264] = _dec_ops_h264;
dev->dec_ops[CEDRUS_CODEC_H265] = _dec_ops_h265;
+   dev->dec_ops[CEDRUS_CODEC_VP8] = _dec_ops_vp8;
 
mutex_init(>dev_mutex);
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index f8264953dd04..353cb04b4ce5 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -35,6 +35,7 @@ enum cedrus_codec {
CEDRUS_CODEC_MPEG2,
CEDRUS_CODEC_H264,
CEDRUS_CODEC_H265,
+   CEDRUS_CODEC_VP8,
CEDRUS_CODEC_LAST,
 };
 
@@ -76,6 +77,10 @@ struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_scaling_matrix  *scaling_matrix;
 };
 
+struct cedrus_vp8_run {
+   const struct v4l2_ctrl_vp8_frame_header *slice_params;
+};
+
 struct cedrus_run {
struct vb2_v4l2_buffer  *src;
struct vb2_v4l2_buffer  *dst;
@@ -84,6 +89,7 @@ struct cedrus_run {
struct cedrus_h264_run  h264;
struct cedrus_mpeg2_run mpeg2;
struct cedrus_h265_run  h265;
+   struct cedrus_vp8_run   vp8;
};
 };
 
@@ -141,6 +147,14 @@ struct cedrus_ctx {
void*entry_points_buf;
dma_addr_t  entry_points_buf_addr;
} h265;
+   struct {
+   unsigned intlast_frame_p_type;
+   unsigned intlast_filter_type;
+   unsigned intlast_sharpness_level;
+
+   u8  *entropy_probs_buf;
+   dma_addr_t  entropy_probs_buf_dma;
+   } vp8;
} codec;
 };
 
@@ -188,6 +202,7 @@ struct cedrus_dev {
 extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
 extern struct cedrus_dec_ops cedrus_dec_ops_h264;
 extern struct cedrus_dec_ops cedrus_dec_ops_h265;
+extern struct cedrus_dec_ops cedrus_dec_ops_vp8;
 
 static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
 {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index 38c0bd7cf672..740b738fdde6 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -70,6 +70,11 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX);
break;
 
+   ca

[PATCH] media: cedrus: Add support for additional output formats

2020-05-20 Thread Jernej Skrabec
If VPU supports untiled output, it actually supports several different
YUV 4:2:0 layouts, namely NV12, NV21, YUV420 and YVU420.

Add support for all of them.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 18 +-
 .../staging/media/sunxi/cedrus/cedrus_video.c  | 18 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index daf5f244f93b..c119fd8c4b92 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -83,9 +83,25 @@ void cedrus_dst_format_set(struct cedrus_dev *dev,
 
switch (fmt->pixelformat) {
case V4L2_PIX_FMT_NV12:
+   case V4L2_PIX_FMT_NV21:
+   case V4L2_PIX_FMT_YUV420:
+   case V4L2_PIX_FMT_YVU420:
chroma_size = ALIGN(width, 16) * ALIGN(height, 16) / 2;
 
-   reg = VE_PRIMARY_OUT_FMT_NV12;
+   switch (fmt->pixelformat) {
+   case V4L2_PIX_FMT_NV12:
+   reg = VE_PRIMARY_OUT_FMT_NV12;
+   break;
+   case V4L2_PIX_FMT_NV21:
+   reg = VE_PRIMARY_OUT_FMT_NV21;
+   break;
+   case V4L2_PIX_FMT_YUV420:
+   reg = VE_PRIMARY_OUT_FMT_YU12;
+   break;
+   case V4L2_PIX_FMT_YVU420:
+   reg = VE_PRIMARY_OUT_FMT_YV12;
+   break;
+   }
cedrus_write(dev, VE_PRIMARY_OUT_FMT, reg);
 
reg = chroma_size / 2;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 15cf1f10221b..016021d71df2 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -55,6 +55,21 @@ static struct cedrus_format cedrus_formats[] = {
.directions = CEDRUS_DECODE_DST,
.capabilities   = CEDRUS_CAPABILITY_UNTILED,
},
+   {
+   .pixelformat= V4L2_PIX_FMT_NV21,
+   .directions = CEDRUS_DECODE_DST,
+   .capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   },
+   {
+   .pixelformat= V4L2_PIX_FMT_YUV420,
+   .directions = CEDRUS_DECODE_DST,
+   .capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   },
+   {
+   .pixelformat= V4L2_PIX_FMT_YVU420,
+   .directions = CEDRUS_DECODE_DST,
+   .capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   },
 };
 
 #define CEDRUS_FORMATS_COUNT   ARRAY_SIZE(cedrus_formats)
@@ -130,6 +145,9 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
break;
 
case V4L2_PIX_FMT_NV12:
+   case V4L2_PIX_FMT_NV21:
+   case V4L2_PIX_FMT_YUV420:
+   case V4L2_PIX_FMT_YVU420:
/* 16-aligned stride. */
bytesperline = ALIGN(width, 16);
 
-- 
2.26.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: cedrus: h264: Fix 4K decoding on H6

2020-03-15 Thread Jernej Skrabec
Due to unknown reason, H6 needs larger intraprediction buffer for 4K
videos than other SoCs. This was discovered by playing 4096x2304 video,
which is maximum what H6 VPU is supposed to support.

Fixes: 03e612e701a6 ("media: cedrus: Fix H264 4k support")
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index bfb4a4820a67..54ee2aa423e2 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -610,8 +610,12 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
goto err_mv_col_buf;
}
 
+   /*
+* NOTE: Multiplying by two deviates from CedarX logic, but it
+* is for some unknown reason needed for H264 4K decoding on H6.
+*/
ctx->codec.h264.intra_pred_buf_size =
-   ALIGN(ctx->src_fmt.width, 64) * 5;
+   ALIGN(ctx->src_fmt.width, 64) * 5 * 2;
ctx->codec.h264.intra_pred_buf =
dma_alloc_coherent(dev->dev,
   ctx->codec.h264.intra_pred_buf_size,
-- 
2.25.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 0/2] media: cedrus: hevc: Minor fixes

2019-12-13 Thread Jernej Skrabec
I noticed that some HEVC videos are not decoded correctly. It turns out
that same workaround which works for H264 also works for HEVC. Crash is
in HEVC more noticable. Any HEVC video decoding afterwards produces only
green screen.

Second patch just adds missing luma bit depth which was probably
overlooked in initial HEVC driver.

This was developed on top of:
https://patchwork.linuxtv.org/cover/60729/

Best regards,
Jernej

Jernej Skrabec (2):
  media: cedrus: Fix decoding for some HEVC videos
  media: cedrus: hevc: Add luma bit depth

 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 26 ---
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  1 +
 2 files changed, 24 insertions(+), 3 deletions(-)

-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/2] media: cedrus: hevc: Add luma bit depth

2019-12-13 Thread Jernej Skrabec
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 5a207f1e137c..13e58977309f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -420,6 +420,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
  
VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size)
 |
  
VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3)
 |
  
VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
+ 
VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
  VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
 
reg |= 
VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE,
-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/2] media: cedrus: Fix decoding for some HEVC videos

2019-12-13 Thread Jernej Skrabec
It seems that for some HEVC videos at least one bitstream parsing
trigger must be called in order to be decoded correctly. There is no
explanation why this helps, but it was observed that several videos
with this fix are now decoded correctly and there is no regression with
others.

Without this fix, those same videos totally crash HEVC decoder (other
decoder engines are unaffected). After decoding those problematic
videos, HEVC decoder always returns only green image (all zeros).
Only complete HW reset helps.

This fix is similar to that for H264.

Signed-off-by: Jernej Skrabec 
---
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 25 ---
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  1 +
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 109d3289418c..5a207f1e137c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2018 Bootlin
  */
 
+#include 
 #include 
 
 #include 
@@ -283,6 +284,23 @@ static void cedrus_h265_write_scaling_list(struct 
cedrus_ctx *ctx,
}
 }
 
+static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num)
+{
+   int count = 0;
+
+   while (count < num) {
+   int tmp = min(num - count, 32);
+
+   cedrus_write(dev, VE_DEC_H265_TRIGGER,
+VE_DEC_H265_TRIGGER_FLUSH_BITS |
+VE_DEC_H265_TRIGGER_TYPE_N_BITS(tmp));
+   while (cedrus_read(dev, VE_DEC_H265_STATUS) & 
VE_DEC_H265_STATUS_VLD_BUSY)
+   udelay(1);
+
+   count += tmp;
+   }
+}
+
 static void cedrus_h265_setup(struct cedrus_ctx *ctx,
  struct cedrus_run *run)
 {
@@ -347,10 +365,9 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
 
/* Source offset and length in bits. */
 
-   reg = slice_params->data_bit_offset;
-   cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, reg);
+   cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
 
-   reg = slice_params->bit_size - slice_params->data_bit_offset;
+   reg = slice_params->bit_size;
cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
 
/* Source beginning and end addresses. */
@@ -385,6 +402,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
/* Initialize bitstream access. */
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
 
+   cedrus_h265_skip_bits(dev, slice_params->data_bit_offset);
+
/* Bitstream parameters. */
 
reg = 
VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) |
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 0d9449fe2b28..df1cceef8d93 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -424,6 +424,7 @@
 
 #define VE_DEC_H265_TRIGGER(VE_ENGINE_DEC_H265 + 0x34)
 
+#define VE_DEC_H265_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8)
 #define VE_DEC_H265_TRIGGER_STCD_VC1   (0x02 << 4)
 #define VE_DEC_H265_TRIGGER_STCD_AVS   (0x01 << 4)
 #define VE_DEC_H265_TRIGGER_STCD_HEVC  (0x00 << 4)
-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 3/4] media: uapi: hevc: Add segment address field

2019-12-13 Thread Jernej Skrabec
If HEVC frame consists of multiple slices, segment address has to be
known in order to properly decode it.

Add segment address field to slice parameters.

Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 5 -
 include/media/hevc-ctrls.h   | 5 -
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst 
b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
index aab1451e54d4..5415d5babcc2 100644
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
@@ -3975,6 +3975,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
 * - __u32
   - ``data_bit_offset``
   - Offset (in bits) to the video data in the current slice data.
+* - __u32
+  - ``slice_segment_addr``
+  -
 * - __u8
   - ``nal_unit_type``
   -
@@ -4052,7 +4055,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
   - ``num_rps_poc_lt_curr``
   - The number of reference pictures in the long-term set.
 * - __u8
-  - ``padding[7]``
+  - ``padding[5]``
   - Applications and drivers must set this to zero.
 * - struct :c:type:`v4l2_hevc_dpb_entry`
   - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]``
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
index 1592e52c3614..3e2e32098312 100644
--- a/include/media/hevc-ctrls.h
+++ b/include/media/hevc-ctrls.h
@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params {
__u32   bit_size;
__u32   data_bit_offset;
 
+   /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+   __u32   slice_segment_addr;
+
/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
__u8nal_unit_type;
__u8nuh_temporal_id_plus1;
@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params {
__u8num_rps_poc_st_curr_after;
__u8num_rps_poc_lt_curr;
 
-   __u8padding;
+   __u8padding[5];
 
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 4/4] media: cedrus: hevc: Add support for multiple slices

2019-12-13 Thread Jernej Skrabec
Now that segment address is available, support for multi-slice frames
can be easily added.

Signed-off-by: Jernej Skrabec 
---
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 26 ---
 .../staging/media/sunxi/cedrus/cedrus_video.c |  1 +
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 888bfd5ca224..109d3289418c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -291,6 +291,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params *slice_params;
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
+   unsigned int width_in_ctb_luma, ctb_size_luma;
+   unsigned int log2_max_luma_coding_block_size;
dma_addr_t src_buf_addr;
dma_addr_t src_buf_end_addr;
u32 chroma_log2_weight_denom;
@@ -303,15 +305,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
slice_params = run->h265.slice_params;
pred_weight_table = _params->pred_weight_table;
 
+   log2_max_luma_coding_block_size =
+   sps->log2_min_luma_coding_block_size_minus3 + 3 +
+   sps->log2_diff_max_min_luma_coding_block_size;
+   ctb_size_luma = 1UL << log2_max_luma_coding_block_size;
+   width_in_ctb_luma =
+   DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
+
/* MV column buffer size and allocation. */
if (!ctx->codec.h265.mv_col_buf_size) {
unsigned int num_buffers =
run->dst->vb2_buf.vb2_queue->num_buffers;
-   unsigned int log2_max_luma_coding_block_size =
-   sps->log2_min_luma_coding_block_size_minus3 + 3 +
-   sps->log2_diff_max_min_luma_coding_block_size;
-   unsigned int ctb_size_luma =
-   1UL << log2_max_luma_coding_block_size;
 
/*
 * Each CTB requires a MV col buffer with a specific unit size.
@@ -366,15 +370,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
 
-   /* Coding tree block address: start at the beginning. */
-   reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
+   /* Coding tree block address */
+   reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % 
width_in_ctb_luma);
+   reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / 
width_in_ctb_luma);
cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
 
cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
 
/* Clear the number of correctly-decoded coding tree blocks. */
-   cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
+   if (ctx->fh.m2m_ctx->new_frame)
+   cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
 
/* Initialize bitstream access. */
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
@@ -523,8 +529,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT,
pps->flags);
 
-   /* FIXME: For multi-slice support. */
-   reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
+   if (ctx->fh.m2m_ctx->new_frame)
+   reg |= 
VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
 
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 15cf1f10221b..497b1199d3fe 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -311,6 +311,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void 
*priv,
 
switch (ctx->src_fmt.pixelformat) {
case V4L2_PIX_FMT_H264_SLICE:
+   case V4L2_PIX_FMT_HEVC_SLICE:
vq->subsystem_flags |=
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 1/4] media: uapi: hevc: Add scaling matrix control

2019-12-13 Thread Jernej Skrabec
HEVC has a scaling matrix concept. Add support for it.

Signed-off-by: Jernej Skrabec 
---
 .../media/uapi/v4l/ext-ctrls-codec.rst| 41 +++
 .../media/uapi/v4l/pixfmt-compressed.rst  |  1 +
 drivers/media/v4l2-core/v4l2-ctrls.c  | 10 +
 include/media/hevc-ctrls.h| 11 +
 4 files changed, 63 insertions(+)

diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst 
b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
index 28313c0f4e7c..aab1451e54d4 100644
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
@@ -4180,6 +4180,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
   - ``padding[6]``
   - Applications and drivers must set this to zero.
 
+``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)``
+Specifies the scaling matrix (as extracted from the bitstream) for
+the associated HEVC slice data. The bitstream parameters are
+defined according to :ref:`hevc`, section 7.4.5 "Scaling list
+data semantics". For further documentation, refer to the above
+specification, unless there is an explicit comment stating
+otherwise.
+
+.. note::
+
+   This compound control is not yet part of the public kernel API and
+   it is expected to change.
+
+.. c:type:: v4l2_ctrl_hevc_scaling_matrix
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+* - __u8
+  - ``scaling_list_4x4[6][16]``
+  -
+* - __u8
+  - ``scaling_list_8x8[6][64]``
+  -
+* - __u8
+  - ``scaling_list_16x16[6][64]``
+  -
+* - __u8
+  - ``scaling_list_32x32[2][64]``
+  -
+* - __u8
+  - ``scaling_list_dc_coef_16x16[6]``
+  -
+* - __u8
+  - ``scaling_list_dc_coef_32x32[2]``
+  -
+
 ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)``
 Specifies the decoding mode to use. Currently exposes slice-based and
 frame-based decoding but new modes might be added later on.
diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst 
b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
index 561bda112809..3aabc322daa4 100644
--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst
+++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
@@ -207,6 +207,7 @@ Compressed Formats
 * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS``
 * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS``
 * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS``
+* ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX``
See the :ref:`associated Codec Control IDs `.
Buffers associated with this pixel format must contain the appropriate
number of macroblocks to decode a full corresponding frame.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 2928c5e0a73d..8cc5ef33b8fd 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -975,6 +975,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_HEVC_SPS:  return "HEVC 
Sequence Parameter Set";
case V4L2_CID_MPEG_VIDEO_HEVC_PPS:  return "HEVC 
Picture Parameter Set";
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC 
Slice Parameters";
+   case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:   return "HEVC 
Scaling Matrix";
case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:  return "HEVC 
Decode Mode";
case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:   return "HEVC 
Start Code";
 
@@ -1407,6 +1408,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum 
v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:
*type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS;
break;
+   case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:
+   *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX;
+   break;
case V4L2_CID_UNIT_CELL_SIZE:
*type = V4L2_CTRL_TYPE_AREA;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
@@ -1857,6 +1861,9 @@ static int std_validate_compound(const struct v4l2_ctrl 
*ctrl, u32 idx,
zero_padding(*p_hevc_slice_params);
break;
 
+   case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
+   break;
+
case V4L2_CTRL_TYPE_AREA:
area = p;
if (!area->width || !area->height)
@@ -2546,6 +2553,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params);
break;
+   case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
+   elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix);
+   break;
c

[PATCH v2 0/4] media: cedrus: hevc: Add support for scaling matrix and multi-slice frames

2019-12-13 Thread Jernej Skrabec
Currently there is no control for HEVC scaling matrix and segment address
field is also missing. This series adds those and implements support for
them in Cedrus driver.

Following videos were used for testing:
- scaling matrix:
http://jernej.libreelec.tv/videos/h265/slist_test.mp4
- multi-slice:
http://jernej.libreelec.tv/videos/h265/Dredd%20%E2%80%93%20DTS%20Sound%20Check%20DTS-HD%20MA%207.1.m2ts

Best regards,
Jernej

Changes from v1:
- always set CTB_ADDR_X and CTB_ADDR_Y (patch 4)

Jernej Skrabec (4):
  media: uapi: hevc: Add scaling matrix control
  media: cedrus: hevc: Add support for scaling matrix
  media: uapi: hevc: Add segment address field
  media: cedrus: hevc: Add support for multiple slices

 .../media/uapi/v4l/ext-ctrls-codec.rst| 46 -
 .../media/uapi/v4l/pixfmt-compressed.rst  |  1 +
 drivers/media/v4l2-core/v4l2-ctrls.c  | 10 ++
 drivers/staging/media/sunxi/cedrus/cedrus.c   |  7 ++
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |  2 +
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 96 ---
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  2 +
 .../staging/media/sunxi/cedrus/cedrus_video.c |  1 +
 include/media/hevc-ctrls.h| 16 +++-
 10 files changed, 169 insertions(+), 13 deletions(-)

-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 2/4] media: cedrus: hevc: Add support for scaling matrix

2019-12-13 Thread Jernej Skrabec
HEVC frames may use scaling list feature. Add support for it.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.c   |  7 ++
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |  2 +
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 70 ++-
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  2 +
 5 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index c6ddd46eff82..bf68bc6b20c8 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -116,6 +116,13 @@ static const struct cedrus_control cedrus_controls[] = {
.codec  = CEDRUS_CODEC_H265,
.required   = true,
},
+   {
+   .cfg = {
+   .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
+   },
+   .codec  = CEDRUS_CODEC_H265,
+   .required   = true,
+   },
{
.cfg = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 9676ab8a..d945f4f0ff2d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -73,6 +73,7 @@ struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_sps *sps;
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params*slice_params;
+   const struct v4l2_ctrl_hevc_scaling_matrix  *scaling_matrix;
 };
 
 struct cedrus_run {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index 4a2fc33a1d79..327ed6c264dc 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -66,6 +66,8 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_HEVC_PPS);
run.h265.slice_params = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
+   run.h265.scaling_matrix = cedrus_find_control_data(ctx,
+   V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX);
break;
 
default:
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 6945dc74e1d7..888bfd5ca224 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -220,6 +220,69 @@ static void cedrus_h265_pred_weight_write(struct 
cedrus_dev *dev,
}
 }
 
+static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
+  struct cedrus_run *run)
+{
+   const struct v4l2_ctrl_hevc_scaling_matrix *scaling;
+   struct cedrus_dev *dev = ctx->dev;
+   u32 i, j, k, val;
+
+   scaling = run->h265.scaling_matrix;
+
+   cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0,
+(scaling->scaling_list_dc_coef_32x32[1] << 24) |
+(scaling->scaling_list_dc_coef_32x32[0] << 16) |
+(scaling->scaling_list_dc_coef_16x16[1] << 8) |
+(scaling->scaling_list_dc_coef_16x16[0] << 0));
+
+   cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1,
+(scaling->scaling_list_dc_coef_16x16[5] << 24) |
+(scaling->scaling_list_dc_coef_16x16[4] << 16) |
+(scaling->scaling_list_dc_coef_16x16[3] << 8) |
+(scaling->scaling_list_dc_coef_16x16[2] << 0));
+
+   cedrus_h265_sram_write_offset(dev, 
VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS);
+
+   for (i = 0; i < 6; i++)
+   for (j = 0; j < 8; j++)
+   for (k = 0; k < 8; k += 4) {
+   val = ((u32)scaling->scaling_list_8x8[i][j + (k 
+ 3) * 8] << 24) |
+ ((u32)scaling->scaling_list_8x8[i][j + (k 
+ 2) * 8] << 16) |
+ ((u32)scaling->scaling_list_8x8[i][j + (k 
+ 1) * 8] << 8) |
+ scaling->scaling_list_8x8[i][j + k * 8];
+   cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
+   }
+
+   for (i = 0; i < 2; i++)
+   for (j = 0; j < 8; j++)
+   for (k = 0; k < 8; k += 4) {
+   val = ((u32)scaling->scaling_list_32x32[i][j + 
(k + 3) * 8] << 24) |
+ ((u32)scaling->scaling_

[PATCH v2 2/3] media: cedrus: Fix H264 4k support

2019-11-06 Thread Jernej Skrabec
H264 decoder needs additional or bigger buffers in order to decode 4k
videos.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  7 ++
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 91 +--
 .../staging/media/sunxi/cedrus/cedrus_regs.h  | 11 +++
 3 files changed, 101 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index c45fb9a7ad07..9676ab8a 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -116,8 +116,15 @@ struct cedrus_ctx {
ssize_t mv_col_buf_size;
void*pic_info_buf;
dma_addr_t  pic_info_buf_dma;
+   ssize_t pic_info_buf_size;
void*neighbor_info_buf;
dma_addr_t  neighbor_info_buf_dma;
+   void*deblk_buf;
+   dma_addr_t  deblk_buf_dma;
+   ssize_t deblk_buf_size;
+   void*intra_pred_buf;
+   dma_addr_t  intra_pred_buf_dma;
+   ssize_t intra_pred_buf_size;
} h264;
struct {
void*mv_col_buf;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index d2c854ecdf15..ab83a6f1f921 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -39,7 +39,7 @@ struct cedrus_h264_sram_ref_pic {
 #define CEDRUS_H264_FRAME_NUM  18
 
 #define CEDRUS_NEIGHBOR_INFO_BUF_SIZE  (16 * SZ_1K)
-#define CEDRUS_PIC_INFO_BUF_SIZE   (128 * SZ_1K)
+#define CEDRUS_MIN_PIC_INFO_BUF_SIZE   (130 * SZ_1K)
 
 static void cedrus_h264_write_sram(struct cedrus_dev *dev,
   enum cedrus_h264_sram_off off,
@@ -342,6 +342,20 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
 VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
 VE_H264_VLD_ADDR_LAST);
 
+   if (ctx->src_fmt.width > 2048) {
+   cedrus_write(dev, VE_BUF_CTRL,
+VE_BUF_CTRL_INTRAPRED_MIXED_RAM |
+VE_BUF_CTRL_DBLK_MIXED_RAM);
+   cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR,
+ctx->codec.h264.deblk_buf_dma);
+   cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR,
+ctx->codec.h264.intra_pred_buf_dma);
+   } else {
+   cedrus_write(dev, VE_BUF_CTRL,
+VE_BUF_CTRL_INTRAPRED_INT_SRAM |
+VE_BUF_CTRL_DBLK_INT_SRAM);
+   }
+
/*
 * FIXME: Since the bitstream parsing is done in software, and
 * in userspace, this shouldn't be needed anymore. But it
@@ -502,18 +516,30 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
 static int cedrus_h264_start(struct cedrus_ctx *ctx)
 {
struct cedrus_dev *dev = ctx->dev;
+   unsigned int pic_info_size;
unsigned int field_size;
unsigned int mv_col_size;
int ret;
 
+   /* Formula for picture buffer size is taken from CedarX source. */
+
+   if (ctx->src_fmt.width > 2048)
+   pic_info_size = CEDRUS_H264_FRAME_NUM * 0x4000;
+   else
+   pic_info_size = CEDRUS_H264_FRAME_NUM * 0x1000;
+
/*
-* FIXME: It seems that the H6 cedarX code is using a formula
-* here based on the size of the frame, while all the older
-* code is using a fixed size, so that might need to be
-* changed at some point.
+* FIXME: If V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is set,
+* there is no need to multiply by 2.
 */
+   pic_info_size += ctx->src_fmt.height * 2 * 64;
+
+   if (pic_info_size < CEDRUS_MIN_PIC_INFO_BUF_SIZE)
+   pic_info_size = CEDRUS_MIN_PIC_INFO_BUF_SIZE;
+
+   ctx->codec.h264.pic_info_buf_size = pic_info_size;
ctx->codec.h264.pic_info_buf =
-   dma_alloc_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
+   dma_alloc_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size,
   >codec.h264.pic_info_buf_dma,
   GFP_KERNEL);
if (!ctx->codec.h264.pic_info_buf)
@@ -566,15 +592,56 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
goto err_neighbor_buf;
}
 
+   if (ctx->src_fmt.width > 2048) {
+   /*
+* Formulas for deblock and intra prediction buffer sizes
+* are taken from CedarX source.
+*/
+
+   ctx->code

[PATCH v2 0/3] media: cedrus: Add support for 4k videos

2019-11-06 Thread Jernej Skrabec
While cedrus driver accepts videos up to 3840x2160, they are not decoded
correctly. Driver doesn't correctly set mode register for widths greater
than 2048 (patch 1). H264 engine also needs additional buffers which are
not provided currently (patch 2). Finally, there are several different
resolutions which can be considered 4k. Biggest is 4096x2304 which is
also supported by HW. Set that new maximum size (patch 3).

HEVC engine was also tested with 4k video.

Following video was used for H264 video testing:
http://jernej.libreelec.tv/videos/h264/PUPPIES%20BATH%20IN%204K%20(ULTRA%20HD)(Original_H.264-AAC)%20(4ksamples.com).mp4

Note that at this point memory allocation is suboptimal and H264 engine
allocates far more memory that it is really needed. For above video to
work, I had to set CMA size to 512 MiB and add "vmalloc=512M" to kernel
arguments. Memory optimizations will be done later.

Best regards,
Jernej

Changes from v1:
- added Paul's acked-by
- added define for minimum pic info buf size
- added comments that formulas come from CedarX source

Jernej Skrabec (3):
  media: cedrus: Properly signal size in mode register
  media: cedrus: Fix H264 4k support
  media: cedrus: Increase maximum supported size

 drivers/staging/media/sunxi/cedrus/cedrus.h   |  7 ++
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 93 +--
 .../staging/media/sunxi/cedrus/cedrus_h265.c  |  2 +-
 .../staging/media/sunxi/cedrus/cedrus_hw.c|  9 +-
 .../staging/media/sunxi/cedrus/cedrus_hw.h|  2 +-
 .../staging/media/sunxi/cedrus/cedrus_mpeg2.c |  2 +-
 .../staging/media/sunxi/cedrus/cedrus_regs.h  | 13 +++
 .../staging/media/sunxi/cedrus/cedrus_video.c |  4 +-
 8 files changed, 116 insertions(+), 16 deletions(-)

-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 1/3] media: cedrus: Properly signal size in mode register

2019-11-06 Thread Jernej Skrabec
Mode register also holds information if video width is bigger than 2048
and if it is equal to 4096.

Rework cedrus_engine_enable() to properly signal this properties.

Signed-off-by: Jernej Skrabec 
Acked-by: Paul Kocialkowski 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c  | 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_h265.c  | 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c| 9 +++--
 drivers/staging/media/sunxi/cedrus/cedrus_hw.h| 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c | 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_regs.h  | 2 ++
 6 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 7487f6ab7576..d2c854ecdf15 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -485,7 +485,7 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
 {
struct cedrus_dev *dev = ctx->dev;
 
-   cedrus_engine_enable(dev, CEDRUS_CODEC_H264);
+   cedrus_engine_enable(ctx, CEDRUS_CODEC_H264);
 
cedrus_write(dev, VE_H264_SDROT_CTRL, 0);
cedrus_write(dev, VE_H264_EXTRA_BUFFER1,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 9bc921866f70..6945dc74e1d7 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -276,7 +276,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
}
 
/* Activate H265 engine. */
-   cedrus_engine_enable(dev, CEDRUS_CODEC_H265);
+   cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
 
/* Source offset and length in bits. */
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 570a9165dd5d..3acfa21bc124 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -30,7 +30,7 @@
 #include "cedrus_hw.h"
 #include "cedrus_regs.h"
 
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
+int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec)
 {
u32 reg = 0;
 
@@ -58,7 +58,12 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum 
cedrus_codec codec)
return -EINVAL;
}
 
-   cedrus_write(dev, VE_MODE, reg);
+   if (ctx->src_fmt.width == 4096)
+   reg |= VE_MODE_PIC_WIDTH_IS_4096;
+   if (ctx->src_fmt.width > 2048)
+   reg |= VE_MODE_PIC_WIDTH_MORE_2048;
+
+   cedrus_write(ctx->dev, VE_MODE, reg);
 
return 0;
 }
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index 27d0882397aa..604ff932fbf5 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -16,7 +16,7 @@
 #ifndef _CEDRUS_HW_H_
 #define _CEDRUS_HW_H_
 
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
+int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec);
 void cedrus_engine_disable(struct cedrus_dev *dev);
 
 void cedrus_dst_format_set(struct cedrus_dev *dev,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
index 13c34927bad5..8bcd6b8f9e2d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
@@ -96,7 +96,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct 
cedrus_run *run)
quantization = run->mpeg2.quantization;
 
/* Activate MPEG engine. */
-   cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2);
+   cedrus_engine_enable(ctx, CEDRUS_CODEC_MPEG2);
 
/* Set intra quantization matrix. */
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 4275a307d282..ace3d49fcd82 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -35,6 +35,8 @@
 
 #define VE_MODE0x00
 
+#define VE_MODE_PIC_WIDTH_IS_4096  BIT(22)
+#define VE_MODE_PIC_WIDTH_MORE_2048BIT(21)
 #define VE_MODE_REC_WR_MODE_2MB(0x01 << 20)
 #define VE_MODE_REC_WR_MODE_1MB(0x00 << 20)
 #define VE_MODE_DDR_MODE_BW_128(0x03 << 16)
-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 3/3] media: cedrus: Increase maximum supported size

2019-11-06 Thread Jernej Skrabec
There are few variations of 4k resolutions. The biggest one is
4096x2304 which is also supported by HW. It has also nice property that
both width and size are divisible by maximum HEVC CTB size, which is 64.

Signed-off-by: Jernej Skrabec 
Acked-by: Paul Kocialkowski 
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index cc15a5cf107d..15cf1f10221b 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -29,8 +29,8 @@
 
 #define CEDRUS_MIN_WIDTH   16U
 #define CEDRUS_MIN_HEIGHT  16U
-#define CEDRUS_MAX_WIDTH   3840U
-#define CEDRUS_MAX_HEIGHT  2160U
+#define CEDRUS_MAX_WIDTH   4096U
+#define CEDRUS_MAX_HEIGHT  2304U
 
 static struct cedrus_format cedrus_formats[] = {
{
-- 
2.24.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 4/4] media: cedrus: hevc: Add support for multiple slices

2019-10-26 Thread Jernej Skrabec
Now that segment address is available, support for multi-slice frames
can be easily added.

Signed-off-by: Jernej Skrabec 
---
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 21 +++
 .../staging/media/sunxi/cedrus/cedrus_video.c |  1 +
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 888bfd5ca224..e909adf6f30f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -366,15 +366,28 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
 
-   /* Coding tree block address: start at the beginning. */
+   /* Coding tree block address */
reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
+   if (!ctx->fh.m2m_ctx->new_frame) {
+   unsigned int log2_max_luma_coding_block_size =
+   sps->log2_min_luma_coding_block_size_minus3 + 3 +
+   sps->log2_diff_max_min_luma_coding_block_size;
+   unsigned int ctb_size_luma =
+   1UL << log2_max_luma_coding_block_size;
+   unsigned int width_in_ctb_luma =
+   DIV_ROUND_UP(sps->pic_width_in_luma_samples, 
ctb_size_luma);
+
+   reg = 
VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % 
width_in_ctb_luma);
+   reg |= 
VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / 
width_in_ctb_luma);
+   }
cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
 
cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
 
/* Clear the number of correctly-decoded coding tree blocks. */
-   cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
+   if (ctx->fh.m2m_ctx->new_frame)
+   cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
 
/* Initialize bitstream access. */
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
@@ -523,8 +536,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT,
pps->flags);
 
-   /* FIXME: For multi-slice support. */
-   reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
+   if (ctx->fh.m2m_ctx->new_frame)
+   reg |= 
VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
 
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 15cf1f10221b..497b1199d3fe 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -311,6 +311,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void 
*priv,
 
switch (ctx->src_fmt.pixelformat) {
case V4L2_PIX_FMT_H264_SLICE:
+   case V4L2_PIX_FMT_HEVC_SLICE:
vq->subsystem_flags |=
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/4] media: cedrus: hevc: Add support for scaling matrix

2019-10-26 Thread Jernej Skrabec
HEVC frames may use scaling list feature. Add support for it.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.c   |  7 ++
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |  2 +
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 70 ++-
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  2 +
 5 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index c6ddd46eff82..bf68bc6b20c8 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -116,6 +116,13 @@ static const struct cedrus_control cedrus_controls[] = {
.codec  = CEDRUS_CODEC_H265,
.required   = true,
},
+   {
+   .cfg = {
+   .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
+   },
+   .codec  = CEDRUS_CODEC_H265,
+   .required   = true,
+   },
{
.cfg = {
.id = V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 9676ab8a..d945f4f0ff2d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -73,6 +73,7 @@ struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_sps *sps;
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params*slice_params;
+   const struct v4l2_ctrl_hevc_scaling_matrix  *scaling_matrix;
 };
 
 struct cedrus_run {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index 4a2fc33a1d79..327ed6c264dc 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -66,6 +66,8 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_HEVC_PPS);
run.h265.slice_params = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
+   run.h265.scaling_matrix = cedrus_find_control_data(ctx,
+   V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX);
break;
 
default:
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 6945dc74e1d7..888bfd5ca224 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -220,6 +220,69 @@ static void cedrus_h265_pred_weight_write(struct 
cedrus_dev *dev,
}
 }
 
+static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
+  struct cedrus_run *run)
+{
+   const struct v4l2_ctrl_hevc_scaling_matrix *scaling;
+   struct cedrus_dev *dev = ctx->dev;
+   u32 i, j, k, val;
+
+   scaling = run->h265.scaling_matrix;
+
+   cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0,
+(scaling->scaling_list_dc_coef_32x32[1] << 24) |
+(scaling->scaling_list_dc_coef_32x32[0] << 16) |
+(scaling->scaling_list_dc_coef_16x16[1] << 8) |
+(scaling->scaling_list_dc_coef_16x16[0] << 0));
+
+   cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1,
+(scaling->scaling_list_dc_coef_16x16[5] << 24) |
+(scaling->scaling_list_dc_coef_16x16[4] << 16) |
+(scaling->scaling_list_dc_coef_16x16[3] << 8) |
+(scaling->scaling_list_dc_coef_16x16[2] << 0));
+
+   cedrus_h265_sram_write_offset(dev, 
VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS);
+
+   for (i = 0; i < 6; i++)
+   for (j = 0; j < 8; j++)
+   for (k = 0; k < 8; k += 4) {
+   val = ((u32)scaling->scaling_list_8x8[i][j + (k 
+ 3) * 8] << 24) |
+ ((u32)scaling->scaling_list_8x8[i][j + (k 
+ 2) * 8] << 16) |
+ ((u32)scaling->scaling_list_8x8[i][j + (k 
+ 1) * 8] << 8) |
+ scaling->scaling_list_8x8[i][j + k * 8];
+   cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
+   }
+
+   for (i = 0; i < 2; i++)
+   for (j = 0; j < 8; j++)
+   for (k = 0; k < 8; k += 4) {
+   val = ((u32)scaling->scaling_list_32x32[i][j + 
(k + 3) * 8] << 24) |
+ ((u32)scaling->scaling_

[PATCH 0/4] media: cedrus: hevc: Add support for scaling matrix and multi-slice frames

2019-10-26 Thread Jernej Skrabec
Currently there is no control for HEVC scaling matrix and segment address
field is also missing. This series adds those and implements support for
them in Cedrus driver.

Following videos were using for testing:
- scaling matrix:
http://jernej.libreelec.tv/videos/h265/slist_test.mp4
- multi-slice:
http://jernej.libreelec.tv/videos/h265/Dredd%20%E2%80%93%20DTS%20Sound%20Check%20DTS-HD%20MA%207.1.m2ts

Best regards,
Jernej

Jernej Skrabec (4):
  media: uapi: hevc: Add scaling matrix control
  media: cedrus: hevc: Add support for scaling matrix
  media: uapi: hevc: Add segment address field
  media: cedrus: hevc: Add support for multiple slices

 .../media/uapi/v4l/ext-ctrls-codec.rst| 46 +-
 .../media/uapi/v4l/pixfmt-compressed.rst  |  1 +
 drivers/media/v4l2-core/v4l2-ctrls.c  | 10 ++
 drivers/staging/media/sunxi/cedrus/cedrus.c   |  7 ++
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |  2 +
 .../staging/media/sunxi/cedrus/cedrus_h265.c  | 91 ++-
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  2 +
 .../staging/media/sunxi/cedrus/cedrus_video.c |  1 +
 include/media/hevc-ctrls.h| 16 +++-
 10 files changed, 170 insertions(+), 7 deletions(-)

-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 3/4] media: uapi: hevc: Add segment address field

2019-10-26 Thread Jernej Skrabec
If HEVC frame consists of multiple slices, segment address has to be
known in order to properly decode it.

Add segment address field to slice parameters.

Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 5 -
 include/media/hevc-ctrls.h   | 5 -
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst 
b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
index 382e85e16444..99e4a7099614 100644
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
@@ -3971,6 +3971,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
 * - __u32
   - ``data_bit_offset``
   - Offset (in bits) to the video data in the current slice data.
+* - __u32
+  - ``slice_segment_addr``
+  -
 * - __u8
   - ``nal_unit_type``
   -
@@ -4048,7 +4051,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
   - ``num_rps_poc_lt_curr``
   - The number of reference pictures in the long-term set.
 * - __u8
-  - ``padding[7]``
+  - ``padding[5]``
   - Applications and drivers must set this to zero.
 * - struct :c:type:`v4l2_hevc_dpb_entry`
   - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]``
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
index 1592e52c3614..3e2e32098312 100644
--- a/include/media/hevc-ctrls.h
+++ b/include/media/hevc-ctrls.h
@@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params {
__u32   bit_size;
__u32   data_bit_offset;
 
+   /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+   __u32   slice_segment_addr;
+
/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
__u8nal_unit_type;
__u8nuh_temporal_id_plus1;
@@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params {
__u8num_rps_poc_st_curr_after;
__u8num_rps_poc_lt_curr;
 
-   __u8padding;
+   __u8padding[5];
 
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/4] media: uapi: hevc: Add scaling matrix control

2019-10-26 Thread Jernej Skrabec
HEVC has a scaling matrix concept. Add support for it.

Signed-off-by: Jernej Skrabec 
---
 .../media/uapi/v4l/ext-ctrls-codec.rst| 41 +++
 .../media/uapi/v4l/pixfmt-compressed.rst  |  1 +
 drivers/media/v4l2-core/v4l2-ctrls.c  | 10 +
 include/media/hevc-ctrls.h| 11 +
 4 files changed, 63 insertions(+)

diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst 
b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
index a1209f68c5e8..382e85e16444 100644
--- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
+++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst
@@ -4176,6 +4176,47 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
   - ``padding[6]``
   - Applications and drivers must set this to zero.
 
+``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)``
+Specifies the scaling matrix (as extracted from the bitstream) for
+the associated HEVC slice data. The bitstream parameters are
+defined according to :ref:`hevc`, section 7.4.5 "Scaling list
+data semantics". For further documentation, refer to the above
+specification, unless there is an explicit comment stating
+otherwise.
+
+.. note::
+
+   This compound control is not yet part of the public kernel API and
+   it is expected to change.
+
+.. c:type:: v4l2_ctrl_hevc_scaling_matrix
+
+.. cssclass:: longtable
+
+.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+* - __u8
+  - ``scaling_list_4x4[6][16]``
+  -
+* - __u8
+  - ``scaling_list_8x8[6][64]``
+  -
+* - __u8
+  - ``scaling_list_16x16[6][64]``
+  -
+* - __u8
+  - ``scaling_list_32x32[2][64]``
+  -
+* - __u8
+  - ``scaling_list_dc_coef_16x16[6]``
+  -
+* - __u8
+  - ``scaling_list_dc_coef_32x32[2]``
+  -
+
 ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)``
 Specifies the decoding mode to use. Currently exposes slice-based and
 frame-based decoding but new modes might be added later on.
diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst 
b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
index 561bda112809..3aabc322daa4 100644
--- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst
+++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst
@@ -207,6 +207,7 @@ Compressed Formats
 * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS``
 * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS``
 * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS``
+* ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX``
See the :ref:`associated Codec Control IDs `.
Buffers associated with this pixel format must contain the appropriate
number of macroblocks to decode a full corresponding frame.
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index b4caf2d4d076..2803165cbc6a 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -975,6 +975,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_HEVC_SPS:  return "HEVC 
Sequence Parameter Set";
case V4L2_CID_MPEG_VIDEO_HEVC_PPS:  return "HEVC 
Picture Parameter Set";
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC 
Slice Parameters";
+   case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:   return "HEVC 
Scaling Matrix";
case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:  return "HEVC 
Decode Mode";
case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:   return "HEVC 
Start Code";
 
@@ -1407,6 +1408,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum 
v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:
*type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS;
break;
+   case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:
+   *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX;
+   break;
case V4L2_CID_UNIT_CELL_SIZE:
*type = V4L2_CTRL_TYPE_AREA;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
@@ -1856,6 +1860,9 @@ static int std_validate_compound(const struct v4l2_ctrl 
*ctrl, u32 idx,
zero_padding(*p_hevc_slice_params);
break;
 
+   case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
+   break;
+
case V4L2_CTRL_TYPE_AREA:
area = p;
if (!area->width || !area->height)
@@ -2545,6 +2552,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params);
break;
+   case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
+   elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix);
+   break;
c

[PATCH 0/3] media: cedrus: Add support for 4k videos

2019-10-26 Thread Jernej Skrabec
While cedrus driver accepts videos up to 3840x2160, they are not decoded
correctly. Driver doesn't correctly set mode register for widths greater
than 2048 (patch 1). H264 engine also needs additional buffers which are
not provided currently (patch 2). Finally, there are several different
resolutions which can be considered 4k. Biggest is 4096x2304 which is
also supported by HW. Set that new maximum size (patch 3).

HEVC engine was not yet tested with 4k video, but as far as I know, it
doesn't need any special setting besides patch 1.

Following video was used for H264 video testing:
http://jernej.libreelec.tv/videos/h264/PUPPIES%20BATH%20IN%204K%20(ULTRA%20HD)(Original_H.264-AAC)%20(4ksamples.com).mp4

Note that at this point memory allocation is suboptimal and H264 engine
allocates far more memory that it is really needed. For above video to
work, I had to set CMA size to 512 MiB and add "vmalloc=512M" to kernel
arguments. Memory optimizations will be done later.

This series is based on top of https://patchwork.linuxtv.org/cover/59653/

Best regards,
Jernej

Jernej Skrabec (3):
  media: cedrus: Properly signal size in mode register
  media: cedrus: Fix H264 4k support
  media: cedrus: Increase maximum supported size

 drivers/staging/media/sunxi/cedrus/cedrus.h   |  7 ++
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 85 +--
 .../staging/media/sunxi/cedrus/cedrus_h265.c  |  2 +-
 .../staging/media/sunxi/cedrus/cedrus_hw.c|  9 +-
 .../staging/media/sunxi/cedrus/cedrus_hw.h|  2 +-
 .../staging/media/sunxi/cedrus/cedrus_mpeg2.c |  2 +-
 .../staging/media/sunxi/cedrus/cedrus_regs.h  | 13 +++
 .../staging/media/sunxi/cedrus/cedrus_video.c |  4 +-
 8 files changed, 108 insertions(+), 16 deletions(-)

-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/3] media: cedrus: Fix H264 4k support

2019-10-26 Thread Jernej Skrabec
H264 decoder needs additional or bigger buffers in order to decode 4k
videos.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  7 ++
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 83 +--
 .../staging/media/sunxi/cedrus/cedrus_regs.h  | 11 +++
 3 files changed, 93 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index c45fb9a7ad07..9676ab8a 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -116,8 +116,15 @@ struct cedrus_ctx {
ssize_t mv_col_buf_size;
void*pic_info_buf;
dma_addr_t  pic_info_buf_dma;
+   ssize_t pic_info_buf_size;
void*neighbor_info_buf;
dma_addr_t  neighbor_info_buf_dma;
+   void*deblk_buf;
+   dma_addr_t  deblk_buf_dma;
+   ssize_t deblk_buf_size;
+   void*intra_pred_buf;
+   dma_addr_t  intra_pred_buf_dma;
+   ssize_t intra_pred_buf_size;
} h264;
struct {
void*mv_col_buf;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index d2c854ecdf15..19962f4213d4 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -39,7 +39,6 @@ struct cedrus_h264_sram_ref_pic {
 #define CEDRUS_H264_FRAME_NUM  18
 
 #define CEDRUS_NEIGHBOR_INFO_BUF_SIZE  (16 * SZ_1K)
-#define CEDRUS_PIC_INFO_BUF_SIZE   (128 * SZ_1K)
 
 static void cedrus_h264_write_sram(struct cedrus_dev *dev,
   enum cedrus_h264_sram_off off,
@@ -342,6 +341,20 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
 VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
 VE_H264_VLD_ADDR_LAST);
 
+   if (ctx->src_fmt.width > 2048) {
+   cedrus_write(dev, VE_BUF_CTRL,
+VE_BUF_CTRL_INTRAPRED_MIXED_RAM |
+VE_BUF_CTRL_DBLK_MIXED_RAM);
+   cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR,
+ctx->codec.h264.deblk_buf_dma);
+   cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR,
+ctx->codec.h264.intra_pred_buf_dma);
+   } else {
+   cedrus_write(dev, VE_BUF_CTRL,
+VE_BUF_CTRL_INTRAPRED_INT_SRAM |
+VE_BUF_CTRL_DBLK_INT_SRAM);
+   }
+
/*
 * FIXME: Since the bitstream parsing is done in software, and
 * in userspace, this shouldn't be needed anymore. But it
@@ -502,18 +515,28 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
 static int cedrus_h264_start(struct cedrus_ctx *ctx)
 {
struct cedrus_dev *dev = ctx->dev;
+   unsigned int pic_info_size;
unsigned int field_size;
unsigned int mv_col_size;
int ret;
 
+   if (ctx->src_fmt.width > 2048)
+   pic_info_size = CEDRUS_H264_FRAME_NUM * 0x4000;
+   else
+   pic_info_size = CEDRUS_H264_FRAME_NUM * 0x1000;
+
/*
-* FIXME: It seems that the H6 cedarX code is using a formula
-* here based on the size of the frame, while all the older
-* code is using a fixed size, so that might need to be
-* changed at some point.
+* FIXME: If V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is set,
+* there is no need to multiply by 2.
 */
+   pic_info_size += ctx->src_fmt.height * 2 * 64;
+
+   if (pic_info_size < 130 * SZ_1K)
+   pic_info_size = 130 * SZ_1K;
+
+   ctx->codec.h264.pic_info_buf_size = pic_info_size;
ctx->codec.h264.pic_info_buf =
-   dma_alloc_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
+   dma_alloc_coherent(dev->dev, ctx->codec.h264.pic_info_buf_size,
   >codec.h264.pic_info_buf_dma,
   GFP_KERNEL);
if (!ctx->codec.h264.pic_info_buf)
@@ -566,15 +589,51 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
goto err_neighbor_buf;
}
 
+   if (ctx->src_fmt.width > 2048) {
+   ctx->codec.h264.deblk_buf_size =
+   ALIGN(ctx->src_fmt.width, 32) * 12;
+   ctx->codec.h264.deblk_buf =
+   dma_alloc_coherent(dev->dev,
+  ctx->codec.h264.deblk_buf_size,
+  >codec.h

[PATCH 3/3] media: cedrus: Increase maximum supported size

2019-10-26 Thread Jernej Skrabec
There are few variations of 4k resolutions. The biggest one is
4096x2304 which is also supported by HW. It has also nice property that
both width and size are divisible by maximum HEVC CTB size, which is 64.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index cc15a5cf107d..15cf1f10221b 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -29,8 +29,8 @@
 
 #define CEDRUS_MIN_WIDTH   16U
 #define CEDRUS_MIN_HEIGHT  16U
-#define CEDRUS_MAX_WIDTH   3840U
-#define CEDRUS_MAX_HEIGHT  2160U
+#define CEDRUS_MAX_WIDTH   4096U
+#define CEDRUS_MAX_HEIGHT  2304U
 
 static struct cedrus_format cedrus_formats[] = {
{
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/3] media: cedrus: Properly signal size in mode register

2019-10-26 Thread Jernej Skrabec
Mode register also holds information if video width is bigger than 2048
and if it is equal to 4096.

Rework cedrus_engine_enable() to properly signal this properties.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c  | 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_h265.c  | 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c| 9 +++--
 drivers/staging/media/sunxi/cedrus/cedrus_hw.h| 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c | 2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_regs.h  | 2 ++
 6 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 7487f6ab7576..d2c854ecdf15 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -485,7 +485,7 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
 {
struct cedrus_dev *dev = ctx->dev;
 
-   cedrus_engine_enable(dev, CEDRUS_CODEC_H264);
+   cedrus_engine_enable(ctx, CEDRUS_CODEC_H264);
 
cedrus_write(dev, VE_H264_SDROT_CTRL, 0);
cedrus_write(dev, VE_H264_EXTRA_BUFFER1,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 9bc921866f70..6945dc74e1d7 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -276,7 +276,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
}
 
/* Activate H265 engine. */
-   cedrus_engine_enable(dev, CEDRUS_CODEC_H265);
+   cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
 
/* Source offset and length in bits. */
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 570a9165dd5d..3acfa21bc124 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -30,7 +30,7 @@
 #include "cedrus_hw.h"
 #include "cedrus_regs.h"
 
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
+int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec)
 {
u32 reg = 0;
 
@@ -58,7 +58,12 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum 
cedrus_codec codec)
return -EINVAL;
}
 
-   cedrus_write(dev, VE_MODE, reg);
+   if (ctx->src_fmt.width == 4096)
+   reg |= VE_MODE_PIC_WIDTH_IS_4096;
+   if (ctx->src_fmt.width > 2048)
+   reg |= VE_MODE_PIC_WIDTH_MORE_2048;
+
+   cedrus_write(ctx->dev, VE_MODE, reg);
 
return 0;
 }
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index 27d0882397aa..604ff932fbf5 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -16,7 +16,7 @@
 #ifndef _CEDRUS_HW_H_
 #define _CEDRUS_HW_H_
 
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
+int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec);
 void cedrus_engine_disable(struct cedrus_dev *dev);
 
 void cedrus_dst_format_set(struct cedrus_dev *dev,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
index 13c34927bad5..8bcd6b8f9e2d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
@@ -96,7 +96,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct 
cedrus_run *run)
quantization = run->mpeg2.quantization;
 
/* Activate MPEG engine. */
-   cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2);
+   cedrus_engine_enable(ctx, CEDRUS_CODEC_MPEG2);
 
/* Set intra quantization matrix. */
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 4275a307d282..ace3d49fcd82 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -35,6 +35,8 @@
 
 #define VE_MODE0x00
 
+#define VE_MODE_PIC_WIDTH_IS_4096  BIT(22)
+#define VE_MODE_PIC_WIDTH_MORE_2048BIT(21)
 #define VE_MODE_REC_WR_MODE_2MB(0x01 << 20)
 #define VE_MODE_REC_WR_MODE_1MB(0x00 << 20)
 #define VE_MODE_DDR_MODE_BW_128(0x03 << 16)
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 0/2] media: cedrus: improvements

2019-10-26 Thread Jernej Skrabec
This is continuation of https://lkml.org/lkml/2019/5/30/1459 with several
patches removed (2 merged, others needs redesign) and one added.

Patch 1 fixes h264 playback issue which happens in rare cases.

Patch 2 replaces direct accesses to capture queue from m2m contex with
helpers which was designed exactly for that. It's also safer since
helpers do some checks.

Best regards,
Jernej

Changes from v2.
- Removed patch 2, because Paul plans to take different approach
- Rebased patch 1

Jernej Skrabec (2):
  media: cedrus: Fix decoding for some H264 videos
  media: cedrus: Use helpers to access capture queue

 drivers/staging/media/sunxi/cedrus/cedrus.h   |  8 +++-
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 38 ---
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  3 ++
 3 files changed, 42 insertions(+), 7 deletions(-)

-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 2/2] media: cedrus: Use helpers to access capture queue

2019-10-26 Thread Jernej Skrabec
Accessing capture queue structue directly is not safe. Use helpers for
that.

Acked-by: Paul Kocialkowski 
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h  | 8 ++--
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++--
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 986e059e3202..c45fb9a7ad07 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -197,12 +197,16 @@ static inline dma_addr_t cedrus_buf_addr(struct 
vb2_buffer *buf,
 static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx,
 int index, unsigned int plane)
 {
-   struct vb2_buffer *buf;
+   struct vb2_buffer *buf = NULL;
+   struct vb2_queue *vq;
 
if (index < 0)
return 0;
 
-   buf = ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[index];
+   vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+   if (vq)
+   buf = vb2_get_buffer(vq, index);
+
return buf ? cedrus_buf_addr(buf, >dst_fmt, plane) : 0;
 }
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index db336449c4f2..7487f6ab7576 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -97,7 +97,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
const struct v4l2_ctrl_h264_decode_params *decode = 
run->h264.decode_params;
const struct v4l2_ctrl_h264_slice_params *slice = 
run->h264.slice_params;
const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
-   struct vb2_queue *cap_q = >fh.m2m_ctx->cap_q_ctx.q;
+   struct vb2_queue *cap_q;
struct cedrus_buffer *output_buf;
struct cedrus_dev *dev = ctx->dev;
unsigned long used_dpbs = 0;
@@ -105,6 +105,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
unsigned int output = 0;
unsigned int i;
 
+   cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
memset(pic_list, 0, sizeof(pic_list));
 
for (i = 0; i < ARRAY_SIZE(decode->dpb); i++) {
@@ -168,12 +170,14 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
   enum cedrus_h264_sram_off sram)
 {
const struct v4l2_ctrl_h264_decode_params *decode = 
run->h264.decode_params;
-   struct vb2_queue *cap_q = >fh.m2m_ctx->cap_q_ctx.q;
+   struct vb2_queue *cap_q;
struct cedrus_dev *dev = ctx->dev;
u8 sram_array[CEDRUS_MAX_REF_IDX];
unsigned int i;
size_t size;
 
+   cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
memset(sram_array, 0, sizeof(sram_array));
 
for (i = 0; i < num_ref; i++) {
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 1/2] media: cedrus: Fix decoding for some H264 videos

2019-10-26 Thread Jernej Skrabec
It seems that for some H264 videos at least one bitstream parsing
trigger must be called in order to be decoded correctly. There is no
explanation why this helps, but it was observed that two sample videos
with this fix are now decoded correctly and there is no regression with
others.

Acked-by: Paul Kocialkowski 
Signed-off-by: Jernej Skrabec 
---
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 30 +--
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  3 ++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index cd85668f9c80..db336449c4f2 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -6,6 +6,7 @@
  * Copyright (c) 2018 Bootlin
  */
 
+#include 
 #include 
 
 #include 
@@ -289,6 +290,28 @@ static void cedrus_write_pred_weight_table(struct 
cedrus_ctx *ctx,
}
 }
 
+/*
+ * It turns out that using VE_H264_VLD_OFFSET to skip bits is not reliable. In
+ * rare cases frame is not decoded correctly. However, setting offset to 0 and
+ * skipping appropriate amount of bits with flush bits trigger always works.
+ */
+static void cedrus_skip_bits(struct cedrus_dev *dev, int num)
+{
+   int count = 0;
+
+   while (count < num) {
+   int tmp = min(num - count, 32);
+
+   cedrus_write(dev, VE_H264_TRIGGER_TYPE,
+VE_H264_TRIGGER_TYPE_FLUSH_BITS |
+VE_H264_TRIGGER_TYPE_N_BITS(tmp));
+   while (cedrus_read(dev, VE_H264_STATUS) & 
VE_H264_STATUS_VLD_BUSY)
+   udelay(1);
+
+   count += tmp;
+   }
+}
+
 static void cedrus_set_params(struct cedrus_ctx *ctx,
  struct cedrus_run *run)
 {
@@ -299,14 +322,13 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
struct vb2_buffer *src_buf = >src->vb2_buf;
struct cedrus_dev *dev = ctx->dev;
dma_addr_t src_buf_addr;
-   u32 offset = slice->header_bit_size;
-   u32 len = (slice->size * 8) - offset;
+   u32 len = slice->size * 8;
unsigned int pic_width_in_mbs;
bool mbaff_pic;
u32 reg;
 
cedrus_write(dev, VE_H264_VLD_LEN, len);
-   cedrus_write(dev, VE_H264_VLD_OFFSET, offset);
+   cedrus_write(dev, VE_H264_VLD_OFFSET, 0);
 
src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
cedrus_write(dev, VE_H264_VLD_END,
@@ -325,6 +347,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
cedrus_write(dev, VE_H264_TRIGGER_TYPE,
 VE_H264_TRIGGER_TYPE_INIT_SWDEC);
 
+   cedrus_skip_bits(dev, slice->header_bit_size);
+
if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
 (slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
  slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 6fc28d21a6c7..4275a307d282 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -541,13 +541,16 @@
 VE_H264_CTRL_SLICE_DECODE_INT)
 
 #define VE_H264_TRIGGER_TYPE   0x224
+#define VE_H264_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8)
 #define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE  (8 << 0)
 #define VE_H264_TRIGGER_TYPE_INIT_SWDEC(7 << 0)
+#define VE_H264_TRIGGER_TYPE_FLUSH_BITS(3 << 0)
 
 #define VE_H264_STATUS 0x228
 #define VE_H264_STATUS_VLD_DATA_REQ_INT
VE_H264_CTRL_VLD_DATA_REQ_INT
 #define VE_H264_STATUS_DECODE_ERR_INT  VE_H264_CTRL_DECODE_ERR_INT
 #define VE_H264_STATUS_SLICE_DECODE_INT
VE_H264_CTRL_SLICE_DECODE_INT
+#define VE_H264_STATUS_VLD_BUSYBIT(8)
 
 #define VE_H264_STATUS_INT_MASKVE_H264_CTRL_INT_MASK
 
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 1/3] media: cedrus: Fix decoding for some H264 videos

2019-10-02 Thread Jernej Skrabec
It seems that for some H264 videos at least one bitstream parsing
trigger must be called in order to be decoded correctly. There is no
explanation why this helps, but it was observed that two sample videos
with this fix are now decoded correctly and there is no regression with
others.

Signed-off-by: Jernej Skrabec 
---
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 30 +--
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  3 ++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index d6a782703c9b..bd848146eada 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -6,6 +6,7 @@
  * Copyright (c) 2018 Bootlin
  */
 
+#include 
 #include 
 
 #include 
@@ -289,6 +290,28 @@ static void cedrus_write_pred_weight_table(struct 
cedrus_ctx *ctx,
}
 }
 
+/*
+ * It turns out that using VE_H264_VLD_OFFSET to skip bits is not reliable. In
+ * rare cases frame is not decoded correctly. However, setting offset to 0 and
+ * skipping appropriate amount of bits with flush bits trigger always works.
+ */
+static void cedrus_skip_bits(struct cedrus_dev *dev, int num)
+{
+   int count = 0;
+
+   while (count < num) {
+   int tmp = min(num - count, 32);
+
+   cedrus_write(dev, VE_H264_TRIGGER_TYPE,
+VE_H264_TRIGGER_TYPE_FLUSH_BITS |
+VE_H264_TRIGGER_TYPE_N_BITS(tmp));
+   while (cedrus_read(dev, VE_H264_STATUS) & 
VE_H264_STATUS_VLD_BUSY)
+   udelay(1);
+
+   count += tmp;
+   }
+}
+
 static void cedrus_set_params(struct cedrus_ctx *ctx,
  struct cedrus_run *run)
 {
@@ -299,12 +322,11 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
struct vb2_buffer *src_buf = >src->vb2_buf;
struct cedrus_dev *dev = ctx->dev;
dma_addr_t src_buf_addr;
-   u32 offset = slice->header_bit_size;
-   u32 len = (slice->size * 8) - offset;
+   u32 len = slice->size * 8;
u32 reg;
 
cedrus_write(dev, VE_H264_VLD_LEN, len);
-   cedrus_write(dev, VE_H264_VLD_OFFSET, offset);
+   cedrus_write(dev, VE_H264_VLD_OFFSET, 0);
 
src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
cedrus_write(dev, VE_H264_VLD_END,
@@ -323,6 +345,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
cedrus_write(dev, VE_H264_TRIGGER_TYPE,
 VE_H264_TRIGGER_TYPE_INIT_SWDEC);
 
+   cedrus_skip_bits(dev, slice->header_bit_size);
+
if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
 (slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
  slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 3329f9aaf975..b52926a54025 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -538,13 +538,16 @@
 VE_H264_CTRL_SLICE_DECODE_INT)
 
 #define VE_H264_TRIGGER_TYPE   0x224
+#define VE_H264_TRIGGER_TYPE_N_BITS(x) (((x) & 0x3f) << 8)
 #define VE_H264_TRIGGER_TYPE_AVC_SLICE_DECODE  (8 << 0)
 #define VE_H264_TRIGGER_TYPE_INIT_SWDEC(7 << 0)
+#define VE_H264_TRIGGER_TYPE_FLUSH_BITS(3 << 0)
 
 #define VE_H264_STATUS 0x228
 #define VE_H264_STATUS_VLD_DATA_REQ_INT
VE_H264_CTRL_VLD_DATA_REQ_INT
 #define VE_H264_STATUS_DECODE_ERR_INT  VE_H264_CTRL_DECODE_ERR_INT
 #define VE_H264_STATUS_SLICE_DECODE_INT
VE_H264_CTRL_SLICE_DECODE_INT
+#define VE_H264_STATUS_VLD_BUSYBIT(8)
 
 #define VE_H264_STATUS_INT_MASKVE_H264_CTRL_INT_MASK
 
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 2/3] media: cedrus: Fix H264 default reference index count

2019-10-02 Thread Jernej Skrabec
Reference index count in VE_H264_PPS should come from PPS control.
However, this is not really important, because reference index count is
in our case always overridden by that from slice header.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index bd848146eada..4a0e69855c7f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -364,12 +364,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
 
// picture parameters
reg = 0;
-   /*
-* FIXME: the kernel headers are allowing the default value to
-* be passed, but the libva doesn't give us that.
-*/
-   reg |= (slice->num_ref_idx_l0_active_minus1 & 0x1f) << 10;
-   reg |= (slice->num_ref_idx_l1_active_minus1 & 0x1f) << 5;
+   reg |= (pps->num_ref_idx_l0_default_active_minus1 & 0x1f) << 10;
+   reg |= (pps->num_ref_idx_l1_default_active_minus1 & 0x1f) << 5;
reg |= (pps->weighted_bipred_idc & 0x3) << 2;
if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
reg |= VE_H264_PPS_ENTROPY_CODING_MODE;
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 0/3] media: cedrus: improvements

2019-10-02 Thread Jernej Skrabec
This is continuation of https://lkml.org/lkml/2019/5/30/1459 with several
patches removed (2 merged, others needs redesign) and one added.

Patch 1 fixes h264 playback issue which happens in rare cases.

Patch 2 sets PPS default reference index count in register from PPS
control. Currently it was set to values from slice control.

Patch 3 replaces direct accesses to capture queue from m2m contex with
helpers which was designed exactly for that. It's also safer since
helpers do some checks.

Best regards,
Jernej

Jernej Skrabec (3):
  media: cedrus: Fix decoding for some H264 videos
  media: cedrus: Fix H264 default reference index count
  media: cedrus: Use helpers to access capture queue

 drivers/staging/media/sunxi/cedrus/cedrus.h   |  8 +++-
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 46 ++-
 .../staging/media/sunxi/cedrus/cedrus_regs.h  |  3 ++
 3 files changed, 44 insertions(+), 13 deletions(-)

-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 3/3] media: cedrus: Use helpers to access capture queue

2019-10-02 Thread Jernej Skrabec
Accessing capture queue structue directly is not safe. Use helpers for
that.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h  | 8 ++--
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++--
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 986e059e3202..c45fb9a7ad07 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -197,12 +197,16 @@ static inline dma_addr_t cedrus_buf_addr(struct 
vb2_buffer *buf,
 static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx,
 int index, unsigned int plane)
 {
-   struct vb2_buffer *buf;
+   struct vb2_buffer *buf = NULL;
+   struct vb2_queue *vq;
 
if (index < 0)
return 0;
 
-   buf = ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[index];
+   vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+   if (vq)
+   buf = vb2_get_buffer(vq, index);
+
return buf ? cedrus_buf_addr(buf, >dst_fmt, plane) : 0;
 }
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 4a0e69855c7f..4650982c69a8 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -97,7 +97,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
const struct v4l2_ctrl_h264_decode_params *decode = 
run->h264.decode_params;
const struct v4l2_ctrl_h264_slice_params *slice = 
run->h264.slice_params;
const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
-   struct vb2_queue *cap_q = >fh.m2m_ctx->cap_q_ctx.q;
+   struct vb2_queue *cap_q;
struct cedrus_buffer *output_buf;
struct cedrus_dev *dev = ctx->dev;
unsigned long used_dpbs = 0;
@@ -105,6 +105,8 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
unsigned int output = 0;
unsigned int i;
 
+   cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
memset(pic_list, 0, sizeof(pic_list));
 
for (i = 0; i < ARRAY_SIZE(decode->dpb); i++) {
@@ -168,12 +170,14 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
   enum cedrus_h264_sram_off sram)
 {
const struct v4l2_ctrl_h264_decode_params *decode = 
run->h264.decode_params;
-   struct vb2_queue *cap_q = >fh.m2m_ctx->cap_q_ctx.q;
+   struct vb2_queue *cap_q;
struct cedrus_dev *dev = ctx->dev;
u8 sram_array[CEDRUS_MAX_REF_IDX];
unsigned int i;
size_t size;
 
+   cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
memset(sram_array, 0, sizeof(sram_array));
 
for (i = 0; i < num_ref; i++) {
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 3/6] media: v4l2-mem2mem: add stateless_(try_)decoder_cmd ioctl helpers

2019-09-29 Thread Jernej Skrabec
These helpers are used by stateless codecs when they support multiple
slices per frame and hold capture buffer flag is set. It's expected that
all such codecs will use this code.

Signed-off-by: Jernej Skrabec 
---
 drivers/media/v4l2-core/v4l2-mem2mem.c | 35 ++
 include/media/v4l2-mem2mem.h   |  4 +++
 2 files changed, 39 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 19937dd3c6f6..2677a07e4c9b 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -1154,6 +1154,41 @@ int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, 
void *fh,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_try_decoder_cmd);
 
+int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh,
+struct v4l2_decoder_cmd *dc)
+{
+   if (dc->cmd != V4L2_DEC_CMD_FLUSH)
+   return -EINVAL;
+
+   dc->flags = 0;
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_try_decoder_cmd);
+
+int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv,
+struct v4l2_decoder_cmd *dc)
+{
+   struct v4l2_fh *fh = file->private_data;
+   struct vb2_v4l2_buffer *out_vb, *cap_vb;
+   int ret;
+
+   ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, dc);
+   if (ret < 0)
+   return ret;
+
+   out_vb = v4l2_m2m_last_src_buf(fh->m2m_ctx);
+   cap_vb = v4l2_m2m_last_dst_buf(fh->m2m_ctx);
+
+   if (out_vb)
+   out_vb->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
+   else if (cap_vb && cap_vb->is_held)
+   v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_decoder_cmd);
+
 /*
  * v4l2_file_operations helpers. It is assumed here same lock is used
  * for the output and the capture buffer queue.
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index c9fa96c8eed1..8ae2f56c7fa3 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -714,6 +714,10 @@ int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void 
*fh,
   struct v4l2_encoder_cmd *ec);
 int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh,
   struct v4l2_decoder_cmd *dc);
+int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh,
+struct v4l2_decoder_cmd *dc);
+int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv,
+struct v4l2_decoder_cmd *dc);
 int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma);
 __poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait);
 
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 6/6] media: cedrus: Add support for holding capture buffer

2019-09-29 Thread Jernej Skrabec
When frame contains multiple slices and driver works in slice mode, it's
more efficient to hold capture buffer in queue until all slices of a
same frame are decoded.

Add support for that to Cedrus driver by exposing and implementing
V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF capability.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_dec.c   |  9 +
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c|  8 +---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 14 ++
 3 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index e49c3396ca4d..67f7d4326fc1 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -31,6 +31,14 @@ void cedrus_device_run(void *priv)
 
run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+   if (v4l2_m2m_release_capture_buf(run.src, run.dst)) {
+   v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+   v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_DONE);
+   run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+   }
+   run.dst->is_held = run.src->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
+
run.first_slice = !run.dst->vb2_buf.copied_timestamp ||
run.src->vb2_buf.timestamp != run.dst->vb2_buf.timestamp;
 
@@ -46,6 +54,7 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
run.mpeg2.quantization = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
+   run.dst->is_held = false;
break;
 
case V4L2_PIX_FMT_H264_SLICE:
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index fc8579b90dab..b466041c25db 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -122,7 +122,7 @@ static irqreturn_t cedrus_irq(int irq, void *data)
dev->dec_ops[ctx->current_codec]->irq_clear(ctx);
 
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-   dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+   dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
if (!src_buf || !dst_buf) {
v4l2_err(>v4l2_dev,
@@ -136,8 +136,10 @@ static irqreturn_t cedrus_irq(int irq, void *data)
state = VB2_BUF_STATE_DONE;
 
v4l2_m2m_buf_done(src_buf, state);
-   v4l2_m2m_buf_done(dst_buf, state);
-
+   if (!dst_buf->is_held) {
+   v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+   v4l2_m2m_buf_done(dst_buf, state);
+   }
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 
return IRQ_HANDLED;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 3ec3a2db790c..82198b2bb081 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -303,6 +303,17 @@ static int cedrus_s_fmt_vid_out(struct file *file, void 
*priv,
 
ctx->src_fmt = f->fmt.pix;
 
+   switch (ctx->src_fmt.pixelformat) {
+   case V4L2_PIX_FMT_H264_SLICE:
+   vq->subsystem_flags |=
+   VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
+   break;
+   default:
+   vq->subsystem_flags &=
+   (u32)~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
+   break;
+   }
+
/* Propagate colorspace information to capture. */
ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
@@ -336,6 +347,9 @@ const struct v4l2_ioctl_ops cedrus_ioctl_ops = {
.vidioc_streamon= v4l2_m2m_ioctl_streamon,
.vidioc_streamoff   = v4l2_m2m_ioctl_streamoff,
 
+   .vidioc_try_decoder_cmd = 
v4l2_m2m_ioctl_stateless_try_decoder_cmd,
+   .vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd,
+
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
 };
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 0/6] media: cedrus: h264: Support multi-slice frames

2019-09-29 Thread Jernej Skrabec
This series adds support for decoding multi-slice H264 frames along with
support for V4L2_DEC_CMD_FLUSH and V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF.

Code was tested by modified ffmpeg, which can be found here:
https://github.com/jernejsk/FFmpeg, branch mainline-test
It has to be configured with at least following options:
--enable-v4l2-request --enable-libudev --enable-libdrm

Samples used for testing:
http://jernej.libreelec.tv/videos/h264/BA1_FT_C.mp4
http://jernej.libreelec.tv/videos/h264/h264.mp4

Command line used for testing:
ffmpeg -hwaccel drm -hwaccel_device /dev/dri/card0 -i h264.mp4 -pix_fmt bgra -f 
fbdev /dev/fb0

Please note that V4L2_DEC_CMD_FLUSH was not tested because I'm
not sure how. ffmpeg follows exactly which slice is last in frame
and sets hold flag accordingly. Improper usage of hold flag would
corrupt ffmpeg assumptions and it would probably crash. Any ideas
how to test this are welcome!

Thanks to Jonas for adjusting ffmpeg.

Please let me know what you think.

Best regards,
Jernej

Changes from v1:
- added Rb tags
- updated V4L2_DEC_CMD_FLUSH documentation
- updated first slice detection in Cedrus
- hold capture buffer flag is set according to source format
- added v4l m2m stateless_(try_)decoder_cmd ioctl helpers

Hans Verkuil (2):
  vb2: add V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF
  videodev2.h: add V4L2_DEC_CMD_FLUSH

Jernej Skrabec (4):
  media: v4l2-mem2mem: add stateless_(try_)decoder_cmd ioctl helpers
  media: cedrus: Detect first slice of a frame
  media: cedrus: h264: Support multiple slices per frame
  media: cedrus: Add support for holding capture buffer

 Documentation/media/uapi/v4l/buffer.rst   | 13 ++
 .../media/uapi/v4l/vidioc-decoder-cmd.rst | 10 +++-
 .../media/uapi/v4l/vidioc-reqbufs.rst |  6 +++
 .../media/videodev2.h.rst.exceptions  |  1 +
 .../media/common/videobuf2/videobuf2-v4l2.c   |  8 +++-
 drivers/media/v4l2-core/v4l2-mem2mem.c| 35 ++
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  1 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   | 11 +
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 11 -
 .../staging/media/sunxi/cedrus/cedrus_hw.c|  8 ++--
 .../staging/media/sunxi/cedrus/cedrus_video.c | 14 ++
 include/media/v4l2-mem2mem.h  | 46 +++
 include/media/videobuf2-core.h|  3 ++
 include/media/videobuf2-v4l2.h|  5 ++
 include/uapi/linux/videodev2.h| 14 --
 15 files changed, 175 insertions(+), 11 deletions(-)

-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 2/6] videodev2.h: add V4L2_DEC_CMD_FLUSH

2019-09-29 Thread Jernej Skrabec
From: Hans Verkuil 

Add this new V4L2_DEC_CMD_FLUSH decoder command and document it.

Reviewed-by: Boris Brezillon 
Reviewed-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
[Adjusted description]
Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst | 10 +-
 Documentation/media/videodev2.h.rst.exceptions  |  1 +
 include/uapi/linux/videodev2.h  |  1 +
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst 
b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst
index 57f0066f4cff..f1a504836f31 100644
--- a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst
+++ b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst
@@ -208,7 +208,15 @@ introduced in Linux 3.3. They are, however, mandatory for 
stateful mem2mem decod
been started yet, the driver will return an ``EPERM`` error code. When
the decoder is already running, this command does nothing. No
flags are defined for this command.
-
+* - ``V4L2_DEC_CMD_FLUSH``
+  - 4
+  - Flush any held capture buffers. Only valid for stateless decoders.
+   This command is typically used when the application reached the
+   end of the stream and the last output buffer had the
+   ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag set. This would prevent
+   dequeueing the capture buffer containing the last decoded frame.
+   So this command can be used to explicitly flush that final decoded
+   frame. This command does nothing if there are no held capture buffers.
 
 Return Value
 
diff --git a/Documentation/media/videodev2.h.rst.exceptions 
b/Documentation/media/videodev2.h.rst.exceptions
index adeb6b7a15cb..a79028e4d929 100644
--- a/Documentation/media/videodev2.h.rst.exceptions
+++ b/Documentation/media/videodev2.h.rst.exceptions
@@ -434,6 +434,7 @@ replace define V4L2_DEC_CMD_START decoder-cmds
 replace define V4L2_DEC_CMD_STOP decoder-cmds
 replace define V4L2_DEC_CMD_PAUSE decoder-cmds
 replace define V4L2_DEC_CMD_RESUME decoder-cmds
+replace define V4L2_DEC_CMD_FLUSH decoder-cmds
 
 replace define V4L2_DEC_CMD_START_MUTE_AUDIO decoder-cmds
 replace define V4L2_DEC_CMD_PAUSE_TO_BLACK decoder-cmds
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4fa9f543742d..91a79e16089c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1978,6 +1978,7 @@ struct v4l2_encoder_cmd {
 #define V4L2_DEC_CMD_STOP(1)
 #define V4L2_DEC_CMD_PAUSE   (2)
 #define V4L2_DEC_CMD_RESUME  (3)
+#define V4L2_DEC_CMD_FLUSH   (4)
 
 /* Flags for V4L2_DEC_CMD_START */
 #define V4L2_DEC_CMD_START_MUTE_AUDIO  (1 << 0)
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 5/6] media: cedrus: h264: Support multiple slices per frame

2019-09-29 Thread Jernej Skrabec
With recent changes, support for decoding multi-slice frames can be
easily added now.

Signal VPU if current slice is first in frame or not and add information
about first macroblock coordinates.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index d6a782703c9b..b7260cfeb6f4 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -301,6 +301,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
dma_addr_t src_buf_addr;
u32 offset = slice->header_bit_size;
u32 len = (slice->size * 8) - offset;
+   unsigned int pic_width_in_mbs;
+   bool mbaff_pic;
u32 reg;
 
cedrus_write(dev, VE_H264_VLD_LEN, len);
@@ -370,12 +372,19 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE;
cedrus_write(dev, VE_H264_SPS, reg);
 
+   mbaff_pic = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) &&
+   (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
+   pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1;
+
// slice parameters
reg = 0;
+   reg |= ((slice->first_mb_in_slice % pic_width_in_mbs) & 0xff) << 24;
+   reg |= (((slice->first_mb_in_slice / pic_width_in_mbs) * (mbaff_pic + 
1)) & 0xff) << 16;
reg |= decode->nal_ref_idc ? BIT(12) : 0;
reg |= (slice->slice_type & 0xf) << 8;
reg |= slice->cabac_init_idc & 0x3;
-   reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
+   if (run->first_slice)
+   reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
reg |= VE_H264_SHS_FIELD_PIC;
if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 4/6] media: cedrus: Detect first slice of a frame

2019-09-29 Thread Jernej Skrabec
When codec supports multiple slices in one frame, VPU has to know when
first slice of each frame is being processed, presumably to correctly
clear/set data in auxiliary buffers.

Add first_slice field to cedrus_run structure and set it according to
timestamps of capture and output buffers. If timestamps are different,
it's first slice and viceversa.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h | 1 +
 drivers/staging/media/sunxi/cedrus/cedrus_dec.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 2f017a651848..32cb38e541c6 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -70,6 +70,7 @@ struct cedrus_mpeg2_run {
 struct cedrus_run {
struct vb2_v4l2_buffer  *src;
struct vb2_v4l2_buffer  *dst;
+   bool first_slice;
 
union {
struct cedrus_h264_run  h264;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index 56ca4c9ad01c..e49c3396ca4d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -31,6 +31,8 @@ void cedrus_device_run(void *priv)
 
run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+   run.first_slice = !run.dst->vb2_buf.copied_timestamp ||
+   run.src->vb2_buf.timestamp != run.dst->vb2_buf.timestamp;
 
/* Apply request(s) controls if needed. */
src_req = run.src->vb2_buf.req_obj.req;
-- 
2.23.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 3/8] media: docs-rst: Document m2m stateless video decoder interface

2019-08-22 Thread Jernej Skrabec
From: Alexandre Courbot 

Documents the protocol that user-space should follow when
communicating with stateless video decoders.

The stateless video decoding API makes use of the new request and tags
APIs. While it has been implemented with the Cedrus driver so far, it
should probably still be considered staging for a short while.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/dev-mem2mem.rst  |   1 +
 .../media/uapi/v4l/dev-stateless-decoder.rst  | 424 ++
 2 files changed, 425 insertions(+)
 create mode 100644 Documentation/media/uapi/v4l/dev-stateless-decoder.rst

diff --git a/Documentation/media/uapi/v4l/dev-mem2mem.rst 
b/Documentation/media/uapi/v4l/dev-mem2mem.rst
index caa05f5f6380..70953958cee6 100644
--- a/Documentation/media/uapi/v4l/dev-mem2mem.rst
+++ b/Documentation/media/uapi/v4l/dev-mem2mem.rst
@@ -46,3 +46,4 @@ devices are given in the following sections.
 :maxdepth: 1
 
 dev-decoder
+dev-stateless-decoder
diff --git a/Documentation/media/uapi/v4l/dev-stateless-decoder.rst 
b/Documentation/media/uapi/v4l/dev-stateless-decoder.rst
new file mode 100644
index ..4a26646eeec5
--- /dev/null
+++ b/Documentation/media/uapi/v4l/dev-stateless-decoder.rst
@@ -0,0 +1,424 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _stateless_decoder:
+
+**
+Memory-to-memory Stateless Video Decoder Interface
+**
+
+A stateless decoder is a decoder that works without retaining any kind of state
+between processed frames. This means that each frame is decoded independently
+of any previous and future frames, and that the client is responsible for
+maintaining the decoding state and providing it to the decoder with each
+decoding request. This is in contrast to the stateful video decoder interface,
+where the hardware and driver maintain the decoding state and all the client
+has to do is to provide the raw encoded stream and dequeue decoded frames in
+display order.
+
+This section describes how user-space ("the client") is expected to communicate
+with stateless decoders in order to successfully decode an encoded stream.
+Compared to stateful codecs, the decoder/client sequence is simpler, but the
+cost of this simplicity is extra complexity in the client which is responsible
+for maintaining a consistent decoding state.
+
+Stateless decoders make use of the :ref:`media-request-api`. A stateless
+decoder must expose the ``V4L2_BUF_CAP_SUPPORTS_REQUESTS`` capability on its
+``OUTPUT`` queue when :c:func:`VIDIOC_REQBUFS` or :c:func:`VIDIOC_CREATE_BUFS`
+are invoked.
+
+Depending on the encoded formats supported by the decoder, a single decoded
+frame may be the result of several decode requests (for instance, H.264 streams
+with multiple slices per frame). Decoders that support such formats must also
+expose the ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` capability on their
+``OUTPUT`` queue.
+
+Querying capabilities
+=
+
+1. To enumerate the set of coded formats supported by the decoder, the client
+   calls :c:func:`VIDIOC_ENUM_FMT` on the ``OUTPUT`` queue.
+
+   * The driver must always return the full set of supported ``OUTPUT`` 
formats,
+ irrespective of the format currently set on the ``CAPTURE`` queue.
+
+   * Simultaneously, the driver must restrain the set of values returned by
+ codec-specific capability controls (such as H.264 profiles) to the set
+ actually supported by the hardware.
+
+2. To enumerate the set of supported raw formats, the client calls
+   :c:func:`VIDIOC_ENUM_FMT` on the ``CAPTURE`` queue.
+
+   * The driver must return only the formats supported for the format currently
+ active on the ``OUTPUT`` queue.
+
+   * Depending on the currently set ``OUTPUT`` format, the set of supported raw
+ formats may depend on the value of some codec-dependent controls.
+ The client is responsible for making sure that these controls are set
+ before querying the ``CAPTURE`` queue. Failure to do so will result in the
+ default values for these controls being used, and a returned set of 
formats
+ that may not be usable for the media the client is trying to decode.
+
+3. The client may use :c:func:`VIDIOC_ENUM_FRAMESIZES` to detect supported
+   resolutions for a given format, passing desired pixel format in
+   :c:type:`v4l2_frmsizeenum`'s ``pixel_format``.
+
+4. Supported profiles and levels for the current ``OUTPUT`` format, if
+   applicable, may be queried using their respective controls via
+   :c:func:`VIDIOC_QUERYCTRL`.
+
+Initialization
+==
+
+1. Set the coded format on the ``OUTPUT`` queue via :c:func:`VIDIOC_S_FMT`.
+
+   * **Required fields:**
+
+ ``type``
+ a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
+
+ ``pixelformat``
+ a coded pixel format.
+
+ ``width``, ``height``
+ coded width 

[PATCH 6/8] media: cedrus: h264: Support multiple slices per frame

2019-08-22 Thread Jernej Skrabec
With recent changes, support for decoding multi-slice frames can be
easily added now.

Signal VPU if current slice is first in frame or not and add information
about first macroblock coordinates.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index d6a782703c9b..b7260cfeb6f4 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -301,6 +301,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
dma_addr_t src_buf_addr;
u32 offset = slice->header_bit_size;
u32 len = (slice->size * 8) - offset;
+   unsigned int pic_width_in_mbs;
+   bool mbaff_pic;
u32 reg;
 
cedrus_write(dev, VE_H264_VLD_LEN, len);
@@ -370,12 +372,19 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE;
cedrus_write(dev, VE_H264_SPS, reg);
 
+   mbaff_pic = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) &&
+   (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
+   pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1;
+
// slice parameters
reg = 0;
+   reg |= ((slice->first_mb_in_slice % pic_width_in_mbs) & 0xff) << 24;
+   reg |= (((slice->first_mb_in_slice / pic_width_in_mbs) * (mbaff_pic + 
1)) & 0xff) << 16;
reg |= decode->nal_ref_idc ? BIT(12) : 0;
reg |= (slice->slice_type & 0xf) << 8;
reg |= slice->cabac_init_idc & 0x3;
-   reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
+   if (run->first_slice)
+   reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
reg |= VE_H264_SHS_FIELD_PIC;
if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
-- 
2.22.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 7/8] media: cedrus: Add support for holding capture buffer

2019-08-22 Thread Jernej Skrabec
When frame contains multiple slices and driver works in slice mode, it's
more efficient to hold capture buffer in queue until all slices of a
same frame are decoded.

Add support for that to Cedrus driver by exposing and implementing
V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF capability.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_dec.c   | 9 +
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c| 8 +---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 1 +
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index d7b54accfe83..68462b99750e 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -31,6 +31,14 @@ void cedrus_device_run(void *priv)
 
run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+   if (v4l2_m2m_release_capture_buf(run.src, run.dst)) {
+   v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+   v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_DONE);
+   run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+   }
+   run.dst->is_held = run.src->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
+
run.first_slice =
run.src->vb2_buf.timestamp != run.dst->vb2_buf.timestamp;
 
@@ -46,6 +54,7 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
run.mpeg2.quantization = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
+   run.dst->is_held = false;
break;
 
case V4L2_PIX_FMT_H264_SLICE:
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index a942cd9bed57..99fedec80224 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -122,7 +122,7 @@ static irqreturn_t cedrus_irq(int irq, void *data)
dev->dec_ops[ctx->current_codec]->irq_clear(ctx);
 
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-   dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+   dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
if (!src_buf || !dst_buf) {
v4l2_err(>v4l2_dev,
@@ -136,8 +136,10 @@ static irqreturn_t cedrus_irq(int irq, void *data)
state = VB2_BUF_STATE_DONE;
 
v4l2_m2m_buf_done(src_buf, state);
-   v4l2_m2m_buf_done(dst_buf, state);
-
+   if (!dst_buf->is_held) {
+   v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+   v4l2_m2m_buf_done(dst_buf, state);
+   }
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 
return IRQ_HANDLED;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 3efd247b..5153b2bba21e 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -515,6 +515,7 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
src_vq->drv_priv = ctx;
+   src_vq->subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
src_vq->buf_struct_size = sizeof(struct cedrus_buffer);
src_vq->min_buffers_needed = 1;
src_vq->ops = _qops;
-- 
2.22.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/8] vb2: add V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF

2019-08-22 Thread Jernej Skrabec
From: Hans Verkuil 

This patch adds support for the V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF flag.
It also adds a new V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF capability and
a v4l2_m2m_release_capture_buf() helper function.

Drivers should set vb2_queue->subsystem_flags to
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF to indicate support for this flag.

The device_run() function should look like this:

if (v4l2_m2m_release_capture_buf(out_vb, cap_vb)) {
v4l2_m2m_dst_buf_remove(m2m_ctx);
v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE);
cap_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
}
cap_vb->is_held = out_vb->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;

...

v4l2_m2m_buf_done(out_vb, VB2_BUF_STATE_DONE);
if (!cap_vb->is_held) {
v4l2_m2m_dst_buf_remove(m2m_ctx);
v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE);
}

In order to handle the corner case where V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF
is always set for the output buffer, and you reached the last frame (so no
new output buffer will be queued with a new timestamp), the driver must
implement support for the V4L2_DEC_CMD_FLUSH command, and that should do:

struct vb2_v4l2_buffer *out_vb = v4l2_m2m_last_src_buf(m2m_ctx);
struct vb2_v4l2_buffer *cap_vb = v4l2_m2m_last_dst_buf(m2m_ctx);

if (out_vb)
out_vb->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
else if (cap_vb && cap_vb->is_held)
v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE);

For formats that do not support slicing (e.g. VP8), the FLUSH command
just does nothing.

Signed-off-by: Hans Verkuil 
Tested-by: Boris Brezillon 
Reviewed-by: Boris Brezillon 
[Adjust example code]
Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/buffer.rst   | 13 ++
 .../media/uapi/v4l/vidioc-reqbufs.rst |  6 +++
 .../media/common/videobuf2/videobuf2-v4l2.c   |  8 +++-
 include/media/v4l2-mem2mem.h  | 42 +++
 include/media/videobuf2-core.h|  3 ++
 include/media/videobuf2-v4l2.h|  5 +++
 include/uapi/linux/videodev2.h| 13 +++---
 7 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/Documentation/media/uapi/v4l/buffer.rst 
b/Documentation/media/uapi/v4l/buffer.rst
index 1cbd9cde57f3..afb03906ead9 100644
--- a/Documentation/media/uapi/v4l/buffer.rst
+++ b/Documentation/media/uapi/v4l/buffer.rst
@@ -607,6 +607,19 @@ Buffer Flags
applications shall use this flag for output buffers if the data in
this buffer has not been created by the CPU but by some
DMA-capable unit, in which case caches have not been used.
+* .. _`V4L2-BUF-FLAG-M2M-HOLD-CAPTURE-BUF`:
+
+  - ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF``
+  - 0x0200
+  - Only valid if ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` is
+set. It is typically used with stateless decoders where multiple
+   output buffers each decode to a slice of the decoded frame.
+   Applications can set this flag when queueing the output buffer
+   to prevent the driver from dequeueing the capture buffer after
+   the output buffer has been decoded (i.e. the capture buffer is
+   'held'). If the timestamp of this output buffer differs from that
+   of the previous output buffer, then that indicates the start of a
+   new frame and the previously held capture buffer is dequeued.
 * .. _`V4L2-BUF-FLAG-LAST`:
 
   - ``V4L2_BUF_FLAG_LAST``
diff --git a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst 
b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
index d7faef10e39b..d0c643db477a 100644
--- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
+++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst
@@ -125,6 +125,7 @@ aborting or finishing any DMA in progress, an implicit
 .. _V4L2-BUF-CAP-SUPPORTS-DMABUF:
 .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS:
 .. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS:
+.. _V4L2-BUF-CAP-SUPPORTS-M2M-HOLD-CAPTURE-BUF:
 
 .. cssclass:: longtable
 
@@ -150,6 +151,11 @@ aborting or finishing any DMA in progress, an implicit
   - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still
 mapped or exported via DMABUF. These orphaned buffers will be freed
 when they are unmapped or when the exported DMABUF fds are closed.
+* - ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF``
+  - 0x0020
+  - Only valid for stateless decoders. If set, then userspace can set the
+``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag to hold off on returning 
the
+   capture buffer until the OUTPUT timestamp changes.
 
 Return Value
 
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 5a9ba3846f0a..699787f48f46 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -50,7 +50,8 @@ module_param(debug, int, 0644);
 V4L

[PATCH 8/8] media: cedrus: Add support for V4L2_DEC_CMD_FLUSH

2019-08-22 Thread Jernej Skrabec
This command is useful for explicitly flushing last decoded frame.

Signed-off-by: Jernej Skrabec 
---
 .../staging/media/sunxi/cedrus/cedrus_video.c | 34 +++
 1 file changed, 34 insertions(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 5153b2bba21e..9eae69d5741c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -331,6 +331,37 @@ static int cedrus_s_fmt_vid_out(struct file *file, void 
*priv,
return 0;
 }
 
+static int cedrus_try_decoder_cmd(struct file *file, void *fh,
+ struct v4l2_decoder_cmd *dc)
+{
+   if (dc->cmd != V4L2_DEC_CMD_FLUSH)
+   return -EINVAL;
+
+   return 0;
+}
+
+static int cedrus_decoder_cmd(struct file *file, void *fh,
+ struct v4l2_decoder_cmd *dc)
+{
+   struct cedrus_ctx *ctx = cedrus_file2ctx(file);
+   struct vb2_v4l2_buffer *out_vb, *cap_vb;
+   int ret;
+
+   ret = cedrus_try_decoder_cmd(file, fh, dc);
+   if (ret < 0)
+   return ret;
+
+   out_vb = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
+   cap_vb = v4l2_m2m_last_dst_buf(ctx->fh.m2m_ctx);
+
+   if (out_vb)
+   out_vb->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
+   else if (cap_vb && cap_vb->is_held)
+   v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE);
+
+   return 0;
+}
+
 const struct v4l2_ioctl_ops cedrus_ioctl_ops = {
.vidioc_querycap= cedrus_querycap,
 
@@ -355,6 +386,9 @@ const struct v4l2_ioctl_ops cedrus_ioctl_ops = {
.vidioc_streamon= v4l2_m2m_ioctl_streamon,
.vidioc_streamoff   = v4l2_m2m_ioctl_streamoff,
 
+   .vidioc_try_decoder_cmd = cedrus_try_decoder_cmd,
+   .vidioc_decoder_cmd = cedrus_decoder_cmd,
+
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
 };
-- 
2.22.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/8] videodev2.h: add V4L2_DEC_CMD_FLUSH

2019-08-22 Thread Jernej Skrabec
From: Hans Verkuil 

Add this new V4L2_DEC_CMD_FLUSH decoder command and document it.

Signed-off-by: Hans Verkuil 
Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst | 11 ++-
 Documentation/media/videodev2.h.rst.exceptions  |  1 +
 include/uapi/linux/videodev2.h  |  1 +
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst 
b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst
index 57f0066f4cff..0bffef6058f7 100644
--- a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst
+++ b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst
@@ -208,7 +208,16 @@ introduced in Linux 3.3. They are, however, mandatory for 
stateful mem2mem decod
been started yet, the driver will return an ``EPERM`` error code. When
the decoder is already running, this command does nothing. No
flags are defined for this command.
-
+* - ``V4L2_DEC_CMD_FLUSH``
+  - 4
+  - Flush any held capture buffers. Only valid for stateless decoders,
+and only if ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` was set.
+   This command is typically used when the application reached the
+   end of the stream and the last output buffer had the
+   ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag set. This would prevent
+   dequeueing the last capture buffer containing the last decoded frame.
+   So this command can be used to explicitly flush that last decoded
+   frame.
 
 Return Value
 
diff --git a/Documentation/media/videodev2.h.rst.exceptions 
b/Documentation/media/videodev2.h.rst.exceptions
index adeb6b7a15cb..a79028e4d929 100644
--- a/Documentation/media/videodev2.h.rst.exceptions
+++ b/Documentation/media/videodev2.h.rst.exceptions
@@ -434,6 +434,7 @@ replace define V4L2_DEC_CMD_START decoder-cmds
 replace define V4L2_DEC_CMD_STOP decoder-cmds
 replace define V4L2_DEC_CMD_PAUSE decoder-cmds
 replace define V4L2_DEC_CMD_RESUME decoder-cmds
+replace define V4L2_DEC_CMD_FLUSH decoder-cmds
 
 replace define V4L2_DEC_CMD_START_MUTE_AUDIO decoder-cmds
 replace define V4L2_DEC_CMD_PAUSE_TO_BLACK decoder-cmds
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4fa9f543742d..91a79e16089c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1978,6 +1978,7 @@ struct v4l2_encoder_cmd {
 #define V4L2_DEC_CMD_STOP(1)
 #define V4L2_DEC_CMD_PAUSE   (2)
 #define V4L2_DEC_CMD_RESUME  (3)
+#define V4L2_DEC_CMD_FLUSH   (4)
 
 /* Flags for V4L2_DEC_CMD_START */
 #define V4L2_DEC_CMD_START_MUTE_AUDIO  (1 << 0)
-- 
2.22.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 4/8] media: docs-rst: Document memory-to-memory video encoder interface

2019-08-22 Thread Jernej Skrabec
From: Tomasz Figa 

Due to complexity of the video encoding process, the V4L2 drivers of
stateful encoder hardware require specific sequences of V4L2 API calls
to be followed. These include capability enumeration, initialization,
encoding, encode parameters change, drain and reset.

Specifics of the above have been discussed during Media Workshops at
LinuxCon Europe 2012 in Barcelona and then later Embedded Linux
Conference Europe 2014 in Düsseldorf. The de facto Codec API that
originated at those events was later implemented by the drivers we already
have merged in mainline, such as s5p-mfc or coda.

The only thing missing was the real specification included as a part of
Linux Media documentation. Fix it now and document the encoder part of
the Codec API.

Signed-off-by: Tomasz Figa 
Signed-off-by: Hans Verkuil 
Signed-off-by: Jernej Skrabec 
---
 Documentation/media/uapi/v4l/dev-encoder.rst  | 608 ++
 Documentation/media/uapi/v4l/dev-mem2mem.rst  |   1 +
 Documentation/media/uapi/v4l/pixfmt-v4l2.rst  |   5 +
 Documentation/media/uapi/v4l/v4l2.rst |   2 +
 .../media/uapi/v4l/vidioc-encoder-cmd.rst |  51 +-
 5 files changed, 647 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/media/uapi/v4l/dev-encoder.rst

diff --git a/Documentation/media/uapi/v4l/dev-encoder.rst 
b/Documentation/media/uapi/v4l/dev-encoder.rst
new file mode 100644
index ..e9d29d6de67a
--- /dev/null
+++ b/Documentation/media/uapi/v4l/dev-encoder.rst
@@ -0,0 +1,608 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _encoder:
+
+*
+Memory-to-Memory Stateful Video Encoder Interface
+*
+
+A stateful video encoder takes raw video frames in display order and encodes
+them into a bytestream. It generates complete chunks of the bytestream, 
including
+all metadata, headers, etc. The resulting bytestream does not require any
+further post-processing by the client.
+
+Performing software stream processing, header generation etc. in the driver
+in order to support this interface is strongly discouraged. In case such
+operations are needed, use of the Stateless Video Encoder Interface (in
+development) is strongly advised.
+
+Conventions and Notations Used in This Document
+===
+
+1. The general V4L2 API rules apply if not specified in this document
+   otherwise.
+
+2. The meaning of words "must", "may", "should", etc. is as per `RFC
+   2119 <https://tools.ietf.org/html/rfc2119>`_.
+
+3. All steps not marked "optional" are required.
+
+4. :c:func:`VIDIOC_G_EXT_CTRLS` and :c:func:`VIDIOC_S_EXT_CTRLS` may be used
+   interchangeably with :c:func:`VIDIOC_G_CTRL` and :c:func:`VIDIOC_S_CTRL`,
+   unless specified otherwise.
+
+5. Single-planar API (see :ref:`planar-apis`) and applicable structures may be
+   used interchangeably with multi-planar API, unless specified otherwise,
+   depending on encoder capabilities and following the general V4L2 guidelines.
+
+6. i = [a..b]: sequence of integers from a to b, inclusive, i.e. i =
+   [0..2]: i = 0, 1, 2.
+
+7. Given an ``OUTPUT`` buffer A, then A’ represents a buffer on the ``CAPTURE``
+   queue containing data that resulted from processing buffer A.
+
+Glossary
+
+
+Refer to :ref:`decoder-glossary`.
+
+State Machine
+=
+
+.. kernel-render:: DOT
+   :alt: DOT digraph of encoder state machine
+   :caption: Encoder State Machine
+
+   digraph encoder_state_machine {
+   node [shape = doublecircle, label="Encoding"] Encoding;
+
+   node [shape = circle, label="Initialization"] Initialization;
+   node [shape = circle, label="Stopped"] Stopped;
+   node [shape = circle, label="Drain"] Drain;
+   node [shape = circle, label="Reset"] Reset;
+
+   node [shape = point]; qi
+   qi -> Initialization [ label = "open()" ];
+
+   Initialization -> Encoding [ label = "Both queues streaming" ];
+
+   Encoding -> Drain [ label = "V4L2_ENC_CMD_STOP" ];
+   Encoding -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
+   Encoding -> Stopped [ label = "VIDIOC_STREAMOFF(OUTPUT)" ];
+   Encoding -> Encoding;
+
+   Drain -> Stopped [ label = "All CAPTURE\nbuffers 
dequeued\nor\nVIDIOC_STREAMOFF(OUTPUT)" ];
+   Drain -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
+
+   Reset -> Encoding [ label = "VIDIOC_STREAMON(CAPTURE)" ];
+   Reset -> Initialization [ label = "VIDIOC_REQBUFS(OUTPUT, 0)" ];
+
+   Stopped -> Encoding [ label = 
"V4L2_ENC_CMD_START\nor\nVIDIOC_STREAMON(OUTPUT)" ];
+   Stopped -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
+   }
+
+Querying Capabilities
+=
+
+1. To

[PATCH 0/8] media: cedrus: h264: Support multi-slice frames

2019-08-22 Thread Jernej Skrabec
This series is continuation of work from
https://patchwork.linuxtv.org/cover/58186/

It picks up unmerged patches (9-12) from aforementioned series and
adds support for decoding multi-slice H264 frames along with support
for V4L2_DEC_CMD_FLUSH and V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF in
Cedrus driver.

Code was tested by modified ffmpeg, which can be found here:
https://github.com/jernejsk/FFmpeg, branch mainline-test
It has to be configured with at least following options:
--enable-v4l2-request --enable-libudev --enable-libdrm

Samples used for testing:
http://jernej.libreelec.tv/videos/h264/BA1_FT_C.mp4
http://jernej.libreelec.tv/videos/h264/h264.mp4

Command line used for testing:
ffmpeg -hwaccel drm -hwaccel_device /dev/dri/card0 -i h264.mp4 -pix_fmt bgra -f 
fbdev /dev/fb0

Please note that V4L2_DEC_CMD_FLUSH was not tested because I'm
not sure how. ffmpeg follows exactly which slice is last in frame
and sets hold flag accordingly. Improper usage of hold flag would
corrupt ffmpeg assumptions and it would probably crash. Any ideas
how to test this are welcome!

Thanks to Jonas for adjusting ffmpeg.

Please let me know what you think.

Best regards,
Jernej

Alexandre Courbot (1):
  media: docs-rst: Document m2m stateless video decoder interface

Hans Verkuil (2):
  vb2: add V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF
  videodev2.h: add V4L2_DEC_CMD_FLUSH

Jernej Skrabec (4):
  media: cedrus: Detect first slice of a frame
  media: cedrus: h264: Support multiple slices per frame
  media: cedrus: Add support for holding capture buffer
  media: cedrus: Add support for V4L2_DEC_CMD_FLUSH

Tomasz Figa (1):
  media: docs-rst: Document memory-to-memory video encoder interface

 Documentation/media/uapi/v4l/buffer.rst   |  13 +
 Documentation/media/uapi/v4l/dev-encoder.rst  | 608 ++
 Documentation/media/uapi/v4l/dev-mem2mem.rst  |   2 +
 .../media/uapi/v4l/dev-stateless-decoder.rst  | 424 
 Documentation/media/uapi/v4l/pixfmt-v4l2.rst  |   5 +
 Documentation/media/uapi/v4l/v4l2.rst |   2 +
 .../media/uapi/v4l/vidioc-decoder-cmd.rst |  11 +-
 .../media/uapi/v4l/vidioc-encoder-cmd.rst |  51 +-
 .../media/uapi/v4l/vidioc-reqbufs.rst |   6 +
 .../media/videodev2.h.rst.exceptions  |   1 +
 .../media/common/videobuf2/videobuf2-v4l2.c   |   8 +-
 drivers/staging/media/sunxi/cedrus/cedrus.h   |   1 +
 .../staging/media/sunxi/cedrus/cedrus_dec.c   |  11 +
 .../staging/media/sunxi/cedrus/cedrus_h264.c  |  11 +-
 .../staging/media/sunxi/cedrus/cedrus_hw.c|   8 +-
 .../staging/media/sunxi/cedrus/cedrus_video.c |  35 +
 include/media/v4l2-mem2mem.h  |  42 ++
 include/media/videobuf2-core.h|   3 +
 include/media/videobuf2-v4l2.h|   5 +
 include/uapi/linux/videodev2.h|  14 +-
 20 files changed, 1230 insertions(+), 31 deletions(-)
 create mode 100644 Documentation/media/uapi/v4l/dev-encoder.rst
 create mode 100644 Documentation/media/uapi/v4l/dev-stateless-decoder.rst

-- 
2.22.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 5/8] media: cedrus: Detect first slice of a frame

2019-08-22 Thread Jernej Skrabec
When codec supports multiple slices in one frame, VPU has to know when
first slice of each frame is being processed, presumably to correctly
clear/set data in auxiliary buffers.

Add first_slice field to cedrus_run structure and set it according to
timestamps of capture and output buffers. If timestamps are different,
it's first slice and viceversa.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h | 1 +
 drivers/staging/media/sunxi/cedrus/cedrus_dec.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 2f017a651848..32cb38e541c6 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -70,6 +70,7 @@ struct cedrus_mpeg2_run {
 struct cedrus_run {
struct vb2_v4l2_buffer  *src;
struct vb2_v4l2_buffer  *dst;
+   bool first_slice;
 
union {
struct cedrus_h264_run  h264;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index 56ca4c9ad01c..d7b54accfe83 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -31,6 +31,8 @@ void cedrus_device_run(void *priv)
 
run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+   run.first_slice =
+   run.src->vb2_buf.timestamp != run.dst->vb2_buf.timestamp;
 
/* Apply request(s) controls if needed. */
src_req = run.src->vb2_buf.req_obj.req;
-- 
2.22.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 4/7] media: cedrus: Remove dst_bufs from context

2019-05-30 Thread Jernej Skrabec
This array is just duplicated capture buffer queue. Remove it and adjust
code to look into capture buffer queue instead.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  4 +---
 .../staging/media/sunxi/cedrus/cedrus_h264.c  |  4 ++--
 .../staging/media/sunxi/cedrus/cedrus_video.c | 22 ---
 3 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 3f476d0fd981..d8e6777e5e27 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -100,8 +100,6 @@ struct cedrus_ctx {
struct v4l2_ctrl_handlerhdl;
struct v4l2_ctrl**ctrls;
 
-   struct vb2_buffer   *dst_bufs[VIDEO_MAX_FRAME];
-
union {
struct {
void*mv_col_buf;
@@ -187,7 +185,7 @@ static inline dma_addr_t cedrus_dst_buf_addr(struct 
cedrus_ctx *ctx,
if (index < 0)
return 0;
 
-   buf = ctx->dst_bufs[index];
+   buf = ctx->fh.m2m_ctx->cap_q_ctx.q.bufs[index];
return buf ? cedrus_buf_addr(buf, >dst_fmt, plane) : 0;
 }
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index d0ee3f90ff46..b2290f98d81a 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -119,7 +119,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
if (buf_idx < 0)
continue;
 
-   cedrus_buf = vb2_to_cedrus_buffer(ctx->dst_bufs[buf_idx]);
+   cedrus_buf = vb2_to_cedrus_buffer(cap_q->bufs[buf_idx]);
position = cedrus_buf->codec.h264.position;
used_dpbs |= BIT(position);
 
@@ -194,7 +194,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
if (buf_idx < 0)
continue;
 
-   ref_buf = to_vb2_v4l2_buffer(ctx->dst_bufs[buf_idx]);
+   ref_buf = to_vb2_v4l2_buffer(cap_q->bufs[buf_idx]);
cedrus_buf = vb2_v4l2_to_cedrus_buffer(ref_buf);
position = cedrus_buf->codec.h264.position;
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index e2b530b1a956..681dfe3367a6 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -411,26 +411,6 @@ static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 
state)
}
 }
 
-static int cedrus_buf_init(struct vb2_buffer *vb)
-{
-   struct vb2_queue *vq = vb->vb2_queue;
-   struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
-
-   if (!V4L2_TYPE_IS_OUTPUT(vq->type))
-   ctx->dst_bufs[vb->index] = vb;
-
-   return 0;
-}
-
-static void cedrus_buf_cleanup(struct vb2_buffer *vb)
-{
-   struct vb2_queue *vq = vb->vb2_queue;
-   struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
-
-   if (!V4L2_TYPE_IS_OUTPUT(vq->type))
-   ctx->dst_bufs[vb->index] = NULL;
-}
-
 static int cedrus_buf_out_validate(struct vb2_buffer *vb)
 {
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -517,8 +497,6 @@ static void cedrus_buf_request_complete(struct vb2_buffer 
*vb)
 static struct vb2_ops cedrus_qops = {
.queue_setup= cedrus_queue_setup,
.buf_prepare= cedrus_buf_prepare,
-   .buf_init   = cedrus_buf_init,
-   .buf_cleanup= cedrus_buf_cleanup,
.buf_queue  = cedrus_buf_queue,
.buf_out_validate   = cedrus_buf_out_validate,
.buf_request_complete   = cedrus_buf_request_complete,
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 3/7] media: cedrus: Fix decoding for some H264 videos

2019-05-30 Thread Jernej Skrabec
It seems that for some H264 videos at least one bitstream parsing
trigger must be called in order to be decoded correctly. There is no
explanation why this helps, but it was observed that two sample videos
with this fix are now decoded correctly and there is no regression with
others.

Signed-off-by: Jernej Skrabec 
---
I have two samples which are fixed by this:
http://jernej.libreelec.tv/videos/h264/test.mkv
http://jernej.libreelec.tv/videos/h264/Dredd%20%E2%80%93%20DTS%20Sound%20Check%20DTS-HD%20MA%207.1.m2ts

Although second one also needs support for multi-slice frames, which is not yet 
implemented here.

 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 22 ---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index cc8d17f211a1..d0ee3f90ff46 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -6,6 +6,7 @@
  * Copyright (c) 2018 Bootlin
  */
 
+#include 
 #include 
 
 #include 
@@ -289,6 +290,20 @@ static void cedrus_write_pred_weight_table(struct 
cedrus_ctx *ctx,
}
 }
 
+static void cedrus_skip_bits(struct cedrus_dev *dev, int num)
+{
+   for (; num > 32; num -= 32) {
+   cedrus_write(dev, VE_H264_TRIGGER_TYPE, 0x3 | (32 << 8));
+   while (cedrus_read(dev, VE_H264_STATUS) & (1 << 8))
+   udelay(1);
+   }
+   if (num > 0) {
+   cedrus_write(dev, VE_H264_TRIGGER_TYPE, 0x3 | (num << 8));
+   while (cedrus_read(dev, VE_H264_STATUS) & (1 << 8))
+   udelay(1);
+   }
+}
+
 static void cedrus_set_params(struct cedrus_ctx *ctx,
  struct cedrus_run *run)
 {
@@ -299,12 +314,11 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
struct vb2_buffer *src_buf = >src->vb2_buf;
struct cedrus_dev *dev = ctx->dev;
dma_addr_t src_buf_addr;
-   u32 offset = slice->header_bit_size;
-   u32 len = (slice->size * 8) - offset;
+   u32 len = slice->size * 8;
u32 reg;
 
cedrus_write(dev, VE_H264_VLD_LEN, len);
-   cedrus_write(dev, VE_H264_VLD_OFFSET, offset);
+   cedrus_write(dev, VE_H264_VLD_OFFSET, 0);
 
src_buf_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
cedrus_write(dev, VE_H264_VLD_END,
@@ -323,6 +337,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
cedrus_write(dev, VE_H264_TRIGGER_TYPE,
 VE_H264_TRIGGER_TYPE_INIT_SWDEC);
 
+   cedrus_skip_bits(dev, slice->header_bit_size);
+
if (((pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) &&
 (slice->slice_type == V4L2_H264_SLICE_TYPE_P ||
  slice->slice_type == V4L2_H264_SLICE_TYPE_SP)) ||
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 7/7] media: cedrus: Improve H264 memory efficiency

2019-05-30 Thread Jernej Skrabec
H264 decoder driver preallocated pretty big worst case mv col buffer
pool. It turns out that pool is most of the time much bigger than it
needs to be.

Solution implemented here is to allocate memory only if capture buffer
is actually used and only as much as it is really necessary.

This is also preparation for 4K video decoding support, which will be
implemented later.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  4 -
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 81 +++
 2 files changed, 28 insertions(+), 57 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 16c1bdfd243a..fcbbbef65494 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -106,10 +106,6 @@ struct cedrus_ctx {
 
union {
struct {
-   void*mv_col_buf;
-   dma_addr_t  mv_col_buf_dma;
-   ssize_t mv_col_buf_field_size;
-   ssize_t mv_col_buf_size;
void*pic_info_buf;
dma_addr_t  pic_info_buf_dma;
void*neighbor_info_buf;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index b2290f98d81a..758fd0049e8f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -54,17 +54,14 @@ static void cedrus_h264_write_sram(struct cedrus_dev *dev,
cedrus_write(dev, VE_AVC_SRAM_PORT_DATA, *buffer++);
 }
 
-static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx,
- unsigned int position,
+static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_buffer *buf,
  unsigned int field)
 {
-   dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma;
-
-   /* Adjust for the position */
-   addr += position * ctx->codec.h264.mv_col_buf_field_size * 2;
+   dma_addr_t addr = buf->extra_buf_dma;
 
/* Adjust for the field */
-   addr += field * ctx->codec.h264.mv_col_buf_field_size;
+   if (field)
+   addr += buf->extra_buf_size / 2;
 
return addr;
 }
@@ -76,7 +73,6 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
struct cedrus_h264_sram_ref_pic *pic)
 {
struct vb2_buffer *vbuf = >m2m_buf.vb.vb2_buf;
-   unsigned int position = buf->codec.h264.position;
 
pic->top_field_order_cnt = cpu_to_le32(top_field_order_cnt);
pic->bottom_field_order_cnt = cpu_to_le32(bottom_field_order_cnt);
@@ -84,10 +80,8 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
 
pic->luma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, >dst_fmt, 0));
pic->chroma_ptr = cpu_to_le32(cedrus_buf_addr(vbuf, >dst_fmt, 1));
-   pic->mv_col_top_ptr =
-   cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 0));
-   pic->mv_col_bot_ptr =
-   cpu_to_le32(cedrus_h264_mv_col_buf_addr(ctx, position, 1));
+   pic->mv_col_top_ptr = cpu_to_le32(cedrus_h264_mv_col_buf_addr(buf, 0));
+   pic->mv_col_bot_ptr = cpu_to_le32(cedrus_h264_mv_col_buf_addr(buf, 1));
 }
 
 static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
@@ -142,6 +136,28 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
output_buf = vb2_to_cedrus_buffer(>dst->vb2_buf);
output_buf->codec.h264.position = position;
 
+   if (!output_buf->extra_buf_size) {
+   const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
+   unsigned int field_size;
+
+   field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
+   DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
+   if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
+   field_size = field_size * 2;
+   if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
+   field_size = field_size * 2;
+
+   output_buf->extra_buf_size = field_size * 2;
+   output_buf->extra_buf =
+   dma_alloc_coherent(dev->dev,
+  output_buf->extra_buf_size,
+  _buf->extra_buf_dma,
+  GFP_KERNEL);
+
+   if (!output_buf->extra_buf)
+   output_buf->extra_buf_size = 0;
+   }
+
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD;
else if (sps->flags & V4L2_

[PATCH 6/7] media: cedrus: Add infra for extra buffers connected to capture buffers

2019-05-30 Thread Jernej Skrabec
H264 and HEVC engines need additional buffers for each capture buffer.
H264 engine has this currently solved by allocating fixed size pool,
which is not ideal. Most of the time pool size is much bigger than it
needs to be.

Ideally, extra buffer should be allocated at buffer initialization, but
that's not efficient. It's size in H264 depends on flags set in SPS, but
that information is not available in buffer init callback.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.h   |  4 
 .../staging/media/sunxi/cedrus/cedrus_video.c | 19 +++
 2 files changed, 23 insertions(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index d8e6777e5e27..16c1bdfd243a 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -81,6 +81,10 @@ struct cedrus_run {
 struct cedrus_buffer {
struct v4l2_m2m_buffer  m2m_buf;
 
+   void*extra_buf;
+   dma_addr_t  extra_buf_dma;
+   ssize_t extra_buf_size;
+
union {
struct {
unsigned intposition;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 681dfe3367a6..d756e0e69634 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -411,6 +411,24 @@ static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 
state)
}
 }
 
+static void cedrus_buf_cleanup(struct vb2_buffer *vb)
+{
+   struct vb2_queue *vq = vb->vb2_queue;
+
+   if (!V4L2_TYPE_IS_OUTPUT(vq->type)) {
+   struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
+   struct cedrus_buffer *cedrus_buf;
+
+   cedrus_buf = vb2_to_cedrus_buffer(vq->bufs[vb->index]);
+
+   if (cedrus_buf->extra_buf_size)
+   dma_free_coherent(ctx->dev->dev,
+ cedrus_buf->extra_buf_size,
+ cedrus_buf->extra_buf,
+ cedrus_buf->extra_buf_dma);
+   }
+}
+
 static int cedrus_buf_out_validate(struct vb2_buffer *vb)
 {
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -497,6 +515,7 @@ static void cedrus_buf_request_complete(struct vb2_buffer 
*vb)
 static struct vb2_ops cedrus_qops = {
.queue_setup= cedrus_queue_setup,
.buf_prepare= cedrus_buf_prepare,
+   .buf_cleanup= cedrus_buf_cleanup,
.buf_queue  = cedrus_buf_queue,
.buf_out_validate   = cedrus_buf_out_validate,
.buf_request_complete   = cedrus_buf_request_complete,
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/7] media: cedrus: Disable engine after each slice decoding

2019-05-30 Thread Jernej Skrabec
libvdpau-sunxi always disables engine after each decoded slice.
Do same in Cedrus driver.

Presumably this also lowers power consumption which is always nice.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index c34aec7c6e40..9c5819def186 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -123,6 +123,7 @@ static irqreturn_t cedrus_irq(int irq, void *data)
 
dev->dec_ops[ctx->current_codec]->irq_disable(ctx);
dev->dec_ops[ctx->current_codec]->irq_clear(ctx);
+   cedrus_engine_disable(dev);
 
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 5/7] media: cedrus: Don't set chroma size for scale & rotation

2019-05-30 Thread Jernej Skrabec
Scale and rotation are currently not implemented, so it makes no sense to
set chroma size for it.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 9c5819def186..9de20ae47916 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -79,9 +79,6 @@ void cedrus_dst_format_set(struct cedrus_dev *dev,
reg = VE_PRIMARY_OUT_FMT_NV12;
cedrus_write(dev, VE_PRIMARY_OUT_FMT, reg);
 
-   reg = VE_CHROMA_BUF_LEN_SDRT(chroma_size / 2);
-   cedrus_write(dev, VE_CHROMA_BUF_LEN, reg);
-
reg = chroma_size / 2;
cedrus_write(dev, VE_PRIMARY_CHROMA_BUF_LEN, reg);
 
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 0/7] media: cedrus: Improvements/cleanup

2019-05-30 Thread Jernej Skrabec
Here is first batch of random Cedrus improvements/cleanups. Only patch 2
has a change which raises a question about H264 controls.

Changes were tested on H3 SoC using modified ffmpeg and Kodi.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (7):
  media: cedrus: Disable engine after each slice decoding
  media: cedrus: Fix H264 default reference index count
  media: cedrus: Fix decoding for some H264 videos
  media: cedrus: Remove dst_bufs from context
  media: cedrus: Don't set chroma size for scale & rotation
  media: cedrus: Add infra for extra buffers connected to capture
buffers
  media: cedrus: Improve H264 memory efficiency

 drivers/staging/media/sunxi/cedrus/cedrus.h   |  12 +-
 .../staging/media/sunxi/cedrus/cedrus_h264.c  | 115 --
 .../staging/media/sunxi/cedrus/cedrus_hw.c|   4 +-
 .../staging/media/sunxi/cedrus/cedrus_video.c |  25 ++--
 4 files changed, 68 insertions(+), 88 deletions(-)

-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/7] media: cedrus: Fix H264 default reference index count

2019-05-30 Thread Jernej Skrabec
Reference index count in VE_H264_PPS reg should come from PPS control.
However, this is not really important because reference index count is
in our case always overridden by that from slice header.

Cc: nico...@ndufresne.ca
Cc: boris.brezil...@collabora.com
Cc: jo...@kwiboo.se

Signed-off-by: Jernej Skrabec 
---
We have to decide if we drop pps->num_ref_idx_l0_default_active_minus1
and pps->num_ref_idx_l1_default_active_minus1 fields or add
num_ref_idx_l0_active_override_flag and num_ref_idx_l0_active_override_flag
to slice control.

Current control doesn't have those two flags, so in Cedrus override flag is
always set and we rely on userspace to set slice->num_ref_idx_l0_active_minus1
and slice->num_ref_idx_l1_active_minus1 to correct values. This means that
values stored in PPS are not needed and always ignored by VPU.

If I understand correctly, algorithm is very simple:

ref_count = PPS->ref_count
if (override_flag)
ref_count = slice->ref_count

It seems that VAAPI provides only final value. In my opinion we should do the
same - get rid of PPS default ref index count fields.

 drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index a30bb283f69f..cc8d17f211a1 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -340,12 +340,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
 
// picture parameters
reg = 0;
-   /*
-* FIXME: the kernel headers are allowing the default value to
-* be passed, but the libva doesn't give us that.
-*/
-   reg |= (slice->num_ref_idx_l0_active_minus1 & 0x1f) << 10;
-   reg |= (slice->num_ref_idx_l1_active_minus1 & 0x1f) << 5;
+   reg |= (pps->num_ref_idx_l0_default_active_minus1 & 0x1f) << 10;
+   reg |= (pps->num_ref_idx_l1_default_active_minus1 & 0x1f) << 5;
reg |= (pps->weighted_bipred_idc & 0x3) << 2;
if (pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
reg |= VE_H264_PPS_ENTROPY_CODING_MODE;
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: cedrus: Allow different mod clock rates

2019-05-18 Thread Jernej Skrabec
Some VPU variants may run at higher clock speeds. They actually need
extra speed to be capable of decoding more complex codecs like HEVC or
bigger image sizes (4K).

Expand variant structure with mod_rate information.

Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.c| 11 ---
 drivers/staging/media/sunxi/cedrus/cedrus.h|  1 +
 drivers/staging/media/sunxi/cedrus/cedrus_hw.c |  2 +-
 drivers/staging/media/sunxi/cedrus/cedrus_hw.h |  2 --
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index d0429c0e6b6b..9349a082a29c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -369,36 +369,41 @@ static int cedrus_remove(struct platform_device *pdev)
 }
 
 static const struct cedrus_variant sun4i_a10_cedrus_variant = {
-   /* No particular capability. */
+   .mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun5i_a13_cedrus_variant = {
-   /* No particular capability. */
+   .mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun7i_a20_cedrus_variant = {
-   /* No particular capability. */
+   .mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun8i_a33_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   .mod_rate   = 32000,
 };
 
 static const struct cedrus_variant sun8i_h3_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   .mod_rate   = 40200,
 };
 
 static const struct cedrus_variant sun50i_a64_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   .mod_rate   = 40200,
 };
 
 static const struct cedrus_variant sun50i_h5_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED,
+   .mod_rate   = 40200,
 };
 
 static const struct cedrus_variant sun50i_h6_cedrus_variant = {
.capabilities   = CEDRUS_CAPABILITY_UNTILED,
.quirks = CEDRUS_QUIRK_NO_DMA_OFFSET,
+   .mod_rate   = 6,
 };
 
 static const struct of_device_id cedrus_dt_match[] = {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h 
b/drivers/staging/media/sunxi/cedrus/cedrus.h
index c57c04b41d2e..25ee1f80f2c7 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -94,6 +94,7 @@ struct cedrus_dec_ops {
 struct cedrus_variant {
unsigned intcapabilities;
unsigned intquirks;
+   unsigned intmod_rate;
 };
 
 struct cedrus_dev {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index fbfff7c1c771..60406b2d4595 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -236,7 +236,7 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
goto err_sram;
}
 
-   ret = clk_set_rate(dev->mod_clk, CEDRUS_CLOCK_RATE_DEFAULT);
+   ret = clk_set_rate(dev->mod_clk, variant->mod_rate);
if (ret) {
dev_err(dev->dev, "Failed to set clock rate\n");
 
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h 
b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index b43c77d54b95..27d0882397aa 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -16,8 +16,6 @@
 #ifndef _CEDRUS_HW_H_
 #define _CEDRUS_HW_H_
 
-#define CEDRUS_CLOCK_RATE_DEFAULT  32000
-
 int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
 void cedrus_engine_disable(struct cedrus_dev *dev);
 
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: cedrus: Fix initialization order

2019-04-07 Thread Jernej Skrabec
Currently, MEDIA_IOC_G_TOPOLOGY ioctl on cedrus fails due to incorrect
initialization order. Fix that by moving video_register_device() before
v4l2_m2m_register_media_controller() and while at it, fix error path.

Reported-by: Jonas Karlman 
Signed-off-by: Jernej Skrabec 
---
 drivers/staging/media/sunxi/cedrus/cedrus.c | 24 ++---
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c 
b/drivers/staging/media/sunxi/cedrus/cedrus.c
index b98add3cdedd..d0429c0e6b6b 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -300,7 +300,7 @@ static int cedrus_probe(struct platform_device *pdev)
 "Failed to initialize V4L2 M2M device\n");
ret = PTR_ERR(dev->m2m_dev);
 
-   goto err_video;
+   goto err_v4l2;
}
 
dev->mdev.dev = >dev;
@@ -310,23 +310,23 @@ static int cedrus_probe(struct platform_device *pdev)
dev->mdev.ops = _m2m_media_ops;
dev->v4l2_dev.mdev = >mdev;
 
-   ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
-
MEDIA_ENT_F_PROC_VIDEO_DECODER);
-   if (ret) {
-   v4l2_err(>v4l2_dev,
-"Failed to initialize V4L2 M2M media controller\n");
-   goto err_m2m;
-   }
-
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
v4l2_err(>v4l2_dev, "Failed to register video device\n");
-   goto err_v4l2;
+   goto err_m2m;
}
 
v4l2_info(>v4l2_dev,
  "Device registered as /dev/video%d\n", vfd->num);
 
+   ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
+
MEDIA_ENT_F_PROC_VIDEO_DECODER);
+   if (ret) {
+   v4l2_err(>v4l2_dev,
+"Failed to initialize V4L2 M2M media controller\n");
+   goto err_video;
+   }
+
ret = media_device_register(>mdev);
if (ret) {
v4l2_err(>v4l2_dev, "Failed to register media device\n");
@@ -339,10 +339,10 @@ static int cedrus_probe(struct platform_device *pdev)
 
 err_m2m_mc:
v4l2_m2m_unregister_media_controller(dev->m2m_dev);
-err_m2m:
-   v4l2_m2m_release(dev->m2m_dev);
 err_video:
video_unregister_device(>vfd);
+err_m2m:
+   v4l2_m2m_release(dev->m2m_dev);
 err_v4l2:
v4l2_device_unregister(>v4l2_dev);
 
-- 
2.21.0

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel