mirror of
https://github.com/Fishwaldo/build.git
synced 2025-04-27 00:11:23 +00:00
* Attach Meson64 to mainline with a bunch of patches. Tested, but need further work. * Enable DVFS on N2 which sometimes works, sometime doesn't, cleanup * Enable beta targets for Meson64 kernel family * Bump with version
886 lines
27 KiB
Diff
886 lines
27 KiB
Diff
|
|
From: Maxime Jourdan <mjourdan@baylibre.com>
|
|
|
|
Add support for the HEVC & VP9 common decoder support, handling
|
|
Amlogic GXBB, GXL, G12A and SM1 platforms.
|
|
|
|
This handles the "HEVC" hw decoder used for HEVC and VP9, and will be
|
|
using in the new H264 multi-instance decoder for G12A & SM1 platforms.
|
|
|
|
Signed-off-by: Maxime Jourdan <mjourdan@baylibre.com>
|
|
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
|
---
|
|
drivers/staging/media/meson/vdec/Makefile | 4 +-
|
|
.../media/meson/vdec/codec_hevc_common.c | 285 ++++++++++++++++++
|
|
.../media/meson/vdec/codec_hevc_common.h | 77 +++++
|
|
drivers/staging/media/meson/vdec/hevc_regs.h | 211 +++++++++++++
|
|
drivers/staging/media/meson/vdec/vdec_hevc.c | 231 ++++++++++++++
|
|
drivers/staging/media/meson/vdec/vdec_hevc.h | 13 +
|
|
6 files changed, 819 insertions(+), 2 deletions(-)
|
|
create mode 100644 drivers/staging/media/meson/vdec/codec_hevc_common.c
|
|
create mode 100644 drivers/staging/media/meson/vdec/codec_hevc_common.h
|
|
create mode 100644 drivers/staging/media/meson/vdec/hevc_regs.h
|
|
create mode 100644 drivers/staging/media/meson/vdec/vdec_hevc.c
|
|
create mode 100644 drivers/staging/media/meson/vdec/vdec_hevc.h
|
|
|
|
diff --git a/drivers/staging/media/meson/vdec/Makefile b/drivers/staging/media/meson/vdec/Makefile
|
|
index 711d990c760e..f55b6e625034 100644
|
|
--- a/drivers/staging/media/meson/vdec/Makefile
|
|
+++ b/drivers/staging/media/meson/vdec/Makefile
|
|
@@ -2,7 +2,7 @@
|
|
# Makefile for Amlogic meson video decoder driver
|
|
|
|
meson-vdec-objs = esparser.o vdec.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 += vdec_1.o vdec_hevc.o
|
|
+meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_hevc_common.o
|
|
|
|
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o
|
|
diff --git a/drivers/staging/media/meson/vdec/codec_hevc_common.c b/drivers/staging/media/meson/vdec/codec_hevc_common.c
|
|
new file mode 100644
|
|
index 000000000000..72a4e38a42dc
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/meson/vdec/codec_hevc_common.c
|
|
@@ -0,0 +1,285 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (C) 2018 Maxime Jourdan <mjourdan@baylibre.com>
|
|
+ */
|
|
+
|
|
+#include <media/v4l2-mem2mem.h>
|
|
+#include <media/videobuf2-dma-contig.h>
|
|
+
|
|
+#include "codec_hevc_common.h"
|
|
+#include "vdec_helpers.h"
|
|
+#include "hevc_regs.h"
|
|
+
|
|
+#define MMU_COMPRESS_HEADER_SIZE 0x48000
|
|
+#define MMU_MAP_SIZE 0x4800
|
|
+
|
|
+/* Configure decode head read mode */
|
|
+void codec_hevc_setup_decode_head(struct amvdec_session *sess, int is_10bit)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ u32 body_size = amvdec_am21c_body_size(sess->width, sess->height);
|
|
+ u32 head_size = amvdec_am21c_head_size(sess->width, sess->height);
|
|
+
|
|
+ if (!codec_hevc_use_fbc(sess->pixfmt_cap, is_10bit)) {
|
|
+ /* Enable 2-plane reference read mode */
|
|
+ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, BIT(31));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (codec_hevc_use_mmu(core->platform->revision,
|
|
+ sess->pixfmt_cap, is_10bit))
|
|
+ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, BIT(4));
|
|
+ else
|
|
+ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, 0);
|
|
+
|
|
+ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL2, body_size / 32);
|
|
+ amvdec_write_dos(core, HEVC_CM_BODY_LENGTH, body_size);
|
|
+ amvdec_write_dos(core, HEVC_CM_HEADER_OFFSET, body_size);
|
|
+ amvdec_write_dos(core, HEVC_CM_HEADER_LENGTH, head_size);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(codec_hevc_setup_decode_head);
|
|
+
|
|
+static void codec_hevc_setup_buffers_gxbb(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm,
|
|
+ int is_10bit)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ struct v4l2_m2m_buffer *buf;
|
|
+ u32 buf_num = v4l2_m2m_num_dst_bufs_ready(sess->m2m_ctx);
|
|
+ dma_addr_t buf_y_paddr = 0;
|
|
+ dma_addr_t buf_uv_paddr = 0;
|
|
+ u32 idx = 0;
|
|
+ u32 val;
|
|
+ int i;
|
|
+
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0);
|
|
+
|
|
+ v4l2_m2m_for_each_dst_buf(sess->m2m_ctx, buf) {
|
|
+ struct vb2_buffer *vb = &buf->vb.vb2_buf;
|
|
+
|
|
+ idx = vb->index;
|
|
+
|
|
+ if (codec_hevc_use_downsample(sess->pixfmt_cap, is_10bit))
|
|
+ buf_y_paddr = comm->fbc_buffer_paddr[idx];
|
|
+ else
|
|
+ buf_y_paddr = vb2_dma_contig_plane_dma_addr(vb, 0);
|
|
+
|
|
+ if (codec_hevc_use_fbc(sess->pixfmt_cap, is_10bit)) {
|
|
+ val = buf_y_paddr | (idx << 8) | 1;
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
|
|
+ val);
|
|
+ } else {
|
|
+ buf_uv_paddr = vb2_dma_contig_plane_dma_addr(vb, 1);
|
|
+ val = buf_y_paddr | ((idx * 2) << 8) | 1;
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
|
|
+ val);
|
|
+ val = buf_uv_paddr | ((idx * 2 + 1) << 8) | 1;
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
|
|
+ val);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (codec_hevc_use_fbc(sess->pixfmt_cap, is_10bit))
|
|
+ val = buf_y_paddr | (idx << 8) | 1;
|
|
+ else
|
|
+ val = buf_y_paddr | ((idx * 2) << 8) | 1;
|
|
+
|
|
+ /* Fill the remaining unused slots with the last buffer's Y addr */
|
|
+ for (i = buf_num; i < MAX_REF_PIC_NUM; ++i)
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, val);
|
|
+
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1);
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, 1);
|
|
+ for (i = 0; i < 32; ++i)
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
|
|
+}
|
|
+
|
|
+static void codec_hevc_setup_buffers_gxl(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm,
|
|
+ int is_10bit)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ struct v4l2_m2m_buffer *buf;
|
|
+ u32 revision = core->platform->revision;
|
|
+ u32 pixfmt_cap = sess->pixfmt_cap;
|
|
+ int i;
|
|
+
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
|
|
+ BIT(2) | BIT(1));
|
|
+
|
|
+ v4l2_m2m_for_each_dst_buf(sess->m2m_ctx, buf) {
|
|
+ struct vb2_buffer *vb = &buf->vb.vb2_buf;
|
|
+ dma_addr_t buf_y_paddr = 0;
|
|
+ dma_addr_t buf_uv_paddr = 0;
|
|
+ u32 idx = vb->index;
|
|
+
|
|
+ if (codec_hevc_use_mmu(revision, pixfmt_cap, is_10bit))
|
|
+ buf_y_paddr = comm->mmu_header_paddr[idx];
|
|
+ else if (codec_hevc_use_downsample(pixfmt_cap, is_10bit))
|
|
+ buf_y_paddr = comm->fbc_buffer_paddr[idx];
|
|
+ else
|
|
+ buf_y_paddr = vb2_dma_contig_plane_dma_addr(vb, 0);
|
|
+
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_DATA,
|
|
+ buf_y_paddr >> 5);
|
|
+
|
|
+ if (!codec_hevc_use_fbc(pixfmt_cap, is_10bit)) {
|
|
+ buf_uv_paddr = vb2_dma_contig_plane_dma_addr(vb, 1);
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_DATA,
|
|
+ buf_uv_paddr >> 5);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1);
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, 1);
|
|
+ for (i = 0; i < 32; ++i)
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
|
|
+}
|
|
+
|
|
+void codec_hevc_free_fbc_buffers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm)
|
|
+{
|
|
+ struct device *dev = sess->core->dev;
|
|
+ u32 am21_size = amvdec_am21c_size(sess->width, sess->height);
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < MAX_REF_PIC_NUM; ++i) {
|
|
+ if (comm->fbc_buffer_vaddr[i]) {
|
|
+ dma_free_coherent(dev, am21_size,
|
|
+ comm->fbc_buffer_vaddr[i],
|
|
+ comm->fbc_buffer_paddr[i]);
|
|
+ comm->fbc_buffer_vaddr[i] = NULL;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(codec_hevc_free_fbc_buffers);
|
|
+
|
|
+static int codec_hevc_alloc_fbc_buffers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm)
|
|
+{
|
|
+ struct device *dev = sess->core->dev;
|
|
+ struct v4l2_m2m_buffer *buf;
|
|
+ u32 am21_size = amvdec_am21c_size(sess->width, sess->height);
|
|
+
|
|
+ v4l2_m2m_for_each_dst_buf(sess->m2m_ctx, buf) {
|
|
+ u32 idx = buf->vb.vb2_buf.index;
|
|
+ dma_addr_t paddr;
|
|
+ void *vaddr = dma_alloc_coherent(dev, am21_size, &paddr,
|
|
+ GFP_KERNEL);
|
|
+ if (!vaddr) {
|
|
+ dev_err(dev, "Couldn't allocate FBC buffer %u\n", idx);
|
|
+ codec_hevc_free_fbc_buffers(sess, comm);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ comm->fbc_buffer_vaddr[idx] = vaddr;
|
|
+ comm->fbc_buffer_paddr[idx] = paddr;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void codec_hevc_free_mmu_headers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm)
|
|
+{
|
|
+ struct device *dev = sess->core->dev;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < MAX_REF_PIC_NUM; ++i) {
|
|
+ if (comm->mmu_header_vaddr[i]) {
|
|
+ dma_free_coherent(dev, MMU_COMPRESS_HEADER_SIZE,
|
|
+ comm->mmu_header_vaddr[i],
|
|
+ comm->mmu_header_paddr[i]);
|
|
+ comm->mmu_header_vaddr[i] = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (comm->mmu_map_vaddr) {
|
|
+ dma_free_coherent(dev, MMU_MAP_SIZE,
|
|
+ comm->mmu_map_vaddr,
|
|
+ comm->mmu_map_paddr);
|
|
+ comm->mmu_map_vaddr = NULL;
|
|
+ }
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(codec_hevc_free_mmu_headers);
|
|
+
|
|
+static int codec_hevc_alloc_mmu_headers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm)
|
|
+{
|
|
+ struct device *dev = sess->core->dev;
|
|
+ struct v4l2_m2m_buffer *buf;
|
|
+
|
|
+ comm->mmu_map_vaddr = dma_alloc_coherent(dev, MMU_MAP_SIZE,
|
|
+ &comm->mmu_map_paddr,
|
|
+ GFP_KERNEL);
|
|
+ if (!comm->mmu_map_vaddr)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ v4l2_m2m_for_each_dst_buf(sess->m2m_ctx, buf) {
|
|
+ u32 idx = buf->vb.vb2_buf.index;
|
|
+ dma_addr_t paddr;
|
|
+ void *vaddr = dma_alloc_coherent(dev, MMU_COMPRESS_HEADER_SIZE,
|
|
+ &paddr, GFP_KERNEL);
|
|
+ if (!vaddr) {
|
|
+ dev_err(dev, "Couldn't allocate MMU header %u\n", idx);
|
|
+ codec_hevc_free_mmu_headers(sess, comm);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ comm->mmu_header_vaddr[idx] = vaddr;
|
|
+ comm->mmu_header_paddr[idx] = paddr;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int codec_hevc_setup_buffers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm,
|
|
+ int is_10bit)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ int ret;
|
|
+
|
|
+ if (codec_hevc_use_downsample(sess->pixfmt_cap, is_10bit)) {
|
|
+ ret = codec_hevc_alloc_fbc_buffers(sess, comm);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (codec_hevc_use_mmu(core->platform->revision,
|
|
+ sess->pixfmt_cap, is_10bit)) {
|
|
+ ret = codec_hevc_alloc_mmu_headers(sess, comm);
|
|
+ if (ret) {
|
|
+ codec_hevc_free_fbc_buffers(sess, comm);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (core->platform->revision == VDEC_REVISION_GXBB)
|
|
+ codec_hevc_setup_buffers_gxbb(sess, comm, is_10bit);
|
|
+ else
|
|
+ codec_hevc_setup_buffers_gxl(sess, comm, is_10bit);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(codec_hevc_setup_buffers);
|
|
+
|
|
+void codec_hevc_fill_mmu_map(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm,
|
|
+ struct vb2_buffer *vb)
|
|
+{
|
|
+ u32 size = amvdec_am21c_size(sess->width, sess->height);
|
|
+ u32 nb_pages = size / PAGE_SIZE;
|
|
+ u32 *mmu_map = comm->mmu_map_vaddr;
|
|
+ u32 first_page;
|
|
+ u32 i;
|
|
+
|
|
+ if (sess->pixfmt_cap == V4L2_PIX_FMT_NV12M)
|
|
+ first_page = comm->fbc_buffer_paddr[vb->index] >> PAGE_SHIFT;
|
|
+ else
|
|
+ first_page = vb2_dma_contig_plane_dma_addr(vb, 0) >> PAGE_SHIFT;
|
|
+
|
|
+ for (i = 0; i < nb_pages; ++i)
|
|
+ mmu_map[i] = first_page + i;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(codec_hevc_fill_mmu_map);
|
|
diff --git a/drivers/staging/media/meson/vdec/codec_hevc_common.h b/drivers/staging/media/meson/vdec/codec_hevc_common.h
|
|
new file mode 100644
|
|
index 000000000000..de16d2e43061
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/meson/vdec/codec_hevc_common.h
|
|
@@ -0,0 +1,77 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ */
|
|
+/*
|
|
+ * Copyright (C) 2018 BayLibre, SAS
|
|
+ * Author: Maxime Jourdan <mjourdan@baylibre.com>
|
|
+ */
|
|
+
|
|
+#ifndef __MESON_VDEC_HEVC_COMMON_H_
|
|
+#define __MESON_VDEC_HEVC_COMMON_H_
|
|
+
|
|
+#include "vdec.h"
|
|
+
|
|
+#define PARSER_CMD_SKIP_CFG_0 0x0000090b
|
|
+#define PARSER_CMD_SKIP_CFG_1 0x1b14140f
|
|
+#define PARSER_CMD_SKIP_CFG_2 0x001b1910
|
|
+static const u16 vdec_hevc_parser_cmd[] = {
|
|
+ 0x0401, 0x8401, 0x0800, 0x0402,
|
|
+ 0x9002, 0x1423, 0x8CC3, 0x1423,
|
|
+ 0x8804, 0x9825, 0x0800, 0x04FE,
|
|
+ 0x8406, 0x8411, 0x1800, 0x8408,
|
|
+ 0x8409, 0x8C2A, 0x9C2B, 0x1C00,
|
|
+ 0x840F, 0x8407, 0x8000, 0x8408,
|
|
+ 0x2000, 0xA800, 0x8410, 0x04DE,
|
|
+ 0x840C, 0x840D, 0xAC00, 0xA000,
|
|
+ 0x08C0, 0x08E0, 0xA40E, 0xFC00,
|
|
+ 0x7C00
|
|
+};
|
|
+
|
|
+#define MAX_REF_PIC_NUM 24
|
|
+
|
|
+struct codec_hevc_common {
|
|
+ void *fbc_buffer_vaddr[MAX_REF_PIC_NUM];
|
|
+ dma_addr_t fbc_buffer_paddr[MAX_REF_PIC_NUM];
|
|
+
|
|
+ void *mmu_header_vaddr[MAX_REF_PIC_NUM];
|
|
+ dma_addr_t mmu_header_paddr[MAX_REF_PIC_NUM];
|
|
+
|
|
+ void *mmu_map_vaddr;
|
|
+ dma_addr_t mmu_map_paddr;
|
|
+};
|
|
+
|
|
+/* Returns 1 if we must use framebuffer compression */
|
|
+static inline int codec_hevc_use_fbc(u32 pixfmt, int is_10bit)
|
|
+{
|
|
+ /* TOFIX: Handle Amlogic Compressed buffer for 8bit also */
|
|
+ return is_10bit;
|
|
+}
|
|
+
|
|
+/* Returns 1 if we are decoding 10-bit but outputting 8-bit NV12 */
|
|
+static inline int codec_hevc_use_downsample(u32 pixfmt, int is_10bit)
|
|
+{
|
|
+ return is_10bit;
|
|
+}
|
|
+
|
|
+/* Returns 1 if we are decoding using the IOMMU */
|
|
+static inline int codec_hevc_use_mmu(u32 revision, u32 pixfmt, int is_10bit)
|
|
+{
|
|
+ return revision >= VDEC_REVISION_G12A &&
|
|
+ codec_hevc_use_fbc(pixfmt, is_10bit);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Configure decode head read mode
|
|
+ */
|
|
+void codec_hevc_setup_decode_head(struct amvdec_session *sess, int is_10bit);
|
|
+
|
|
+void codec_hevc_free_fbc_buffers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm);
|
|
+
|
|
+int codec_hevc_setup_buffers(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm,
|
|
+ int is_10bit);
|
|
+
|
|
+void codec_hevc_fill_mmu_map(struct amvdec_session *sess,
|
|
+ struct codec_hevc_common *comm,
|
|
+ struct vb2_buffer *vb);
|
|
+
|
|
+#endif
|
|
diff --git a/drivers/staging/media/meson/vdec/hevc_regs.h b/drivers/staging/media/meson/vdec/hevc_regs.h
|
|
new file mode 100644
|
|
index 000000000000..55c1a80b955a
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/meson/vdec/hevc_regs.h
|
|
@@ -0,0 +1,211 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ */
|
|
+/*
|
|
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __MESON_VDEC_HEVC_REGS_H_
|
|
+#define __MESON_VDEC_HEVC_REGS_H_
|
|
+
|
|
+#define HEVC_ASSIST_MMU_MAP_ADDR 0xc024
|
|
+
|
|
+#define HEVC_ASSIST_MBOX1_CLR_REG 0xc1d4
|
|
+#define HEVC_ASSIST_MBOX1_MASK 0xc1d8
|
|
+
|
|
+#define HEVC_ASSIST_SCRATCH_0 0xc300
|
|
+#define HEVC_ASSIST_SCRATCH_1 0xc304
|
|
+#define HEVC_ASSIST_SCRATCH_2 0xc308
|
|
+#define HEVC_ASSIST_SCRATCH_3 0xc30c
|
|
+#define HEVC_ASSIST_SCRATCH_4 0xc310
|
|
+#define HEVC_ASSIST_SCRATCH_5 0xc314
|
|
+#define HEVC_ASSIST_SCRATCH_6 0xc318
|
|
+#define HEVC_ASSIST_SCRATCH_7 0xc31c
|
|
+#define HEVC_ASSIST_SCRATCH_8 0xc320
|
|
+#define HEVC_ASSIST_SCRATCH_9 0xc324
|
|
+#define HEVC_ASSIST_SCRATCH_A 0xc328
|
|
+#define HEVC_ASSIST_SCRATCH_B 0xc32c
|
|
+#define HEVC_ASSIST_SCRATCH_C 0xc330
|
|
+#define HEVC_ASSIST_SCRATCH_D 0xc334
|
|
+#define HEVC_ASSIST_SCRATCH_E 0xc338
|
|
+#define HEVC_ASSIST_SCRATCH_F 0xc33c
|
|
+#define HEVC_ASSIST_SCRATCH_G 0xc340
|
|
+#define HEVC_ASSIST_SCRATCH_H 0xc344
|
|
+#define HEVC_ASSIST_SCRATCH_I 0xc348
|
|
+#define HEVC_ASSIST_SCRATCH_J 0xc34c
|
|
+#define HEVC_ASSIST_SCRATCH_K 0xc350
|
|
+#define HEVC_ASSIST_SCRATCH_L 0xc354
|
|
+#define HEVC_ASSIST_SCRATCH_M 0xc358
|
|
+#define HEVC_ASSIST_SCRATCH_N 0xc35c
|
|
+
|
|
+#define HEVC_PARSER_VERSION 0xc400
|
|
+#define HEVC_STREAM_CONTROL 0xc404
|
|
+#define HEVC_STREAM_START_ADDR 0xc408
|
|
+#define HEVC_STREAM_END_ADDR 0xc40c
|
|
+#define HEVC_STREAM_WR_PTR 0xc410
|
|
+#define HEVC_STREAM_RD_PTR 0xc414
|
|
+#define HEVC_STREAM_LEVEL 0xc418
|
|
+#define HEVC_STREAM_FIFO_CTL 0xc41c
|
|
+#define HEVC_SHIFT_CONTROL 0xc420
|
|
+#define HEVC_SHIFT_STARTCODE 0xc424
|
|
+#define HEVC_SHIFT_EMULATECODE 0xc428
|
|
+#define HEVC_SHIFT_STATUS 0xc42c
|
|
+#define HEVC_SHIFTED_DATA 0xc430
|
|
+#define HEVC_SHIFT_BYTE_COUNT 0xc434
|
|
+#define HEVC_SHIFT_COMMAND 0xc438
|
|
+#define HEVC_ELEMENT_RESULT 0xc43c
|
|
+#define HEVC_CABAC_CONTROL 0xc440
|
|
+#define HEVC_PARSER_SLICE_INFO 0xc444
|
|
+#define HEVC_PARSER_CMD_WRITE 0xc448
|
|
+#define HEVC_PARSER_CORE_CONTROL 0xc44c
|
|
+#define HEVC_PARSER_CMD_FETCH 0xc450
|
|
+#define HEVC_PARSER_CMD_STATUS 0xc454
|
|
+#define HEVC_PARSER_LCU_INFO 0xc458
|
|
+#define HEVC_PARSER_HEADER_INFO 0xc45c
|
|
+#define HEVC_PARSER_INT_CONTROL 0xc480
|
|
+#define HEVC_PARSER_INT_STATUS 0xc484
|
|
+#define HEVC_PARSER_IF_CONTROL 0xc488
|
|
+#define HEVC_PARSER_PICTURE_SIZE 0xc48c
|
|
+#define HEVC_PARSER_LCU_START 0xc490
|
|
+#define HEVC_PARSER_HEADER_INFO2 0xc494
|
|
+#define HEVC_PARSER_QUANT_READ 0xc498
|
|
+#define HEVC_PARSER_RESERVED_27 0xc49c
|
|
+#define HEVC_PARSER_CMD_SKIP_0 0xc4a0
|
|
+#define HEVC_PARSER_CMD_SKIP_1 0xc4a4
|
|
+#define HEVC_PARSER_CMD_SKIP_2 0xc4a8
|
|
+#define HEVC_SAO_IF_STATUS 0xc4c0
|
|
+#define HEVC_SAO_IF_DATA_Y 0xc4c4
|
|
+#define HEVC_SAO_IF_DATA_U 0xc4c8
|
|
+#define HEVC_SAO_IF_DATA_V 0xc4cc
|
|
+#define HEVC_STREAM_SWAP_ADDR 0xc4d0
|
|
+#define HEVC_STREAM_SWAP_CTRL 0xc4d4
|
|
+#define HEVC_IQIT_IF_WAIT_CNT 0xc4d8
|
|
+#define HEVC_MPRED_IF_WAIT_CNT 0xc4dc
|
|
+#define HEVC_SAO_IF_WAIT_CNT 0xc4e0
|
|
+
|
|
+#define HEVC_MPRED_VERSION 0xc800
|
|
+#define HEVC_MPRED_CTRL0 0xc804
|
|
+ #define MPRED_CTRL0_NEW_PIC BIT(2)
|
|
+ #define MPRED_CTRL0_NEW_TILE BIT(3)
|
|
+ #define MPRED_CTRL0_NEW_SLI_SEG BIT(4)
|
|
+ #define MPRED_CTRL0_TMVP BIT(5)
|
|
+ #define MPRED_CTRL0_LDC BIT(6)
|
|
+ #define MPRED_CTRL0_COL_FROM_L0 BIT(7)
|
|
+ #define MPRED_CTRL0_ABOVE_EN BIT(9)
|
|
+ #define MPRED_CTRL0_MV_WR_EN BIT(10)
|
|
+ #define MPRED_CTRL0_MV_RD_EN BIT(11)
|
|
+ #define MPRED_CTRL0_BUF_LINEAR BIT(13)
|
|
+#define HEVC_MPRED_CTRL1 0xc808
|
|
+#define HEVC_MPRED_INT_EN 0xc80c
|
|
+#define HEVC_MPRED_INT_STATUS 0xc810
|
|
+#define HEVC_MPRED_PIC_SIZE 0xc814
|
|
+#define HEVC_MPRED_PIC_SIZE_LCU 0xc818
|
|
+#define HEVC_MPRED_TILE_START 0xc81c
|
|
+#define HEVC_MPRED_TILE_SIZE_LCU 0xc820
|
|
+#define HEVC_MPRED_REF_NUM 0xc824
|
|
+#define HEVC_MPRED_REF_EN_L0 0xc830
|
|
+#define HEVC_MPRED_REF_EN_L1 0xc834
|
|
+#define HEVC_MPRED_COLREF_EN_L0 0xc838
|
|
+#define HEVC_MPRED_COLREF_EN_L1 0xc83c
|
|
+#define HEVC_MPRED_AXI_WCTRL 0xc840
|
|
+#define HEVC_MPRED_AXI_RCTRL 0xc844
|
|
+#define HEVC_MPRED_ABV_START_ADDR 0xc848
|
|
+#define HEVC_MPRED_MV_WR_START_ADDR 0xc84c
|
|
+#define HEVC_MPRED_MV_RD_START_ADDR 0xc850
|
|
+#define HEVC_MPRED_MV_WPTR 0xc854
|
|
+#define HEVC_MPRED_MV_RPTR 0xc858
|
|
+#define HEVC_MPRED_MV_WR_ROW_JUMP 0xc85c
|
|
+#define HEVC_MPRED_MV_RD_ROW_JUMP 0xc860
|
|
+#define HEVC_MPRED_CURR_LCU 0xc864
|
|
+#define HEVC_MPRED_ABV_WPTR 0xc868
|
|
+#define HEVC_MPRED_ABV_RPTR 0xc86c
|
|
+#define HEVC_MPRED_CTRL2 0xc870
|
|
+#define HEVC_MPRED_CTRL3 0xc874
|
|
+#define HEVC_MPRED_L0_REF00_POC 0xc880
|
|
+#define HEVC_MPRED_L1_REF00_POC 0xc8c0
|
|
+
|
|
+#define HEVC_MPRED_CUR_POC 0xc980
|
|
+#define HEVC_MPRED_COL_POC 0xc984
|
|
+#define HEVC_MPRED_MV_RD_END_ADDR 0xc988
|
|
+
|
|
+#define HEVC_MSP 0xcc00
|
|
+#define HEVC_MPSR 0xcc04
|
|
+#define HEVC_MCPU_INTR_MSK 0xcc10
|
|
+#define HEVC_MCPU_INTR_REQ 0xcc14
|
|
+#define HEVC_CPSR 0xcc84
|
|
+
|
|
+#define HEVC_IMEM_DMA_CTRL 0xcd00
|
|
+#define HEVC_IMEM_DMA_ADR 0xcd04
|
|
+#define HEVC_IMEM_DMA_COUNT 0xcd08
|
|
+
|
|
+#define HEVCD_IPP_TOP_CNTL 0xd000
|
|
+#define HEVCD_IPP_LINEBUFF_BASE 0xd024
|
|
+#define HEVCD_IPP_AXIIF_CONFIG 0xd02c
|
|
+
|
|
+#define HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR 0xd180
|
|
+#define HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR 0xd184
|
|
+#define HEVCD_MPP_ANC2AXI_TBL_DATA 0xd190
|
|
+
|
|
+#define HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR 0xd300
|
|
+#define HEVCD_MPP_ANC_CANVAS_DATA_ADDR 0xd304
|
|
+#define HEVCD_MPP_DECOMP_CTL1 0xd308
|
|
+#define HEVCD_MPP_DECOMP_CTL2 0xd30c
|
|
+#define HEVCD_MCRCC_CTL1 0xd3c0
|
|
+#define HEVCD_MCRCC_CTL2 0xd3c4
|
|
+#define HEVCD_MCRCC_CTL3 0xd3c8
|
|
+
|
|
+#define HEVC_DBLK_CFG0 0xd400
|
|
+#define HEVC_DBLK_CFG1 0xd404
|
|
+#define HEVC_DBLK_CFG2 0xd408
|
|
+#define HEVC_DBLK_CFG3 0xd40c
|
|
+#define HEVC_DBLK_CFG4 0xd410
|
|
+#define HEVC_DBLK_CFG5 0xd414
|
|
+#define HEVC_DBLK_CFG6 0xd418
|
|
+#define HEVC_DBLK_CFG7 0xd41c
|
|
+#define HEVC_DBLK_CFG8 0xd420
|
|
+#define HEVC_DBLK_CFG9 0xd424
|
|
+#define HEVC_DBLK_CFGA 0xd428
|
|
+#define HEVC_DBLK_STS0 0xd42c
|
|
+#define HEVC_DBLK_STS1 0xd430
|
|
+#define HEVC_DBLK_CFGE 0xd438
|
|
+
|
|
+#define HEVC_SAO_VERSION 0xd800
|
|
+#define HEVC_SAO_CTRL0 0xd804
|
|
+#define HEVC_SAO_CTRL1 0xd808
|
|
+#define HEVC_SAO_PIC_SIZE 0xd814
|
|
+#define HEVC_SAO_PIC_SIZE_LCU 0xd818
|
|
+#define HEVC_SAO_TILE_START 0xd81c
|
|
+#define HEVC_SAO_TILE_SIZE_LCU 0xd820
|
|
+#define HEVC_SAO_Y_START_ADDR 0xd82c
|
|
+#define HEVC_SAO_Y_LENGTH 0xd830
|
|
+#define HEVC_SAO_C_START_ADDR 0xd834
|
|
+#define HEVC_SAO_C_LENGTH 0xd838
|
|
+#define HEVC_SAO_Y_WPTR 0xd83c
|
|
+#define HEVC_SAO_C_WPTR 0xd840
|
|
+#define HEVC_SAO_ABV_START_ADDR 0xd844
|
|
+#define HEVC_SAO_VB_WR_START_ADDR 0xd848
|
|
+#define HEVC_SAO_VB_RD_START_ADDR 0xd84c
|
|
+#define HEVC_SAO_ABV_WPTR 0xd850
|
|
+#define HEVC_SAO_ABV_RPTR 0xd854
|
|
+#define HEVC_SAO_VB_WPTR 0xd858
|
|
+#define HEVC_SAO_VB_RPTR 0xd85c
|
|
+#define HEVC_SAO_CTRL2 0xd880
|
|
+#define HEVC_SAO_CTRL3 0xd884
|
|
+#define HEVC_SAO_CTRL4 0xd888
|
|
+#define HEVC_SAO_CTRL5 0xd88c
|
|
+#define HEVC_SAO_CTRL6 0xd890
|
|
+#define HEVC_SAO_CTRL7 0xd894
|
|
+#define HEVC_CM_BODY_START_ADDR 0xd898
|
|
+#define HEVC_CM_BODY_LENGTH 0xd89c
|
|
+#define HEVC_CM_HEADER_START_ADDR 0xd8a0
|
|
+#define HEVC_CM_HEADER_LENGTH 0xd8a4
|
|
+#define HEVC_CM_HEADER_OFFSET 0xd8ac
|
|
+#define HEVC_SAO_MMU_VH0_ADDR 0xd8e8
|
|
+#define HEVC_SAO_MMU_VH1_ADDR 0xd8ec
|
|
+
|
|
+#define HEVC_IQIT_CLK_RST_CTRL 0xdc00
|
|
+#define HEVC_IQIT_SCALELUT_WR_ADDR 0xdc08
|
|
+#define HEVC_IQIT_SCALELUT_RD_ADDR 0xdc0c
|
|
+#define HEVC_IQIT_SCALELUT_DATA 0xdc10
|
|
+
|
|
+#define HEVC_PSCALE_CTRL 0xe444
|
|
+
|
|
+#endif
|
|
diff --git a/drivers/staging/media/meson/vdec/vdec_hevc.c b/drivers/staging/media/meson/vdec/vdec_hevc.c
|
|
new file mode 100644
|
|
index 000000000000..af41215e106c
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/meson/vdec/vdec_hevc.c
|
|
@@ -0,0 +1,231 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
|
|
+ *
|
|
+ * VDEC_HEVC is a video decoding block that allows decoding of
|
|
+ * HEVC, VP9
|
|
+ */
|
|
+
|
|
+#include <linux/firmware.h>
|
|
+#include <linux/clk.h>
|
|
+
|
|
+#include "vdec_1.h"
|
|
+#include "vdec_helpers.h"
|
|
+#include "hevc_regs.h"
|
|
+#include "dos_regs.h"
|
|
+
|
|
+/* AO Registers */
|
|
+#define AO_RTI_GEN_PWR_SLEEP0 0xe8
|
|
+#define AO_RTI_GEN_PWR_ISO0 0xec
|
|
+ #define GEN_PWR_VDEC_HEVC (BIT(7) | BIT(6))
|
|
+ #define GEN_PWR_VDEC_HEVC_SM1 (BIT(2))
|
|
+
|
|
+#define MC_SIZE (4096 * 4)
|
|
+
|
|
+static int vdec_hevc_load_firmware(struct amvdec_session *sess,
|
|
+ const char *fwname)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ struct device *dev = core->dev_dec;
|
|
+ const struct firmware *fw;
|
|
+ static void *mc_addr;
|
|
+ static dma_addr_t mc_addr_map;
|
|
+ int ret;
|
|
+ u32 i = 100;
|
|
+
|
|
+ ret = request_firmware(&fw, fwname, dev);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "Unable to request firmware %s\n", fwname);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (fw->size < MC_SIZE) {
|
|
+ dev_err(dev, "Firmware size %zu is too small. Expected %u.\n",
|
|
+ fw->size, MC_SIZE);
|
|
+ ret = -EINVAL;
|
|
+ goto release_firmware;
|
|
+ }
|
|
+
|
|
+ mc_addr = dma_alloc_coherent(core->dev, MC_SIZE, &mc_addr_map,
|
|
+ GFP_KERNEL);
|
|
+ if (!mc_addr) {
|
|
+ dev_err(dev, "Failed allocating memory for firmware loading\n");
|
|
+ ret = -ENOMEM;
|
|
+ goto release_firmware;
|
|
+ }
|
|
+
|
|
+ memcpy(mc_addr, fw->data, MC_SIZE);
|
|
+
|
|
+ amvdec_write_dos(core, HEVC_MPSR, 0);
|
|
+ amvdec_write_dos(core, HEVC_CPSR, 0);
|
|
+
|
|
+ amvdec_write_dos(core, HEVC_IMEM_DMA_ADR, mc_addr_map);
|
|
+ amvdec_write_dos(core, HEVC_IMEM_DMA_COUNT, MC_SIZE / 4);
|
|
+ amvdec_write_dos(core, HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
|
|
+
|
|
+ while (i && (readl(core->dos_base + HEVC_IMEM_DMA_CTRL) & 0x8000))
|
|
+ i--;
|
|
+
|
|
+ if (i == 0) {
|
|
+ dev_err(dev, "Firmware load fail (DMA hang?)\n");
|
|
+ ret = -ENODEV;
|
|
+ }
|
|
+
|
|
+ dma_free_coherent(core->dev, MC_SIZE, mc_addr, mc_addr_map);
|
|
+release_firmware:
|
|
+ release_firmware(fw);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void vdec_hevc_stbuf_init(struct amvdec_session *sess)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+
|
|
+ amvdec_write_dos(core, HEVC_STREAM_CONTROL,
|
|
+ amvdec_read_dos(core, HEVC_STREAM_CONTROL) & ~1);
|
|
+ amvdec_write_dos(core, HEVC_STREAM_START_ADDR, sess->vififo_paddr);
|
|
+ amvdec_write_dos(core, HEVC_STREAM_END_ADDR,
|
|
+ sess->vififo_paddr + sess->vififo_size);
|
|
+ amvdec_write_dos(core, HEVC_STREAM_RD_PTR, sess->vififo_paddr);
|
|
+ amvdec_write_dos(core, HEVC_STREAM_WR_PTR, sess->vififo_paddr);
|
|
+}
|
|
+
|
|
+/* VDEC_HEVC specific ESPARSER configuration */
|
|
+static void vdec_hevc_conf_esparser(struct amvdec_session *sess)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+
|
|
+ /* set vififo_vbuf_rp_sel=>vdec_hevc */
|
|
+ amvdec_write_dos(core, DOS_GEN_CTRL0, 3 << 1);
|
|
+ amvdec_write_dos(core, HEVC_STREAM_CONTROL,
|
|
+ amvdec_read_dos(core, HEVC_STREAM_CONTROL) | BIT(3));
|
|
+ amvdec_write_dos(core, HEVC_STREAM_CONTROL,
|
|
+ amvdec_read_dos(core, HEVC_STREAM_CONTROL) | 1);
|
|
+ amvdec_write_dos(core, HEVC_STREAM_FIFO_CTL,
|
|
+ amvdec_read_dos(core, HEVC_STREAM_FIFO_CTL) | BIT(29));
|
|
+}
|
|
+
|
|
+static u32 vdec_hevc_vififo_level(struct amvdec_session *sess)
|
|
+{
|
|
+ return readl_relaxed(sess->core->dos_base + HEVC_STREAM_LEVEL);
|
|
+}
|
|
+
|
|
+static int vdec_hevc_stop(struct amvdec_session *sess)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
|
|
+
|
|
+ /* Disable interrupt */
|
|
+ amvdec_write_dos(core, HEVC_ASSIST_MBOX1_MASK, 0);
|
|
+ /* Disable firmware processor */
|
|
+ amvdec_write_dos(core, HEVC_MPSR, 0);
|
|
+
|
|
+ if (sess->priv)
|
|
+ codec_ops->stop(sess);
|
|
+
|
|
+ /* Enable VDEC_HEVC Isolation */
|
|
+ if (core->platform->revision == VDEC_REVISION_SM1)
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0,
|
|
+ GEN_PWR_VDEC_HEVC_SM1,
|
|
+ GEN_PWR_VDEC_HEVC_SM1);
|
|
+ else
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0,
|
|
+ 0xc00, 0xc00);
|
|
+
|
|
+ /* VDEC_HEVC Memories */
|
|
+ amvdec_write_dos(core, DOS_MEM_PD_HEVC, 0xffffffffUL);
|
|
+
|
|
+ if (core->platform->revision == VDEC_REVISION_SM1)
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
|
|
+ GEN_PWR_VDEC_HEVC_SM1,
|
|
+ GEN_PWR_VDEC_HEVC_SM1);
|
|
+ else
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
|
|
+ GEN_PWR_VDEC_HEVC, GEN_PWR_VDEC_HEVC);
|
|
+
|
|
+ clk_disable_unprepare(core->vdec_hevc_clk);
|
|
+ if (core->platform->revision == VDEC_REVISION_G12A ||
|
|
+ core->platform->revision == VDEC_REVISION_SM1)
|
|
+ clk_disable_unprepare(core->vdec_hevcf_clk);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int vdec_hevc_start(struct amvdec_session *sess)
|
|
+{
|
|
+ int ret;
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
|
|
+
|
|
+ if (core->platform->revision == VDEC_REVISION_G12A ||
|
|
+ core->platform->revision == VDEC_REVISION_SM1) {
|
|
+ clk_set_rate(core->vdec_hevcf_clk, 666666666);
|
|
+ ret = clk_prepare_enable(core->vdec_hevcf_clk);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ clk_set_rate(core->vdec_hevc_clk, 666666666);
|
|
+ ret = clk_prepare_enable(core->vdec_hevc_clk);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (core->platform->revision == VDEC_REVISION_SM1)
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
|
|
+ GEN_PWR_VDEC_HEVC_SM1, 0);
|
|
+ else
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
|
|
+ GEN_PWR_VDEC_HEVC, 0);
|
|
+ udelay(10);
|
|
+
|
|
+ /* Reset VDEC_HEVC*/
|
|
+ amvdec_write_dos(core, DOS_SW_RESET3, 0xffffffff);
|
|
+ amvdec_write_dos(core, DOS_SW_RESET3, 0x00000000);
|
|
+
|
|
+ amvdec_write_dos(core, DOS_GCLK_EN3, 0xffffffff);
|
|
+
|
|
+ /* VDEC_HEVC Memories */
|
|
+ amvdec_write_dos(core, DOS_MEM_PD_HEVC, 0x00000000);
|
|
+
|
|
+ /* Remove VDEC_HEVC Isolation */
|
|
+ if (core->platform->revision == VDEC_REVISION_SM1)
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0,
|
|
+ GEN_PWR_VDEC_HEVC_SM1, 0);
|
|
+ else
|
|
+ regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0,
|
|
+ 0xc00, 0);
|
|
+
|
|
+ amvdec_write_dos(core, DOS_SW_RESET3, 0xffffffff);
|
|
+ amvdec_write_dos(core, DOS_SW_RESET3, 0x00000000);
|
|
+
|
|
+ vdec_hevc_stbuf_init(sess);
|
|
+
|
|
+ ret = vdec_hevc_load_firmware(sess, sess->fmt_out->firmware_path);
|
|
+ if (ret)
|
|
+ goto stop;
|
|
+
|
|
+ ret = codec_ops->start(sess);
|
|
+ if (ret)
|
|
+ goto stop;
|
|
+
|
|
+ amvdec_write_dos(core, DOS_SW_RESET3, BIT(12) | BIT(11));
|
|
+ amvdec_write_dos(core, DOS_SW_RESET3, 0);
|
|
+ amvdec_read_dos(core, DOS_SW_RESET3);
|
|
+
|
|
+ amvdec_write_dos(core, HEVC_MPSR, 1);
|
|
+ /* Let the firmware settle */
|
|
+ udelay(10);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+stop:
|
|
+ vdec_hevc_stop(sess);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+struct amvdec_ops vdec_hevc_ops = {
|
|
+ .start = vdec_hevc_start,
|
|
+ .stop = vdec_hevc_stop,
|
|
+ .conf_esparser = vdec_hevc_conf_esparser,
|
|
+ .vififo_level = vdec_hevc_vififo_level,
|
|
+};
|
|
diff --git a/drivers/staging/media/meson/vdec/vdec_hevc.h b/drivers/staging/media/meson/vdec/vdec_hevc.h
|
|
new file mode 100644
|
|
index 000000000000..cd576a73a966
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/meson/vdec/vdec_hevc.h
|
|
@@ -0,0 +1,13 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ */
|
|
+/*
|
|
+ * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
|
|
+ */
|
|
+
|
|
+#ifndef __MESON_VDEC_VDEC_HEVC_H_
|
|
+#define __MESON_VDEC_VDEC_HEVC_H_
|
|
+
|
|
+#include "vdec.h"
|
|
+
|
|
+extern struct amvdec_ops vdec_hevc_ops;
|
|
+
|
|
+#endif
|