summarylogtreecommitdiffstats
path: root/general-meson-vdec-improve-mmu-and-fbc-handling-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'general-meson-vdec-improve-mmu-and-fbc-handling-.patch')
-rw-r--r--general-meson-vdec-improve-mmu-and-fbc-handling-.patch586
1 files changed, 586 insertions, 0 deletions
diff --git a/general-meson-vdec-improve-mmu-and-fbc-handling-.patch b/general-meson-vdec-improve-mmu-and-fbc-handling-.patch
new file mode 100644
index 000000000000..d174d75e3986
--- /dev/null
+++ b/general-meson-vdec-improve-mmu-and-fbc-handling-.patch
@@ -0,0 +1,586 @@
+From df7d1adad3f60c8cb3f33235b6301093801b7b47 Mon Sep 17 00:00:00 2001
+From: benjamin545 <benjamin545@gmail.com>
+Date: Thu, 15 Jul 2021 16:32:39 -0400
+Subject: [PATCH 63/90] WIP: drivers: meson: vdec: improve mmu and fbc handling
+ and add 10 bit handling
+
+---
+ drivers/staging/media/meson/vdec/codec_h264.c | 3 +-
+ .../media/meson/vdec/codec_hevc_common.c | 164 +++++++++++-------
+ .../media/meson/vdec/codec_hevc_common.h | 3 +-
+ drivers/staging/media/meson/vdec/codec_vp9.c | 36 ++--
+ drivers/staging/media/meson/vdec/esparser.c | 1 +
+ drivers/staging/media/meson/vdec/vdec.h | 1 +
+ .../staging/media/meson/vdec/vdec_helpers.c | 46 +++--
+ .../staging/media/meson/vdec/vdec_helpers.h | 10 +-
+ 8 files changed, 163 insertions(+), 101 deletions(-)
+
+diff --git a/drivers/staging/media/meson/vdec/codec_h264.c b/drivers/staging/media/meson/vdec/codec_h264.c
+index c61128fc4bb9..d53c9a464bde 100644
+--- a/drivers/staging/media/meson/vdec/codec_h264.c
++++ b/drivers/staging/media/meson/vdec/codec_h264.c
+@@ -353,7 +353,8 @@ static void codec_h264_src_change(struct amvdec_session *sess)
+ frame_width, frame_height, crop_right, crop_bottom);
+
+ codec_h264_set_par(sess);
+- amvdec_src_change(sess, frame_width, frame_height, h264->max_refs + 5);
++ amvdec_src_change(sess, frame_width, frame_height,
++ h264->max_refs + 5, 8);
+ }
+
+ /*
+diff --git a/drivers/staging/media/meson/vdec/codec_hevc_common.c b/drivers/staging/media/meson/vdec/codec_hevc_common.c
+index 0315cc0911cd..d6ed82dc93ca 100644
+--- a/drivers/staging/media/meson/vdec/codec_hevc_common.c
++++ b/drivers/staging/media/meson/vdec/codec_hevc_common.c
+@@ -30,8 +30,11 @@ const u16 vdec_hevc_parser_cmd[] = {
+ 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);
++ u32 use_mmu = codec_hevc_use_mmu(core->platform->revision,
++ sess->pixfmt_cap, is_10bit);
++ u32 body_size = amvdec_amfbc_body_size(sess->width, sess->height,
++ is_10bit, use_mmu);
++ u32 head_size = amvdec_amfbc_head_size(sess->width, sess->height);
+
+ if (!codec_hevc_use_fbc(sess->pixfmt_cap, is_10bit)) {
+ /* Enable 2-plane reference read mode */
+@@ -39,9 +42,17 @@ void codec_hevc_setup_decode_head(struct amvdec_session *sess, int is_10bit)
+ return;
+ }
+
++ /* enable mem saving mode for 8-bit */
++ if (!is_10bit)
++ amvdec_write_dos_bits(core, HEVC_SAO_CTRL5, BIT(9));
++ else
++ amvdec_clear_dos_bits(core, HEVC_SAO_CTRL5, BIT(9));
++
+ if (codec_hevc_use_mmu(core->platform->revision,
+ sess->pixfmt_cap, is_10bit))
+ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, BIT(4));
++ else if (!is_10bit)
++ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, BIT(3));
+ else
+ amvdec_write_dos(core, HEVCD_MPP_DECOMP_CTL1, 0);
+
+@@ -73,7 +84,7 @@ static void codec_hevc_setup_buffers_gxbb(struct amvdec_session *sess,
+
+ idx = vb->index;
+
+- if (codec_hevc_use_downsample(sess->pixfmt_cap, is_10bit))
++ if (codec_hevc_use_fbc(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);
+@@ -114,8 +125,8 @@ static void codec_hevc_setup_buffers_gxl(struct amvdec_session *sess,
+ {
+ struct amvdec_core *core = sess->core;
+ struct v4l2_m2m_buffer *buf;
+- u32 revision = core->platform->revision;
+ u32 pixfmt_cap = sess->pixfmt_cap;
++ const u32 revision = core->platform->revision;
+ int i;
+
+ amvdec_write_dos(core, HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+@@ -127,12 +138,14 @@ static void codec_hevc_setup_buffers_gxl(struct amvdec_session *sess,
+ 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);
++ if (codec_hevc_use_downsample(pixfmt_cap, is_10bit)) {
++ if (codec_hevc_use_mmu(revision, pixfmt_cap, is_10bit))
++ buf_y_paddr = comm->mmu_header_paddr[idx];
++ else
++ 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);
+@@ -150,60 +163,67 @@ static void codec_hevc_setup_buffers_gxl(struct amvdec_session *sess,
+ 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_mmu_headers(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;
++ 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;
+ }
+ }
+ }
+-EXPORT_SYMBOL_GPL(codec_hevc_free_fbc_buffers);
++EXPORT_SYMBOL_GPL(codec_hevc_free_mmu_headers);
+
+-static int codec_hevc_alloc_fbc_buffers(struct amvdec_session *sess,
++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;
+- 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);
++ void *vaddr = dma_alloc_coherent(dev, MMU_COMPRESS_HEADER_SIZE,
++ &paddr, GFP_KERNEL);
+ if (!vaddr) {
+- codec_hevc_free_fbc_buffers(sess, comm);
++ codec_hevc_free_mmu_headers(sess, comm);
+ return -ENOMEM;
+ }
+
+- comm->fbc_buffer_vaddr[idx] = vaddr;
+- comm->fbc_buffer_paddr[idx] = paddr;
++ comm->mmu_header_vaddr[idx] = vaddr;
++ comm->mmu_header_paddr[idx] = paddr;
+ }
+
+ return 0;
+ }
+
+-void codec_hevc_free_mmu_headers(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 use_mmu;
++ u32 am21_size;
+ int i;
+
++ use_mmu = codec_hevc_use_mmu(sess->core->platform->revision,
++ sess->pixfmt_cap,
++ sess->bitdepth == 10 ? 1 : 0);
++
++ am21_size = amvdec_amfbc_size(sess->width, sess->height,
++ sess->bitdepth == 10 ? 1 : 0, use_mmu);
++
+ 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->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;
+ }
+ }
+
+@@ -213,33 +233,49 @@ void codec_hevc_free_mmu_headers(struct amvdec_session *sess,
+ comm->mmu_map_paddr);
+ comm->mmu_map_vaddr = NULL;
+ }
++
++ codec_hevc_free_mmu_headers(sess, comm);
+ }
+-EXPORT_SYMBOL_GPL(codec_hevc_free_mmu_headers);
++EXPORT_SYMBOL_GPL(codec_hevc_free_fbc_buffers);
+
+-static int codec_hevc_alloc_mmu_headers(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;
++ u32 use_mmu;
++ u32 am21_size;
++ const u32 revision = sess->core->platform->revision;
++ const u32 is_10bit = sess->bitdepth == 10 ? 1 : 0;
++ int ret;
+
+- comm->mmu_map_vaddr = dma_alloc_coherent(dev, MMU_MAP_SIZE,
+- &comm->mmu_map_paddr,
+- GFP_KERNEL);
+- if (!comm->mmu_map_vaddr)
+- return -ENOMEM;
++ use_mmu = codec_hevc_use_mmu(revision, sess->pixfmt_cap,
++ is_10bit);
++
++ am21_size = amvdec_amfbc_size(sess->width, sess->height,
++ is_10bit, use_mmu);
+
+ 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);
++ void *vaddr = dma_alloc_coherent(dev, am21_size, &paddr,
++ GFP_KERNEL);
+ if (!vaddr) {
+- codec_hevc_free_mmu_headers(sess, comm);
++ codec_hevc_free_fbc_buffers(sess, comm);
+ return -ENOMEM;
+ }
+
+- comm->mmu_header_vaddr[idx] = vaddr;
+- comm->mmu_header_paddr[idx] = paddr;
++ comm->fbc_buffer_vaddr[idx] = vaddr;
++ comm->fbc_buffer_paddr[idx] = paddr;
++ }
++
++ if (codec_hevc_use_mmu(revision, sess->pixfmt_cap, is_10bit) &&
++ codec_hevc_use_downsample(sess->pixfmt_cap, is_10bit)) {
++ ret = codec_hevc_alloc_mmu_headers(sess, comm);
++ if (ret) {
++ codec_hevc_free_fbc_buffers(sess, comm);
++ return ret;
++ }
+ }
+
+ return 0;
+@@ -250,21 +286,24 @@ int codec_hevc_setup_buffers(struct amvdec_session *sess,
+ int is_10bit)
+ {
+ struct amvdec_core *core = sess->core;
++ struct device *dev = core->dev;
+ 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)) {
++ comm->mmu_map_vaddr = dma_alloc_coherent(dev, MMU_MAP_SIZE,
++ &comm->mmu_map_paddr,
++ GFP_KERNEL);
++ if (!comm->mmu_map_vaddr)
++ return -ENOMEM;
+ }
+
+ 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;
+- }
++ sess->pixfmt_cap, is_10bit) ||
++ codec_hevc_use_downsample(sess->pixfmt_cap, is_10bit)) {
++ ret = codec_hevc_alloc_fbc_buffers(sess, comm);
++ if (ret)
++ return ret;
+ }
+
+ if (core->platform->revision == VDEC_REVISION_GXBB)
+@@ -278,19 +317,24 @@ 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)
++ struct vb2_buffer *vb,
++ u32 is_10bit)
+ {
+- u32 size = amvdec_am21c_size(sess->width, sess->height);
+- u32 nb_pages = size / PAGE_SIZE;
++ u32 use_mmu;
++ u32 size;
++ u32 nb_pages;
+ 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;
++ use_mmu = codec_hevc_use_mmu(sess->core->platform->revision,
++ sess->pixfmt_cap, is_10bit);
++
++ size = amvdec_amfbc_size(sess->width, sess->height, is_10bit,
++ use_mmu);
+
++ nb_pages = size / PAGE_SIZE;
++ first_page = comm->fbc_buffer_paddr[vb->index] >> PAGE_SHIFT;
+ for (i = 0; i < nb_pages; ++i)
+ mmu_map[i] = first_page + i;
+ }
+diff --git a/drivers/staging/media/meson/vdec/codec_hevc_common.h b/drivers/staging/media/meson/vdec/codec_hevc_common.h
+index cf072b8a9da2..13f9f1d90a94 100644
+--- a/drivers/staging/media/meson/vdec/codec_hevc_common.h
++++ b/drivers/staging/media/meson/vdec/codec_hevc_common.h
+@@ -64,6 +64,7 @@ int codec_hevc_setup_buffers(struct amvdec_session *sess,
+
+ void codec_hevc_fill_mmu_map(struct amvdec_session *sess,
+ struct codec_hevc_common *comm,
+- struct vb2_buffer *vb);
++ struct vb2_buffer *vb,
++ u32 is_10bit);
+
+ #endif
+diff --git a/drivers/staging/media/meson/vdec/codec_vp9.c b/drivers/staging/media/meson/vdec/codec_vp9.c
+index 897f5d7a6aad..bfc312ec2a56 100644
+--- a/drivers/staging/media/meson/vdec/codec_vp9.c
++++ b/drivers/staging/media/meson/vdec/codec_vp9.c
+@@ -458,12 +458,6 @@ struct codec_vp9 {
+ struct list_head ref_frames_list;
+ u32 frames_num;
+
+- /* In case of downsampling (decoding with FBC but outputting in NV12M),
+- * we need to allocate additional buffers for FBC.
+- */
+- void *fbc_buffer_vaddr[MAX_REF_PIC_NUM];
+- dma_addr_t fbc_buffer_paddr[MAX_REF_PIC_NUM];
+-
+ int ref_frame_map[REF_FRAMES];
+ int next_ref_frame_map[REF_FRAMES];
+ struct vp9_frame *frame_refs[REFS_PER_FRAME];
+@@ -901,11 +895,8 @@ static void codec_vp9_set_sao(struct amvdec_session *sess,
+ buf_y_paddr =
+ vb2_dma_contig_plane_dma_addr(vb, 0);
+
+- if (codec_hevc_use_fbc(sess->pixfmt_cap, vp9->is_10bit)) {
+- val = amvdec_read_dos(core, HEVC_SAO_CTRL5) & ~0xff0200;
+- amvdec_write_dos(core, HEVC_SAO_CTRL5, val);
+- amvdec_write_dos(core, HEVC_CM_BODY_START_ADDR, buf_y_paddr);
+- }
++ if (codec_hevc_use_fbc(sess->pixfmt_cap, vp9->is_10bit))
++ amvdec_write_dos(core, HEVC_CM_BODY_START_ADDR, buf_y_paddr);
+
+ if (sess->pixfmt_cap == V4L2_PIX_FMT_NV12M) {
+ buf_y_paddr =
+@@ -920,8 +911,12 @@ static void codec_vp9_set_sao(struct amvdec_session *sess,
+
+ 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]);
++ dma_addr_t header_adr;
++ if (codec_hevc_use_downsample(sess->pixfmt_cap, vp9->is_10bit))
++ header_adr = vp9->common.mmu_header_paddr[vb->index];
++ else
++ header_adr = vb2_dma_contig_plane_dma_addr(vb, 0);
++ amvdec_write_dos(core, HEVC_CM_HEADER_START_ADDR, header_adr);
+ /* use HEVC_CM_HEADER_START_ADDR */
+ amvdec_write_dos_bits(core, HEVC_SAO_CTRL5, BIT(10));
+ }
+@@ -1148,9 +1143,13 @@ static void codec_vp9_set_mc(struct amvdec_session *sess,
+ {
+ struct amvdec_core *core = sess->core;
+ u32 scale = 0;
++ u32 use_mmu;
+ u32 sz;
+ int i;
+
++ use_mmu = codec_hevc_use_mmu(core->platform->revision,
++ sess->pixfmt_cap, vp9->is_10bit);
++
+ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, 1);
+ codec_vp9_set_refs(sess, vp9);
+ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+@@ -1166,8 +1165,9 @@ static void codec_vp9_set_mc(struct amvdec_session *sess,
+ vp9->frame_refs[i]->height != vp9->height)
+ scale = 1;
+
+- sz = amvdec_am21c_body_size(vp9->frame_refs[i]->width,
+- vp9->frame_refs[i]->height);
++ sz = amvdec_amfbc_body_size(vp9->frame_refs[i]->width,
++ vp9->frame_refs[i]->height,
++ vp9->is_10bit, use_mmu);
+
+ amvdec_write_dos(core, VP9D_MPP_REFINFO_DATA,
+ vp9->frame_refs[i]->width);
+@@ -1283,7 +1283,8 @@ static void codec_vp9_process_frame(struct amvdec_session *sess)
+ 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);
++ &vp9->cur_frame->vbuf->vb2_buf,
++ vp9->is_10bit);
+
+ intra_only = param->p.show_frame ? 0 : param->p.intra_only;
+
+@@ -2132,7 +2133,8 @@ static irqreturn_t codec_vp9_threaded_isr(struct amvdec_session *sess)
+
+ codec_vp9_fetch_rpm(sess);
+ if (codec_vp9_process_rpm(vp9)) {
+- amvdec_src_change(sess, vp9->width, vp9->height, 16);
++ amvdec_src_change(sess, vp9->width, vp9->height, 16,
++ vp9->is_10bit ? 10 : 8);
+
+ /* No frame is actually processed */
+ vp9->cur_frame = NULL;
+diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
+index e18334e57fc0..610a92b9f6f2 100644
+--- a/drivers/staging/media/meson/vdec/esparser.c
++++ b/drivers/staging/media/meson/vdec/esparser.c
+@@ -319,6 +319,7 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
+ if (esparser_vififo_get_free_space(sess) < payload_size ||
+ atomic_read(&sess->esparser_queued_bufs) >= num_dst_bufs)
+ return -EAGAIN;
++
+ } else if (esparser_vififo_get_free_space(sess) < payload_size) {
+ return -EAGAIN;
+ }
+diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h
+index 0906b8fb5cc6..a48170fe4cff 100644
+--- a/drivers/staging/media/meson/vdec/vdec.h
++++ b/drivers/staging/media/meson/vdec/vdec.h
+@@ -244,6 +244,7 @@ struct amvdec_session {
+ u32 width;
+ u32 height;
+ u32 colorspace;
++ u32 bitdepth;
+ u8 ycbcr_enc;
+ u8 quantization;
+ u8 xfer_func;
+diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.c b/drivers/staging/media/meson/vdec/vdec_helpers.c
+index 203d7afa085d..23a69c51c634 100644
+--- a/drivers/staging/media/meson/vdec/vdec_helpers.c
++++ b/drivers/staging/media/meson/vdec/vdec_helpers.c
+@@ -50,32 +50,40 @@ void amvdec_write_parser(struct amvdec_core *core, u32 reg, u32 val)
+ }
+ EXPORT_SYMBOL_GPL(amvdec_write_parser);
+
+-/* 4 KiB per 64x32 block */
+-u32 amvdec_am21c_body_size(u32 width, u32 height)
++/* AMFBC body is made out of 64x32 blocks with varying block size */
++u32 amvdec_amfbc_body_size(u32 width, u32 height, u32 is_10bit, u32 use_mmu)
+ {
+ u32 width_64 = ALIGN(width, 64) / 64;
+ u32 height_32 = ALIGN(height, 32) / 32;
++ u32 blk_size = 4096;
+
+- return SZ_4K * width_64 * height_32;
++ if (!is_10bit) {
++ if (use_mmu)
++ blk_size = 3200;
++ else
++ blk_size = 3072;
++ }
++
++ return blk_size * width_64 * height_32;
+ }
+-EXPORT_SYMBOL_GPL(amvdec_am21c_body_size);
++EXPORT_SYMBOL_GPL(amvdec_amfbc_body_size);
+
+ /* 32 bytes per 128x64 block */
+-u32 amvdec_am21c_head_size(u32 width, u32 height)
++u32 amvdec_amfbc_head_size(u32 width, u32 height)
+ {
+ u32 width_128 = ALIGN(width, 128) / 128;
+ u32 height_64 = ALIGN(height, 64) / 64;
+
+ return 32 * width_128 * height_64;
+ }
+-EXPORT_SYMBOL_GPL(amvdec_am21c_head_size);
++EXPORT_SYMBOL_GPL(amvdec_amfbc_head_size);
+
+-u32 amvdec_am21c_size(u32 width, u32 height)
++u32 amvdec_amfbc_size(u32 width, u32 height, u32 is_10bit, u32 use_mmu)
+ {
+- return ALIGN(amvdec_am21c_body_size(width, height) +
+- amvdec_am21c_head_size(width, height), SZ_64K);
++ return ALIGN(amvdec_amfbc_body_size(width, height, is_10bit, use_mmu) +
++ amvdec_amfbc_head_size(width, height), SZ_64K);
+ }
+-EXPORT_SYMBOL_GPL(amvdec_am21c_size);
++EXPORT_SYMBOL_GPL(amvdec_amfbc_size);
+
+ static int canvas_alloc(struct amvdec_session *sess, u8 *canvas_id)
+ {
+@@ -436,7 +444,7 @@ void amvdec_set_par_from_dar(struct amvdec_session *sess,
+ EXPORT_SYMBOL_GPL(amvdec_set_par_from_dar);
+
+ void amvdec_src_change(struct amvdec_session *sess, u32 width,
+- u32 height, u32 dpb_size)
++ u32 height, u32 dpb_size, u32 bitdepth)
+ {
+ static const struct v4l2_event ev = {
+ .type = V4L2_EVENT_SOURCE_CHANGE,
+@@ -444,25 +452,27 @@ void amvdec_src_change(struct amvdec_session *sess, u32 width,
+
+ v4l2_ctrl_s_ctrl(sess->ctrl_min_buf_capture, dpb_size);
+
++ sess->bitdepth = bitdepth;
++
+ /*
+ * Check if the capture queue is already configured well for our
+- * usecase. If so, keep decoding with it and do not send the event
++ * usecase. If so, keep decoding with it.
+ */
+ if (sess->streamon_cap &&
+ sess->width == width &&
+ sess->height == height &&
+ dpb_size <= sess->num_dst_bufs) {
+ sess->fmt_out->codec_ops->resume(sess);
+- return;
+- }
++ } else {
++ sess->status = STATUS_NEEDS_RESUME;
++ sess->changed_format = 0;
++ }
+
+- sess->changed_format = 0;
+ sess->width = width;
+ sess->height = height;
+- sess->status = STATUS_NEEDS_RESUME;
+
+- dev_dbg(sess->core->dev, "Res. changed (%ux%u), DPB size %u\n",
+- width, height, dpb_size);
++ dev_dbg(sess->core->dev, "Res. changed (%ux%u), DPB %u, bitdepth %u\n",
++ width, height, dpb_size, bitdepth);
+ v4l2_event_queue_fh(&sess->fh, &ev);
+ }
+ EXPORT_SYMBOL_GPL(amvdec_src_change);
+diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.h b/drivers/staging/media/meson/vdec/vdec_helpers.h
+index 88137d15aa3a..fca4251f7599 100644
+--- a/drivers/staging/media/meson/vdec/vdec_helpers.h
++++ b/drivers/staging/media/meson/vdec/vdec_helpers.h
+@@ -27,9 +27,10 @@ void amvdec_clear_dos_bits(struct amvdec_core *core, u32 reg, u32 val);
+ u32 amvdec_read_parser(struct amvdec_core *core, u32 reg);
+ void amvdec_write_parser(struct amvdec_core *core, u32 reg, u32 val);
+
+-u32 amvdec_am21c_body_size(u32 width, u32 height);
+-u32 amvdec_am21c_head_size(u32 width, u32 height);
+-u32 amvdec_am21c_size(u32 width, u32 height);
++/* Helpers for the Amlogic compressed framebuffer format */
++u32 amvdec_amfbc_body_size(u32 width, u32 height, u32 is_10bit, u32 use_mmu);
++u32 amvdec_amfbc_head_size(u32 width, u32 height);
++u32 amvdec_amfbc_size(u32 width, u32 height, u32 is_10bit, u32 use_mmu);
+
+ /**
+ * amvdec_dst_buf_done_idx() - Signal that a buffer is done decoding
+@@ -77,9 +78,10 @@ void amvdec_set_par_from_dar(struct amvdec_session *sess,
+ * @width: picture width detected by the hardware
+ * @height: picture height detected by the hardware
+ * @dpb_size: Decoded Picture Buffer size (= amount of buffers for decoding)
++ * @bitdepth: Bit depth (usually 10 or 8) of the coded content
+ */
+ void amvdec_src_change(struct amvdec_session *sess, u32 width,
+- u32 height, u32 dpb_size);
++ u32 height, u32 dpb_size, u32 bitdepth);
+
+ /**
+ * amvdec_abort() - Abort the current decoding session
+--
+2.35.1
+