summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authoryjun2022-04-25 11:46:44 +0800
committeryjun2022-04-25 11:46:44 +0800
commitc125b79690b319c3348cb88c768ad0bb718643e8 (patch)
treee91c2a97b9fa94eab72a615379b6f9372de1fbb6
parent6c5931fb034098e8aa111835b9817f75a4a69bec (diff)
downloadaur-c125b79690b319c3348cb88c768ad0bb718643e8.tar.gz
updpkg: linux-phicomm-n1 5.17.4 && some meson-vdec, hdmix, mmc optimation patches
-rw-r--r--.SRCINFO46
-rw-r--r--.gitignore1
-rw-r--r--PKGBUILD72
-rw-r--r--config2
-rw-r--r--general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch29
-rw-r--r--general-gpu-drm-add-new-display-resolution-2560x1440.patch76
-rw-r--r--general-hdmi-codec-reorder-channel-allocation-list.patch202
-rw-r--r--general-increase-cma-pool-896MB.patch56
-rw-r--r--general-memory-marked-nomap.patch38
-rw-r--r--general-meson-aiu-Fix-HDMI-codec-control-selection.patch233
-rw-r--r--general-meson-gx-mmc-fix-deferred-probing.patch35
-rw-r--r--general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch59
-rw-r--r--general-meson-vdec-add-HEVC-decode-codec.patch1609
-rw-r--r--general-meson-vdec-add-handling-to-HEVC-decoder-.patch157
-rw-r--r--general-meson-vdec-check-if-parser-has-really-parser.patch51
-rw-r--r--general-meson-vdec-improve-mmu-and-fbc-handling-.patch586
-rw-r--r--general-meson-vdec-remove-redundant-if-statement.patch29
-rw-r--r--general-revert-meson_drv_shutdown.patch25
-rw-r--r--general-sound-soc-remove-mono-channel-as-it-curren.patch37
-rw-r--r--general-usb-core-improve-handling-of-hubs-with-no-ports.patch54
20 files changed, 3384 insertions, 13 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 2f58252b01f7..b5291374e6b8 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = linux-phicomm-n1
- pkgver = 5.17.3
- pkgrel = 2
+ pkgver = 5.17.4
+ pkgrel = 1
url = https://www.kernel.org/
arch = aarch64
license = GPL2
@@ -23,16 +23,48 @@ pkgbase = linux-phicomm-n1
source = 90-linux.hook
source = 02-revert-TEXT_OFFSET-deletion.patch
source = 03-make-proc-cpuinfo-consistent-on-arm64-and-arm.patch
- source = https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-5.17.3.xz
+ source = general-meson-gx-mmc-fix-deferred-probing.patch
+ source = general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch
+ source = general-meson-aiu-Fix-HDMI-codec-control-selection.patch
+ source = general-gpu-drm-add-new-display-resolution-2560x1440.patch
+ source = general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch
+ source = general-hdmi-codec-reorder-channel-allocation-list.patch
+ source = general-revert-meson_drv_shutdown.patch
+ source = general-meson-vdec-remove-redundant-if-statement.patch
+ source = general-meson-vdec-add-HEVC-decode-codec.patch
+ source = general-meson-vdec-check-if-parser-has-really-parser.patch
+ source = general-meson-vdec-add-handling-to-HEVC-decoder-.patch
+ source = general-meson-vdec-improve-mmu-and-fbc-handling-.patch
+ source = general-memory-marked-nomap.patch
+ source = general-usb-core-improve-handling-of-hubs-with-no-ports.patch
+ source = general-increase-cma-pool-896MB.patch
+ source = general-sound-soc-remove-mono-channel-as-it-curren.patch
+ source = https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-5.17.4.xz
md5sums = 07321a70a48d062cebd0358132f11771
md5sums = 14b9c040a7a9320ea91a779cd8f14f02
- md5sums = ea6fbed2433a6cfd22a7cff33f23414b
+ md5sums = f9877f4fee835a3b5880d59855c356e0
md5sums = 30130b4dcd8ad4364ddbfd56c3058d5e
md5sums = ce6c81ad1ad1f8b333fd6077d47abdaf
md5sums = 0d0435888ecad675870ecda4045a9d45
md5sums = 614a77d2f4c92817ab4e5f989f9a76c9
md5sums = 7a18066683f3351b2bbd2653db783f80
- md5sums = 72b09a90defb8367b4f2d971af2773f3
+ md5sums = 55f160f63da3d642dc274b9830622187
+ md5sums = 679e90aa8d00df767dbd9315238bcecc
+ md5sums = f4573afe0c73b90e48186c32fd374040
+ md5sums = d590f2af9d150f00bf9e5e4239e16105
+ md5sums = 116c87fd40aa252e6702ad61af27b824
+ md5sums = d3ce443630c8c9768637d4b123dd8c70
+ md5sums = 06d09873c61527e9488bf65973dc96c5
+ md5sums = c7f753fbb98202b9148ad7b4aed8ecad
+ md5sums = 87d3fc334bc0309968948a084a1c3459
+ md5sums = 90b82b89d96283e1f03d302676ecfe78
+ md5sums = eed9d1f3957af438f1c60d3d405dbb2d
+ md5sums = a4643fd62a9bf5b042d41cd0ddfa6906
+ md5sums = 3c2bada63ca2427c78e224db5ded7c09
+ md5sums = 425ec378dc6973e6185895d7a13a8d66
+ md5sums = 38e3b2c9490ac3b8201db37e73ff2534
+ md5sums = dfcd0e763405a425b3f277394ed65a5d
+ md5sums = b76bfbb5308a55f951ec17365fe3560d
pkgname = linux-phicomm-n1
pkgdesc = The Linux kernel and modules - AArch64 kernel for Phicomm N1
@@ -42,7 +74,7 @@ pkgname = linux-phicomm-n1
depends = kmod
depends = mkinitcpio>=0.7
optdepends = crda: to set the correct wireless channels of your country
- provides = linux=5.17.3
+ provides = linux=5.17.4
provides = WIREGUARD-MODULE
conflicts = linux
replaces = linux-armv8
@@ -50,5 +82,5 @@ pkgname = linux-phicomm-n1
pkgname = linux-phicomm-n1-headers
pkgdesc = Header files and scripts for building modules for linux kernel - AArch64 kernel for Phicomm N1
- provides = linux-headers=5.17.3
+ provides = linux-headers=5.17.4
conflicts = linux-headers
diff --git a/.gitignore b/.gitignore
index cec918efe176..ff05e4e3c4fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ pkg*.xz
TODO
lost+found/
set-source-mirror.sh
+patches
diff --git a/PKGBUILD b/PKGBUILD
index 3505b9a882e3..05a8b116e53a 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -11,12 +11,15 @@
# 02-revert-TEXT_OFFSET-deletion.patch:
# https://github.com/SuzukiHonoka/s905d-kernel-precompiled/tree/master/patch
+# Armbina patches
+# https://github.com/armbian/build/tree/master/patch/kernel/archive/meson64-5.17
+
pkgbase=linux-phicomm-n1
_srcname=linux-5.17
_kernelname=${pkgbase#linux}
_desc="AArch64 kernel for Phicomm N1"
-pkgver=5.17.3
-pkgrel=2
+pkgver=5.17.4
+pkgrel=1
arch=('aarch64')
url="https://www.kernel.org/"
license=('GPL2')
@@ -32,20 +35,54 @@ source=(
'60-linux.hook'
'90-linux.hook'
'02-revert-TEXT_OFFSET-deletion.patch'
- '03-make-proc-cpuinfo-consistent-on-arm64-and-arm.patch')
+ '03-make-proc-cpuinfo-consistent-on-arm64-and-arm.patch'
+ # patches from armbian
+ "general-meson-gx-mmc-fix-deferred-probing.patch"
+ "general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch"
+ "general-meson-aiu-Fix-HDMI-codec-control-selection.patch"
+ "general-gpu-drm-add-new-display-resolution-2560x1440.patch"
+ "general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch"
+ "general-hdmi-codec-reorder-channel-allocation-list.patch"
+ "general-revert-meson_drv_shutdown.patch"
+ "general-meson-vdec-remove-redundant-if-statement.patch"
+ "general-meson-vdec-add-HEVC-decode-codec.patch"
+ "general-meson-vdec-check-if-parser-has-really-parser.patch"
+ "general-meson-vdec-add-handling-to-HEVC-decoder-.patch"
+ "general-meson-vdec-improve-mmu-and-fbc-handling-.patch"
+ "general-memory-marked-nomap.patch"
+ "general-usb-core-improve-handling-of-hubs-with-no-ports.patch"
+ "general-increase-cma-pool-896MB.patch"
+ "general-sound-soc-remove-mono-channel-as-it-curren.patch"
+)
[[ ${pkgver##*.} != 0 ]] && \
source+=("https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-${pkgver}.xz")
md5sums=('07321a70a48d062cebd0358132f11771'
'14b9c040a7a9320ea91a779cd8f14f02'
- 'ea6fbed2433a6cfd22a7cff33f23414b'
+ 'f9877f4fee835a3b5880d59855c356e0'
'30130b4dcd8ad4364ddbfd56c3058d5e'
'ce6c81ad1ad1f8b333fd6077d47abdaf'
'0d0435888ecad675870ecda4045a9d45'
'614a77d2f4c92817ab4e5f989f9a76c9'
'7a18066683f3351b2bbd2653db783f80'
- '72b09a90defb8367b4f2d971af2773f3')
+ '55f160f63da3d642dc274b9830622187'
+ '679e90aa8d00df767dbd9315238bcecc'
+ 'f4573afe0c73b90e48186c32fd374040'
+ 'd590f2af9d150f00bf9e5e4239e16105'
+ '116c87fd40aa252e6702ad61af27b824'
+ 'd3ce443630c8c9768637d4b123dd8c70'
+ '06d09873c61527e9488bf65973dc96c5'
+ 'c7f753fbb98202b9148ad7b4aed8ecad'
+ '87d3fc334bc0309968948a084a1c3459'
+ '90b82b89d96283e1f03d302676ecfe78'
+ 'eed9d1f3957af438f1c60d3d405dbb2d'
+ 'a4643fd62a9bf5b042d41cd0ddfa6906'
+ '3c2bada63ca2427c78e224db5ded7c09'
+ '425ec378dc6973e6185895d7a13a8d66'
+ '38e3b2c9490ac3b8201db37e73ff2534'
+ 'dfcd0e763405a425b3f277394ed65a5d'
+ 'b76bfbb5308a55f951ec17365fe3560d')
prepare() {
cd ${_srcname}
@@ -64,6 +101,31 @@ prepare() {
# Make proc cpuinfo consistent on arm64 and arm
patch -p1 < "${srcdir}/03-make-proc-cpuinfo-consistent-on-arm64-and-arm.patch"
+ # Patches from Armbian
+ # MMC
+ patch -p1 < "${srcdir}/general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch"
+ patch -p1 < "${srcdir}/general-meson-gx-mmc-fix-deferred-probing.patch"
+
+ # DRM and HDMI
+ patch -p1 < "${srcdir}/general-meson-aiu-Fix-HDMI-codec-control-selection.patch"
+ patch -p1 < "${srcdir}/general-gpu-drm-add-new-display-resolution-2560x1440.patch"
+ patch -p1 < "${srcdir}/general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch"
+ patch -p1 < "${srcdir}/general-hdmi-codec-reorder-channel-allocation-list.patch"
+ patch -p1 < "${srcdir}/general-revert-meson_drv_shutdown.patch"
+
+ # MESON-VDEC
+ patch -p1 < "${srcdir}/general-meson-vdec-remove-redundant-if-statement.patch"
+ patch -p1 < "${srcdir}/general-meson-vdec-add-HEVC-decode-codec.patch"
+ patch -p1 < "${srcdir}/general-meson-vdec-check-if-parser-has-really-parser.patch"
+ patch -p1 < "${srcdir}/general-meson-vdec-add-handling-to-HEVC-decoder-.patch"
+ patch -p1 < "${srcdir}/general-meson-vdec-improve-mmu-and-fbc-handling-.patch"
+
+ # MISC
+ patch -p1 < "${srcdir}/general-memory-marked-nomap.patch"
+ patch -p1 < "${srcdir}/general-usb-core-improve-handling-of-hubs-with-no-ports.patch"
+ patch -p1 < "${srcdir}/general-increase-cma-pool-896MB.patch"
+ patch -p1 < "${srcdir}/general-sound-soc-remove-mono-channel-as-it-curren.patch"
+
# Dts for Phicomm-N1
target_dts="meson-gxl-s905d-phicomm-n1.dts"
cat "${srcdir}/${target_dts}" > "./arch/arm64/boot/dts/amlogic/${target_dts}"
diff --git a/config b/config
index 5e942f3aa087..3ec561f92d52 100644
--- a/config
+++ b/config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 5.17.3-1 Kernel Configuration
+# Linux/arm64 5.17.4-1 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="gcc (GCC) 11.2.0"
CONFIG_CC_IS_GCC=y
diff --git a/general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch b/general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch
new file mode 100644
index 000000000000..07ee4d3fbfd1
--- /dev/null
+++ b/general-drm-dw-hdmi-call-hdmi_set_cts_n-after-clock.patch
@@ -0,0 +1,29 @@
+From 192ff185a6f85f2519cc4b97aa015a836f5a8fbb Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <jonas@kwiboo.se>
+Date: Mon, 9 Jul 2018 21:25:15 +0200
+Subject: [PATCH 10/84] TEMP: drm: dw-hdmi: call hdmi_set_cts_n after clock is
+ enabled
+
+---
+ drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+index 521d689..e4ab11a 100644
+--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+@@ -688,6 +688,11 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable)
+ else
+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
++
++ if (enable) {
++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
++ }
+ }
+
+ static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi)
+--
+2.7.1
+
diff --git a/general-gpu-drm-add-new-display-resolution-2560x1440.patch b/general-gpu-drm-add-new-display-resolution-2560x1440.patch
new file mode 100644
index 000000000000..4dadf47dcedf
--- /dev/null
+++ b/general-gpu-drm-add-new-display-resolution-2560x1440.patch
@@ -0,0 +1,76 @@
+From 9175674ca107a9090936d7373927567f41d1ae7e Mon Sep 17 00:00:00 2001
+From: Dongjin Kim <tobetter@gmail.com>
+Date: Thu, 10 Sep 2020 11:01:33 +0900
+Subject: [PATCH] ODROID-COMMON: gpu/drm: add new display resolution 2560x1440
+
+Signed-off-by: Joy Cho <joy.cho@hardkernel.com>
+Signed-off-by: Dongjin Kim <tobetter@gmail.com>
+---
+ drivers/gpu/drm/meson/meson_vclk.c | 18 ++++++++++++++++++
+ drivers/gpu/drm/meson/meson_venc.c | 5 +++--
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
+index 2a82119eb58e..eb4c251d79b7 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.c
++++ b/drivers/gpu/drm/meson/meson_vclk.c
+@@ -357,6 +357,8 @@ enum {
+ MESON_VCLK_HDMI_594000,
+ /* 2970 /1 /1 /1 /5 /1 => /1 /2 */
+ MESON_VCLK_HDMI_594000_YUV420,
++/* 4830 /2 /1 /2 /5 /1 => /1 /1 */
++ MESON_VCLK_HDMI_241500,
+ };
+
+ struct meson_vclk_params {
+@@ -467,6 +469,18 @@ struct meson_vclk_params {
+ .vid_pll_div = VID_PLL_DIV_5,
+ .vclk_div = 1,
+ },
++ [MESON_VCLK_HDMI_241500] = {
++ .pll_freq = 4830000,
++ .phy_freq = 2415000,
++ .venc_freq = 241500,
++ .vclk_freq = 241500,
++ .pixel_freq = 241500,
++ .pll_od1 = 2,
++ .pll_od2 = 1,
++ .pll_od3 = 2,
++ .vid_pll_div = VID_PLL_DIV_5,
++ .vclk_div = 1,
++ },
+ { /* sentinel */ },
+ };
+
+@@ -873,6 +887,10 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+ m = 0xf7;
+ frac = vic_alternate_clock ? 0x8148 : 0x10000;
+ break;
++ case 4830000:
++ m = 0xc9;
++ frac = 0xd560;
++ break;
+ }
+
+ meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
+index 3c55ed003359..559ab3b5e212 100644
+--- a/drivers/gpu/drm/meson/meson_venc.c
++++ b/drivers/gpu/drm/meson/meson_venc.c
+@@ -866,10 +866,11 @@ meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
+ DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
+ return MODE_BAD;
+
+- if (mode->hdisplay < 640 || mode->hdisplay > 1920)
++ /* support higher resolution than 1920x1080 */
++ if (mode->hdisplay < 640 || mode->hdisplay > 2560)
+ return MODE_BAD_HVALUE;
+
+- if (mode->vdisplay < 480 || mode->vdisplay > 1200)
++ if (mode->vdisplay < 480 || mode->vdisplay > 1600)
+ return MODE_BAD_VVALUE;
+
+ return MODE_OK;
+--
+2.35.1
+
diff --git a/general-hdmi-codec-reorder-channel-allocation-list.patch b/general-hdmi-codec-reorder-channel-allocation-list.patch
new file mode 100644
index 000000000000..a48b290d4ef2
--- /dev/null
+++ b/general-hdmi-codec-reorder-channel-allocation-list.patch
@@ -0,0 +1,202 @@
+From dd29d3d05631c4afdab56fb696424565a4afefba Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <jonas@kwiboo.se>
+Date: Sun, 23 Dec 2018 02:24:38 +0100
+Subject: [PATCH 53/90] WIP: ASoC: hdmi-codec: reorder channel allocation list
+
+Wrong channel allocation is selected by hdmi_codec_get_ch_alloc_table_idx().
+
+E.g when ELD reports FL|FR|LFE|FC|RL|RR or FL|FR|LFE|FC|RL|RR|RC|RLC|RRC
+
+ca_id 0x01 with speaker mask FL|FR|LFE gets selected instead of
+ca_id 0x03 with speaker mask FL|FR|LFE|FC for 4 channels
+
+and
+
+ca_id 0x04 with speaker mask FL|FR|RC gets selected instead of
+ca_id 0x0b with speaker mask FL|FR|LFE|FC|RL|RR for 6 channels
+
+Fix this by reorder the channel allocation list with
+most specific speaker mask at the top.
+
+Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
+---
+ sound/soc/codecs/hdmi-codec.c | 140 +++++++++++++++++++---------------
+ 1 file changed, 77 insertions(+), 63 deletions(-)
+
+diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
+index b07607a9ecea..a12015471ea2 100644
+--- a/sound/soc/codecs/hdmi-codec.c
++++ b/sound/soc/codecs/hdmi-codec.c
+@@ -188,84 +188,97 @@ static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
+ /*
+ * hdmi_codec_channel_alloc: speaker configuration available for CEA
+ *
+- * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct
++ * This is an ordered list where ca_id must exist in hdmi_codec_8ch_chmaps
+ * The preceding ones have better chances to be selected by
+ * hdmi_codec_get_ch_alloc_table_idx().
+ */
+ static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
+ { .ca_id = 0x00, .n_ch = 2,
+- .mask = FL | FR},
+- /* 2.1 */
+- { .ca_id = 0x01, .n_ch = 4,
+- .mask = FL | FR | LFE},
+- /* Dolby Surround */
++ .mask = FL | FR },
++ { .ca_id = 0x03, .n_ch = 4,
++ .mask = FL | FR | LFE | FC },
+ { .ca_id = 0x02, .n_ch = 4,
+ .mask = FL | FR | FC },
+- /* surround51 */
++ { .ca_id = 0x01, .n_ch = 4,
++ .mask = FL | FR | LFE },
+ { .ca_id = 0x0b, .n_ch = 6,
+- .mask = FL | FR | LFE | FC | RL | RR},
+- /* surround40 */
+- { .ca_id = 0x08, .n_ch = 6,
+- .mask = FL | FR | RL | RR },
+- /* surround41 */
+- { .ca_id = 0x09, .n_ch = 6,
+- .mask = FL | FR | LFE | RL | RR },
+- /* surround50 */
++ .mask = FL | FR | LFE | FC | RL | RR },
+ { .ca_id = 0x0a, .n_ch = 6,
+ .mask = FL | FR | FC | RL | RR },
+- /* 6.1 */
+- { .ca_id = 0x0f, .n_ch = 8,
+- .mask = FL | FR | LFE | FC | RL | RR | RC },
+- /* surround71 */
++ { .ca_id = 0x09, .n_ch = 6,
++ .mask = FL | FR | LFE | RL | RR },
++ { .ca_id = 0x08, .n_ch = 6,
++ .mask = FL | FR | RL | RR },
++ { .ca_id = 0x07, .n_ch = 6,
++ .mask = FL | FR | LFE | FC | RC },
++ { .ca_id = 0x06, .n_ch = 6,
++ .mask = FL | FR | FC | RC },
++ { .ca_id = 0x05, .n_ch = 6,
++ .mask = FL | FR | LFE | RC },
++ { .ca_id = 0x04, .n_ch = 6,
++ .mask = FL | FR | RC },
+ { .ca_id = 0x13, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },
+- /* others */
+- { .ca_id = 0x03, .n_ch = 8,
+- .mask = FL | FR | LFE | FC },
+- { .ca_id = 0x04, .n_ch = 8,
+- .mask = FL | FR | RC},
+- { .ca_id = 0x05, .n_ch = 8,
+- .mask = FL | FR | LFE | RC },
+- { .ca_id = 0x06, .n_ch = 8,
+- .mask = FL | FR | FC | RC },
+- { .ca_id = 0x07, .n_ch = 8,
+- .mask = FL | FR | LFE | FC | RC },
+- { .ca_id = 0x0c, .n_ch = 8,
+- .mask = FL | FR | RC | RL | RR },
+- { .ca_id = 0x0d, .n_ch = 8,
+- .mask = FL | FR | LFE | RL | RR | RC },
+- { .ca_id = 0x0e, .n_ch = 8,
+- .mask = FL | FR | FC | RL | RR | RC },
+- { .ca_id = 0x10, .n_ch = 8,
+- .mask = FL | FR | RL | RR | RLC | RRC },
+- { .ca_id = 0x11, .n_ch = 8,
+- .mask = FL | FR | LFE | RL | RR | RLC | RRC },
++ { .ca_id = 0x1f, .n_ch = 8,
++ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
+ { .ca_id = 0x12, .n_ch = 8,
+ .mask = FL | FR | FC | RL | RR | RLC | RRC },
+- { .ca_id = 0x14, .n_ch = 8,
+- .mask = FL | FR | FLC | FRC },
+- { .ca_id = 0x15, .n_ch = 8,
+- .mask = FL | FR | LFE | FLC | FRC },
+- { .ca_id = 0x16, .n_ch = 8,
+- .mask = FL | FR | FC | FLC | FRC },
+- { .ca_id = 0x17, .n_ch = 8,
+- .mask = FL | FR | LFE | FC | FLC | FRC },
+- { .ca_id = 0x18, .n_ch = 8,
+- .mask = FL | FR | RC | FLC | FRC },
+- { .ca_id = 0x19, .n_ch = 8,
+- .mask = FL | FR | LFE | RC | FLC | FRC },
+- { .ca_id = 0x1a, .n_ch = 8,
+- .mask = FL | FR | RC | FC | FLC | FRC },
+- { .ca_id = 0x1b, .n_ch = 8,
+- .mask = FL | FR | LFE | RC | FC | FLC | FRC },
+- { .ca_id = 0x1c, .n_ch = 8,
+- .mask = FL | FR | RL | RR | FLC | FRC },
+- { .ca_id = 0x1d, .n_ch = 8,
+- .mask = FL | FR | LFE | RL | RR | FLC | FRC },
+ { .ca_id = 0x1e, .n_ch = 8,
+ .mask = FL | FR | FC | RL | RR | FLC | FRC },
+- { .ca_id = 0x1f, .n_ch = 8,
+- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
++ { .ca_id = 0x11, .n_ch = 8,
++ .mask = FL | FR | LFE | RL | RR | RLC | RRC },
++ { .ca_id = 0x1d, .n_ch = 8,
++ .mask = FL | FR | LFE | RL | RR | FLC | FRC },
++ { .ca_id = 0x10, .n_ch = 8,
++ .mask = FL | FR | RL | RR | RLC | RRC },
++ { .ca_id = 0x1c, .n_ch = 8,
++ .mask = FL | FR | RL | RR | FLC | FRC },
++ { .ca_id = 0x0f, .n_ch = 8,
++ .mask = FL | FR | LFE | FC | RL | RR | RC },
++ { .ca_id = 0x1b, .n_ch = 8,
++ .mask = FL | FR | LFE | RC | FC | FLC | FRC },
++ { .ca_id = 0x0e, .n_ch = 8,
++ .mask = FL | FR | FC | RL | RR | RC },
++ { .ca_id = 0x1a, .n_ch = 8,
++ .mask = FL | FR | RC | FC | FLC | FRC },
++ { .ca_id = 0x0d, .n_ch = 8,
++ .mask = FL | FR | LFE | RL | RR | RC },
++ { .ca_id = 0x19, .n_ch = 8,
++ .mask = FL | FR | LFE | RC | FLC | FRC },
++ { .ca_id = 0x0c, .n_ch = 8,
++ .mask = FL | FR | RC | RL | RR },
++ { .ca_id = 0x18, .n_ch = 8,
++ .mask = FL | FR | RC | FLC | FRC },
++ { .ca_id = 0x17, .n_ch = 8,
++ .mask = FL | FR | LFE | FC | FLC | FRC },
++ { .ca_id = 0x16, .n_ch = 8,
++ .mask = FL | FR | FC | FLC | FRC },
++ { .ca_id = 0x15, .n_ch = 8,
++ .mask = FL | FR | LFE | FLC | FRC },
++ { .ca_id = 0x14, .n_ch = 8,
++ .mask = FL | FR | FLC | FRC },
++ { .ca_id = 0x0b, .n_ch = 8,
++ .mask = FL | FR | LFE | FC | RL | RR },
++ { .ca_id = 0x0a, .n_ch = 8,
++ .mask = FL | FR | FC | RL | RR },
++ { .ca_id = 0x09, .n_ch = 8,
++ .mask = FL | FR | LFE | RL | RR },
++ { .ca_id = 0x08, .n_ch = 8,
++ .mask = FL | FR | RL | RR },
++ { .ca_id = 0x07, .n_ch = 8,
++ .mask = FL | FR | LFE | FC | RC },
++ { .ca_id = 0x06, .n_ch = 8,
++ .mask = FL | FR | FC | RC },
++ { .ca_id = 0x05, .n_ch = 8,
++ .mask = FL | FR | LFE | RC },
++ { .ca_id = 0x04, .n_ch = 8,
++ .mask = FL | FR | RC },
++ { .ca_id = 0x03, .n_ch = 8,
++ .mask = FL | FR | LFE | FC },
++ { .ca_id = 0x02, .n_ch = 8,
++ .mask = FL | FR | FC },
++ { .ca_id = 0x01, .n_ch = 8,
++ .mask = FL | FR | LFE },
+ };
+
+ struct hdmi_codec_priv {
+@@ -374,7 +387,8 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+ struct hdmi_codec_priv *hcp = info->private_data;
+
+- map = info->chmap[hcp->chmap_idx].map;
++ if (hcp->chmap_idx != HDMI_CODEC_CHMAP_IDX_UNKNOWN)
++ map = info->chmap[hcp->chmap_idx].map;
+
+ for (i = 0; i < info->max_channels; i++) {
+ if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN)
+--
+2.35.1
+
diff --git a/general-increase-cma-pool-896MB.patch b/general-increase-cma-pool-896MB.patch
new file mode 100644
index 000000000000..fd0911c4ff6b
--- /dev/null
+++ b/general-increase-cma-pool-896MB.patch
@@ -0,0 +1,56 @@
+From 4b6096bb3fd5bdc139a45e022e4a2380ea919dea Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <christianshewitt@gmail.com>
+Date: Sat, 13 Apr 2019 05:41:51 +0000
+Subject: [PATCH 01/90] HACK: set meson-gx cma pool to 896MB
+
+This change sets the CMA pool to a larger 896MB! value for vdec use
+
+Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
+---
+ arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+index aa14ea017a61..99b8916e0c5d 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+@@ -58,7 +58,7 @@ secmon_reserved_bl32: secmon@5300000 {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+- size = <0x0 0x10000000>;
++ size = <0x0 0x38000000>;
+ alignment = <0x0 0x400000>;
+ linux,cma-default;
+ };
+--
+2.35.1
+
+From 18586e3d94827f63903c4cd596a0a06134261c00 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <christianshewitt@gmail.com>
+Date: Wed, 14 Aug 2019 19:58:14 +0000
+Subject: [PATCH 02/90] HACK: set meson-g12 cma pool to 896MB
+
+This change sets the CMA pool to a larger 896MB! value for vdec use
+
+Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
+---
+ arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+index f84d4b489e0b..04da23119ff1 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+@@ -116,7 +116,7 @@ secmon_reserved_bl32: secmon@5300000 {
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+- size = <0x0 0x10000000>;
++ size = <0x0 0x38000000>;
+ alignment = <0x0 0x400000>;
+ linux,cma-default;
+ };
+--
+2.35.1
+
diff --git a/general-memory-marked-nomap.patch b/general-memory-marked-nomap.patch
new file mode 100644
index 000000000000..6f01098af3fb
--- /dev/null
+++ b/general-memory-marked-nomap.patch
@@ -0,0 +1,38 @@
+From 4d11a956070513a173dd9fd0d6e981918a6331e4 Mon Sep 17 00:00:00 2001
+From: Stefan Agner <stefan@agner.ch>
+Date: Wed, 15 Sep 2021 05:00:45 +0000
+Subject: [PATCH 11/90] HACK: of: partial revert of fdt.c changes
+
+This resolves reports similar to the below which are present in dmesg
+since Linux 5.10; which are also causing crashes in some distros:
+
+[ 0.000000] OF: fdt: Reserved memory: failed to reserve memory for node 'secmon@5000000': base 0x0000000005000000, size 3 MiB
+
+Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
+---
+ drivers/of/fdt.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
+index ec315b060cd5..15e9c0c2a2c6 100644
+--- a/drivers/of/fdt.c
++++ b/drivers/of/fdt.c
+@@ -481,15 +481,6 @@ static int __init early_init_dt_reserve_memory_arch(phys_addr_t base,
+ phys_addr_t size, bool nomap)
+ {
+ if (nomap) {
+- /*
+- * If the memory is already reserved (by another region), we
+- * should not allow it to be marked nomap, but don't worry
+- * if the region isn't memory as it won't be mapped.
+- */
+- if (memblock_overlaps_region(&memblock.memory, base, size) &&
+- memblock_is_region_reserved(base, size))
+- return -EBUSY;
+-
+ return memblock_mark_nomap(base, size);
+ }
+ return memblock_reserve(base, size);
+--
+2.35.1
+
diff --git a/general-meson-aiu-Fix-HDMI-codec-control-selection.patch b/general-meson-aiu-Fix-HDMI-codec-control-selection.patch
new file mode 100644
index 000000000000..03428e12142f
--- /dev/null
+++ b/general-meson-aiu-Fix-HDMI-codec-control-selection.patch
@@ -0,0 +1,233 @@
+From 712edc341073c350a11658186609eafd292dbe8a Mon Sep 17 00:00:00 2001
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Date: Sun, 3 Oct 2021 05:35:48 +0000
+Subject: [PATCH 27/90] FROMLIST(v1): ASoC: meson: aiu: Fix HDMI codec control
+ selection
+
+The HDMI controllers on Amlogic Meson SoCs which use the AIU
+audio-controller have two different audio format inputs:
+- I2S which is also the only configuration supported on GXBB, GXL and
+ GXM SoCs since there's no SPDIF support in the DesignWare HDMI
+ controller driver (at the time of writing this)
+- SPDIF can be used optionally, including pass-through formats
+
+Switching between these requires us to set different registers:
+AIU_HDMI_CLK_DATA_CTRL[1:0] "HDMI_DATA_CLK_SEL":
+- 0x0 disables the HDMI output clock
+- 0x1 selects the PCM clock
+- 0x2 selects the AIU clock
+- 0x3 is reserved
+
+AIU_HDMI_CLK_DATA_CTRL[5:4] "HDMI_DATA_SEL":
+- 0x0 outputs constant zero, disables HDMI data
+- 0x1 selects PCM data
+- 0x2 selects AIU I2S data
+- 0x3 is reserved
+
+AIU_CLK_CTRL_MORE[6] "HDMITX_SEL_AOCLKX2":
+- 0x0 selects cts_i958 as AIU clk to hdmi_tx_audio_master_clk
+- 0x1 selects cts_aoclkx2_int as AIU clk to hdmi_tx_audio_master_clk
+
+The Meson8/8b/8m2 vendor driver uses the following settings:
+SPDIF output to the HDMI controller:
+- 0x2 (AIU clock) in AIU_HDMI_CLK_DATA_CTRL[1:0]
+- 0x0 (no HDMI data) in AIU_HDMI_CLK_DATA_CTRL[5:4]
+- 0x0 (using cts_i958 as AIU clk) in AIU_CLK_CTRL_MORE[6]
+I2S output to the HDMI controller:
+- 0x2 (AIU clock) in AIU_HDMI_CLK_DATA_CTRL[1:0]
+- 0x2 (I2S data) in AIU_HDMI_CLK_DATA_CTRL[5:4]
+- 0x0 (using cts_aoclkx2_int as AIU clk) in AIU_CLK_CTRL_MORE[6]
+
+The GXBB/GXL/GXM vendor driver uses the following settings:
+SPDIF output to the HDMI controller:
+- not setting AIU_HDMI_CLK_DATA_CTRL at all
+- 0x0 (using cts_i958 as AIU clk) in AIU_CLK_CTRL_MORE[6]
+I2S output to the HDMI controller:
+- 0x2 (AIU clock) in AIU_HDMI_CLK_DATA_CTRL[1:0]
+- 0x2 (I2S data) in AIU_HDMI_CLK_DATA_CTRL[5:4]
+- 0x0 (using cts_aoclkx2_int as AIU clk) in AIU_CLK_CTRL_MORE[6]
+
+Set the three registers at the same time following what the vendor
+driver does on Meson8/8b/8m2 SoCs. This makes the SPDIF output to the
+HDMI controller work. The entries and order of the entries in the enum
+is not changed on purpose to not break old configurations.
+
+Fixes: b82b734c0e9a7 ("ASoC: meson: aiu: add hdmi codec control support")
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+---
+ sound/soc/meson/aiu-codec-ctrl.c | 108 ++++++++++++++++++++++--------
+ sound/soc/meson/aiu-encoder-i2s.c | 6 --
+ 2 files changed, 80 insertions(+), 34 deletions(-)
+
+diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c
+index c3ea733fce91..2b8575491aeb 100644
+--- a/sound/soc/meson/aiu-codec-ctrl.c
++++ b/sound/soc/meson/aiu-codec-ctrl.c
+@@ -12,14 +12,60 @@
+ #include "aiu.h"
+ #include "meson-codec-glue.h"
+
+-#define CTRL_CLK_SEL GENMASK(1, 0)
+-#define CTRL_DATA_SEL_SHIFT 4
+-#define CTRL_DATA_SEL (0x3 << CTRL_DATA_SEL_SHIFT)
+-
+-static const char * const aiu_codec_ctrl_mux_texts[] = {
+- "DISABLED", "PCM", "I2S",
++#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL GENMASK(1, 0)
++#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_DISABLE 0x0
++#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_PCM 0x1
++#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_AIU 0x2
++#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL GENMASK(5, 4)
++#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_OUTPUT_ZERO 0x0
++#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_PCM_DATA 0x1
++#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_I2S_DATA 0x2
++
++#define AIU_CLK_CTRL_MORE_AMCLK BIT(6)
++
++#define AIU_HDMI_CTRL_MUX_DISABLED 0
++#define AIU_HDMI_CTRL_MUX_PCM 1
++#define AIU_HDMI_CTRL_MUX_I2S 2
++
++static const char * const aiu_codec_hdmi_ctrl_mux_texts[] = {
++ [AIU_HDMI_CTRL_MUX_DISABLED] = "DISABLED",
++ [AIU_HDMI_CTRL_MUX_PCM] = "PCM",
++ [AIU_HDMI_CTRL_MUX_I2S] = "I2S",
+ };
+
++static int aiu_codec_ctrl_mux_get_enum(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_soc_component *component =
++ snd_soc_dapm_kcontrol_component(kcontrol);
++ unsigned int ctrl, more, mux = AIU_HDMI_CTRL_MUX_DISABLED;
++
++ ctrl = snd_soc_component_read(component, AIU_HDMI_CLK_DATA_CTRL);
++ if (FIELD_GET(AIU_HDMI_CLK_DATA_CTRL_CLK_SEL, ctrl) !=
++ AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_AIU) {
++ goto out;
++ }
++
++ more = snd_soc_component_read(component, AIU_CLK_CTRL_MORE);
++ if (FIELD_GET(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, ctrl) ==
++ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_I2S_DATA &&
++ !!(more & AIU_CLK_CTRL_MORE_AMCLK)) {
++ mux = AIU_HDMI_CTRL_MUX_I2S;
++ goto out;
++ }
++
++ if (FIELD_GET(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL, ctrl) ==
++ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_OUTPUT_ZERO &&
++ !(more & AIU_CLK_CTRL_MORE_AMCLK)) {
++ mux = AIU_HDMI_CTRL_MUX_PCM;
++ goto out;
++ }
++
++out:
++ ucontrol->value.enumerated.item[0] = mux;
++ return 0;
++}
++
+ static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -28,45 +74,51 @@ static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+- unsigned int mux, changed;
++ unsigned int mux, ctrl, more;
+
+ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
+- changed = snd_soc_component_test_bits(component, e->reg,
+- CTRL_DATA_SEL,
+- FIELD_PREP(CTRL_DATA_SEL, mux));
+
+- if (!changed)
+- return 0;
++ if (mux == AIU_HDMI_CTRL_MUX_I2S) {
++ ctrl = FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL,
++ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_I2S_DATA);
++ more = AIU_CLK_CTRL_MORE_AMCLK;
++ } else {
++ ctrl = FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_DATA_SEL,
++ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_OUTPUT_ZERO);
++ more = 0;
++ }
++
++ if (mux == AIU_HDMI_CTRL_MUX_DISABLED) {
++ ctrl |= FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_CLK_SEL,
++ AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_DISABLE);
++ } else {
++ ctrl |= FIELD_PREP(AIU_HDMI_CLK_DATA_CTRL_CLK_SEL,
++ AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_AIU);
++ }
+
+ /* Force disconnect of the mux while updating */
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
+
+- /* Reset the source first */
+- snd_soc_component_update_bits(component, e->reg,
+- CTRL_CLK_SEL |
+- CTRL_DATA_SEL,
+- FIELD_PREP(CTRL_CLK_SEL, 0) |
+- FIELD_PREP(CTRL_DATA_SEL, 0));
++ snd_soc_component_update_bits(component, AIU_HDMI_CLK_DATA_CTRL,
++ AIU_HDMI_CLK_DATA_CTRL_CLK_SEL |
++ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL,
++ ctrl);
+
+- /* Set the appropriate source */
+- snd_soc_component_update_bits(component, e->reg,
+- CTRL_CLK_SEL |
+- CTRL_DATA_SEL,
+- FIELD_PREP(CTRL_CLK_SEL, mux) |
+- FIELD_PREP(CTRL_DATA_SEL, mux));
++ snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE,
++ AIU_CLK_CTRL_MORE_AMCLK,
++ more);
+
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+
+ return 0;
+ }
+
+-static SOC_ENUM_SINGLE_DECL(aiu_hdmi_ctrl_mux_enum, AIU_HDMI_CLK_DATA_CTRL,
+- CTRL_DATA_SEL_SHIFT,
+- aiu_codec_ctrl_mux_texts);
++static SOC_ENUM_SINGLE_VIRT_DECL(aiu_hdmi_ctrl_mux_enum,
++ aiu_codec_hdmi_ctrl_mux_texts);
+
+ static const struct snd_kcontrol_new aiu_hdmi_ctrl_mux =
+ SOC_DAPM_ENUM_EXT("HDMI Source", aiu_hdmi_ctrl_mux_enum,
+- snd_soc_dapm_get_enum_double,
++ aiu_codec_ctrl_mux_get_enum,
+ aiu_codec_ctrl_mux_put_enum);
+
+ static const struct snd_soc_dapm_widget aiu_hdmi_ctrl_widgets[] = {
+diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
+index 67729de41a73..88637deb2d7a 100644
+--- a/sound/soc/meson/aiu-encoder-i2s.c
++++ b/sound/soc/meson/aiu-encoder-i2s.c
+@@ -23,7 +23,6 @@
+ #define AIU_CLK_CTRL_AOCLK_INVERT BIT(6)
+ #define AIU_CLK_CTRL_LRCLK_INVERT BIT(7)
+ #define AIU_CLK_CTRL_LRCLK_SKEW GENMASK(9, 8)
+-#define AIU_CLK_CTRL_MORE_HDMI_AMCLK BIT(6)
+ #define AIU_CLK_CTRL_MORE_I2S_DIV GENMASK(5, 0)
+ #define AIU_CODEC_DAC_LRCLK_CTRL_DIV GENMASK(11, 0)
+
+@@ -176,11 +175,6 @@ static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component,
+ if (ret)
+ return ret;
+
+- /* Make sure amclk is used for HDMI i2s as well */
+- snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE,
+- AIU_CLK_CTRL_MORE_HDMI_AMCLK,
+- AIU_CLK_CTRL_MORE_HDMI_AMCLK);
+-
+ return 0;
+ }
+
+--
+2.35.1
+
diff --git a/general-meson-gx-mmc-fix-deferred-probing.patch b/general-meson-gx-mmc-fix-deferred-probing.patch
new file mode 100644
index 000000000000..77e98a3257b5
--- /dev/null
+++ b/general-meson-gx-mmc-fix-deferred-probing.patch
@@ -0,0 +1,35 @@
+From b83c8168c58ccb96f92a4b6ecf1b8b7483fcced3 Mon Sep 17 00:00:00 2001
+From: Sergey Shtylyov <s.shtylyov@omp.ru>
+Date: Fri, 24 Dec 2021 06:09:57 +0000
+Subject: [PATCH 38/90] FROMLIST(v1): mmc: meson-gx: fix deferred probing
+
+The driver overrides the error codes and IRQ0 returned by platform_get_irq()
+to -EINVAL, so if it returns -EPROBE_DEFER, the driver will fail the probe
+permanently instead of the deferred probing. Switch to propagating the error
+codes upstream. IRQ0 is no longer returned by platform_get_irq(), so we now
+can safely ignore it...
+
+Fixes: cbcaac6d7dd2 ("mmc: meson-gx-mmc: Fix platform_get_irq's error checking")
+Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+---
+ drivers/mmc/host/meson-gx-mmc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
+index 58ab9d90bc8b..1a11a4bf4d4f 100644
+--- a/drivers/mmc/host/meson-gx-mmc.c
++++ b/drivers/mmc/host/meson-gx-mmc.c
+@@ -1183,8 +1183,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
+ }
+
+ host->irq = platform_get_irq(pdev, 0);
+- if (host->irq <= 0) {
+- ret = -EINVAL;
++ if (host->irq < 0) {
++ ret = host->irq;
+ goto free_host;
+ }
+
+--
+2.35.1
+
diff --git a/general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch b/general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch
new file mode 100644
index 000000000000..704e97c2d495
--- /dev/null
+++ b/general-meson-gx-mmc-set-core-clock-phase-to-270-degres.patch
@@ -0,0 +1,59 @@
+From 5c5664545a97520bbce591add5a7dbbea143b999 Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <narmstrong@baylibre.com>
+Date: Thu, 14 Jan 2021 17:43:02 +0100
+Subject: [PATCH 54/90] WIP: mmc: meson-gx-mmc: set core clock phase to 270
+ degrees for AXG compatible controllers
+
+Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
+---
+ drivers/mmc/host/meson-gx-mmc.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
+index 1a11a4bf4d4f..df60312a1765 100644
+--- a/drivers/mmc/host/meson-gx-mmc.c
++++ b/drivers/mmc/host/meson-gx-mmc.c
+@@ -38,6 +38,7 @@
+ #define CLK_RX_PHASE_MASK GENMASK(13, 12)
+ #define CLK_PHASE_0 0
+ #define CLK_PHASE_180 2
++#define CLK_PHASE_270 3
+ #define CLK_V2_TX_DELAY_MASK GENMASK(19, 16)
+ #define CLK_V2_RX_DELAY_MASK GENMASK(23, 20)
+ #define CLK_V2_ALWAYS_ON BIT(24)
+@@ -136,6 +137,7 @@ struct meson_mmc_data {
+ unsigned int rx_delay_mask;
+ unsigned int always_on;
+ unsigned int adjust;
++ unsigned int clk_core_phase;
+ };
+
+ struct sd_emmc_desc {
+@@ -428,7 +430,7 @@ static int meson_mmc_clk_init(struct meson_host *host)
+ /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+ clk_reg = CLK_ALWAYS_ON(host);
+ clk_reg |= CLK_DIV_MASK;
+- clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
++ clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->data->clk_core_phase);
+ clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0);
+ clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0);
+ writel(clk_reg, host->regs + SD_EMMC_CLOCK);
+@@ -1337,6 +1339,7 @@ static const struct meson_mmc_data meson_gx_data = {
+ .rx_delay_mask = CLK_V2_RX_DELAY_MASK,
+ .always_on = CLK_V2_ALWAYS_ON,
+ .adjust = SD_EMMC_ADJUST,
++ .clk_core_phase = CLK_PHASE_180,
+ };
+
+ static const struct meson_mmc_data meson_axg_data = {
+@@ -1344,6 +1347,7 @@ static const struct meson_mmc_data meson_axg_data = {
+ .rx_delay_mask = CLK_V3_RX_DELAY_MASK,
+ .always_on = CLK_V3_ALWAYS_ON,
+ .adjust = SD_EMMC_V3_ADJUST,
++ .clk_core_phase = CLK_PHASE_270,
+ };
+
+ static const struct of_device_id meson_mmc_of_match[] = {
+--
+2.35.1
+
diff --git a/general-meson-vdec-add-HEVC-decode-codec.patch b/general-meson-vdec-add-HEVC-decode-codec.patch
new file mode 100644
index 000000000000..cb8319fca9ef
--- /dev/null
+++ b/general-meson-vdec-add-HEVC-decode-codec.patch
@@ -0,0 +1,1609 @@
+From 478ef90d4bb38e6c5ae11c4abd6142fc7336c746 Mon Sep 17 00:00:00 2001
+From: benjamin545 <benjamin545@gmail.com>
+Date: Thu, 15 Jul 2021 17:08:42 -0400
+Subject: [PATCH 64/90] WIP: drivers: meson: vdec: add HEVC decode codec
+
+---
+ drivers/staging/media/meson/vdec/Makefile | 2 +-
+ drivers/staging/media/meson/vdec/codec_hevc.c | 1440 +++++++++++++++++
+ drivers/staging/media/meson/vdec/codec_hevc.h | 13 +
+ drivers/staging/media/meson/vdec/esparser.c | 2 +-
+ drivers/staging/media/meson/vdec/hevc_regs.h | 1 +
+ .../staging/media/meson/vdec/vdec_platform.c | 49 +
+ 6 files changed, 1505 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/staging/media/meson/vdec/codec_hevc.c
+ create mode 100644 drivers/staging/media/meson/vdec/codec_hevc.h
+
+diff --git a/drivers/staging/media/meson/vdec/Makefile b/drivers/staging/media/meson/vdec/Makefile
+index 6e726af84ac9..16f848e456b9 100644
+--- a/drivers/staging/media/meson/vdec/Makefile
++++ b/drivers/staging/media/meson/vdec/Makefile
+@@ -3,6 +3,6 @@
+
+ meson-vdec-objs = esparser.o vdec.o vdec_helpers.o vdec_platform.o
+ meson-vdec-objs += vdec_1.o vdec_hevc.o
+-meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_hevc_common.o codec_vp9.o
++meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_hevc_common.o codec_vp9.o codec_hevc.o
+
+ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o
+diff --git a/drivers/staging/media/meson/vdec/codec_hevc.c b/drivers/staging/media/meson/vdec/codec_hevc.c
+new file mode 100644
+index 000000000000..3a6fd04a2d33
+--- /dev/null
++++ b/drivers/staging/media/meson/vdec/codec_hevc.c
+@@ -0,0 +1,1440 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2018 Maxime Jourdan <mjourdan@baylibre.com>
++ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
++ */
++
++#include <media/v4l2-mem2mem.h>
++#include <media/videobuf2-dma-contig.h>
++
++#include "codec_hevc.h"
++#include "dos_regs.h"
++#include "hevc_regs.h"
++#include "vdec_helpers.h"
++#include "codec_hevc_common.h"
++
++/* HEVC reg mapping */
++#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0
++ #define HEVC_ACTION_DONE 0xff
++#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1
++#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2
++#define HEVC_VPS_BUFFER HEVC_ASSIST_SCRATCH_3
++#define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4
++#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5
++#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6
++#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7
++#define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7
++#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8
++#define HEVC_sao_mem_unit HEVC_ASSIST_SCRATCH_9
++#define HEVC_SAO_ABV HEVC_ASSIST_SCRATCH_A
++#define HEVC_sao_vb_size HEVC_ASSIST_SCRATCH_B
++#define HEVC_SAO_VB HEVC_ASSIST_SCRATCH_C
++#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D
++#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E
++#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F
++#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_F
++#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G
++#define HEVC_DECODE_MODE2 HEVC_ASSIST_SCRATCH_H
++#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I
++#define HEVC_DECODE_MODE HEVC_ASSIST_SCRATCH_J
++ #define DECODE_MODE_SINGLE 0
++#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
++#define HEVC_AUX_ADR HEVC_ASSIST_SCRATCH_L
++#define HEVC_AUX_DATA_SIZE HEVC_ASSIST_SCRATCH_M
++#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N
++
++#define AMRISC_MAIN_REQ 0x04
++
++/* HEVC Constants */
++#define MAX_REF_PIC_NUM 24
++#define MAX_REF_ACTIVE 16
++#define MAX_TILE_COL_NUM 10
++#define MAX_TILE_ROW_NUM 20
++#define MAX_SLICE_NUM 800
++#define INVALID_POC 0x80000000
++
++/* HEVC Workspace layout */
++#define MPRED_MV_BUF_SIZE 0x120000
++
++#define IPP_SIZE 0x4000
++#define SAO_ABV_SIZE 0x30000
++#define SAO_VB_SIZE 0x30000
++#define SH_TM_RPS_SIZE 0x800
++#define VPS_SIZE 0x800
++#define SPS_SIZE 0x800
++#define PPS_SIZE 0x2000
++#define SAO_UP_SIZE 0x2800
++#define SWAP_BUF_SIZE 0x800
++#define SWAP_BUF2_SIZE 0x800
++#define SCALELUT_SIZE 0x8000
++#define DBLK_PARA_SIZE 0x20000
++#define DBLK_DATA_SIZE 0x80000
++#define DBLK_DATA2_SIZE 0x80000
++#define MMU_VBH_SIZE 0x5000
++#define MPRED_ABV_SIZE 0x8000
++#define MPRED_MV_SIZE (MPRED_MV_BUF_SIZE * MAX_REF_PIC_NUM)
++#define RPM_BUF_SIZE 0x100
++#define LMEM_SIZE 0xA00
++
++#define IPP_OFFSET 0x00
++#define SAO_ABV_OFFSET (IPP_OFFSET + IPP_SIZE)
++#define SAO_VB_OFFSET (SAO_ABV_OFFSET + SAO_ABV_SIZE)
++#define SH_TM_RPS_OFFSET (SAO_VB_OFFSET + SAO_VB_SIZE)
++#define VPS_OFFSET (SH_TM_RPS_OFFSET + SH_TM_RPS_SIZE)
++#define SPS_OFFSET (VPS_OFFSET + VPS_SIZE)
++#define PPS_OFFSET (SPS_OFFSET + SPS_SIZE)
++#define SAO_UP_OFFSET (PPS_OFFSET + PPS_SIZE)
++#define SWAP_BUF_OFFSET (SAO_UP_OFFSET + SAO_UP_SIZE)
++#define SWAP_BUF2_OFFSET (SWAP_BUF_OFFSET + SWAP_BUF_SIZE)
++#define SCALELUT_OFFSET (SWAP_BUF2_OFFSET + SWAP_BUF2_SIZE)
++#define DBLK_PARA_OFFSET (SCALELUT_OFFSET + SCALELUT_SIZE)
++#define DBLK_DATA_OFFSET (DBLK_PARA_OFFSET + DBLK_PARA_SIZE)
++#define DBLK_DATA2_OFFSET (DBLK_DATA_OFFSET + DBLK_DATA_SIZE)
++#define MMU_VBH_OFFSET (DBLK_DATA2_OFFSET + DBLK_DATA2_SIZE)
++#define MPRED_ABV_OFFSET (MMU_VBH_OFFSET + MMU_VBH_SIZE)
++#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)
++
++/* ISR decode status */
++#define HEVC_DEC_IDLE 0x0
++#define HEVC_NAL_UNIT_VPS 0x1
++#define HEVC_NAL_UNIT_SPS 0x2
++#define HEVC_NAL_UNIT_PPS 0x3
++#define HEVC_NAL_UNIT_CODED_SLICE_SEGMENT 0x4
++#define HEVC_CODED_SLICE_SEGMENT_DAT 0x5
++#define HEVC_SLICE_DECODING 0x6
++#define HEVC_NAL_UNIT_SEI 0x7
++#define HEVC_SLICE_SEGMENT_DONE 0x8
++#define HEVC_NAL_SEARCH_DONE 0x9
++#define HEVC_DECPIC_DATA_DONE 0xa
++#define HEVC_DECPIC_DATA_ERROR 0xb
++#define HEVC_SEI_DAT 0xc
++#define HEVC_SEI_DAT_DONE 0xd
++
++/* RPM misc_flag0 */
++#define PCM_LOOP_FILTER_DISABLED_FLAG_BIT 0
++#define PCM_ENABLE_FLAG_BIT 1
++#define LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT 2
++#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 3
++#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT 4
++#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 5
++#define DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT 6
++#define SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT 7
++#define SLICE_SAO_LUMA_FLAG_BIT 8
++#define SLICE_SAO_CHROMA_FLAG_BIT 9
++#define SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 10
++
++/* Constants for HEVC_MPRED_CTRL1 */
++#define AMVP_MAX_NUM_CANDS_MEM 3
++#define AMVP_MAX_NUM_CANDS 2
++#define NUM_CHROMA_MODE 5
++#define DM_CHROMA_IDX 36
++
++/* Buffer sizes */
++#define SIZE_WORKSPACE ALIGN(LMEM_OFFSET + LMEM_SIZE, 64 * SZ_1K)
++#define SIZE_AUX (SZ_1K * 16)
++#define SIZE_FRAME_MMU (0x1200 * 4)
++#define RPM_SIZE 0x80
++#define RPS_USED_BIT 14
++
++/* Data received from the HW in this form, do not rearrange */
++union rpm_param {
++ struct {
++ u16 data[RPM_SIZE];
++ } l;
++ struct {
++ u16 CUR_RPS[MAX_REF_ACTIVE];
++ u16 num_ref_idx_l0_active;
++ u16 num_ref_idx_l1_active;
++ u16 slice_type;
++ u16 slice_temporal_mvp_enable_flag;
++ u16 dependent_slice_segment_flag;
++ u16 slice_segment_address;
++ u16 num_title_rows_minus1;
++ u16 pic_width_in_luma_samples;
++ u16 pic_height_in_luma_samples;
++ u16 log2_min_coding_block_size_minus3;
++ u16 log2_diff_max_min_coding_block_size;
++ u16 log2_max_pic_order_cnt_lsb_minus4;
++ u16 POClsb;
++ u16 collocated_from_l0_flag;
++ u16 collocated_ref_idx;
++ u16 log2_parallel_merge_level;
++ u16 five_minus_max_num_merge_cand;
++ u16 sps_num_reorder_pics_0;
++ u16 modification_flag;
++ u16 tiles_flags;
++ u16 num_tile_columns_minus1;
++ u16 num_tile_rows_minus1;
++ u16 tile_width[8];
++ u16 tile_height[8];
++ u16 misc_flag0;
++ u16 pps_beta_offset_div2;
++ u16 pps_tc_offset_div2;
++ u16 slice_beta_offset_div2;
++ u16 slice_tc_offset_div2;
++ u16 pps_cb_qp_offset;
++ u16 pps_cr_qp_offset;
++ u16 first_slice_segment_in_pic_flag;
++ u16 m_temporalId;
++ u16 m_nalUnitType;
++ u16 vui_num_units_in_tick_hi;
++ u16 vui_num_units_in_tick_lo;
++ u16 vui_time_scale_hi;
++ u16 vui_time_scale_lo;
++ u16 bit_depth;
++ u16 profile_etc;
++ u16 sei_frame_field_info;
++ u16 video_signal_type;
++ u16 modification_list[0x20];
++ u16 conformance_window_flag;
++ u16 conf_win_left_offset;
++ u16 conf_win_right_offset;
++ u16 conf_win_top_offset;
++ u16 conf_win_bottom_offset;
++ u16 chroma_format_idc;
++ u16 color_description;
++ u16 aspect_ratio_idc;
++ u16 sar_width;
++ u16 sar_height;
++ } p;
++};
++
++enum nal_unit_type {
++ NAL_UNIT_CODED_SLICE_BLA = 16,
++ NAL_UNIT_CODED_SLICE_BLANT = 17,
++ NAL_UNIT_CODED_SLICE_BLA_N_LP = 18,
++ NAL_UNIT_CODED_SLICE_IDR = 19,
++ NAL_UNIT_CODED_SLICE_IDR_N_LP = 20,
++};
++
++enum slice_type {
++ B_SLICE = 0,
++ P_SLICE = 1,
++ I_SLICE = 2,
++};
++
++/* A frame being decoded */
++struct hevc_frame {
++ struct list_head list;
++ struct vb2_v4l2_buffer *vbuf;
++ u32 offset;
++ u32 poc;
++
++ int referenced;
++ u32 num_reorder_pic;
++
++ u32 cur_slice_idx;
++ u32 cur_slice_type;
++
++ /* 2 lists (L0/L1) ; 800 slices ; 16 refs */
++ u32 ref_poc_list[2][MAX_SLICE_NUM][MAX_REF_ACTIVE];
++ u32 ref_num[2];
++};
++
++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;
++
++ /* AUX buffer */
++ void *aux_vaddr;
++ dma_addr_t aux_paddr;
++
++ /* Contains many information parsed from the bitstream */
++ union rpm_param rpm_param;
++
++ /* Information computed from the RPM */
++ u32 lcu_size; // Largest Coding Unit
++ u32 lcu_x_num;
++ u32 lcu_y_num;
++ u32 lcu_total;
++
++ /* Current Frame being handled */
++ struct hevc_frame *cur_frame;
++ u32 curr_poc;
++ /* Collocated Reference Picture */
++ struct hevc_frame *col_frame;
++ u32 col_poc;
++
++ /* All ref frames used by the HW at a given time */
++ struct list_head ref_frames_list;
++ u32 frames_num;
++
++ /* Coded resolution reported by the hardware */
++ u32 width, height;
++ /* Resolution minus the conformance window offsets */
++ u32 dst_width, dst_height;
++
++ u32 prev_tid0_poc;
++ u32 slice_segment_addr;
++ u32 slice_addr;
++ u32 ldc_flag;
++
++ /* Whether we detected the bitstream as 10-bit */
++ int is_10bit;
++};
++
++static u32 codec_hevc_num_pending_bufs(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc;
++ u32 ret;
++
++ hevc = sess->priv;
++ if (!hevc)
++ return 0;
++
++ mutex_lock(&hevc->lock);
++ ret = hevc->frames_num;
++ mutex_unlock(&hevc->lock);
++
++ return ret;
++}
++
++/* Update the L0 and L1 reference lists for a given frame */
++static void codec_hevc_update_frame_refs(struct amvdec_session *sess,
++ struct hevc_frame *frame)
++{
++ struct codec_hevc *hevc = sess->priv;
++ union rpm_param *params = &hevc->rpm_param;
++ int num_ref_idx_l0_active =
++ (params->p.num_ref_idx_l0_active > MAX_REF_ACTIVE) ?
++ MAX_REF_ACTIVE : params->p.num_ref_idx_l0_active;
++ int num_ref_idx_l1_active =
++ (params->p.num_ref_idx_l1_active > MAX_REF_ACTIVE) ?
++ MAX_REF_ACTIVE : params->p.num_ref_idx_l1_active;
++ int ref_picset0[MAX_REF_ACTIVE] = { 0 };
++ int ref_picset1[MAX_REF_ACTIVE] = { 0 };
++ u16 *mod_list = params->p.modification_list;
++ int num_neg = 0;
++ int num_pos = 0;
++ int total_num;
++ int i;
++
++ for (i = 0; i < MAX_REF_ACTIVE; i++) {
++ frame->ref_poc_list[0][frame->cur_slice_idx][i] = 0;
++ frame->ref_poc_list[1][frame->cur_slice_idx][i] = 0;
++ }
++
++ for (i = 0; i < MAX_REF_ACTIVE; i++) {
++ u16 cur_rps = params->p.CUR_RPS[i];
++ int delt = cur_rps & ((1 << (RPS_USED_BIT - 1)) - 1);
++
++ if (cur_rps & 0x8000)
++ break;
++
++ if (!((cur_rps >> RPS_USED_BIT) & 1))
++ continue;
++
++ if ((cur_rps >> (RPS_USED_BIT - 1)) & 1) {
++ ref_picset0[num_neg] =
++ frame->poc - ((1 << (RPS_USED_BIT - 1)) - delt);
++ num_neg++;
++ } else {
++ ref_picset1[num_pos] = frame->poc + delt;
++ num_pos++;
++ }
++ }
++
++ total_num = num_neg + num_pos;
++
++ if (total_num <= 0)
++ goto end;
++
++ for (i = 0; i < num_ref_idx_l0_active; i++) {
++ int cidx;
++ if (params->p.modification_flag & 0x1)
++ cidx = mod_list[i];
++ else
++ cidx = i % total_num;
++
++ frame->ref_poc_list[0][frame->cur_slice_idx][i] =
++ cidx >= num_neg ? ref_picset1[cidx - num_neg] :
++ ref_picset0[cidx];
++ }
++
++ if (params->p.slice_type != B_SLICE)
++ goto end;
++
++ if (params->p.modification_flag & 0x2) {
++ for (i = 0; i < num_ref_idx_l1_active; i++) {
++ int cidx;
++ if (params->p.modification_flag & 0x1)
++ cidx = mod_list[num_ref_idx_l0_active + i];
++ else
++ cidx = mod_list[i];
++
++ frame->ref_poc_list[1][frame->cur_slice_idx][i] =
++ (cidx >= num_pos) ? ref_picset0[cidx - num_pos]
++ : ref_picset1[cidx];
++ }
++ } else {
++ for (i = 0; i < num_ref_idx_l1_active; i++) {
++ int cidx = i % total_num;
++ frame->ref_poc_list[1][frame->cur_slice_idx][i] =
++ cidx >= num_pos ? ref_picset0[cidx - num_pos] :
++ ref_picset1[cidx];
++ }
++ }
++
++end:
++ frame->ref_num[0] = num_ref_idx_l0_active;
++ frame->ref_num[1] = num_ref_idx_l1_active;
++
++ dev_dbg(sess->core->dev,
++ "Frame %u; slice %u; slice_type %u; num_l0 %u; num_l1 %u\n",
++ frame->poc, frame->cur_slice_idx, params->p.slice_type,
++ frame->ref_num[0], frame->ref_num[1]);
++}
++
++static void codec_hevc_update_ldc_flag(struct codec_hevc *hevc)
++{
++ struct hevc_frame *frame = hevc->cur_frame;
++ u32 slice_type = frame->cur_slice_type;
++ u32 slice_idx = frame->cur_slice_idx;
++ int i;
++
++ hevc->ldc_flag = 0;
++
++ if (slice_type == I_SLICE)
++ return;
++
++ hevc->ldc_flag = 1;
++ for (i = 0; (i < frame->ref_num[0]) && hevc->ldc_flag; i++) {
++ if (frame->ref_poc_list[0][slice_idx][i] > frame->poc) {
++ hevc->ldc_flag = 0;
++ break;
++ }
++ }
++
++ if (slice_type == P_SLICE)
++ return;
++
++ for (i = 0; (i < frame->ref_num[1]) && hevc->ldc_flag; i++) {
++ if (frame->ref_poc_list[1][slice_idx][i] > frame->poc) {
++ hevc->ldc_flag = 0;
++ break;
++ }
++ }
++}
++
++/* Tag "old" frames that are no longer referenced */
++static void codec_hevc_update_referenced(struct codec_hevc *hevc)
++{
++ union rpm_param *param = &hevc->rpm_param;
++ struct hevc_frame *frame;
++ int i;
++ u32 curr_poc = hevc->curr_poc;
++
++ list_for_each_entry(frame, &hevc->ref_frames_list, list) {
++ int is_referenced = 0;
++ u32 poc_tmp;
++
++ if (!frame->referenced)
++ continue;
++
++ for (i = 0; i < MAX_REF_ACTIVE; i++) {
++ int delt;
++ if (param->p.CUR_RPS[i] & 0x8000)
++ break;
++
++ delt = param->p.CUR_RPS[i] &
++ ((1 << (RPS_USED_BIT - 1)) - 1);
++ if (param->p.CUR_RPS[i] & (1 << (RPS_USED_BIT - 1))) {
++ poc_tmp = curr_poc -
++ ((1 << (RPS_USED_BIT - 1)) - delt);
++ } else
++ poc_tmp = curr_poc + delt;
++ if (poc_tmp == frame->poc) {
++ is_referenced = 1;
++ break;
++ }
++ }
++
++ frame->referenced = is_referenced;
++ }
++}
++
++static struct hevc_frame *
++codec_hevc_get_lowest_poc_frame(struct codec_hevc *hevc)
++{
++ struct hevc_frame *tmp, *ret = NULL;
++ u32 poc = INT_MAX;
++
++ list_for_each_entry(tmp, &hevc->ref_frames_list, list) {
++ if (tmp->poc < poc) {
++ ret = tmp;
++ poc = tmp->poc;
++ }
++ }
++
++ return ret;
++}
++
++/* Try to output as many frames as possible */
++static void codec_hevc_output_frames(struct amvdec_session *sess)
++{
++ struct hevc_frame *tmp;
++ struct codec_hevc *hevc = sess->priv;
++
++ while ((tmp = codec_hevc_get_lowest_poc_frame(hevc))) {
++ if (hevc->curr_poc &&
++ (tmp->referenced ||
++ tmp->num_reorder_pic >= hevc->frames_num))
++ break;
++
++ dev_dbg(sess->core->dev, "DONE frame poc %u; vbuf %u\n",
++ tmp->poc, tmp->vbuf->vb2_buf.index);
++ amvdec_dst_buf_done_offset(sess, tmp->vbuf, tmp->offset,
++ V4L2_FIELD_NONE, false);
++ list_del(&tmp->list);
++ kfree(tmp);
++ hevc->frames_num--;
++ }
++}
++
++
++static int
++codec_hevc_setup_workspace(struct amvdec_session *sess,
++ struct codec_hevc *hevc)
++{
++ struct amvdec_core *core = sess->core;
++ u32 revision = core->platform->revision;
++ dma_addr_t wkaddr;
++
++ /* Allocate some memory for the HEVC decoder's state */
++ hevc->workspace_vaddr = dma_alloc_coherent(core->dev, SIZE_WORKSPACE,
++ &wkaddr, GFP_KERNEL);
++ if (!hevc->workspace_vaddr)
++ return -ENOMEM;
++
++ hevc->workspace_paddr = wkaddr;
++
++ amvdec_write_dos(core, HEVCD_IPP_LINEBUFF_BASE, wkaddr + IPP_OFFSET);
++ amvdec_write_dos(core, HEVC_RPM_BUFFER, wkaddr + RPM_OFFSET);
++ amvdec_write_dos(core, HEVC_SHORT_TERM_RPS, wkaddr + SH_TM_RPS_OFFSET);
++ amvdec_write_dos(core, HEVC_VPS_BUFFER, wkaddr + VPS_OFFSET);
++ amvdec_write_dos(core, HEVC_SPS_BUFFER, wkaddr + SPS_OFFSET);
++ amvdec_write_dos(core, HEVC_PPS_BUFFER, wkaddr + PPS_OFFSET);
++ amvdec_write_dos(core, HEVC_SAO_UP, wkaddr + SAO_UP_OFFSET);
++
++ if (codec_hevc_use_mmu(revision, sess->pixfmt_cap, hevc->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,
++ hevc->common.mmu_map_paddr);
++ else
++ amvdec_write_dos(core, H265_MMU_MAP_BUFFER,
++ hevc->common.mmu_map_paddr);
++ } else if (revision < VDEC_REVISION_G12A) {
++ amvdec_write_dos(core, HEVC_STREAM_SWAP_BUFFER,
++ wkaddr + SWAP_BUF_OFFSET);
++ amvdec_write_dos(core, HEVC_STREAM_SWAP_BUFFER2,
++ 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);
++ if (revision >= VDEC_REVISION_G12A)
++ amvdec_write_dos(core, HEVC_DBLK_CFGE,
++ wkaddr + DBLK_DATA2_OFFSET);
++
++ amvdec_write_dos(core, LMEM_DUMP_ADR, wkaddr + LMEM_OFFSET);
++
++ return 0;
++}
++
++static int codec_hevc_start(struct amvdec_session *sess)
++{
++ struct amvdec_core *core = sess->core;
++ struct codec_hevc *hevc;
++ u32 val;
++ int i;
++ int ret;
++
++ hevc = kzalloc(sizeof(*hevc), GFP_KERNEL);
++ if (!hevc)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&hevc->ref_frames_list);
++ hevc->curr_poc = INVALID_POC;
++
++ ret = codec_hevc_setup_workspace(sess, hevc);
++ if (ret)
++ goto free_hevc;
++
++ 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) |
++ BIT(0);
++ amvdec_write_dos(core, HEVC_PARSER_INT_CONTROL, val);
++ amvdec_write_dos_bits(core, HEVC_SHIFT_STATUS, BIT(1) | BIT(0));
++ amvdec_write_dos(core, HEVC_SHIFT_CONTROL,
++ (3 << 6) | BIT(5) | BIT(2) | BIT(0));
++ amvdec_write_dos(core, HEVC_CABAC_CONTROL, 1);
++ amvdec_write_dos(core, HEVC_PARSER_CORE_CONTROL, 1);
++ amvdec_write_dos(core, HEVC_DEC_STATUS_REG, 0);
++
++ amvdec_write_dos(core, HEVC_IQIT_SCALELUT_WR_ADDR, 0);
++ for (i = 0; i < 1024; ++i)
++ amvdec_write_dos(core, HEVC_IQIT_SCALELUT_DATA, 0);
++
++ amvdec_write_dos(core, HEVC_DECODE_SIZE, 0);
++
++ amvdec_write_dos(core, HEVC_PARSER_CMD_WRITE, BIT(16));
++ for (i = 0; i < ARRAY_SIZE(vdec_hevc_parser_cmd); ++i)
++ amvdec_write_dos(core, HEVC_PARSER_CMD_WRITE,
++ vdec_hevc_parser_cmd[i]);
++
++ amvdec_write_dos(core, HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0);
++ amvdec_write_dos(core, HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1);
++ amvdec_write_dos(core, HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2);
++ amvdec_write_dos(core, HEVC_PARSER_IF_CONTROL,
++ BIT(5) | BIT(2) | BIT(0));
++
++ amvdec_write_dos(core, HEVCD_IPP_TOP_CNTL, BIT(0));
++ amvdec_write_dos(core, HEVCD_IPP_TOP_CNTL, BIT(1));
++
++ amvdec_write_dos(core, HEVC_WAIT_FLAG, 1);
++
++ /* clear mailbox interrupt */
++ amvdec_write_dos(core, HEVC_ASSIST_MBOX1_CLR_REG, 1);
++ /* enable mailbox interrupt */
++ amvdec_write_dos(core, HEVC_ASSIST_MBOX1_MASK, 1);
++ /* disable PSCALE for hardware sharing */
++ amvdec_write_dos(core, HEVC_PSCALE_CTRL, 0);
++ /* Let the uCode do all the parsing */
++ amvdec_write_dos(core, NAL_SEARCH_CTL, 0xc);
++
++ amvdec_write_dos(core, DECODE_STOP_POS, 0);
++ amvdec_write_dos(core, HEVC_DECODE_MODE, DECODE_MODE_SINGLE);
++ amvdec_write_dos(core, HEVC_DECODE_MODE2, 0);
++
++ /* AUX buffers */
++ hevc->aux_vaddr = dma_alloc_coherent(core->dev, SIZE_AUX,
++ &hevc->aux_paddr, GFP_KERNEL);
++ if (!hevc->aux_vaddr) {
++ dev_err(core->dev, "Failed to request HEVC AUX\n");
++ ret = -ENOMEM;
++ goto free_hevc;
++ }
++
++ amvdec_write_dos(core, HEVC_AUX_ADR, hevc->aux_paddr);
++ amvdec_write_dos(core, HEVC_AUX_DATA_SIZE,
++ (((SIZE_AUX) >> 4) << 16) | 0);
++ mutex_init(&hevc->lock);
++ sess->priv = hevc;
++
++ return 0;
++
++free_hevc:
++ kfree(hevc);
++ return ret;
++}
++
++static void codec_hevc_flush_output(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++ struct hevc_frame *tmp;
++
++ while (!list_empty(&hevc->ref_frames_list)) {
++ tmp = codec_hevc_get_lowest_poc_frame(hevc);
++ amvdec_dst_buf_done(sess, tmp->vbuf, V4L2_FIELD_NONE);
++ list_del(&tmp->list);
++ kfree(tmp);
++ hevc->frames_num--;
++ }
++}
++
++static int codec_hevc_stop(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++ struct amvdec_core *core = sess->core;
++
++ mutex_lock(&hevc->lock);
++ codec_hevc_flush_output(sess);
++
++ if (hevc->workspace_vaddr)
++ dma_free_coherent(core->dev, SIZE_WORKSPACE,
++ hevc->workspace_vaddr,
++ hevc->workspace_paddr);
++
++ if (hevc->aux_vaddr)
++ dma_free_coherent(core->dev, SIZE_AUX,
++ hevc->aux_vaddr, hevc->aux_paddr);
++
++ codec_hevc_free_fbc_buffers(sess, &hevc->common);
++ mutex_unlock(&hevc->lock);
++ mutex_destroy(&hevc->lock);
++
++ return 0;
++}
++
++static struct hevc_frame *
++codec_hevc_get_frame_by_poc(struct codec_hevc *hevc, u32 poc)
++{
++ struct hevc_frame *tmp;
++
++ list_for_each_entry(tmp, &hevc->ref_frames_list, list) {
++ if (tmp->poc == poc)
++ return tmp;
++ }
++
++ return NULL;
++}
++
++static struct hevc_frame *
++codec_hevc_prepare_new_frame(struct amvdec_session *sess)
++{
++ struct amvdec_core *core = sess->core;
++ struct hevc_frame *new_frame = NULL;
++ struct codec_hevc *hevc = sess->priv;
++ struct vb2_v4l2_buffer *vbuf;
++ union rpm_param *params = &hevc->rpm_param;
++
++ new_frame = kzalloc(sizeof(*new_frame), GFP_KERNEL);
++ if (!new_frame)
++ return NULL;
++
++ vbuf = v4l2_m2m_dst_buf_remove(sess->m2m_ctx);
++ if (!vbuf) {
++ dev_err(sess->core->dev, "No dst buffer available\n");
++ return NULL;
++ }
++
++ new_frame->vbuf = vbuf;
++ new_frame->referenced = 1;
++ new_frame->poc = hevc->curr_poc;
++ new_frame->cur_slice_type = params->p.slice_type;
++ new_frame->num_reorder_pic = params->p.sps_num_reorder_pics_0;
++ new_frame->offset = amvdec_read_dos(core, HEVC_SHIFT_BYTE_COUNT);
++
++ list_add_tail(&new_frame->list, &hevc->ref_frames_list);
++ hevc->frames_num++;
++
++ return new_frame;
++}
++
++static void
++codec_hevc_set_sao(struct amvdec_session *sess, struct hevc_frame *frame)
++{
++ struct amvdec_core *core = sess->core;
++ struct codec_hevc *hevc = sess->priv;
++ struct vb2_buffer *vb = &frame->vbuf->vb2_buf;
++ union rpm_param *param = &hevc->rpm_param;
++ u32 pic_height_cu =
++ (hevc->height + hevc->lcu_size - 1) / hevc->lcu_size;
++ u32 sao_mem_unit = (hevc->lcu_size == 16 ? 9 :
++ hevc->lcu_size == 32 ? 14 : 24) << 4;
++ u32 sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu;
++ u32 misc_flag0 = param->p.misc_flag0;
++ dma_addr_t buf_y_paddr;
++ dma_addr_t buf_u_v_paddr;
++ u32 slice_deblocking_filter_disabled_flag;
++ u32 val, val_2;
++
++ val = (amvdec_read_dos(core, HEVC_SAO_CTRL0) & ~0xf) |
++ ilog2(hevc->lcu_size);
++ amvdec_write_dos(core, HEVC_SAO_CTRL0, val);
++
++ amvdec_write_dos(core, HEVC_SAO_PIC_SIZE,
++ hevc->width | (hevc->height << 16));
++ amvdec_write_dos(core, HEVC_SAO_PIC_SIZE_LCU,
++ (hevc->lcu_x_num - 1) | (hevc->lcu_y_num - 1) << 16);
++
++ if (codec_hevc_use_downsample(sess->pixfmt_cap, hevc->is_10bit) ||
++ codec_hevc_use_mmu(core->platform->revision, sess->pixfmt_cap,
++ hevc->is_10bit))
++ buf_y_paddr =
++ hevc->common.fbc_buffer_paddr[vb->index];
++ else
++ buf_y_paddr =
++ vb2_dma_contig_plane_dma_addr(vb, 0);
++
++ if (codec_hevc_use_fbc(sess->pixfmt_cap, hevc->is_10bit)) {
++ val = amvdec_read_dos(core, HEVC_SAO_CTRL5) & ~0xff0000;
++ amvdec_write_dos(core, HEVC_SAO_CTRL5, val);
++ 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);
++ buf_u_v_paddr =
++ vb2_dma_contig_plane_dma_addr(vb, 1);
++ amvdec_write_dos(core, HEVC_SAO_Y_START_ADDR, buf_y_paddr);
++ amvdec_write_dos(core, HEVC_SAO_C_START_ADDR, buf_u_v_paddr);
++ amvdec_write_dos(core, HEVC_SAO_Y_WPTR, buf_y_paddr);
++ amvdec_write_dos(core, HEVC_SAO_C_WPTR, buf_u_v_paddr);
++ }
++
++ if (codec_hevc_use_mmu(core->platform->revision, sess->pixfmt_cap,
++ hevc->is_10bit)) {
++ dma_addr_t header_adr = vb2_dma_contig_plane_dma_addr(vb, 0);
++ if (codec_hevc_use_downsample(sess->pixfmt_cap, hevc->is_10bit))
++ header_adr = hevc->common.mmu_header_paddr[vb->index];
++ 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));
++ amvdec_write_dos_bits(core, HEVC_SAO_CTRL9, BIT(0));
++ }
++
++ 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 (frame->cur_slice_idx == 0) {
++ if (core->platform->revision >= VDEC_REVISION_G12A) {
++ if (core->platform->revision >= VDEC_REVISION_SM1)
++ val = 0xfc << 8;
++ else
++ val = 0x54 << 8;
++
++ /* enable first, compressed write */
++ if (codec_hevc_use_fbc(sess->pixfmt_cap,
++ hevc->is_10bit))
++ val |= BIT(8);
++
++ /* enable second, uncompressed write */
++ if (sess->pixfmt_cap == V4L2_PIX_FMT_NV12M)
++ val |= BIT(9);
++
++ /* dblk pipeline mode=1 for performance */
++ if (hevc->width >= 1280)
++ val |= BIT(4);
++
++ amvdec_write_dos(core, HEVC_DBLK_CFGB, val);
++ amvdec_write_dos(core, HEVC_DBLK_STS1 + 16, BIT(28));
++ }
++
++ amvdec_write_dos(core, HEVC_DBLK_CFG2,
++ hevc->width | (hevc->height << 16));
++
++ val = 0;
++ if ((misc_flag0 >> PCM_ENABLE_FLAG_BIT) & 0x1)
++ val |= ((misc_flag0 >>
++ PCM_LOOP_FILTER_DISABLED_FLAG_BIT) & 0x1) << 3;
++
++ val |= (param->p.pps_cb_qp_offset & 0x1f) << 4;
++ val |= (param->p.pps_cr_qp_offset & 0x1f) << 9;
++ val |= (hevc->lcu_size == 64) ? 0 :
++ ((hevc->lcu_size == 32) ? 1 : 2);
++ amvdec_write_dos(core, HEVC_DBLK_CFG1, val);
++ }
++
++ val = amvdec_read_dos(core, HEVC_SAO_CTRL1) & ~0x3ff3;
++ val |= 0xff0; /* Set endianness for 2-bytes swaps (nv12) */
++ if (core->platform->revision < VDEC_REVISION_G12A) {
++ if (!codec_hevc_use_fbc(sess->pixfmt_cap, hevc->is_10bit))
++ val |= BIT(0); /* disable cm compression */
++ /* TOFIX: Handle Amlogic Framebuffer compression */
++ }
++
++ amvdec_write_dos(core, HEVC_SAO_CTRL1, val);
++
++ if (!codec_hevc_use_fbc(sess->pixfmt_cap, hevc->is_10bit)) {
++ /* no downscale for NV12 */
++ val = amvdec_read_dos(core, HEVC_SAO_CTRL5) & ~0xff0000;
++ amvdec_write_dos(core, HEVC_SAO_CTRL5, val);
++ }
++
++ val = amvdec_read_dos(core, HEVCD_IPP_AXIIF_CONFIG) & ~0x30;
++ val |= 0xf;
++ amvdec_write_dos(core, HEVCD_IPP_AXIIF_CONFIG, val);
++
++ val = 0;
++ val_2 = amvdec_read_dos(core, HEVC_SAO_CTRL0);
++ val_2 &= (~0x300);
++
++ slice_deblocking_filter_disabled_flag = (misc_flag0 >>
++ SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & 0x1;
++ if ((misc_flag0 & (1 << DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT))
++ && (misc_flag0 & (1 << DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT))) {
++ val |= slice_deblocking_filter_disabled_flag << 2;
++
++ if (!slice_deblocking_filter_disabled_flag) {
++ val |= (param->p.slice_beta_offset_div2 & 0xf) << 3;
++ val |= (param->p.slice_tc_offset_div2 & 0xf) << 7;
++ }
++ } else {
++ val |=
++ ((misc_flag0 >>
++ PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) & 0x1) << 2;
++
++ if (((misc_flag0 >> PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT) &
++ 0x1) == 0) {
++ val |= (param->p.pps_beta_offset_div2 & 0xf) << 3;
++ val |= (param->p.pps_tc_offset_div2 & 0xf) << 7;
++ }
++ }
++ if ((misc_flag0 & (1 << PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT))
++ && ((misc_flag0 & (1 << SLICE_SAO_LUMA_FLAG_BIT))
++ || (misc_flag0 & (1 << SLICE_SAO_CHROMA_FLAG_BIT))
++ || (!slice_deblocking_filter_disabled_flag))) {
++ val |=
++ ((misc_flag0 >>
++ SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT)
++ & 0x1) << 1;
++ val_2 |=
++ ((misc_flag0 >>
++ SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT)
++ & 0x1) << 9;
++ } else {
++ val |=
++ ((misc_flag0 >>
++ PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT)
++ & 0x1) << 1;
++ val_2 |=
++ ((misc_flag0 >>
++ PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT)
++ & 0x1) << 9;
++ }
++
++ amvdec_write_dos(core, HEVC_DBLK_CFG9, val);
++ amvdec_write_dos(core, HEVC_SAO_CTRL0, val_2);
++
++ amvdec_write_dos(core, HEVC_sao_mem_unit, sao_mem_unit);
++ amvdec_write_dos(core, HEVC_SAO_ABV,
++ hevc->workspace_paddr + SAO_ABV_OFFSET);
++ amvdec_write_dos(core, HEVC_sao_vb_size, sao_vb_size);
++ amvdec_write_dos(core, HEVC_SAO_VB,
++ hevc->workspace_paddr + SAO_VB_OFFSET);
++}
++
++static dma_addr_t codec_hevc_get_frame_mv_paddr(struct codec_hevc *hevc,
++ struct hevc_frame *frame)
++{
++ return hevc->workspace_paddr + MPRED_MV_OFFSET +
++ (frame->vbuf->vb2_buf.index * MPRED_MV_BUF_SIZE);
++}
++
++static void
++codec_hevc_set_mpred_ctrl(struct amvdec_core *core, struct codec_hevc *hevc)
++{
++ union rpm_param *param = &hevc->rpm_param;
++ u32 slice_type = param->p.slice_type;
++ u32 lcu_size_log2 = ilog2(hevc->lcu_size);
++ u32 val;
++
++ val = slice_type |
++ MPRED_CTRL0_ABOVE_EN |
++ MPRED_CTRL0_MV_WR_EN |
++ MPRED_CTRL0_BUF_LINEAR |
++ (lcu_size_log2 << 16) |
++ (3 << 20) | /* cu_size_log2 */
++ (param->p.log2_parallel_merge_level << 24);
++
++ if (slice_type != I_SLICE)
++ val |= MPRED_CTRL0_MV_RD_EN;
++
++ if (param->p.collocated_from_l0_flag)
++ val |= MPRED_CTRL0_COL_FROM_L0;
++
++ if (param->p.slice_temporal_mvp_enable_flag)
++ val |= MPRED_CTRL0_TMVP;
++
++ if (hevc->ldc_flag)
++ val |= MPRED_CTRL0_LDC;
++
++ if (param->p.dependent_slice_segment_flag)
++ val |= MPRED_CTRL0_NEW_SLI_SEG;
++
++ if (param->p.slice_segment_address == 0)
++ val |= MPRED_CTRL0_NEW_PIC |
++ MPRED_CTRL0_NEW_TILE;
++
++ amvdec_write_dos(core, HEVC_MPRED_CTRL0, val);
++
++ val = (5 - param->p.five_minus_max_num_merge_cand) |
++ (AMVP_MAX_NUM_CANDS << 4) |
++ (AMVP_MAX_NUM_CANDS_MEM << 8) |
++ (NUM_CHROMA_MODE << 12) |
++ (DM_CHROMA_IDX << 16);
++ amvdec_write_dos(core, HEVC_MPRED_CTRL1, val);
++}
++
++static void codec_hevc_set_mpred_mv(struct amvdec_core *core,
++ struct codec_hevc *hevc,
++ struct hevc_frame *frame,
++ struct hevc_frame *col_frame)
++{
++ union rpm_param *param = &hevc->rpm_param;
++ u32 lcu_size_log2 = ilog2(hevc->lcu_size);
++ u32 mv_mem_unit = lcu_size_log2 == 6 ? 0x200 :
++ lcu_size_log2 == 5 ? 0x80 : 0x20;
++ dma_addr_t col_mv_rd_start_addr, col_mv_rd_ptr, col_mv_rd_end_addr;
++ dma_addr_t mpred_mv_wr_ptr;
++ u32 val;
++
++ val = amvdec_read_dos(core, HEVC_MPRED_CURR_LCU);
++
++ col_mv_rd_start_addr = codec_hevc_get_frame_mv_paddr(hevc, col_frame);
++ mpred_mv_wr_ptr = codec_hevc_get_frame_mv_paddr(hevc, frame) +
++ (hevc->slice_addr * mv_mem_unit);
++ col_mv_rd_ptr = col_mv_rd_start_addr +
++ (hevc->slice_addr * mv_mem_unit);
++ col_mv_rd_end_addr = col_mv_rd_start_addr +
++ (hevc->lcu_total * mv_mem_unit);
++
++ amvdec_write_dos(core, HEVC_MPRED_MV_WR_START_ADDR,
++ codec_hevc_get_frame_mv_paddr(hevc, frame));
++ amvdec_write_dos(core, HEVC_MPRED_MV_RD_START_ADDR,
++ col_mv_rd_start_addr);
++
++ if (param->p.slice_segment_address == 0) {
++ amvdec_write_dos(core, HEVC_MPRED_ABV_START_ADDR,
++ hevc->workspace_paddr + MPRED_ABV_OFFSET);
++ amvdec_write_dos(core, HEVC_MPRED_MV_WPTR, mpred_mv_wr_ptr);
++ amvdec_write_dos(core, HEVC_MPRED_MV_RPTR,
++ col_mv_rd_start_addr);
++ } else {
++ amvdec_write_dos(core, HEVC_MPRED_MV_RPTR, col_mv_rd_ptr);
++ }
++
++ amvdec_write_dos(core, HEVC_MPRED_MV_RD_END_ADDR, col_mv_rd_end_addr);
++}
++
++/* Update motion prediction with the current slice */
++static void codec_hevc_set_mpred(struct amvdec_session *sess,
++ struct hevc_frame *frame,
++ struct hevc_frame *col_frame)
++{
++ struct amvdec_core *core = sess->core;
++ struct codec_hevc *hevc = sess->priv;
++ u32 *ref_num = frame->ref_num;
++ u32 *ref_poc_l0 = frame->ref_poc_list[0][frame->cur_slice_idx];
++ u32 *ref_poc_l1 = frame->ref_poc_list[1][frame->cur_slice_idx];
++ u32 val;
++ int i;
++
++ codec_hevc_set_mpred_ctrl(core, hevc);
++ codec_hevc_set_mpred_mv(core, hevc, frame, col_frame);
++
++ amvdec_write_dos(core, HEVC_MPRED_PIC_SIZE,
++ hevc->width | (hevc->height << 16));
++
++ val = ((hevc->lcu_x_num - 1) | (hevc->lcu_y_num - 1) << 16);
++ amvdec_write_dos(core, HEVC_MPRED_PIC_SIZE_LCU, val);
++
++ amvdec_write_dos(core, HEVC_MPRED_REF_NUM,
++ (ref_num[1] << 8) | ref_num[0]);
++ amvdec_write_dos(core, HEVC_MPRED_REF_EN_L0, (1 << ref_num[0]) - 1);
++ amvdec_write_dos(core, HEVC_MPRED_REF_EN_L1, (1 << ref_num[1]) - 1);
++
++ amvdec_write_dos(core, HEVC_MPRED_CUR_POC, hevc->curr_poc);
++ amvdec_write_dos(core, HEVC_MPRED_COL_POC, hevc->col_poc);
++
++ for (i = 0; i < MAX_REF_ACTIVE; ++i) {
++ amvdec_write_dos(core, HEVC_MPRED_L0_REF00_POC + i * 4,
++ ref_poc_l0[i]);
++ amvdec_write_dos(core, HEVC_MPRED_L1_REF00_POC + i * 4,
++ ref_poc_l1[i]);
++ }
++}
++
++/* motion compensation reference cache controller */
++static void codec_hevc_set_mcrcc(struct amvdec_session *sess)
++{
++ struct amvdec_core *core = sess->core;
++ struct codec_hevc *hevc = sess->priv;
++ u32 val, val_2;
++ int l0_cnt = 0;
++ int l1_cnt = 0x7fff;
++
++ if (!codec_hevc_use_fbc(sess->pixfmt_cap, hevc->is_10bit)) {
++ l0_cnt = hevc->cur_frame->ref_num[0];
++ l1_cnt = hevc->cur_frame->ref_num[1];
++ }
++
++ if (hevc->cur_frame->cur_slice_type == I_SLICE) {
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL1, 0);
++ return;
++ }
++
++ if (hevc->cur_frame->cur_slice_type == P_SLICE) {
++ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
++ BIT(1));
++ val = amvdec_read_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
++ val &= 0xffff;
++ val |= (val << 16);
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL2, val);
++
++ if (l0_cnt == 1) {
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL3, val);
++ } else {
++ val = amvdec_read_dos(core,
++ HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
++ val &= 0xffff;
++ val |= (val << 16);
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL3, val);
++ }
++ } else { /* B_SLICE */
++ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, 0);
++ val = amvdec_read_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
++ val &= 0xffff;
++ val |= (val << 16);
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL2, val);
++
++ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
++ BIT(12) | BIT(1));
++ val_2 = amvdec_read_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
++ val_2 &= 0xffff;
++ val_2 |= (val_2 << 16);
++ if (val == val_2 && l1_cnt > 1) {
++ val_2 = amvdec_read_dos(core,
++ HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
++ val_2 &= 0xffff;
++ val_2 |= (val_2 << 16);
++ }
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL3, val);
++ }
++
++ /* enable mcrcc progressive-mode */
++ amvdec_write_dos(core, HEVCD_MCRCC_CTL1, 0xff0);
++}
++
++static void codec_hevc_set_ref_list(struct amvdec_session *sess,
++ u32 ref_num, u32 *ref_poc_list)
++{
++ struct codec_hevc *hevc = sess->priv;
++ struct hevc_frame *ref_frame;
++ struct amvdec_core *core = sess->core;
++ int i;
++ u32 buf_id_y;
++ u32 buf_id_uv;
++
++ for (i = 0; i < ref_num; i++) {
++ ref_frame = codec_hevc_get_frame_by_poc(hevc, ref_poc_list[i]);
++
++ if (!ref_frame) {
++ dev_warn(core->dev, "Couldn't find ref. frame %u\n",
++ ref_poc_list[i]);
++ continue;
++ }
++
++ if (codec_hevc_use_fbc(sess->pixfmt_cap, hevc->is_10bit)) {
++ buf_id_y = buf_id_uv = ref_frame->vbuf->vb2_buf.index;
++ } else {
++ buf_id_y = ref_frame->vbuf->vb2_buf.index * 2;
++ buf_id_uv = buf_id_y + 1;
++ }
++
++ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
++ (buf_id_uv << 16) |
++ (buf_id_uv << 8) |
++ buf_id_y);
++ }
++}
++
++static void codec_hevc_set_mc(struct amvdec_session *sess,
++ struct hevc_frame *frame)
++{
++ struct amvdec_core *core = sess->core;
++
++ if (frame->cur_slice_type == I_SLICE)
++ return;
++
++ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, 1);
++ codec_hevc_set_ref_list(sess, frame->ref_num[0],
++ frame->ref_poc_list[0][frame->cur_slice_idx]);
++
++ if (frame->cur_slice_type == P_SLICE)
++ return;
++
++ amvdec_write_dos(core, HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
++ BIT(12) | BIT(0));
++ codec_hevc_set_ref_list(sess, frame->ref_num[1],
++ frame->ref_poc_list[1][frame->cur_slice_idx]);
++}
++
++static void codec_hevc_update_col_frame(struct codec_hevc *hevc)
++{
++ struct hevc_frame *cur_frame = hevc->cur_frame;
++ union rpm_param *param = &hevc->rpm_param;
++ u32 list_no = 0;
++ u32 col_ref = param->p.collocated_ref_idx;
++ u32 col_from_l0 = param->p.collocated_from_l0_flag;
++ u32 cur_slice_idx = cur_frame->cur_slice_idx;
++
++ if (cur_frame->cur_slice_type == B_SLICE)
++ list_no = 1 - col_from_l0;
++
++ if (col_ref >= cur_frame->ref_num[list_no])
++ hevc->col_poc = INVALID_POC;
++ else
++ hevc->col_poc = cur_frame->ref_poc_list[list_no]
++ [cur_slice_idx]
++ [col_ref];
++
++ if (cur_frame->cur_slice_type == I_SLICE)
++ goto end;
++
++ if (hevc->col_poc != INVALID_POC)
++ hevc->col_frame = codec_hevc_get_frame_by_poc(hevc,
++ hevc->col_poc);
++ else
++ hevc->col_frame = hevc->cur_frame;
++
++end:
++ if (!hevc->col_frame)
++ hevc->col_frame = hevc->cur_frame;
++}
++
++static void codec_hevc_update_pocs(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++ union rpm_param *param = &hevc->rpm_param;
++ u32 nal_unit_type = param->p.m_nalUnitType;
++ u32 temporal_id = param->p.m_temporalId & 0x7;
++ int max_poc_lsb =
++ 1 << (param->p.log2_max_pic_order_cnt_lsb_minus4 + 4);
++ int prev_poc_lsb;
++ int prev_poc_msb;
++ int poc_msb;
++ int poc_lsb = param->p.POClsb;
++
++ if (nal_unit_type == NAL_UNIT_CODED_SLICE_IDR ||
++ nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_N_LP) {
++ hevc->curr_poc = 0;
++ if ((temporal_id - 1) == 0)
++ hevc->prev_tid0_poc = hevc->curr_poc;
++
++ return;
++ }
++
++ prev_poc_lsb = hevc->prev_tid0_poc % max_poc_lsb;
++ prev_poc_msb = hevc->prev_tid0_poc - prev_poc_lsb;
++
++ if ((poc_lsb < prev_poc_lsb) &&
++ ((prev_poc_lsb - poc_lsb) >= (max_poc_lsb / 2)))
++ poc_msb = prev_poc_msb + max_poc_lsb;
++ else if ((poc_lsb > prev_poc_lsb) &&
++ ((poc_lsb - prev_poc_lsb) > (max_poc_lsb / 2)))
++ poc_msb = prev_poc_msb - max_poc_lsb;
++ else
++ poc_msb = prev_poc_msb;
++
++ if (nal_unit_type == NAL_UNIT_CODED_SLICE_BLA ||
++ nal_unit_type == NAL_UNIT_CODED_SLICE_BLANT ||
++ nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_N_LP)
++ poc_msb = 0;
++
++ hevc->curr_poc = (poc_msb + poc_lsb);
++ if ((temporal_id - 1) == 0)
++ hevc->prev_tid0_poc = hevc->curr_poc;
++}
++
++static void codec_hevc_process_segment_header(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++ union rpm_param *param = &hevc->rpm_param;
++
++ if (param->p.first_slice_segment_in_pic_flag == 0) {
++ hevc->slice_segment_addr = param->p.slice_segment_address;
++ if (!param->p.dependent_slice_segment_flag)
++ hevc->slice_addr = hevc->slice_segment_addr;
++ } else {
++ hevc->slice_segment_addr = 0;
++ hevc->slice_addr = 0;
++ }
++
++ codec_hevc_update_pocs(sess);
++}
++
++static int codec_hevc_process_segment(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++ struct amvdec_core *core = sess->core;
++ union rpm_param *param = &hevc->rpm_param;
++ u32 slice_segment_address = param->p.slice_segment_address;
++
++ /* First slice: new frame */
++ if (slice_segment_address == 0) {
++ codec_hevc_update_referenced(hevc);
++ codec_hevc_output_frames(sess);
++
++ hevc->cur_frame = codec_hevc_prepare_new_frame(sess);
++ if (!hevc->cur_frame)
++ return -1;
++ } else {
++ hevc->cur_frame->cur_slice_idx++;
++ }
++
++ codec_hevc_update_frame_refs(sess, hevc->cur_frame);
++ codec_hevc_update_col_frame(hevc);
++ codec_hevc_update_ldc_flag(hevc);
++ if (codec_hevc_use_mmu(core->platform->revision, sess->pixfmt_cap,
++ hevc->is_10bit))
++ codec_hevc_fill_mmu_map(sess, &hevc->common,
++ &hevc->cur_frame->vbuf->vb2_buf,
++ hevc->is_10bit);
++ codec_hevc_set_mc(sess, hevc->cur_frame);
++ codec_hevc_set_mcrcc(sess);
++ codec_hevc_set_mpred(sess, hevc->cur_frame, hevc->col_frame);
++ codec_hevc_set_sao(sess, hevc->cur_frame);
++
++ amvdec_write_dos_bits(core, HEVC_WAIT_FLAG, BIT(1));
++ amvdec_write_dos(core, HEVC_DEC_STATUS_REG,
++ HEVC_CODED_SLICE_SEGMENT_DAT);
++
++ /* Interrupt the firmware's processor */
++ amvdec_write_dos(core, HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ);
++
++ return 0;
++}
++
++static int codec_hevc_process_rpm(struct codec_hevc *hevc)
++{
++ union rpm_param *param = &hevc->rpm_param;
++ int src_changed = 0;
++ u32 dst_width, dst_height;
++ u32 lcu_size;
++ u32 is_10bit = 0;
++
++ if (param->p.slice_segment_address ||
++ !param->p.pic_width_in_luma_samples ||
++ !param->p.pic_height_in_luma_samples)
++ return 0;
++
++ if (param->p.bit_depth)
++ is_10bit = 1;
++
++ hevc->width = param->p.pic_width_in_luma_samples;
++ hevc->height = param->p.pic_height_in_luma_samples;
++ dst_width = hevc->width;
++ dst_height = hevc->height;
++
++ lcu_size = 1 << (param->p.log2_min_coding_block_size_minus3 +
++ 3 + param->p.log2_diff_max_min_coding_block_size);
++
++ hevc->lcu_x_num = (hevc->width + lcu_size - 1) / lcu_size;
++ hevc->lcu_y_num = (hevc->height + lcu_size - 1) / lcu_size;
++ hevc->lcu_total = hevc->lcu_x_num * hevc->lcu_y_num;
++
++ if (param->p.conformance_window_flag) {
++ u32 sub_width = 1, sub_height = 1;
++
++ switch (param->p.chroma_format_idc) {
++ case 1:
++ sub_height = 2; /* fallthrough */
++ case 2:
++ sub_width = 2;
++ break;
++ }
++
++ dst_width -= sub_width *
++ (param->p.conf_win_left_offset +
++ param->p.conf_win_right_offset);
++ dst_height -= sub_height *
++ (param->p.conf_win_top_offset +
++ param->p.conf_win_bottom_offset);
++ }
++
++ if (dst_width != hevc->dst_width ||
++ dst_height != hevc->dst_height ||
++ lcu_size != hevc->lcu_size ||
++ is_10bit != hevc->is_10bit)
++ src_changed = 1;
++
++ hevc->dst_width = dst_width;
++ hevc->dst_height = dst_height;
++ hevc->lcu_size = lcu_size;
++ hevc->is_10bit = is_10bit;
++
++ return src_changed;
++}
++
++/*
++ * The RPM section within the workspace contains
++ * many information regarding the parsed bitstream
++ */
++static void codec_hevc_fetch_rpm(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++ u16 *rpm_vaddr = hevc->workspace_vaddr + RPM_OFFSET;
++ int i, j;
++
++ for (i = 0; i < RPM_SIZE; i += 4)
++ for (j = 0; j < 4; j++)
++ hevc->rpm_param.l.data[i + j] = rpm_vaddr[i + 3 - j];
++}
++
++static void codec_hevc_resume(struct amvdec_session *sess)
++{
++ struct codec_hevc *hevc = sess->priv;
++
++ if (codec_hevc_setup_buffers(sess, &hevc->common, hevc->is_10bit)) {
++ amvdec_abort(sess);
++ return;
++ }
++
++ codec_hevc_setup_decode_head(sess, hevc->is_10bit);
++ codec_hevc_process_segment_header(sess);
++ if (codec_hevc_process_segment(sess))
++ amvdec_abort(sess);
++}
++
++static irqreturn_t codec_hevc_threaded_isr(struct amvdec_session *sess)
++{
++ struct amvdec_core *core = sess->core;
++ struct codec_hevc *hevc = sess->priv;
++ u32 dec_status = amvdec_read_dos(core, HEVC_DEC_STATUS_REG);
++
++ if (!hevc)
++ return IRQ_HANDLED;
++
++ mutex_lock(&hevc->lock);
++ if (dec_status != HEVC_SLICE_SEGMENT_DONE) {
++ dev_err(core->dev_dec, "Unrecognized dec_status: %08X\n",
++ dec_status);
++ amvdec_abort(sess);
++ goto unlock;
++ }
++
++ sess->keyframe_found = 1;
++ codec_hevc_fetch_rpm(sess);
++ if (codec_hevc_process_rpm(hevc)) {
++ amvdec_src_change(sess, hevc->dst_width, hevc->dst_height, 16,
++ hevc->is_10bit ? 10 : 8);
++ goto unlock;
++ }
++
++ codec_hevc_process_segment_header(sess);
++ if (codec_hevc_process_segment(sess))
++ amvdec_abort(sess);
++
++unlock:
++ mutex_unlock(&hevc->lock);
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t codec_hevc_isr(struct amvdec_session *sess)
++{
++ return IRQ_WAKE_THREAD;
++}
++
++struct amvdec_codec_ops codec_hevc_ops = {
++ .start = codec_hevc_start,
++ .stop = codec_hevc_stop,
++ .isr = codec_hevc_isr,
++ .threaded_isr = codec_hevc_threaded_isr,
++ .num_pending_bufs = codec_hevc_num_pending_bufs,
++ .drain = codec_hevc_flush_output,
++ .resume = codec_hevc_resume,
++};
+diff --git a/drivers/staging/media/meson/vdec/codec_hevc.h b/drivers/staging/media/meson/vdec/codec_hevc.h
+new file mode 100644
+index 000000000000..f2f9b2464df1
+--- /dev/null
++++ b/drivers/staging/media/meson/vdec/codec_hevc.h
+@@ -0,0 +1,13 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
++ */
++
++#ifndef __MESON_VDEC_CODEC_HEVC_H_
++#define __MESON_VDEC_CODEC_HEVC_H_
++
++#include "vdec.h"
++
++extern struct amvdec_codec_ops codec_hevc_ops;
++
++#endif
+diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
+index 610a92b9f6f2..9b6034936d32 100644
+--- a/drivers/staging/media/meson/vdec/esparser.c
++++ b/drivers/staging/media/meson/vdec/esparser.c
+@@ -309,7 +309,7 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
+ * they could pause when there is no capture buffer available and
+ * resume on this notification.
+ */
+- if (sess->fmt_out->pixfmt == V4L2_PIX_FMT_VP9) {
++ if (sess->fmt_out->pixfmt == V4L2_PIX_FMT_VP9 || sess->fmt_out->pixfmt ==V4L2_PIX_FMT_HEVC) {
+ if (codec_ops->num_pending_bufs)
+ num_dst_bufs = codec_ops->num_pending_bufs(sess);
+
+diff --git a/drivers/staging/media/meson/vdec/hevc_regs.h b/drivers/staging/media/meson/vdec/hevc_regs.h
+index 0392f41a1eed..e7eabdd2b119 100644
+--- a/drivers/staging/media/meson/vdec/hevc_regs.h
++++ b/drivers/staging/media/meson/vdec/hevc_regs.h
+@@ -205,6 +205,7 @@
+ #define HEVC_CM_HEADER_START_ADDR 0xd8a0
+ #define HEVC_CM_HEADER_LENGTH 0xd8a4
+ #define HEVC_CM_HEADER_OFFSET 0xd8ac
++#define HEVC_SAO_CTRL9 0xd8b4
+ #define HEVC_SAO_MMU_VH0_ADDR 0xd8e8
+ #define HEVC_SAO_MMU_VH1_ADDR 0xd8ec
+
+diff --git a/drivers/staging/media/meson/vdec/vdec_platform.c b/drivers/staging/media/meson/vdec/vdec_platform.c
+index 88c9d72e1c83..8592cb3aaea9 100644
+--- a/drivers/staging/media/meson/vdec/vdec_platform.c
++++ b/drivers/staging/media/meson/vdec/vdec_platform.c
+@@ -11,6 +11,7 @@
+ #include "vdec_hevc.h"
+ #include "codec_mpeg12.h"
+ #include "codec_h264.h"
++#include "codec_hevc.h"
+ #include "codec_vp9.h"
+
+ static const struct amvdec_format vdec_formats_gxbb[] = {
+@@ -64,6 +65,18 @@ static const struct amvdec_format vdec_formats_gxl[] = {
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
+ .flags = V4L2_FMT_FLAG_COMPRESSED |
+ V4L2_FMT_FLAG_DYN_RESOLUTION,
++ }, {
++ .pixfmt = V4L2_PIX_FMT_HEVC,
++ .min_buffers = 4,
++ .max_buffers = 24,
++ .max_width = 3840,
++ .max_height = 2160,
++ .vdec_ops = &vdec_hevc_ops,
++ .codec_ops = &codec_hevc_ops,
++ .firmware_path = "meson/vdec/gxl_hevc.bin",
++ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
++ .flags = V4L2_FMT_FLAG_COMPRESSED |
++ V4L2_FMT_FLAG_DYN_RESOLUTION,
+ }, {
+ .pixfmt = V4L2_PIX_FMT_H264,
+ .min_buffers = 2,
+@@ -114,6 +127,18 @@ static const struct amvdec_format vdec_formats_gxm[] = {
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
+ .flags = V4L2_FMT_FLAG_COMPRESSED |
+ V4L2_FMT_FLAG_DYN_RESOLUTION,
++ }, {
++ .pixfmt = V4L2_PIX_FMT_HEVC,
++ .min_buffers = 4,
++ .max_buffers = 24,
++ .max_width = 3840,
++ .max_height = 2160,
++ .vdec_ops = &vdec_hevc_ops,
++ .codec_ops = &codec_hevc_ops,
++ .firmware_path = "meson/vdec/gxl_hevc.bin",
++ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
++ .flags = V4L2_FMT_FLAG_COMPRESSED |
++ V4L2_FMT_FLAG_DYN_RESOLUTION,
+ }, {
+ .pixfmt = V4L2_PIX_FMT_H264,
+ .min_buffers = 2,
+@@ -165,6 +190,18 @@ static const struct amvdec_format vdec_formats_g12a[] = {
+ .flags = V4L2_FMT_FLAG_COMPRESSED |
+ V4L2_FMT_FLAG_DYN_RESOLUTION,
+ }, {
++ .pixfmt = V4L2_PIX_FMT_HEVC,
++ .min_buffers = 4,
++ .max_buffers = 24,
++ .max_width = 3840,
++ .max_height = 2160,
++ .vdec_ops = &vdec_hevc_ops,
++ .codec_ops = &codec_hevc_ops,
++ .firmware_path = "meson/vdec/g12a_hevc_mmu.bin",
++ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
++ .flags = V4L2_FMT_FLAG_COMPRESSED |
++ V4L2_FMT_FLAG_DYN_RESOLUTION,
++ },{
+ .pixfmt = V4L2_PIX_FMT_H264,
+ .min_buffers = 2,
+ .max_buffers = 24,
+@@ -214,6 +251,18 @@ static const struct amvdec_format vdec_formats_sm1[] = {
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
+ .flags = V4L2_FMT_FLAG_COMPRESSED |
+ V4L2_FMT_FLAG_DYN_RESOLUTION,
++ }, {
++ .pixfmt = V4L2_PIX_FMT_HEVC,
++ .min_buffers = 4,
++ .max_buffers = 24,
++ .max_width = 3840,
++ .max_height = 2160,
++ .vdec_ops = &vdec_hevc_ops,
++ .codec_ops = &codec_hevc_ops,
++ .firmware_path = "meson/vdec/sm1_hevc_mmu.bin",
++ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
++ .flags = V4L2_FMT_FLAG_COMPRESSED |
++ V4L2_FMT_FLAG_DYN_RESOLUTION,
+ }, {
+ .pixfmt = V4L2_PIX_FMT_H264,
+ .min_buffers = 2,
+--
+2.35.1
+
diff --git a/general-meson-vdec-add-handling-to-HEVC-decoder-.patch b/general-meson-vdec-add-handling-to-HEVC-decoder-.patch
new file mode 100644
index 000000000000..93b3af995dd2
--- /dev/null
+++ b/general-meson-vdec-add-handling-to-HEVC-decoder-.patch
@@ -0,0 +1,157 @@
+From a9f750c672c4c1238cccd1d8d76a138a5602d035 Mon Sep 17 00:00:00 2001
+From: benjamin545 <benjamin545@gmail.com>
+Date: Mon, 2 Aug 2021 15:18:40 -0400
+Subject: [PATCH 65/90] WIP: drivers: meson: vdec: add handling to HEVC decoder
+ to show frames when ready
+
+..rather than when no longer referenced
+
+the HEVC decode driver would not show the next frame until it was no longer referenced,
+this would cause a backup of frames that were ready to render but held up by one or more
+frames that were still referenced. The decoded picture buffer would fill up and stall
+playback as no new frames could be placed in the decoded picture buffer.
+---
+ drivers/staging/media/meson/vdec/codec_hevc.c | 52 ++++++++++++-------
+ 1 file changed, 34 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/staging/media/meson/vdec/codec_hevc.c b/drivers/staging/media/meson/vdec/codec_hevc.c
+index 3a6fd04a2d33..01218efde99b 100644
+--- a/drivers/staging/media/meson/vdec/codec_hevc.c
++++ b/drivers/staging/media/meson/vdec/codec_hevc.c
+@@ -223,6 +223,7 @@ struct hevc_frame {
+ u32 poc;
+
+ int referenced;
++ int show;
+ u32 num_reorder_pic;
+
+ u32 cur_slice_idx;
+@@ -448,9 +449,11 @@ static void codec_hevc_update_referenced(struct codec_hevc *hevc)
+ ((1 << (RPS_USED_BIT - 1)) - 1);
+ if (param->p.CUR_RPS[i] & (1 << (RPS_USED_BIT - 1))) {
+ poc_tmp = curr_poc -
+- ((1 << (RPS_USED_BIT - 1)) - delt);
+- } else
++ ((1 << (RPS_USED_BIT - 1)) - delt);
++ } else {
+ poc_tmp = curr_poc + delt;
++ }
++
+ if (poc_tmp == frame->poc) {
+ is_referenced = 1;
+ break;
+@@ -462,13 +465,13 @@ static void codec_hevc_update_referenced(struct codec_hevc *hevc)
+ }
+
+ static struct hevc_frame *
+-codec_hevc_get_lowest_poc_frame(struct codec_hevc *hevc)
++codec_hevc_get_next_ready_frame(struct codec_hevc *hevc)
+ {
+ struct hevc_frame *tmp, *ret = NULL;
+ u32 poc = INT_MAX;
+
+ list_for_each_entry(tmp, &hevc->ref_frames_list, list) {
+- if (tmp->poc < poc) {
++ if ((tmp->poc < poc) && tmp->show) {
+ ret = tmp;
+ poc = tmp->poc;
+ }
+@@ -478,28 +481,35 @@ codec_hevc_get_lowest_poc_frame(struct codec_hevc *hevc)
+ }
+
+ /* Try to output as many frames as possible */
+-static void codec_hevc_output_frames(struct amvdec_session *sess)
++static void codec_hevc_show_frames(struct amvdec_session *sess)
+ {
+- struct hevc_frame *tmp;
++ struct hevc_frame *tmp, *n;
+ struct codec_hevc *hevc = sess->priv;
+
+- while ((tmp = codec_hevc_get_lowest_poc_frame(hevc))) {
++ while ((tmp = codec_hevc_get_next_ready_frame(hevc))) {
+ if (hevc->curr_poc &&
+- (tmp->referenced ||
+- tmp->num_reorder_pic >= hevc->frames_num))
++ (hevc->frames_num <= tmp->num_reorder_pic))
+ break;
+
+ dev_dbg(sess->core->dev, "DONE frame poc %u; vbuf %u\n",
+ tmp->poc, tmp->vbuf->vb2_buf.index);
+ amvdec_dst_buf_done_offset(sess, tmp->vbuf, tmp->offset,
+ V4L2_FIELD_NONE, false);
++
++ tmp->show = 0;
++ hevc->frames_num--;
++ }
++
++ /* clean output frame buffer */
++ list_for_each_entry_safe(tmp, n, &hevc->ref_frames_list, list) {
++ if (tmp->referenced || tmp->show)
++ continue;
++
+ list_del(&tmp->list);
+ kfree(tmp);
+- hevc->frames_num--;
+ }
+ }
+
+-
+ static int
+ codec_hevc_setup_workspace(struct amvdec_session *sess,
+ struct codec_hevc *hevc)
+@@ -650,14 +660,17 @@ static int codec_hevc_start(struct amvdec_session *sess)
+ static void codec_hevc_flush_output(struct amvdec_session *sess)
+ {
+ struct codec_hevc *hevc = sess->priv;
+- struct hevc_frame *tmp;
++ struct hevc_frame *tmp, *n;
+
+- while (!list_empty(&hevc->ref_frames_list)) {
+- tmp = codec_hevc_get_lowest_poc_frame(hevc);
++ while ((tmp = codec_hevc_get_next_ready_frame(hevc))) {
+ amvdec_dst_buf_done(sess, tmp->vbuf, V4L2_FIELD_NONE);
++ tmp->show = 0;
++ hevc->frames_num--;
++ }
++
++ list_for_each_entry_safe(tmp, n, &hevc->ref_frames_list, list) {
+ list_del(&tmp->list);
+ kfree(tmp);
+- hevc->frames_num--;
+ }
+ }
+
+@@ -719,6 +732,7 @@ codec_hevc_prepare_new_frame(struct amvdec_session *sess)
+
+ new_frame->vbuf = vbuf;
+ new_frame->referenced = 1;
++ new_frame->show = 1;
+ new_frame->poc = hevc->curr_poc;
+ new_frame->cur_slice_type = params->p.slice_type;
+ new_frame->num_reorder_pic = params->p.sps_num_reorder_pics_0;
+@@ -1267,7 +1281,7 @@ static int codec_hevc_process_segment(struct amvdec_session *sess)
+ /* First slice: new frame */
+ if (slice_segment_address == 0) {
+ codec_hevc_update_referenced(hevc);
+- codec_hevc_output_frames(sess);
++ codec_hevc_show_frames(sess);
+
+ hevc->cur_frame = codec_hevc_prepare_new_frame(sess);
+ if (!hevc->cur_frame)
+@@ -1370,9 +1384,11 @@ static void codec_hevc_fetch_rpm(struct amvdec_session *sess)
+ u16 *rpm_vaddr = hevc->workspace_vaddr + RPM_OFFSET;
+ int i, j;
+
+- for (i = 0; i < RPM_SIZE; i += 4)
++ for (i = 0; i < RPM_SIZE; i += 4) {
+ for (j = 0; j < 4; j++)
+- hevc->rpm_param.l.data[i + j] = rpm_vaddr[i + 3 - j];
++ hevc->rpm_param.l.data[i + j] =
++ rpm_vaddr[i + 3 - j];
++ }
+ }
+
+ static void codec_hevc_resume(struct amvdec_session *sess)
+--
+2.35.1
+
diff --git a/general-meson-vdec-check-if-parser-has-really-parser.patch b/general-meson-vdec-check-if-parser-has-really-parser.patch
new file mode 100644
index 000000000000..7b92ede85890
--- /dev/null
+++ b/general-meson-vdec-check-if-parser-has-really-parser.patch
@@ -0,0 +1,51 @@
+From cb0c20e84a934c66961ace27f340cd7c98188dbe Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <narmstrong@baylibre.com>
+Date: Mon, 22 Nov 2021 09:15:21 +0000
+Subject: [PATCH 67/90] WIP: drivers: meson: vdec: check if parser has really
+ parser before marking input buffer as error
+
+Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
+---
+ drivers/staging/media/meson/vdec/esparser.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
+index 9b6034936d32..bb9480f0a70c 100644
+--- a/drivers/staging/media/meson/vdec/esparser.c
++++ b/drivers/staging/media/meson/vdec/esparser.c
+@@ -300,6 +300,7 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
+ u32 num_dst_bufs = 0;
+ u32 offset;
+ u32 pad_size;
++ u32 wp, wp2;
+
+ /*
+ * When max ref frame is held by VP9, this should be -= 3 to prevent a
+@@ -349,15 +350,20 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
+ }
+
+ pad_size = esparser_pad_start_code(core, vb, payload_size);
++ wp = amvdec_read_parser(core, PARSER_VIDEO_WP);
+ ret = esparser_write_data(core, phy, payload_size + pad_size);
++ wp2 = amvdec_read_parser(core, PARSER_VIDEO_WP);
+
+ if (ret <= 0) {
+- dev_warn(core->dev, "esparser: input parsing error\n");
+- amvdec_remove_ts(sess, vb->timestamp);
+- v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+ amvdec_write_parser(core, PARSER_FETCH_CMD, 0);
+
+- return 0;
++ if (ret < 0 || wp2 == wp) {
++ dev_err(core->dev, "esparser: input parsing error ret %d (%x <=> %x)\n", ret, wp, wp2);
++ amvdec_remove_ts(sess, vb->timestamp);
++ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
++
++ return 0;
++ }
+ }
+
+ atomic_inc(&sess->esparser_queued_bufs);
+--
+2.35.1
+
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
+
diff --git a/general-meson-vdec-remove-redundant-if-statement.patch b/general-meson-vdec-remove-redundant-if-statement.patch
new file mode 100644
index 000000000000..489b93556264
--- /dev/null
+++ b/general-meson-vdec-remove-redundant-if-statement.patch
@@ -0,0 +1,29 @@
+From 4aca1a59251338a9f98b58fc67e7749fae32b3be Mon Sep 17 00:00:00 2001
+From: benjamin545 <benjamin545@gmail.com>
+Date: Thu, 15 Jul 2021 14:32:33 -0400
+Subject: [PATCH 62/90] WIP: drivers: meson: vdec: remove redundant if
+ statement
+
+checking if sess->fmt_out->pixfmt is V4L2_PIX_FMT_VP9 was already done
+as a condition to enter the if statement where this additional check is performed
+---
+ drivers/staging/media/meson/vdec/esparser.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
+index db7022707ff8..e18334e57fc0 100644
+--- a/drivers/staging/media/meson/vdec/esparser.c
++++ b/drivers/staging/media/meson/vdec/esparser.c
+@@ -314,8 +314,7 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
+ num_dst_bufs = codec_ops->num_pending_bufs(sess);
+
+ num_dst_bufs += v4l2_m2m_num_dst_bufs_ready(sess->m2m_ctx);
+- if (sess->fmt_out->pixfmt == V4L2_PIX_FMT_VP9)
+- num_dst_bufs -= 3;
++ num_dst_bufs -= 3;
+
+ if (esparser_vififo_get_free_space(sess) < payload_size ||
+ atomic_read(&sess->esparser_queued_bufs) >= num_dst_bufs)
+--
+2.35.1
+
diff --git a/general-revert-meson_drv_shutdown.patch b/general-revert-meson_drv_shutdown.patch
new file mode 100644
index 000000000000..94ae819376e8
--- /dev/null
+++ b/general-revert-meson_drv_shutdown.patch
@@ -0,0 +1,25 @@
+From 22ce3ced8b11ceb313dea2aab1bb8ac028320dbb Mon Sep 17 00:00:00 2001
+From: Igor Pecovnik <igor.pecovnik@gmail.com>
+Date: Tue, 15 Jun 2021 19:53:41 +0200
+Subject: [PATCH] Remove shutdown
+
+Signed-off-by: Igor Pecovnik <igor.pecovnik@gmail.com>
+---
+ drivers/gpu/drm/meson/meson_drv.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
+index 2753067c0..b591aee04 100644
+--- a/drivers/gpu/drm/meson/meson_drv.c
++++ b/drivers/gpu/drm/meson/meson_drv.c
+@@ -564,7 +564,6 @@ static const struct dev_pm_ops meson_drv_pm_ops = {
+
+ static struct platform_driver meson_drm_platform_driver = {
+ .probe = meson_drv_probe,
+- .shutdown = meson_drv_shutdown,
+ .driver = {
+ .name = "meson-drm",
+ .of_match_table = dt_match,
+--
+Created with Armbian build tools https://github.com/armbian/build
+
diff --git a/general-sound-soc-remove-mono-channel-as-it-curren.patch b/general-sound-soc-remove-mono-channel-as-it-curren.patch
new file mode 100644
index 000000000000..8861f8f47836
--- /dev/null
+++ b/general-sound-soc-remove-mono-channel-as-it-curren.patch
@@ -0,0 +1,37 @@
+From 79828b7d8ee8674b1538514a754337554cd4f856 Mon Sep 17 00:00:00 2001
+From: ckkim <changkon12@gmail.com>
+Date: Thu, 20 Feb 2020 18:52:57 +0900
+Subject: [PATCH] ODROID-N2: sound/soc: remove mono channel as it currently
+ doesn't work hdmi output.
+
+Change-Id: I4d43b802815779687ade974f049f2b0517a411d1
+Signed-off-by: ckkim <changkon12@gmail.com>
+---
+ sound/soc/meson/axg-frddr.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c
+index 37f4bb3469b5..b1cbeef98a73 100644
+--- a/sound/soc/meson/axg-frddr.c
++++ b/sound/soc/meson/axg-frddr.c
+@@ -106,7 +106,7 @@ static struct snd_soc_dai_driver axg_frddr_dai_drv = {
+ .name = "FRDDR",
+ .playback = {
+ .stream_name = "Playback",
+- .channels_min = 1,
++ .channels_min = 2,
+ .channels_max = AXG_FIFO_CH_MAX,
+ .rates = AXG_FIFO_RATES,
+ .formats = AXG_FIFO_FORMATS,
+@@ -180,7 +180,7 @@ static struct snd_soc_dai_driver g12a_frddr_dai_drv = {
+ .name = "FRDDR",
+ .playback = {
+ .stream_name = "Playback",
+- .channels_min = 1,
++ .channels_min = 2,
+ .channels_max = AXG_FIFO_CH_MAX,
+ .rates = AXG_FIFO_RATES,
+ .formats = AXG_FIFO_FORMATS,
+--
+2.35.1
+
diff --git a/general-usb-core-improve-handling-of-hubs-with-no-ports.patch b/general-usb-core-improve-handling-of-hubs-with-no-ports.patch
new file mode 100644
index 000000000000..8f553ebfee1d
--- /dev/null
+++ b/general-usb-core-improve-handling-of-hubs-with-no-ports.patch
@@ -0,0 +1,54 @@
+From 477a4f4816028d590f7b013e04b29319dbe66a24 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Wed, 23 Feb 2022 02:21:19 +0000
+Subject: [PATCH 50/90] FROMLIST(v1): usb: core: improve handling of hubs with
+ no ports
+
+I get the "hub doesn't have any ports" error message on a system with
+Amlogic S905W SoC. Seems the SoC has internal USB 3.0 supports but
+is crippled with regard to USB 3.0 ports.
+Maybe we shouldn't consider this scenario an error. So let's change
+the message to info level, but otherwise keep the handling of the
+scenario as it is today. With the patch it looks like this on my
+system.
+
+dwc2 c9100000.usb: supply vusb_d not found, using dummy regulator
+dwc2 c9100000.usb: supply vusb_a not found, using dummy regulator
+dwc2 c9100000.usb: EPs: 7, dedicated fifos, 712 entries in SPRAM
+xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
+xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1
+xhci-hcd xhci-hcd.0.auto: hcc params 0x0228f664 hci version 0x100 quirks 0x0000000002010010
+xhci-hcd xhci-hcd.0.auto: irq 49, io mem 0xc9000000
+hub 1-0:1.0: USB hub found
+hub 1-0:1.0: 2 ports detected
+xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
+xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2
+xhci-hcd xhci-hcd.0.auto: Host supports USB 3.0 SuperSpeed
+usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
+hub 2-0:1.0: USB hub found
+hub 2-0:1.0: hub has no ports, exiting
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+---
+ drivers/usb/core/hub.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 588f3ded89cd..4151b960915b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1423,9 +1423,8 @@ static int hub_configure(struct usb_hub *hub,
+ ret = -ENODEV;
+ goto fail;
+ } else if (hub->descriptor->bNbrPorts == 0) {
+- message = "hub doesn't have any ports!";
+- ret = -ENODEV;
+- goto fail;
++ dev_info(hub_dev, "hub has no ports, exiting\n");
++ return -ENODEV;
+ }
+
+ /*
+--
+2.35.1
+