mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-25 16:21:32 +00:00
252 lines
7.8 KiB
Diff
252 lines
7.8 KiB
Diff
From e795ad9070631877adb8cfabcf4f7c999acc5dad Mon Sep 17 00:00:00 2001
|
|
From: Maxime Jourdan <mjourdan@baylibre.com>
|
|
Date: Sun, 21 Oct 2018 15:14:27 +0200
|
|
Subject: [PATCH] media: meson: vdec: add MJPEG decoding support
|
|
|
|
Add support for V4L2_PIX_FMT_MJPEG
|
|
---
|
|
drivers/media/platform/meson/vdec/Makefile | 2 +-
|
|
.../media/platform/meson/vdec/codec_mjpeg.c | 140 ++++++++++++++++++
|
|
.../media/platform/meson/vdec/codec_mjpeg.h | 13 ++
|
|
.../media/platform/meson/vdec/vdec_platform.c | 31 ++++
|
|
4 files changed, 185 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/media/platform/meson/vdec/codec_mjpeg.c
|
|
create mode 100644 drivers/media/platform/meson/vdec/codec_mjpeg.h
|
|
|
|
diff --git a/drivers/media/platform/meson/vdec/Makefile b/drivers/media/platform/meson/vdec/Makefile
|
|
index bb7a134e2728..acf07f3c3dac 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 codec_mpeg4.o
|
|
+meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_mpeg4.o codec_mjpeg.o
|
|
|
|
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o
|
|
diff --git a/drivers/media/platform/meson/vdec/codec_mjpeg.c b/drivers/media/platform/meson/vdec/codec_mjpeg.c
|
|
new file mode 100644
|
|
index 000000000000..abea9e3f944c
|
|
--- /dev/null
|
|
+++ b/drivers/media/platform/meson/vdec/codec_mjpeg.c
|
|
@@ -0,0 +1,140 @@
|
|
+// 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"
|
|
+
|
|
+/* map FW registers to known MJPEG functions */
|
|
+#define MREG_DECODE_PARAM AV_SCRATCH_2
|
|
+#define MREG_TO_AMRISC AV_SCRATCH_8
|
|
+#define MREG_FROM_AMRISC AV_SCRATCH_9
|
|
+#define MREG_FRAME_OFFSET AV_SCRATCH_A
|
|
+
|
|
+static int codec_mjpeg_can_recycle(struct amvdec_core *core)
|
|
+{
|
|
+ return !amvdec_read_dos(core, MREG_TO_AMRISC);
|
|
+}
|
|
+
|
|
+static void codec_mjpeg_recycle(struct amvdec_core *core, u32 buf_idx)
|
|
+{
|
|
+ amvdec_write_dos(core, MREG_TO_AMRISC, buf_idx + 1);
|
|
+}
|
|
+
|
|
+/* 4 point triangle */
|
|
+static const uint32_t filt_coef[] = {
|
|
+ 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101,
|
|
+ 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303,
|
|
+ 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505,
|
|
+ 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707,
|
|
+ 0x18382808, 0x18382808, 0x17372909, 0x17372909,
|
|
+ 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b,
|
|
+ 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d,
|
|
+ 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f,
|
|
+ 0x10303010
|
|
+};
|
|
+
|
|
+static void codec_mjpeg_init_scaler(struct amvdec_core *core)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ /* PSCALE cbus bmem enable */
|
|
+ amvdec_write_dos(core, PSCALE_CTRL, 0xc000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 0);
|
|
+ for (i = 0; i < ARRAY_SIZE(filt_coef); ++i) {
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, filt_coef[i]);
|
|
+ }
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 74);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x0008);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x60000000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 82);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x0008);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x60000000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 78);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x0008);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x60000000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 86);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x0008);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x60000000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 73);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x10000);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 81);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x10000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 77);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x10000);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_ADDR, 85);
|
|
+ amvdec_write_dos(core, PSCALE_BMEM_DAT, 0x10000);
|
|
+
|
|
+ amvdec_write_dos(core, PSCALE_RST, 0x7);
|
|
+ amvdec_write_dos(core, PSCALE_RST, 0);
|
|
+}
|
|
+
|
|
+static int codec_mjpeg_start(struct amvdec_session *sess)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+
|
|
+ amvdec_write_dos(core, AV_SCRATCH_0, 12);
|
|
+ amvdec_write_dos(core, AV_SCRATCH_1, 0x031a);
|
|
+
|
|
+ amvdec_set_canvases(sess, (u32[]){ AV_SCRATCH_4, 0 },
|
|
+ (u32[]){ 4, 0 });
|
|
+ codec_mjpeg_init_scaler(core);
|
|
+
|
|
+ amvdec_write_dos(core, MREG_TO_AMRISC, 0);
|
|
+ amvdec_write_dos(core, MREG_FROM_AMRISC, 0);
|
|
+ amvdec_write_dos(core, MCPU_INTR_MSK, 0xffff);
|
|
+ amvdec_write_dos(core, MREG_DECODE_PARAM,
|
|
+ (sess->height << 4) | 0x8000);
|
|
+ amvdec_write_dos(core, VDEC_ASSIST_AMR1_INT8, 8);
|
|
+
|
|
+ /* Intra-only codec */
|
|
+ sess->keyframe_found = 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int codec_mjpeg_stop(struct amvdec_session *sess)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static irqreturn_t codec_mjpeg_isr(struct amvdec_session *sess)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ u32 reg;
|
|
+ u32 buffer_index;
|
|
+ u32 offset;
|
|
+
|
|
+ amvdec_write_dos(core, ASSIST_MBOX1_CLR_REG, 1);
|
|
+
|
|
+ reg = amvdec_read_dos(core, MREG_FROM_AMRISC);
|
|
+ if (!(reg & 0x7))
|
|
+ return IRQ_HANDLED;
|
|
+
|
|
+ buffer_index = ((reg & 0x7) - 1) & 3;
|
|
+ offset = amvdec_read_dos(core, MREG_FRAME_OFFSET);
|
|
+ amvdec_dst_buf_done_idx(sess, buffer_index, offset, V4L2_FIELD_NONE);
|
|
+
|
|
+ amvdec_write_dos(core, MREG_FROM_AMRISC, 0);
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
+struct amvdec_codec_ops codec_mjpeg_ops = {
|
|
+ .start = codec_mjpeg_start,
|
|
+ .stop = codec_mjpeg_stop,
|
|
+ .isr = codec_mjpeg_isr,
|
|
+ .can_recycle = codec_mjpeg_can_recycle,
|
|
+ .recycle = codec_mjpeg_recycle,
|
|
+};
|
|
diff --git a/drivers/media/platform/meson/vdec/codec_mjpeg.h b/drivers/media/platform/meson/vdec/codec_mjpeg.h
|
|
new file mode 100644
|
|
index 000000000000..cc1cf731050d
|
|
--- /dev/null
|
|
+++ b/drivers/media/platform/meson/vdec/codec_mjpeg.h
|
|
@@ -0,0 +1,13 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ */
|
|
+/*
|
|
+ * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
|
|
+ */
|
|
+
|
|
+#ifndef __MESON_VDEC_CODEC_MJPEG_H_
|
|
+#define __MESON_VDEC_CODEC_MJPEG_H_
|
|
+
|
|
+#include "vdec.h"
|
|
+
|
|
+extern struct amvdec_codec_ops codec_mjpeg_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 80b43fd5d01f..61def155a5fd 100644
|
|
--- a/drivers/media/platform/meson/vdec/vdec_platform.c
|
|
+++ b/drivers/media/platform/meson/vdec/vdec_platform.c
|
|
@@ -11,9 +11,20 @@
|
|
#include "codec_mpeg12.h"
|
|
#include "codec_h264.h"
|
|
#include "codec_mpeg4.h"
|
|
+#include "codec_mjpeg.h"
|
|
|
|
static const struct amvdec_format vdec_formats_gxbb[] = {
|
|
{
|
|
+ .pixfmt = V4L2_PIX_FMT_MJPEG,
|
|
+ .min_buffers = 4,
|
|
+ .max_buffers = 4,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mjpeg_ops,
|
|
+ .firmware_path = "meson/gx/vmjpeg_mc",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
.pixfmt = V4L2_PIX_FMT_MPEG4,
|
|
.min_buffers = 8,
|
|
.max_buffers = 8,
|
|
@@ -80,6 +91,16 @@ static const struct amvdec_format vdec_formats_gxbb[] = {
|
|
|
|
static const struct amvdec_format vdec_formats_gxl[] = {
|
|
{
|
|
+ .pixfmt = V4L2_PIX_FMT_MJPEG,
|
|
+ .min_buffers = 4,
|
|
+ .max_buffers = 4,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mjpeg_ops,
|
|
+ .firmware_path = "meson/gx/vmjpeg_mc",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
.pixfmt = V4L2_PIX_FMT_MPEG4,
|
|
.min_buffers = 8,
|
|
.max_buffers = 8,
|
|
@@ -146,6 +167,16 @@ static const struct amvdec_format vdec_formats_gxl[] = {
|
|
|
|
static const struct amvdec_format vdec_formats_gxm[] = {
|
|
{
|
|
+ .pixfmt = V4L2_PIX_FMT_MJPEG,
|
|
+ .min_buffers = 4,
|
|
+ .max_buffers = 4,
|
|
+ .max_width = 1920,
|
|
+ .max_height = 1080,
|
|
+ .vdec_ops = &vdec_1_ops,
|
|
+ .codec_ops = &codec_mjpeg_ops,
|
|
+ .firmware_path = "meson/gx/vmjpeg_mc",
|
|
+ .pixfmts_cap = { V4L2_PIX_FMT_YUV420M, 0 },
|
|
+ }, {
|
|
.pixfmt = V4L2_PIX_FMT_MPEG4,
|
|
.min_buffers = 8,
|
|
.max_buffers = 8,
|