mirror of
https://github.com/armbian/build.git
synced 2025-08-12 06:06:58 +02:00
- update to latest patchset from Baylibre - Some bugs addressed - Open items: - HDMI does not want to work on boot - If a "problematic" monitor is present at boot HDMI will not respond to replug - changing monitors after boot results in 1/2 of the display appearing, second replug and it's ok. - Changing HDMI resolution results in corrupted screen (aliasing, static, "lines" etc.)
314 lines
9.2 KiB
Diff
Executable File
314 lines
9.2 KiB
Diff
Executable File
From e222a1cf4bd62745407a9404565d76b8a5770f12 Mon Sep 17 00:00:00 2001
|
|
From: Maxime Jourdan <mjourdan@baylibre.com>
|
|
Date: Wed, 29 Aug 2018 16:01:55 +0200
|
|
Subject: [PATCH] media: meson: vdec: add MPEG4 decoding support
|
|
|
|
Add support for V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_XVID and
|
|
V4L2_PIX_FMT_H.263
|
|
|
|
---
|
|
drivers/media/platform/meson/vdec/Makefile | 2 +-
|
|
drivers/media/platform/meson/vdec/codec_mpeg4.c | 139 ++++++++++++++++++++++
|
|
drivers/media/platform/meson/vdec/codec_mpeg4.h | 13 ++
|
|
drivers/media/platform/meson/vdec/vdec_platform.c | 91 ++++++++++++++
|
|
4 files changed, 244 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/media/platform/meson/vdec/codec_mpeg4.c
|
|
create mode 100644 drivers/media/platform/meson/vdec/codec_mpeg4.h
|
|
|
|
diff --git a/drivers/media/platform/meson/vdec/Makefile b/drivers/media/platform/meson/vdec/Makefile
|
|
index 01dc960..bb7a134 100644
|
|
--- a/drivers/media/platform/meson/vdec/Makefile
|
|
+++ b/drivers/media/platform/meson/vdec/Makefile
|
|
@@ -3,6 +3,6 @@
|
|
|
|
meson-vdec-objs = esparser.o vdec.o vdec_ctrls.o vdec_helpers.o vdec_platform.o
|
|
meson-vdec-objs += vdec_1.o
|
|
-meson-vdec-objs += codec_mpeg12.o codec_h264.o
|
|
+meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_mpeg4.o
|
|
|
|
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o
|
|
diff --git a/drivers/media/platform/meson/vdec/codec_mpeg4.c b/drivers/media/platform/meson/vdec/codec_mpeg4.c
|
|
new file mode 100644
|
|
index 0000000..1d574e5
|
|
--- /dev/null
|
|
+++ b/drivers/media/platform/meson/vdec/codec_mpeg4.c
|
|
@@ -0,0 +1,139 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
|
|
+ */
|
|
+
|
|
+#include <media/v4l2-mem2mem.h>
|
|
+#include <media/videobuf2-dma-contig.h>
|
|
+
|
|
+#include "vdec_helpers.h"
|
|
+#include "dos_regs.h"
|
|
+
|
|
+#define SIZE_WORKSPACE SZ_1M
|
|
+/* Offset added by firmware, to substract from workspace paddr */
|
|
+#define DCAC_BUFF_START_IP 0x02b00000
|
|
+
|
|
+/* map firmware registers to known MPEG4 functions */
|
|
+#define MREG_BUFFERIN AV_SCRATCH_8
|
|
+#define MREG_BUFFEROUT AV_SCRATCH_9
|
|
+#define MP4_NOT_CODED_CNT AV_SCRATCH_A
|
|
+#define MP4_OFFSET_REG AV_SCRATCH_C
|
|
+#define MEM_OFFSET_REG AV_SCRATCH_F
|
|
+#define MREG_FATAL_ERROR AV_SCRATCH_L
|
|
+
|
|
+#define BUF_IDX_MASK GENMASK(2, 0)
|
|
+#define INTERLACE_FLAG BIT(7)
|
|
+#define TOP_FIELD_FIRST_FLAG BIT(6)
|
|
+
|
|
+struct codec_mpeg4 {
|
|
+ /* Buffer for the MPEG4 Workspace */
|
|
+ void *workspace_vaddr;
|
|
+ dma_addr_t workspace_paddr;
|
|
+};
|
|
+
|
|
+static int codec_mpeg4_can_recycle(struct amvdec_core *core)
|
|
+{
|
|
+ return !amvdec_read_dos(core, MREG_BUFFERIN);
|
|
+}
|
|
+
|
|
+static void codec_mpeg4_recycle(struct amvdec_core *core, u32 buf_idx)
|
|
+{
|
|
+ amvdec_write_dos(core, MREG_BUFFERIN, ~BIT(buf_idx));
|
|
+}
|
|
+
|
|
+static int codec_mpeg4_start(struct amvdec_session *sess) {
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ struct codec_mpeg4 *mpeg4 = sess->priv;
|
|
+ int ret;
|
|
+
|
|
+ mpeg4 = kzalloc(sizeof(*mpeg4), GFP_KERNEL);
|
|
+ if (!mpeg4)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ /* Allocate some memory for the MPEG4 decoder's state */
|
|
+ mpeg4->workspace_vaddr = dma_alloc_coherent(core->dev, SIZE_WORKSPACE,
|
|
+ &mpeg4->workspace_paddr,
|
|
+ GFP_KERNEL);
|
|
+ if (!mpeg4->workspace_vaddr) {
|
|
+ dev_err(core->dev, "Failed to request MPEG4 Workspace\n");
|
|
+ ret = -ENOMEM;
|
|
+ goto free_mpeg4;
|
|
+ }
|
|
+
|
|
+ /* Canvas regs: AV_SCRATCH_0-AV_SCRATCH_4;AV_SCRATCH_G-AV_SCRATCH_J */
|
|
+ amvdec_set_canvases(sess, (u32[]){ AV_SCRATCH_0, AV_SCRATCH_G, 0 },
|
|
+ (u32[]){ 4, 4, 0 });
|
|
+
|
|
+ amvdec_write_dos(core, MEM_OFFSET_REG,
|
|
+ mpeg4->workspace_paddr - DCAC_BUFF_START_IP);
|
|
+ amvdec_write_dos(core, PSCALE_CTRL, 0);
|
|
+ amvdec_write_dos(core, MP4_NOT_CODED_CNT, 0);
|
|
+ amvdec_write_dos(core, MREG_BUFFERIN, 0);
|
|
+ amvdec_write_dos(core, MREG_BUFFEROUT, 0);
|
|
+ amvdec_write_dos(core, MREG_FATAL_ERROR, 0);
|
|
+ amvdec_write_dos(core, MDEC_PIC_DC_THRESH, 0x404038aa);
|
|
+
|
|
+ sess->keyframe_found = 1;
|
|
+ sess->priv = mpeg4;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+free_mpeg4:
|
|
+ kfree(mpeg4);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int codec_mpeg4_stop(struct amvdec_session *sess)
|
|
+{
|
|
+ struct codec_mpeg4 *mpeg4 = sess->priv;
|
|
+ struct amvdec_core *core = sess->core;
|
|
+
|
|
+ if (mpeg4->workspace_vaddr) {
|
|
+ dma_free_coherent(core->dev, SIZE_WORKSPACE,
|
|
+ mpeg4->workspace_vaddr,
|
|
+ mpeg4->workspace_paddr);
|
|
+ mpeg4->workspace_vaddr = 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static irqreturn_t codec_mpeg4_isr(struct amvdec_session *sess)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ u32 reg;
|
|
+ u32 buffer_index;
|
|
+ u32 field = V4L2_FIELD_NONE;
|
|
+
|
|
+ reg = amvdec_read_dos(core, MREG_FATAL_ERROR);
|
|
+ if (reg == 1) {
|
|
+ dev_err(core->dev, "mpeg4 fatal error\n");
|
|
+ amvdec_abort(sess);
|
|
+ return IRQ_HANDLED;
|
|
+ }
|
|
+
|
|
+ reg = amvdec_read_dos(core, MREG_BUFFEROUT);
|
|
+ if (!reg)
|
|
+ goto end;
|
|
+
|
|
+ buffer_index = reg & BUF_IDX_MASK;
|
|
+ if (reg & INTERLACE_FLAG)
|
|
+ field = (reg & TOP_FIELD_FIRST_FLAG) ?
|
|
+ V4L2_FIELD_INTERLACED_TB :
|
|
+ V4L2_FIELD_INTERLACED_BT;
|
|
+
|
|
+ amvdec_dst_buf_done_idx(sess, buffer_index, -1, field);
|
|
+ amvdec_write_dos(core, MREG_BUFFEROUT, 0);
|
|
+
|
|
+end:
|
|
+ amvdec_write_dos(core, ASSIST_MBOX1_CLR_REG, 1);
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
+struct amvdec_codec_ops codec_mpeg4_ops = {
|
|
+ .start = codec_mpeg4_start,
|
|
+ .stop = codec_mpeg4_stop,
|
|
+ .isr = codec_mpeg4_isr,
|
|
+ .can_recycle = codec_mpeg4_can_recycle,
|
|
+ .recycle = codec_mpeg4_recycle,
|
|
+};
|
|
diff --git a/drivers/media/platform/meson/vdec/codec_mpeg4.h b/drivers/media/platform/meson/vdec/codec_mpeg4.h
|
|
new file mode 100644
|
|
index 0000000..b91b26413
|
|
--- /dev/null
|
|
+++ b/drivers/media/platform/meson/vdec/codec_mpeg4.h
|
|
@@ -0,0 +1,13 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ */
|
|
+/*
|
|
+ * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
|
|
+ */
|
|
+
|
|
+#ifndef __MESON_VDEC_CODEC_MPEG4_H_
|
|
+#define __MESON_VDEC_CODEC_MPEG4_H_
|
|
+
|
|
+#include "vdec.h"
|
|
+
|
|
+extern struct amvdec_codec_ops codec_mpeg4_ops;
|
|
+
|
|
+#endif
|
|
\ No newline at end of file
|
|
diff --git a/drivers/media/platform/meson/vdec/vdec_platform.c b/drivers/media/platform/meson/vdec/vdec_platform.c
|
|
index baecf59..80b43fd 100644
|
|
--- a/drivers/media/platform/meson/vdec/vdec_platform.c
|
|
+++ b/drivers/media/platform/meson/vdec/vdec_platform.c
|
|
@@ -10,9 +10,40 @@
|
|
#include "vdec_1.h"
|
|
#include "codec_mpeg12.h"
|
|
#include "codec_h264.h"
|
|
+#include "codec_mpeg4.h"
|
|
|
|
static const struct amvdec_format vdec_formats_gxbb[] = {
|
|
{
|
|
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/vmpeg4_mc_5",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
+ .pixfmt = V4L2_PIX_FMT_H263,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/h263_mc",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
+ .pixfmt = V4L2_PIX_FMT_XVID,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/vmpeg4_mc_5",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
.pixfmt = V4L2_PIX_FMT_H264,
|
|
.min_buffers = 2,
|
|
.max_buffers = 24,
|
|
@@ -49,6 +80,36 @@ static const struct amvdec_format vdec_formats_gxbb[] = {
|
|
|
|
static const struct amvdec_format vdec_formats_gxl[] = {
|
|
{
|
|
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/vmpeg4_mc_5",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
+ .pixfmt = V4L2_PIX_FMT_H263,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/h263_mc",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
+ .pixfmt = V4L2_PIX_FMT_XVID,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/vmpeg4_mc_5",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
.pixfmt = V4L2_PIX_FMT_H264,
|
|
.min_buffers = 2,
|
|
.max_buffers = 24,
|
|
@@ -85,6 +146,36 @@ static const struct amvdec_format vdec_formats_gxl[] = {
|
|
|
|
static const struct amvdec_format vdec_formats_gxm[] = {
|
|
{
|
|
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/vmpeg4_mc_5",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
+ .pixfmt = V4L2_PIX_FMT_H263,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/h263_mc",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
+ .pixfmt = V4L2_PIX_FMT_XVID,
|
|
+ .min_buffers = 8,
|
|
+ .max_buffers = 8,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mpeg4_ops,
|
|
+ .firmware_path = "meson/gx/vmpeg4_mc_5",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
.pixfmt = V4L2_PIX_FMT_H264,
|
|
.min_buffers = 2,
|
|
.max_buffers = 24,
|