mirror of
https://github.com/armbian/build.git
synced 2025-08-17 16:46:58 +02:00
AR-1 - Adding support category for distributions AR-4 - Remove Allwinner legacy AR-5 - Drop Udoo family and move Udoo board into newly created imx6 family AR-9 - Rename sunxi-next to sunxi-legacy AR-10 - Rename sunxi-dev to sunxi-current AR-11 - Adding Radxa Rockpi S support AR-13 - Rename rockchip64-default to rockchip64-legacy AR-14 - Add rockchip64-current as mainline source AR-15 - Drop Rockchip 4.19.y NEXT, current become 5.3.y AR-16 - Rename RK3399 default to legacy AR-17 - Rename Odroid XU4 next and default to legacy 4.14.y, add DEV 5.4.y AR-18 - Add Odroid N2 current mainline AR-19 - Move Odroid C1 to meson family AR-20 - Rename mvebu64-default to mvebu64-legacy AR-21 - Rename mvebu-default to mvebu-legacy AR-22 - Rename mvebu-next to mvebu-current AR-23 - Drop meson64 default and next, current becomes former DEV 5.3.y AR-24 - Drop cubox family and move Cubox/Hummingboard boards under imx6 AR-26 - Adjust motd AR-27 - Enabling distribution release status AR-28 - Added new GCC compilers AR-29 - Implementing Ubuntu Eoan AR-30 - Add desktop packages per board or family AR-31 - Remove (Ubuntu/Debian) distribution name from image filename AR-32 - Move arch configs from configuration.sh to separate arm64 and armhf config files AR-33 - Revision numbers for beta builds changed to day_in_the_year AR-34 - Patches support linked patches AR-35 - Break meson64 family into gxbb and gxl AR-36 - Add Nanopineo2 Black AR-38 - Upgrade option from old branches to new one via armbian-config AR-41 - Show full timezone info AR-43 - Merge Odroid N2 to meson64 AR-44 - Enable FORCE_BOOTSCRIPT_UPDATE for all builds
774 lines
27 KiB
Diff
774 lines
27 KiB
Diff
From 58cd69efd60bbf24e4795ac8635769e96eb3b079 Mon Sep 17 00:00:00 2001
|
|
From: Maxime Jourdan <mjourdan@baylibre.com>
|
|
Date: Fri, 1 Mar 2019 12:41:03 +0100
|
|
Subject: [PATCH 12/14] media: meson: vp9: add IOMMU support
|
|
|
|
Starting with GXL (S905X), the HEVC/VP9 decoder hardware supports an
|
|
IOMMU to access the decoded frames. This IOMMU is controlled by writing
|
|
the buffer's page IDs to the firmware, which then does the actual work.
|
|
|
|
This commit adds support for using the IOMMU with VP9/HEVC on G12A, the
|
|
first SoC on which it becomes mandatory.
|
|
|
|
Signed-off-by: Maxime Jourdan <mjourdan@baylibre.com>
|
|
---
|
|
drivers/staging/media/meson/vdec/codec_hevc.c | 35 ++--
|
|
.../media/meson/vdec/codec_hevc_common.c | 177 ++++++++++++++----
|
|
.../media/meson/vdec/codec_hevc_common.h | 31 ++-
|
|
drivers/staging/media/meson/vdec/codec_vp9.c | 71 ++++---
|
|
drivers/staging/media/meson/vdec/hevc_regs.h | 5 +
|
|
drivers/staging/media/meson/vdec/vdec.h | 5 -
|
|
drivers/staging/media/meson/vdec/vdec_hevc.c | 14 +-
|
|
7 files changed, 255 insertions(+), 83 deletions(-)
|
|
|
|
diff --git a/drivers/staging/media/meson/vdec/codec_hevc.c b/drivers/staging/media/meson/vdec/codec_hevc.c
|
|
index e16e937d56e8..65d2ad4d8345 100644
|
|
--- a/drivers/staging/media/meson/vdec/codec_hevc.c
|
|
+++ b/drivers/staging/media/meson/vdec/codec_hevc.c
|
|
@@ -75,6 +75,7 @@
|
|
#define MPRED_MV_SIZE (MPRED_MV_BUF_SIZE * MAX_REF_PIC_NUM)
|
|
#define RPM_BUF_SIZE 0x100
|
|
#define LMEM_SIZE 0xA00
|
|
+#define MMU_MAP_SIZE 0x4800
|
|
|
|
#define IPP_OFFSET 0x00
|
|
#define SAO_ABV_OFFSET (IPP_OFFSET + IPP_SIZE)
|
|
@@ -95,6 +96,7 @@
|
|
#define MPRED_MV_OFFSET (MPRED_ABV_OFFSET + MPRED_ABV_SIZE)
|
|
#define RPM_OFFSET (MPRED_MV_OFFSET + MPRED_MV_SIZE)
|
|
#define LMEM_OFFSET (RPM_OFFSET + RPM_BUF_SIZE)
|
|
+#define MMU_MAP_OFFSET (LMEM_OFFSET + LMEM_SIZE)
|
|
|
|
/* ISR decode status */
|
|
#define HEVC_DEC_IDLE 0x0
|
|
@@ -236,6 +238,9 @@ struct hevc_frame {
|
|
struct codec_hevc {
|
|
struct mutex lock;
|
|
|
|
+ /* Common part of the HEVC decoder */
|
|
+ struct codec_hevc_common common;
|
|
+
|
|
/* Buffer for the HEVC Workspace */
|
|
void *workspace_vaddr;
|
|
dma_addr_t workspace_paddr;
|
|
@@ -517,15 +522,20 @@ codec_hevc_setup_workspace(struct amvdec_core *core, struct codec_hevc *hevc)
|
|
amvdec_write_dos(core, HEVC_PPS_BUFFER, wkaddr + PPS_OFFSET);
|
|
amvdec_write_dos(core, HEVC_SAO_UP, wkaddr + SAO_UP_OFFSET);
|
|
|
|
+ if (core->platform->revision >= VDEC_REVISION_G12A)
|
|
+ amvdec_write_dos(core, HEVC_ASSIST_MMU_MAP_ADDR,
|
|
+ wkaddr + MMU_MAP_OFFSET);
|
|
+
|
|
/* No MMU */
|
|
- amvdec_write_dos(core, HEVC_STREAM_SWAP_BUFFER,
|
|
+ /*amvdec_write_dos(core, HEVC_STREAM_SWAP_BUFFER,
|
|
wkaddr + SWAP_BUF_OFFSET);
|
|
amvdec_write_dos(core, HEVC_STREAM_SWAP_BUFFER2,
|
|
- wkaddr + SWAP_BUF2_OFFSET);
|
|
+ wkaddr + SWAP_BUF2_OFFSET);*/
|
|
amvdec_write_dos(core, HEVC_SCALELUT, wkaddr + SCALELUT_OFFSET);
|
|
amvdec_write_dos(core, HEVC_DBLK_CFG4, wkaddr + DBLK_PARA_OFFSET);
|
|
amvdec_write_dos(core, HEVC_DBLK_CFG5, wkaddr + DBLK_DATA_OFFSET);
|
|
amvdec_write_dos(core, HEVC_DBLK_CFGE, wkaddr + DBLK_DATA2_OFFSET);
|
|
+ amvdec_write_dos(core, LMEM_DUMP_ADR, wkaddr + LMEM_OFFSET);
|
|
|
|
return 0;
|
|
}
|
|
@@ -549,9 +559,10 @@ static int codec_hevc_start(struct amvdec_session *sess)
|
|
if (ret)
|
|
goto free_hevc;
|
|
|
|
- amvdec_write_dos_bits(core, HEVC_STREAM_CONTROL, BIT(0));
|
|
- if (core->platform->revision == VDEC_REVISION_G12A)
|
|
- amvdec_write_dos_bits(core, HEVC_STREAM_CONTROL, (0xf << 25));
|
|
+ val = BIT(0); /* stream_fetch_enable */
|
|
+ if (core->platform->revision >= VDEC_REVISION_G12A)
|
|
+ val |= (0xf << 25); /* arwlen_axi_max */
|
|
+ amvdec_write_dos_bits(core, HEVC_STREAM_CONTROL, val);
|
|
|
|
val = amvdec_read_dos(core, HEVC_PARSER_INT_CONTROL) & 0x03ffffff;
|
|
val |= (3 << 29) | BIT(27) | BIT(24) | BIT(22) | BIT(7) | BIT(4) |
|
|
@@ -608,9 +619,9 @@ static int codec_hevc_start(struct amvdec_session *sess)
|
|
goto free_hevc;
|
|
}
|
|
|
|
- amvdec_write_dos(core, HEVC_AUX_ADR, hevc->aux_paddr);
|
|
+ /*amvdec_write_dos(core, HEVC_AUX_ADR, hevc->aux_paddr);
|
|
amvdec_write_dos(core, HEVC_AUX_DATA_SIZE,
|
|
- (((SIZE_AUX) >> 4) << 16) | 0);
|
|
+ (((SIZE_AUX) >> 4) << 16) | 0);*/
|
|
mutex_init(&hevc->lock);
|
|
sess->priv = hevc;
|
|
|
|
@@ -652,7 +663,7 @@ static int codec_hevc_stop(struct amvdec_session *sess)
|
|
dma_free_coherent(core->dev, SIZE_AUX,
|
|
hevc->aux_vaddr, hevc->aux_paddr);
|
|
|
|
- codec_hevc_free_fbc_buffers(sess);
|
|
+ codec_hevc_free_fbc_buffers(sess, &hevc->common);
|
|
mutex_unlock(&hevc->lock);
|
|
mutex_destroy(&hevc->lock);
|
|
|
|
@@ -732,7 +743,7 @@ codec_hevc_set_sao(struct amvdec_session *sess, struct hevc_frame *frame)
|
|
|
|
if (codec_hevc_use_downsample(sess->pixfmt_cap, hevc->is_10bit))
|
|
buf_y_paddr =
|
|
- sess->fbc_buffer_paddr[frame->vbuf->vb2_buf.index];
|
|
+ hevc->common.fbc_buffer_paddr[frame->vbuf->vb2_buf.index];
|
|
else
|
|
buf_y_paddr =
|
|
vb2_dma_contig_plane_dma_addr(&frame->vbuf->vb2_buf, 0);
|
|
@@ -776,7 +787,7 @@ codec_hevc_set_sao(struct amvdec_session *sess, struct hevc_frame *frame)
|
|
val |= BIT(4);
|
|
|
|
amvdec_write_dos(core, HEVC_DBLK_CFGB, val);
|
|
- amvdec_write_dos(core, HEVC_DBLK_STS1 + 4, BIT(28));
|
|
+ amvdec_write_dos(core, HEVC_DBLK_STS1 + 16, BIT(28));
|
|
}
|
|
|
|
amvdec_write_dos(core, HEVC_DBLK_CFG2,
|
|
@@ -1323,7 +1334,7 @@ static void codec_hevc_resume(struct amvdec_session *sess)
|
|
{
|
|
struct codec_hevc *hevc = sess->priv;
|
|
|
|
- if (codec_hevc_setup_buffers(sess, hevc->is_10bit)) {
|
|
+ if (codec_hevc_setup_buffers(sess, &hevc->common, hevc->is_10bit)) {
|
|
amvdec_abort(sess);
|
|
return;
|
|
}
|
|
@@ -1340,6 +1351,8 @@ static irqreturn_t codec_hevc_threaded_isr(struct amvdec_session *sess)
|
|
struct codec_hevc *hevc = sess->priv;
|
|
u32 dec_status = amvdec_read_dos(core, HEVC_DEC_STATUS_REG);
|
|
|
|
+ printk("ISR!\n");
|
|
+
|
|
if (!hevc)
|
|
return IRQ_HANDLED;
|
|
|
|
diff --git a/drivers/staging/media/meson/vdec/codec_hevc_common.c b/drivers/staging/media/meson/vdec/codec_hevc_common.c
|
|
index 5c372a9b0f03..de7eb6cfbe85 100644
|
|
--- a/drivers/staging/media/meson/vdec/codec_hevc_common.c
|
|
+++ b/drivers/staging/media/meson/vdec/codec_hevc_common.c
|
|
@@ -10,6 +10,9 @@
|
|
#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)
|
|
{
|
|
@@ -23,7 +26,12 @@ void codec_hevc_setup_decode_head(struct amvdec_session *sess, int is_10bit)
|
|
return;
|
|
}
|
|
|
|
- amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, 0);
|
|
+ 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);
|
|
@@ -31,8 +39,9 @@ void codec_hevc_setup_decode_head(struct amvdec_session *sess, int is_10bit)
|
|
}
|
|
EXPORT_SYMBOL_GPL(codec_hevc_setup_decode_head);
|
|
|
|
-static void
|
|
-codec_hevc_setup_buffers_gxbb(struct amvdec_session *sess, int is_10bit)
|
|
+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;
|
|
@@ -46,22 +55,26 @@ codec_hevc_setup_buffers_gxbb(struct amvdec_session *sess, int is_10bit)
|
|
amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0);
|
|
|
|
v4l2_m2m_for_each_dst_buf(sess->m2m_ctx, buf) {
|
|
- idx = buf->vb.vb2_buf.index;
|
|
+ struct vb2_buffer *vb = &buf->vb.vb2_buf;
|
|
+ idx = vb->index;
|
|
|
|
if (codec_hevc_use_downsample(sess->pixfmt_cap, is_10bit))
|
|
- buf_y_paddr = sess->fbc_buffer_paddr[idx];
|
|
+ buf_y_paddr = comm->fbc_buffer_paddr[idx];
|
|
else
|
|
- buf_y_paddr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
|
|
+ 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);
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
|
|
+ val);
|
|
} else {
|
|
- buf_uv_paddr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 1);
|
|
+ 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);
|
|
+ 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);
|
|
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
|
|
+ val);
|
|
}
|
|
}
|
|
|
|
@@ -80,32 +93,37 @@ codec_hevc_setup_buffers_gxbb(struct amvdec_session *sess, int is_10bit)
|
|
amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
|
|
}
|
|
|
|
-static void
|
|
-codec_hevc_setup_buffers_gxl(struct amvdec_session *sess, int is_10bit)
|
|
+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 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 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) {
|
|
- u32 idx = buf->vb.vb2_buf.index;
|
|
+ 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_downsample(sess->pixfmt_cap, is_10bit))
|
|
- buf_y_paddr = sess->fbc_buffer_paddr[idx];
|
|
+ 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(&buf->vb.vb2_buf, 0);
|
|
+ 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(sess->pixfmt_cap, is_10bit)) {
|
|
- buf_uv_paddr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 1);
|
|
+
|
|
+ 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);
|
|
}
|
|
@@ -117,24 +135,26 @@ codec_hevc_setup_buffers_gxl(struct amvdec_session *sess, int is_10bit)
|
|
amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
|
|
}
|
|
|
|
-void codec_hevc_free_fbc_buffers(struct amvdec_session *sess)
|
|
+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 (sess->fbc_buffer_vaddr[i]) {
|
|
+ if (comm->fbc_buffer_vaddr[i]) {
|
|
dma_free_coherent(dev, am21_size,
|
|
- sess->fbc_buffer_vaddr[i],
|
|
- sess->fbc_buffer_paddr[i]);
|
|
- sess->fbc_buffer_vaddr[i] = NULL;
|
|
+ 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)
|
|
+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;
|
|
@@ -147,33 +167,118 @@ static int codec_hevc_alloc_fbc_buffers(struct amvdec_session *sess)
|
|
GFP_KERNEL);
|
|
if (!vaddr) {
|
|
dev_err(dev, "Couldn't allocate FBC buffer %u\n", idx);
|
|
- codec_hevc_free_fbc_buffers(sess);
|
|
+ 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;
|
|
}
|
|
|
|
- sess->fbc_buffer_vaddr[idx] = vaddr;
|
|
- sess->fbc_buffer_paddr[idx] = paddr;
|
|
+ comm->mmu_header_vaddr[idx] = vaddr;
|
|
+ comm->mmu_header_paddr[idx] = paddr;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
-int codec_hevc_setup_buffers(struct amvdec_session *sess, int is_10bit)
|
|
+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);
|
|
+ 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, is_10bit);
|
|
+ codec_hevc_setup_buffers_gxbb(sess, comm, is_10bit);
|
|
else
|
|
- codec_hevc_setup_buffers_gxl(sess, is_10bit);
|
|
+ codec_hevc_setup_buffers_gxl(sess, comm, is_10bit);
|
|
|
|
return 0;
|
|
}
|
|
-EXPORT_SYMBOL_GPL(codec_hevc_setup_buffers);
|
|
\ No newline at end of file
|
|
+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
|
|
index 7c8891529ac8..89c8b61f8a94 100644
|
|
--- a/drivers/staging/media/meson/vdec/codec_hevc_common.h
|
|
+++ b/drivers/staging/media/meson/vdec/codec_hevc_common.h
|
|
@@ -25,6 +25,19 @@ static const u16 vdec_hevc_parser_cmd[] = {
|
|
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)
|
|
{
|
|
@@ -37,13 +50,27 @@ static inline int codec_hevc_use_downsample(u32 pixfmt, int is_10bit)
|
|
return pixfmt == V4L2_PIX_FMT_NV12M && 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);
|
|
+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);
|
|
|
|
-int codec_hevc_setup_buffers(struct amvdec_session *sess, 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/codec_vp9.c b/drivers/staging/media/meson/vdec/codec_vp9.c
|
|
index 39e8eb5937bf..b1643cc01f68 100644
|
|
--- a/drivers/staging/media/meson/vdec/codec_vp9.c
|
|
+++ b/drivers/staging/media/meson/vdec/codec_vp9.c
|
|
@@ -219,6 +219,9 @@ struct vp9_frame {
|
|
struct codec_vp9 {
|
|
struct mutex lock;
|
|
|
|
+ /* Common part with the HEVC decoder */
|
|
+ struct codec_hevc_common common;
|
|
+
|
|
/* Buffer for the VP9 Workspace */
|
|
void *workspace_vaddr;
|
|
dma_addr_t workspace_paddr;
|
|
@@ -438,27 +441,26 @@ static u32 codec_vp9_num_pending_bufs(struct amvdec_session *sess)
|
|
return vp9->frames_num;
|
|
}
|
|
|
|
-static int
|
|
-codec_vp9_setup_workspace(struct amvdec_core *core, struct codec_vp9 *vp9)
|
|
+static int codec_vp9_alloc_workspace(struct amvdec_core *core,
|
|
+ struct codec_vp9 *vp9)
|
|
{
|
|
- dma_addr_t wkaddr;
|
|
-
|
|
/* Allocate some memory for the VP9 decoder's state */
|
|
vp9->workspace_vaddr = dma_alloc_coherent(core->dev, SIZE_WORKSPACE,
|
|
- &wkaddr, GFP_KERNEL);
|
|
+ &vp9->workspace_paddr, GFP_KERNEL);
|
|
if (!vp9->workspace_vaddr) {
|
|
dev_err(core->dev, "Failed to allocate VP9 Workspace\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- memset(vp9->workspace_vaddr + DBLK_PARA_OFFSET, 0, DBLK_PARA_SIZE);
|
|
- memset(vp9->workspace_vaddr + COUNT_OFFSET, 0, COUNT_SIZE);
|
|
- memset(vp9->workspace_vaddr + PROB_OFFSET, 0, PROB_SIZE);
|
|
-
|
|
- printk("Workspace: %08X-%08X\n", wkaddr, wkaddr + SIZE_WORKSPACE);
|
|
- printk("DBLK_PARA: %08X\n", wkaddr + DBLK_PARA_OFFSET);
|
|
+ return 0;
|
|
+}
|
|
|
|
- vp9->workspace_paddr = wkaddr;
|
|
+static void codec_vp9_setup_workspace(struct amvdec_session *sess,
|
|
+ struct codec_vp9 *vp9)
|
|
+{
|
|
+ struct amvdec_core *core = sess->core;
|
|
+ u32 revision = core->platform->revision;
|
|
+ dma_addr_t wkaddr = vp9->workspace_paddr;
|
|
|
|
amvdec_write_dos(core, HEVCD_IPP_LINEBUFF_BASE, wkaddr + IPP_OFFSET);
|
|
amvdec_write_dos(core, VP9_RPM_BUFFER, wkaddr + RPM_OFFSET);
|
|
@@ -466,7 +468,6 @@ codec_vp9_setup_workspace(struct amvdec_core *core, struct codec_vp9 *vp9)
|
|
amvdec_write_dos(core, VP9_PPS_BUFFER, wkaddr + PPS_OFFSET);
|
|
amvdec_write_dos(core, VP9_SAO_UP, wkaddr + SAO_UP_OFFSET);
|
|
|
|
- /* No MMU */
|
|
amvdec_write_dos(core, VP9_STREAM_SWAP_BUFFER,
|
|
wkaddr + SWAP_BUF_OFFSET);
|
|
amvdec_write_dos(core, VP9_STREAM_SWAP_BUFFER2,
|
|
@@ -484,7 +485,19 @@ codec_vp9_setup_workspace(struct amvdec_core *core, struct codec_vp9 *vp9)
|
|
amvdec_write_dos(core, VP9_COUNT_SWAP_BUFFER, wkaddr + COUNT_OFFSET);
|
|
amvdec_write_dos(core, LMEM_DUMP_ADR, wkaddr + LMEM_OFFSET);
|
|
|
|
- return 0;
|
|
+ if (codec_hevc_use_mmu(revision, sess->pixfmt_cap, vp9->is_10bit)) {
|
|
+ amvdec_write_dos(core, HEVC_SAO_MMU_VH0_ADDR,
|
|
+ wkaddr + MMU_VBH_OFFSET);
|
|
+ amvdec_write_dos(core, HEVC_SAO_MMU_VH1_ADDR,
|
|
+ wkaddr + MMU_VBH_OFFSET + (MMU_VBH_SIZE / 2));
|
|
+
|
|
+ if (revision >= VDEC_REVISION_G12A)
|
|
+ amvdec_write_dos(core, HEVC_ASSIST_MMU_MAP_ADDR,
|
|
+ vp9->common.mmu_map_paddr);
|
|
+ else
|
|
+ amvdec_write_dos(core, VP9_MMU_MAP_BUFFER,
|
|
+ vp9->common.mmu_map_paddr);
|
|
+ }
|
|
}
|
|
|
|
static int codec_vp9_start(struct amvdec_session *sess)
|
|
@@ -499,10 +512,11 @@ static int codec_vp9_start(struct amvdec_session *sess)
|
|
if (!vp9)
|
|
return -ENOMEM;
|
|
|
|
- ret = codec_vp9_setup_workspace(core, vp9);
|
|
+ ret = codec_vp9_alloc_workspace(core, vp9);
|
|
if (ret)
|
|
goto free_vp9;
|
|
|
|
+ codec_vp9_setup_workspace(sess, vp9);
|
|
amvdec_write_dos_bits(core, HEVC_STREAM_CONTROL, BIT(0));
|
|
// stream_fifo_hole
|
|
if (core->platform->revision == VDEC_REVISION_G12A)
|
|
@@ -575,7 +589,7 @@ static int codec_vp9_stop(struct amvdec_session *sess)
|
|
vp9->workspace_vaddr,
|
|
vp9->workspace_paddr);
|
|
|
|
- codec_hevc_free_fbc_buffers(sess);
|
|
+ codec_hevc_free_fbc_buffers(sess, &vp9->common);
|
|
return 0;
|
|
}
|
|
|
|
@@ -590,7 +604,7 @@ static void codec_vp9_set_sao(struct amvdec_session *sess, struct vb2_buffer *vb
|
|
|
|
if (codec_hevc_use_downsample(sess->pixfmt_cap, vp9->is_10bit))
|
|
buf_y_paddr =
|
|
- sess->fbc_buffer_paddr[vb->index];
|
|
+ vp9->common.fbc_buffer_paddr[vb->index];
|
|
else
|
|
buf_y_paddr =
|
|
vb2_dma_contig_plane_dma_addr(vb, 0);
|
|
@@ -601,6 +615,7 @@ static void codec_vp9_set_sao(struct amvdec_session *sess, struct vb2_buffer *vb
|
|
amvdec_write_dos(core, HEVC_CM_BODY_START_ADDR, buf_y_paddr);
|
|
}
|
|
|
|
+
|
|
if (sess->pixfmt_cap == V4L2_PIX_FMT_NV12M) {
|
|
buf_y_paddr =
|
|
vb2_dma_contig_plane_dma_addr(vb, 0);
|
|
@@ -612,13 +627,22 @@ static void codec_vp9_set_sao(struct amvdec_session *sess, struct vb2_buffer *vb
|
|
amvdec_write_dos(core, HEVC_SAO_C_WPTR, buf_u_v_paddr);
|
|
}
|
|
|
|
+ if (codec_hevc_use_mmu(core->platform->revision, sess->pixfmt_cap,
|
|
+ vp9->is_10bit)) {
|
|
+ amvdec_write_dos(core, HEVC_CM_HEADER_START_ADDR,
|
|
+ vp9->common.mmu_header_paddr[vb->index]);
|
|
+ /* use HEVC_CM_HEADER_START_ADDR */
|
|
+ amvdec_write_dos_bits(core, HEVC_SAO_CTRL5, BIT(10));
|
|
+ }
|
|
+
|
|
amvdec_write_dos(core, HEVC_SAO_Y_LENGTH,
|
|
amvdec_get_output_size(sess));
|
|
amvdec_write_dos(core, HEVC_SAO_C_LENGTH,
|
|
(amvdec_get_output_size(sess) / 2));
|
|
|
|
if (core->platform->revision >= VDEC_REVISION_G12A) {
|
|
- amvdec_clear_dos_bits(core, HEVC_DBLK_CFGB, BIT(4) | BIT(5) | BIT(8) | BIT(9));
|
|
+ amvdec_clear_dos_bits(core, HEVC_DBLK_CFGB,
|
|
+ BIT(4) | BIT(5) | BIT(8) | BIT(9));
|
|
/* enable first, compressed write */
|
|
if (codec_hevc_use_fbc(sess->pixfmt_cap, vp9->is_10bit))
|
|
amvdec_write_dos_bits(core, HEVC_DBLK_CFGB, BIT(8));
|
|
@@ -630,8 +654,6 @@ static void codec_vp9_set_sao(struct amvdec_session *sess, struct vb2_buffer *vb
|
|
/* dblk pipeline mode=1 for performance */
|
|
if (sess->width >= 1280)
|
|
amvdec_write_dos_bits(core, HEVC_DBLK_CFGB, BIT(4));
|
|
-
|
|
- printk("HEVC_DBLK_CFGB: %08X\n", amvdec_read_dos(core, HEVC_DBLK_CFGB));
|
|
}
|
|
|
|
val = amvdec_read_dos(core, HEVC_SAO_CTRL1) & ~0x3ff3;
|
|
@@ -644,7 +666,6 @@ static void codec_vp9_set_sao(struct amvdec_session *sess, struct vb2_buffer *vb
|
|
}
|
|
|
|
amvdec_write_dos(core, HEVC_SAO_CTRL1, val);
|
|
- printk("HEVC_SAO_CTRL1: %08X\n", val);
|
|
|
|
if (!codec_hevc_use_fbc(sess->pixfmt_cap, vp9->is_10bit)) {
|
|
/* no downscale for NV12 */
|
|
@@ -919,6 +940,11 @@ static void codec_vp9_process_frame(struct amvdec_session *sess)
|
|
codec_vp9_update_next_ref(vp9);
|
|
codec_vp9_show_existing_frame(vp9);
|
|
|
|
+ if (codec_hevc_use_mmu(core->platform->revision, sess->pixfmt_cap,
|
|
+ vp9->is_10bit))
|
|
+ codec_hevc_fill_mmu_map(sess, &vp9->common,
|
|
+ &vp9->cur_frame->vbuf->vb2_buf);
|
|
+
|
|
intra_only = param->p.show_frame ? 0 : param->p.intra_only;
|
|
/* clear mpred (for keyframe only) */
|
|
if (param->p.frame_type != KEY_FRAME && !intra_only) {
|
|
@@ -971,11 +997,12 @@ static void codec_vp9_resume(struct amvdec_session *sess)
|
|
{
|
|
struct codec_vp9 *vp9 = sess->priv;
|
|
|
|
- if (codec_hevc_setup_buffers(sess, vp9->is_10bit)) {
|
|
+ if (codec_hevc_setup_buffers(sess, &vp9->common, vp9->is_10bit)) {
|
|
amvdec_abort(sess);
|
|
return;
|
|
}
|
|
|
|
+ codec_vp9_setup_workspace(sess, vp9);
|
|
codec_hevc_setup_decode_head(sess, vp9->is_10bit);
|
|
codec_vp9_process_lf(vp9);
|
|
codec_vp9_process_frame(sess);
|
|
diff --git a/drivers/staging/media/meson/vdec/hevc_regs.h b/drivers/staging/media/meson/vdec/hevc_regs.h
|
|
index dc2c2e085b05..0392f41a1eed 100644
|
|
--- a/drivers/staging/media/meson/vdec/hevc_regs.h
|
|
+++ b/drivers/staging/media/meson/vdec/hevc_regs.h
|
|
@@ -6,6 +6,8 @@
|
|
#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
|
|
|
|
@@ -200,8 +202,11 @@
|
|
#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
|
|
diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h
|
|
index 95415212b282..95b4c5761a27 100644
|
|
--- a/drivers/staging/media/meson/vdec/vdec.h
|
|
+++ b/drivers/staging/media/meson/vdec/vdec.h
|
|
@@ -20,8 +20,6 @@
|
|
/* 32 buffers in 3-plane YUV420 */
|
|
#define MAX_CANVAS (32 * 3)
|
|
|
|
-#define MAX_REF_PIC_NUM 24
|
|
-
|
|
struct amvdec_buffer {
|
|
struct list_head list;
|
|
struct vb2_buffer *vb;
|
|
@@ -261,9 +259,6 @@ struct amvdec_session {
|
|
u32 wrap_count;
|
|
u32 fw_idx_to_vb2_idx[32];
|
|
|
|
- void *fbc_buffer_vaddr[MAX_REF_PIC_NUM];
|
|
- dma_addr_t fbc_buffer_paddr[MAX_REF_PIC_NUM];
|
|
-
|
|
enum amvdec_status status;
|
|
void *priv;
|
|
};
|
|
diff --git a/drivers/staging/media/meson/vdec/vdec_hevc.c b/drivers/staging/media/meson/vdec/vdec_hevc.c
|
|
index 730ecd771643..70db09c052c3 100644
|
|
--- a/drivers/staging/media/meson/vdec/vdec_hevc.c
|
|
+++ b/drivers/staging/media/meson/vdec/vdec_hevc.c
|
|
@@ -123,9 +123,9 @@ static int vdec_hevc_stop(struct amvdec_session *sess)
|
|
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)
|
|
clk_disable_unprepare(core->vdec_hevcf_clk);
|
|
- clk_disable_unprepare(core->vdec_hevc_clk);
|
|
|
|
return 0;
|
|
}
|
|
@@ -136,11 +136,6 @@ static int vdec_hevc_start(struct amvdec_session *sess)
|
|
struct amvdec_core *core = sess->core;
|
|
struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
|
|
|
|
- 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_G12A) {
|
|
clk_set_rate(core->vdec_hevcf_clk, 666666666);
|
|
ret = clk_prepare_enable(core->vdec_hevcf_clk);
|
|
@@ -148,6 +143,11 @@ static int vdec_hevc_start(struct amvdec_session *sess)
|
|
return ret;
|
|
}
|
|
|
|
+ clk_set_rate(core->vdec_hevc_clk, 666666666);
|
|
+ ret = clk_prepare_enable(core->vdec_hevc_clk);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
|
|
GEN_PWR_VDEC_HEVC, 0);
|
|
udelay(10);
|
|
@@ -177,7 +177,7 @@ static int vdec_hevc_start(struct amvdec_session *sess)
|
|
if (ret)
|
|
goto stop;
|
|
|
|
- amvdec_write_dos(core, DOS_SW_RESET3, BIT(12)|BIT(11));
|
|
+ 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);
|
|
|
|
--
|
|
2.20.1
|
|
|