Subject: [bug#60043] Support for Amlogic SoC

From: phodina <[email-masked]>
Date: Tue, 13 Dec 2022 19:27:17 +0000

Hi,

this patch set adds support for running on Amlogic SoC devices which can be found on multiple Android TV boxes.

Most of the open source work has been done by BayLibre (thanks guys) and they upstreamed lot of code already. [1]

The Android OS on the boxes from the manufacturer can currently be replaced with LibreELEC [2] or Armbian. [3]

However, there are still some patches pending and there's huge variety of the boards. The patches will be removed once more
and more of them get accepted into the upstream.

Therefore I put all the patches into one commit and added another variable that build Linux kernel - resource intensive task.
Is this the right approach? Or git repo with the patches applied is better approach?

The aim is to add tools to Guix to be able to prepare the image for the TV boxes and liberate the living rooms :-)

Of course there will still be some black magic behind the firmware (bl2.bin, acs.bin, bl30.bin, bl301.bin) - something
similar to Raspberry Pi. Nevertheless, that's not part of the patches and it comes with the device and we can just replace
the Android OS on top. Alternatively it can be downloaded and put together if somebody needs the whole image. [4]

[1] https://linux-meson.com/mainlining.html[2] https://libreelec.tv/[3] https://github.com/ophub/amlogic-s9xxx-armbian[4]https://u-boot.readthedocs.io/en/latest/board/amlogic/p212.html

----
Petr

From 8f3a2983b5d4d1c196b2193a2089e0b15235d309 Mon Sep 17 00:00:00 2001
From: Petr Hodina <[email-masked]>
Date: Tue, 13 Dec 2022 10:16:38 +0100
Subject: [PATCH 3/5] gnu: Add ampart.

* gnu/packages/firmware.scm (ampart): New variable.

diff --git a/gnu/packages/firmware.scm b/gnu/packages/firmware.scm
index 2826dfd131..764d4e2a88 100644
--- a/gnu/packages/firmware.scm
+++ b/gnu/packages/firmware.scm
@@ -7,7 +7,7 @@
 ;;; Copyright © 2018 Vagrant Cascadian <[email-masked]>
 ;;; Copyright © 2019 Mathieu Othacehe <[email-masked]>
 ;;; Copyright © 2020, 2021, 2022 Marius Bakke <[email-masked]>
-;;; Copyright © 2021 Petr Hodina <[email-masked]>
+;;; Copyright © 2021, 2022 Petr Hodina <[email-masked]>
 ;;; Copyright © 2022 Maxim Cournoyer <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -76,6 +76,36 @@ (define-module (gnu packages firmware)
   #:use-module (gnu packages web)
   #:use-module (gnu packages xml))
 
+(define-public ampart
+  (package
+    (name "ampart")
+    (version "1.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+			  "https://github.com/7Ji/ampart/archive/refs/tags/v" version
+			  ".tar.gz"))
+              (sha256
+               (base32
+                "0b7j48iddcr9gld5dsmcqjxa97759xkgbda971cqdd29y3q5p9fb"))))
+    (build-system gnu-build-system)
+	(arguments (list
+	            #:tests? #f ; no test suite
+	            #:make-flags #~(list (string-append "CC=" #$(cc-for-target)))
+	            #:phases
+	            #~(modify-phases %standard-phases
+				   (delete 'configure)
+				   (replace 'install
+				   (lambda _
+				   (mkdir-p (string-append #$output "/bin"))
+				   (install-file "ampart" (string-append #$output "/bin")))))))
+    (propagated-inputs (list zlib))
+    (home-page "https://github.com/superna9999/pyamlboot")
+    (synopsis "Partition tool for Amlogic's proprietary eMMC partition format")
+    (description "This packages provides partition tool for Amlogic's
+proprietary eMMC partition format.")
+    (license license:gpl3+)))
+
 (define-public pyamlboot
   (package
     (name "pyamlboot")
-- 
2.38.1

From 9701fd468aa8b88e3505b8cfdca9fcaaa4031816 Mon Sep 17 00:00:00 2001
From: Petr Hodina <[email-masked]>
Date: Tue, 13 Dec 2022 09:57:43 +0100
Subject: [PATCH 2/5] gnu: Add pyamlboot.

* gnu/packages/firmware.scm (pyamlboot): New variable.

diff --git a/gnu/packages/firmware.scm b/gnu/packages/firmware.scm
index e9bb3ed450..2826dfd131 100644
--- a/gnu/packages/firmware.scm
+++ b/gnu/packages/firmware.scm
@@ -34,6 +34,7 @@ (define-module (gnu packages firmware)
   #:use-module (guix git-download)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system meson)
+  #:use-module (guix build-system python)
   #:use-module (gnu packages)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages autotools)
@@ -67,6 +68,7 @@ (define-module (gnu packages firmware)
   #:use-module (gnu packages polkit)
   #:use-module (gnu packages protobuf)
   #:use-module (gnu packages python)
+  #:use-module (gnu packages python-build)
   #:use-module (gnu packages python-xyz)
   #:use-module (gnu packages sqlite)
   #:use-module (gnu packages tls)
@@ -74,6 +76,24 @@ (define-module (gnu packages firmware)
   #:use-module (gnu packages web)
   #:use-module (gnu packages xml))
 
+(define-public pyamlboot
+  (package
+    (name "pyamlboot")
+    (version "1.0.0")
+    (source (origin
+              (method url-fetch)
+              (uri (pypi-uri "pyamlboot" version))
+              (sha256
+               (base32
+                "0ivm6h118y6fsk4xfan5nkdsbyds52qpr98zjfa1ilrswyyddj49"))))
+    (build-system python-build-system)
+    (propagated-inputs (list python-pyusb python-setuptools))
+    (home-page "https://github.com/superna9999/pyamlboot")
+    (synopsis "Amlogic SoC USB Boot utility")
+    (description "This package provides USB Boot utility to interact with the
+	MaskROM on Amlogic SoC.")
+    (license license:asl2.0)))
+
 (define-public ath9k-htc-firmware
   (package
     (name "ath9k-htc-firmware")
-- 
2.38.1

From 988c3333e13dff9286d8e8a281059e88b77af9d1 Mon Sep 17 00:00:00 2001
From: Petr Hodina <[email-masked]>
Date: Tue, 13 Dec 2022 10:38:11 +0100
Subject: [PATCH 4/5] gnu: Add gxlimg.

* gnu/packages/firmware.scm (gxlimg): New variable.

diff --git a/gnu/packages/firmware.scm b/gnu/packages/firmware.scm
index 764d4e2a88..d42340f061 100644
--- a/gnu/packages/firmware.scm
+++ b/gnu/packages/firmware.scm
@@ -338,6 +338,29 @@ (define-public fwupd
 automatic, safe and reliable.  It is used by tools such as GNOME Software.")
     (license license:lgpl2.1+)))
 
+(define-public gxlimg
+(let ((commit "15be56b1f1e2a319227d599a0b7afb0673e9cb9b")
+      (revision "1"))
+  (package
+    (name "gxlimg")
+    (version "1.1")
+    (source (origin
+              (method git-fetch)
+              (uri (git-reference
+			  (url "https://github.com/repk/gxlimg")
+			  (commit commit)))
+              (sha256
+               (base32
+                "0h96834i27sfzn7nvmqk0rwzxk5axiq9mm6ql3yaz81qd8slpljv"))))
+    (build-system meson-build-system)
+    (inputs (list openssl))
+    (native-inputs (list pkg-config))
+    (home-page "https://github.com/repk/gxlimg")
+    (synopsis "Boot Image creation tool for amlogic s905x")
+    (description "@code{Gxlimg} is an amlogic s905x boot image creation
+tools.")
+    (license license:bsd-2))))
+
 (define-public openfwwf-firmware
   (package
     (name "openfwwf-firmware")
-- 
2.38.1

From ba0d032d3f99e588bbf0428940b5f21f3fe0b59d Mon Sep 17 00:00:00 2001
From: Petr Hodina <[email-masked]>
Date: Tue, 13 Dec 2022 10:58:39 +0100
Subject: [PATCH 5/5] gnu: Add u-boot-amlogic.

* gnu/packages/bootloaders.scm (u-boot-amlogic): New variable.

diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 8888c51736..bd9ae06ded 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -886,6 +886,14 @@ (define*-public (make-u-boot-package board triplet
                   uboot-files)
                  #t)))))))))
 
+(define %u-boot-amlogic-description-64-bit
+  "This is a common 64-bit build of U-Boot for all 64-bit capable Amlogic s905x 
+variants.")
+
+(define-public u-boot-amlogic
+  (make-u-boot-package "p212" "aarch64-linux-gnu"
+                       #:append-description %u-boot-amlogic-description-64-bit))
+
 (define-public u-boot-malta
   (make-u-boot-package "malta" "mips64el-linux-gnuabi64"))
 
-- 
2.38.1

From 29566a8832a42f3f70391ed595414c249a50a06e Mon Sep 17 00:00:00 2001
From: Petr Hodina <[email-masked]>
Date: Tue, 13 Dec 2022 09:52:26 +0100
Subject: [PATCH 1/5] gnu: Add linux-libre-arm64-amlogic.

* gnu/packages/linux.scm (linux-libre-arm64-amlogic): New variable.
* gnu/local.mk: Add patches.
* gnu/packages/patches/amlogic-0001-LOCAL-set-meson-gx-cma-pool-to-896MB.patch
* gnu/packages/patches/amlogic-0002-LOCAL-set-meson-g12-cma-pool-to-896MB.patch
* gnu/packages/patches/amlogic-0003-LOCAL-arm64-fix-Kodi-sysinfo-CPU-information.patch
* gnu/packages/patches/amlogic-0004-LOCAL-arm64-meson-add-Amlogic-Meson-GX-PM-Suspend.patch
* gnu/packages/patches/amlogic-0005-LOCAL-arm64-dts-meson-add-support-for-GX-PM-and-Virt.patch
* gnu/packages/patches/amlogic-0006-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch
* gnu/packages/patches/amlogic-0007-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch
* gnu/packages/patches/amlogic-0008-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch
* gnu/packages/patches/amlogic-0009-LOCAL-ALSA-Assign-internal-PCM-chmap-ELD-IEC958-kctl.patch
* gnu/packages/patches/amlogic-0010-LOCAL-usb-hub-disable-autosuspend-for-Genesys-Logic-.patch
* gnu/packages/patches/amlogic-0011-LOCAL-of-partial-revert-of-fdt.c-changes.patch
* gnu/packages/patches/amlogic-0012-FROMGIT-drm-lima-Fix-opp-clkname-setting-in-case-of-.patch
* gnu/packages/patches/amlogic-0013-FROMGIT-6.1-dt-bindings-arm-amlogic-add-Beelink-GT1-.patch
* gnu/packages/patches/amlogic-0014-FROMGIT-6.1-arm64-dts-meson-add-support-for-Beelink-.patch
* gnu/packages/patches/amlogic-0015-FROMLIST-v2-arm64-dts-meson-make-dts-use-gpio-fan-ma.patch
* gnu/packages/patches/amlogic-0016-FROMLIST-v1-mmc-meson-gx-fix-deferred-probing.patch
* gnu/packages/patches/amlogic-0017-FROMLIST-v5-dt-bindings-vendor-prefixes-Add-Titan-Mi.patch
* gnu/packages/patches/amlogic-0018-FROMLIST-v5-dt-bindings-auxdisplay-Add-Titan-Micro-E.patch
* gnu/packages/patches/amlogic-0019-FROMLIST-v5-docs-ABI-document-tm1628-attribute-displ.patch
* gnu/packages/patches/amlogic-0020-FROMLIST-v5-auxdisplay-add-support-for-Titanmec-TM16.patch
* gnu/packages/patches/amlogic-0021-FROMLIST-v5-arm64-dts-meson-gxl-s905w-tx3-mini-add-s.patch
* gnu/packages/patches/amlogic-0022-FROMLIST-v5-MAINTAINERS-Add-entry-for-tm1628-auxdisp.patch
* gnu/packages/patches/amlogic-0023-FROMLIST-v1-drm-bridge-dw_hdmi-fix-preference-of-RGB.patch
* gnu/packages/patches/amlogic-0024-WIP-ASoC-hdmi-codec-reorder-channel-allocation-list.patch
* gnu/packages/patches/amlogic-0025-WIP-mmc-meson-gx-mmc-set-core-clock-phase-to-270-deg.patch
* gnu/packages/patches/amlogic-0026-WIP-arm64-dts-meson-add-Broadcom-WiFi-to-P212-dtsi.patch
* gnu/packages/patches/amlogic-0027-WIP-arm64-dts-meson-move-pwm_ef-node-in-P212-dtsi.patch
* gnu/packages/patches/amlogic-0028-WIP-arm64-dts-meson-remove-WiFi-BT-nodes-from-Khadas.patch
* gnu/packages/patches/amlogic-0029-WIP-arm64-dts-meson-set-p212-p23x-q20x-SDIO-to-100MH.patch
* gnu/packages/patches/amlogic-0030-WIP-arm64-dts-meson-add-UHS-SDIO-capabilities-to-p21.patch
* gnu/packages/patches/amlogic-0031-WIP-arm64-dts-meson-remove-SDIO-node-from-Khadas-VIM.patch
* gnu/packages/patches/amlogic-0032-WIP-arm64-dts-meson-add-audio-playback-to-S905X-P212.patch
* gnu/packages/patches/amlogic-0033-WIP-drivers-meson-vdec-remove-redundant-if-statement.patch
* gnu/packages/patches/amlogic-0034-WIP-drivers-meson-vdec-improve-mmu-and-fbc-handling-.patch
* gnu/packages/patches/amlogic-0035-WIP-drivers-meson-vdec-add-HEVC-decode-codec.patch
* gnu/packages/patches/amlogic-0036-WIP-drivers-meson-vdec-add-handling-to-HEVC-decoder-.patch
* gnu/packages/patches/amlogic-0037-WIP-drivers-meson-vdec-add-HEVC-support-to-GXBB.patch
* gnu/packages/patches/amlogic-0038-WIP-drivers-meson-vdec-check-if-parser-has-really-pa.patch
* gnu/packages/patches/amlogic-0039-WIP-arm64-dts-meson-radxa-zero-add-support-for-the-u.patch
* gnu/packages/patches/amlogic-0040-WIP-dt-bindings-arm-amlogic-add-support-for-Radxa-Ze.patch
* gnu/packages/patches/amlogic-0041-WIP-arm64-dts-meson-add-support-for-Radxa-Zero2.patch
* gnu/packages/patches/amlogic-0042-WIP-arm64-dts-meson-add-audio-playback-to-p201.patch
* gnu/packages/patches/amlogic-0043-WIP-arm64-dts-meson-add-audio-playback-to-p200.patch
* gnu/packages/patches/amlogic-0044-WIP-arm64-dts-meson-add-audio-playback-to-u200.patch
* gnu/packages/patches/amlogic-0045-WIP-arm64-dts-meson-add-Headphone-output-to-Beelink-.patch
* gnu/packages/patches/amlogic-0046-WIP-dt-bindings-arm-amlogic-add-support-for-the-Tani.patch
* gnu/packages/patches/amlogic-0047-WIP-arm64-dts-meson-add-support-for-the-Tanix-TX5-Ma.patch
* gnu/packages/patches/amlogic-0048-WIP-arm64-dts-meson-add-multiple-MeCool-device-trees.patch
* gnu/packages/patches/amlogic-0049-WIP-dt-bindings-arm-amlogic-add-support-for-Minix-NE.patch
* gnu/packages/patches/amlogic-0050-WIP-arm64-dts-meson-add-initial-device-tree-for-Mini.patch
* gnu/packages/patches/amlogic-0051-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch
* gnu/packages/patches/amlogic-0052-WIP-media-rc-add-keymap-for-Beelink-Mini-MXIII-remot.patch
* gnu/packages/patches/amlogic-0053-WIP-dt-bindings-arm-amlogic-add-support-for-Beelink-.patch
* gnu/packages/patches/amlogic-0054-WIP-arm64-dts-meson-add-support-for-Beelink-Mini-MXI.patch
* gnu/packages/patches/amlogic-0055-WIP-media-rc-add-keymap-for-MeCool-M8S-Pro-W-remote.patch
* gnu/packages/patches/amlogic-0056-WIP-dt-bindings-arm-amlogic-add-support-for-MeCool-M.patch
* gnu/packages/patches/amlogic-0057-WIP-arm64-dts-meson-add-support-for-MeCool-M8S-Pro-W.patch
* gnu/packages/patches/amlogic-0058-WIP-dt-bindings-arm-amlogic-add-Vero-4K-binding.patch
* gnu/packages/patches/amlogic-0059-WIP-arm64-dts-meson-add-support-for-OSMC-Vero-4K.patch
* gnu/packages/patches/amlogic-0060-WIP-arm64-dts-meson-add-RTL8822CS-bluetooth-to-X96-A.patch
* gnu/packages/patches/amlogic-0061-WIP-media-rc-add-keymap-for-Venz-V10-remote.patch
* gnu/packages/patches/amlogic-0062-WIP-dt-bindings-arm-amlogic-add-S905L-and-Venz-V10-b.patch
* gnu/packages/patches/amlogic-0063-WIP-arm64-dts-meson-add-support-for-Venz-V10.patch
* gnu/packages/patches/amlogic-0064-WIP-dt-bindings-vendor-prefixes-add-tbee-prefix.patch
* gnu/packages/patches/amlogic-0065-WIP-dt-bindings-arm-amlogic-add-TBee-Box-binding.patch
* gnu/packages/patches/amlogic-0066-WIP-arm64-dts-meson-add-support-for-TBee-Box.patch
* gnu/packages/patches/amlogic-0067-WIP-dt-bindings-arm-amlogic-add-Beelink-GT1-binding.patch
* gnu/packages/patches/amlogic-0068-WIP-arm64-dts-meson-add-support-for-Beelink-GT1.patch
* gnu/packages/patches/amlogic-0069-WIP-arm64-dts-meson-add-vcc_5v-regulator-to-WeTek-dt.patch
* gnu/packages/patches/amlogic-0070-WIP-arm64-dts-meson-add-audio-lineout-to-WeTek-Play2.patch
* gnu/packages/patches/amlogic-0071-WIP-arm64-dts-amlogic-fix-cvbs-disable-on-WeTek-Hub.patch
* gnu/packages/patches/amlogic-0072-WIP-ASoC-dt-bindings-add-compatible-for-es8323-i2c.patch
* gnu/packages/patches/amlogic-0073-WIP-ASoC-codecs-add-support-for-ES8323.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 3329801fa6..f3a1c6b3da 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -876,6 +876,79 @@ dist_patch_DATA =						\
   %D%/packages/patches/akonadi-paths.patch		\
   %D%/packages/patches/akonadi-not-relocatable.patch		\
   %D%/packages/patches/akonadi-timestamps.patch		\
+  %D%/packages/patches/amlogic-0001-LOCAL-set-meson-gx-cma-pool-to-896MB.patch \
+  %D%/packages/patches/amlogic-0002-LOCAL-set-meson-g12-cma-pool-to-896MB.patch \
+  %D%/packages/patches/amlogic-0003-LOCAL-arm64-fix-Kodi-sysinfo-CPU-information.patch \
+  %D%/packages/patches/amlogic-0004-LOCAL-arm64-meson-add-Amlogic-Meson-GX-PM-Suspend.patch \
+  %D%/packages/patches/amlogic-0005-LOCAL-arm64-dts-meson-add-support-for-GX-PM-and-Virt.patch \
+  %D%/packages/patches/amlogic-0006-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch \
+  %D%/packages/patches/amlogic-0007-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch \
+  %D%/packages/patches/amlogic-0008-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch \
+  %D%/packages/patches/amlogic-0009-LOCAL-ALSA-Assign-internal-PCM-chmap-ELD-IEC958-kctl.patch \
+  %D%/packages/patches/amlogic-0010-LOCAL-usb-hub-disable-autosuspend-for-Genesys-Logic-.patch \
+  %D%/packages/patches/amlogic-0011-LOCAL-of-partial-revert-of-fdt.c-changes.patch \
+  %D%/packages/patches/amlogic-0012-FROMGIT-drm-lima-Fix-opp-clkname-setting-in-case-of-.patch \
+  %D%/packages/patches/amlogic-0013-FROMGIT-6.1-dt-bindings-arm-amlogic-add-Beelink-GT1-.patch \
+  %D%/packages/patches/amlogic-0014-FROMGIT-6.1-arm64-dts-meson-add-support-for-Beelink-.patch \
+  %D%/packages/patches/amlogic-0015-FROMLIST-v2-arm64-dts-meson-make-dts-use-gpio-fan-ma.patch \
+  %D%/packages/patches/amlogic-0016-FROMLIST-v1-mmc-meson-gx-fix-deferred-probing.patch \
+  %D%/packages/patches/amlogic-0017-FROMLIST-v5-dt-bindings-vendor-prefixes-Add-Titan-Mi.patch \
+  %D%/packages/patches/amlogic-0018-FROMLIST-v5-dt-bindings-auxdisplay-Add-Titan-Micro-E.patch \
+  %D%/packages/patches/amlogic-0019-FROMLIST-v5-docs-ABI-document-tm1628-attribute-displ.patch \
+  %D%/packages/patches/amlogic-0020-FROMLIST-v5-auxdisplay-add-support-for-Titanmec-TM16.patch \
+  %D%/packages/patches/amlogic-0021-FROMLIST-v5-arm64-dts-meson-gxl-s905w-tx3-mini-add-s.patch \
+  %D%/packages/patches/amlogic-0022-FROMLIST-v5-MAINTAINERS-Add-entry-for-tm1628-auxdisp.patch \
+  %D%/packages/patches/amlogic-0023-FROMLIST-v1-drm-bridge-dw_hdmi-fix-preference-of-RGB.patch \
+  %D%/packages/patches/amlogic-0024-WIP-ASoC-hdmi-codec-reorder-channel-allocation-list.patch \
+  %D%/packages/patches/amlogic-0025-WIP-mmc-meson-gx-mmc-set-core-clock-phase-to-270-deg.patch \
+  %D%/packages/patches/amlogic-0026-WIP-arm64-dts-meson-add-Broadcom-WiFi-to-P212-dtsi.patch \
+  %D%/packages/patches/amlogic-0027-WIP-arm64-dts-meson-move-pwm_ef-node-in-P212-dtsi.patch \
+  %D%/packages/patches/amlogic-0028-WIP-arm64-dts-meson-remove-WiFi-BT-nodes-from-Khadas.patch \
+  %D%/packages/patches/amlogic-0029-WIP-arm64-dts-meson-set-p212-p23x-q20x-SDIO-to-100MH.patch \
+  %D%/packages/patches/amlogic-0030-WIP-arm64-dts-meson-add-UHS-SDIO-capabilities-to-p21.patch \
+  %D%/packages/patches/amlogic-0031-WIP-arm64-dts-meson-remove-SDIO-node-from-Khadas-VIM.patch \
+  %D%/packages/patches/amlogic-0032-WIP-arm64-dts-meson-add-audio-playback-to-S905X-P212.patch \
+  %D%/packages/patches/amlogic-0033-WIP-drivers-meson-vdec-remove-redundant-if-statement.patch \
+  %D%/packages/patches/amlogic-0034-WIP-drivers-meson-vdec-improve-mmu-and-fbc-handling-.patch \
+  %D%/packages/patches/amlogic-0035-WIP-drivers-meson-vdec-add-HEVC-decode-codec.patch \
+  %D%/packages/patches/amlogic-0036-WIP-drivers-meson-vdec-add-handling-to-HEVC-decoder-.patch \
+  %D%/packages/patches/amlogic-0037-WIP-drivers-meson-vdec-add-HEVC-support-to-GXBB.patch \
+  %D%/packages/patches/amlogic-0038-WIP-drivers-meson-vdec-check-if-parser-has-really-pa.patch \
+  %D%/packages/patches/amlogic-0039-WIP-arm64-dts-meson-radxa-zero-add-support-for-the-u.patch \
+  %D%/packages/patches/amlogic-0040-WIP-dt-bindings-arm-amlogic-add-support-for-Radxa-Ze.patch \
+  %D%/packages/patches/amlogic-0041-WIP-arm64-dts-meson-add-support-for-Radxa-Zero2.patch \
+  %D%/packages/patches/amlogic-0042-WIP-arm64-dts-meson-add-audio-playback-to-p201.patch \
+  %D%/packages/patches/amlogic-0043-WIP-arm64-dts-meson-add-audio-playback-to-p200.patch \
+  %D%/packages/patches/amlogic-0044-WIP-arm64-dts-meson-add-audio-playback-to-u200.patch \
+  %D%/packages/patches/amlogic-0045-WIP-arm64-dts-meson-add-Headphone-output-to-Beelink-.patch \
+  %D%/packages/patches/amlogic-0046-WIP-dt-bindings-arm-amlogic-add-support-for-the-Tani.patch \
+  %D%/packages/patches/amlogic-0047-WIP-arm64-dts-meson-add-support-for-the-Tanix-TX5-Ma.patch \
+  %D%/packages/patches/amlogic-0048-WIP-arm64-dts-meson-add-multiple-MeCool-device-trees.patch \
+  %D%/packages/patches/amlogic-0049-WIP-dt-bindings-arm-amlogic-add-support-for-Minix-NE.patch \
+  %D%/packages/patches/amlogic-0050-WIP-arm64-dts-meson-add-initial-device-tree-for-Mini.patch \
+  %D%/packages/patches/amlogic-0051-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch \
+  %D%/packages/patches/amlogic-0052-WIP-media-rc-add-keymap-for-Beelink-Mini-MXIII-remot.patch \
+  %D%/packages/patches/amlogic-0053-WIP-dt-bindings-arm-amlogic-add-support-for-Beelink-.patch \
+  %D%/packages/patches/amlogic-0054-WIP-arm64-dts-meson-add-support-for-Beelink-Mini-MXI.patch \
+  %D%/packages/patches/amlogic-0055-WIP-media-rc-add-keymap-for-MeCool-M8S-Pro-W-remote.patch \
+  %D%/packages/patches/amlogic-0056-WIP-dt-bindings-arm-amlogic-add-support-for-MeCool-M.patch \
+  %D%/packages/patches/amlogic-0057-WIP-arm64-dts-meson-add-support-for-MeCool-M8S-Pro-W.patch \
+  %D%/packages/patches/amlogic-0058-WIP-dt-bindings-arm-amlogic-add-Vero-4K-binding.patch \
+  %D%/packages/patches/amlogic-0059-WIP-arm64-dts-meson-add-support-for-OSMC-Vero-4K.patch \
+  %D%/packages/patches/amlogic-0060-WIP-arm64-dts-meson-add-RTL8822CS-bluetooth-to-X96-A.patch \
+  %D%/packages/patches/amlogic-0061-WIP-media-rc-add-keymap-for-Venz-V10-remote.patch \
+  %D%/packages/patches/amlogic-0062-WIP-dt-bindings-arm-amlogic-add-S905L-and-Venz-V10-b.patch \
+  %D%/packages/patches/amlogic-0063-WIP-arm64-dts-meson-add-support-for-Venz-V10.patch \
+  %D%/packages/patches/amlogic-0064-WIP-dt-bindings-vendor-prefixes-add-tbee-prefix.patch \
+  %D%/packages/patches/amlogic-0065-WIP-dt-bindings-arm-amlogic-add-TBee-Box-binding.patch \
+  %D%/packages/patches/amlogic-0066-WIP-arm64-dts-meson-add-support-for-TBee-Box.patch \
+  %D%/packages/patches/amlogic-0067-WIP-dt-bindings-arm-amlogic-add-Beelink-GT1-binding.patch \
+  %D%/packages/patches/amlogic-0068-WIP-arm64-dts-meson-add-support-for-Beelink-GT1.patch \
+  %D%/packages/patches/amlogic-0069-WIP-arm64-dts-meson-add-vcc_5v-regulator-to-WeTek-dt.patch \
+  %D%/packages/patches/amlogic-0070-WIP-arm64-dts-meson-add-audio-lineout-to-WeTek-Play2.patch \
+  %D%/packages/patches/amlogic-0071-WIP-arm64-dts-amlogic-fix-cvbs-disable-on-WeTek-Hub.patch \
+  %D%/packages/patches/amlogic-0072-WIP-ASoC-dt-bindings-add-compatible-for-es8323-i2c.patch \
+  %D%/packages/patches/amlogic-0073-WIP-ASoC-codecs-add-support-for-ES8323.patch \
   %D%/packages/patches/allegro-mesa-18.2.5-and-later.patch	\
   %D%/packages/patches/anki-mpv-args.patch			\
   %D%/packages/patches/antiword-CVE-2014-8123.patch			\
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index c9a21f590f..279a5461c1 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -1286,6 +1286,90 @@ (define-public linux-libre-arm64-generic
                         ("CONFIG_SND_SOC_ES8316" . m))
                       %default-extra-linux-options)))
 
+(define-public linux-libre-arm64-amlogic
+    (package
+      (inherit linux-libre-arm64-generic)
+      (source (origin
+                (inherit (package-source linux-libre-arm64-generic))
+                ;; Patches from https://github.com/chewitt/LibreELEC.tv.git
+                ;; branch origin/amlogic-upstream
+                ;; commit 38506614e64563cc70be87fe3762d18d49be21d4
+                (patches (append (search-patches
+"amlogic-0001-LOCAL-set-meson-gx-cma-pool-to-896MB.patch"
+"amlogic-0002-LOCAL-set-meson-g12-cma-pool-to-896MB.patch"
+"amlogic-0003-LOCAL-arm64-fix-Kodi-sysinfo-CPU-information.patch"
+"amlogic-0004-LOCAL-arm64-meson-add-Amlogic-Meson-GX-PM-Suspend.patch"
+"amlogic-0005-LOCAL-arm64-dts-meson-add-support-for-GX-PM-and-Virt.patch"
+"amlogic-0006-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch"
+"amlogic-0007-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch"
+"amlogic-0008-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch"
+"amlogic-0009-LOCAL-ALSA-Assign-internal-PCM-chmap-ELD-IEC958-kctl.patch"
+"amlogic-0010-LOCAL-usb-hub-disable-autosuspend-for-Genesys-Logic-.patch"
+"amlogic-0011-LOCAL-of-partial-revert-of-fdt.c-changes.patch"
+"amlogic-0013-FROMGIT-6.1-dt-bindings-arm-amlogic-add-Beelink-GT1-.patch"
+"amlogic-0014-FROMGIT-6.1-arm64-dts-meson-add-support-for-Beelink-.patch"
+"amlogic-0015-FROMLIST-v2-arm64-dts-meson-make-dts-use-gpio-fan-ma.patch"
+"amlogic-0016-FROMLIST-v1-mmc-meson-gx-fix-deferred-probing.patch"
+"amlogic-0017-FROMLIST-v5-dt-bindings-vendor-prefixes-Add-Titan-Mi.patch"
+"amlogic-0018-FROMLIST-v5-dt-bindings-auxdisplay-Add-Titan-Micro-E.patch"
+"amlogic-0019-FROMLIST-v5-docs-ABI-document-tm1628-attribute-displ.patch"
+"amlogic-0020-FROMLIST-v5-auxdisplay-add-support-for-Titanmec-TM16.patch"
+"amlogic-0021-FROMLIST-v5-arm64-dts-meson-gxl-s905w-tx3-mini-add-s.patch"
+"amlogic-0022-FROMLIST-v5-MAINTAINERS-Add-entry-for-tm1628-auxdisp.patch"
+"amlogic-0023-FROMLIST-v1-drm-bridge-dw_hdmi-fix-preference-of-RGB.patch"
+"amlogic-0024-WIP-ASoC-hdmi-codec-reorder-channel-allocation-list.patch"
+"amlogic-0025-WIP-mmc-meson-gx-mmc-set-core-clock-phase-to-270-deg.patch"
+"amlogic-0026-WIP-arm64-dts-meson-add-Broadcom-WiFi-to-P212-dtsi.patch"
+"amlogic-0027-WIP-arm64-dts-meson-move-pwm_ef-node-in-P212-dtsi.patch"
+"amlogic-0028-WIP-arm64-dts-meson-remove-WiFi-BT-nodes-from-Khadas.patch"
+"amlogic-0029-WIP-arm64-dts-meson-set-p212-p23x-q20x-SDIO-to-100MH.patch"
+"amlogic-0030-WIP-arm64-dts-meson-add-UHS-SDIO-capabilities-to-p21.patch"
+"amlogic-0031-WIP-arm64-dts-meson-remove-SDIO-node-from-Khadas-VIM.patch"
+"amlogic-0032-WIP-arm64-dts-meson-add-audio-playback-to-S905X-P212.patch"
+"amlogic-0033-WIP-drivers-meson-vdec-remove-redundant-if-statement.patch"
+"amlogic-0034-WIP-drivers-meson-vdec-improve-mmu-and-fbc-handling-.patch"
+"amlogic-0035-WIP-drivers-meson-vdec-add-HEVC-decode-codec.patch"
+"amlogic-0036-WIP-drivers-meson-vdec-add-handling-to-HEVC-decoder-.patch"
+"amlogic-0037-WIP-drivers-meson-vdec-add-HEVC-support-to-GXBB.patch"
+"amlogic-0038-WIP-drivers-meson-vdec-check-if-parser-has-really-pa.patch"
+"amlogic-0039-WIP-arm64-dts-meson-radxa-zero-add-support-for-the-u.patch"
+"amlogic-0040-WIP-dt-bindings-arm-amlogic-add-support-for-Radxa-Ze.patch"
+"amlogic-0041-WIP-arm64-dts-meson-add-support-for-Radxa-Zero2.patch"
+"amlogic-0042-WIP-arm64-dts-meson-add-audio-playback-to-p201.patch"
+"amlogic-0043-WIP-arm64-dts-meson-add-audio-playback-to-p200.patch"
+"amlogic-0044-WIP-arm64-dts-meson-add-audio-playback-to-u200.patch"
+"amlogic-0045-WIP-arm64-dts-meson-add-Headphone-output-to-Beelink-.patch"
+"amlogic-0046-WIP-dt-bindings-arm-amlogic-add-support-for-the-Tani.patch"
+"amlogic-0047-WIP-arm64-dts-meson-add-support-for-the-Tanix-TX5-Ma.patch"
+"amlogic-0048-WIP-arm64-dts-meson-add-multiple-MeCool-device-trees.patch"
+"amlogic-0049-WIP-dt-bindings-arm-amlogic-add-support-for-Minix-NE.patch"
+"amlogic-0050-WIP-arm64-dts-meson-add-initial-device-tree-for-Mini.patch"
+"amlogic-0051-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch"
+"amlogic-0052-WIP-media-rc-add-keymap-for-Beelink-Mini-MXIII-remot.patch"
+"amlogic-0053-WIP-dt-bindings-arm-amlogic-add-support-for-Beelink-.patch"
+"amlogic-0054-WIP-arm64-dts-meson-add-support-for-Beelink-Mini-MXI.patch"
+"amlogic-0055-WIP-media-rc-add-keymap-for-MeCool-M8S-Pro-W-remote.patch"
+"amlogic-0056-WIP-dt-bindings-arm-amlogic-add-support-for-MeCool-M.patch"
+"amlogic-0057-WIP-arm64-dts-meson-add-support-for-MeCool-M8S-Pro-W.patch"
+"amlogic-0058-WIP-dt-bindings-arm-amlogic-add-Vero-4K-binding.patch"
+"amlogic-0059-WIP-arm64-dts-meson-add-support-for-OSMC-Vero-4K.patch"
+"amlogic-0060-WIP-arm64-dts-meson-add-RTL8822CS-bluetooth-to-X96-A.patch"
+"amlogic-0061-WIP-media-rc-add-keymap-for-Venz-V10-remote.patch"
+"amlogic-0062-WIP-dt-bindings-arm-amlogic-add-S905L-and-Venz-V10-b.patch"
+"amlogic-0063-WIP-arm64-dts-meson-add-support-for-Venz-V10.patch"
+"amlogic-0064-WIP-dt-bindings-vendor-prefixes-add-tbee-prefix.patch"
+"amlogic-0065-WIP-dt-bindings-arm-amlogic-add-TBee-Box-binding.patch"
+"amlogic-0066-WIP-arm64-dts-meson-add-support-for-TBee-Box.patch"
+"amlogic-0067-WIP-dt-bindings-arm-amlogic-add-Beelink-GT1-binding.patch"
+"amlogic-0068-WIP-arm64-dts-meson-add-support-for-Beelink-GT1.patch"
+"amlogic-0069-WIP-arm64-dts-meson-add-vcc_5v-regulator-to-WeTek-dt.patch"
+"amlogic-0070-WIP-arm64-dts-meson-add-audio-lineout-to-WeTek-Play2.patch"
+"amlogic-0071-WIP-arm64-dts-amlogic-fix-cvbs-disable-on-WeTek-Hub.patch"
+"amlogic-0072-WIP-ASoC-dt-bindings-add-compatible-for-es8323-i2c.patch"
+"amlogic-0073-WIP-ASoC-codecs-add-support-for-ES8323.patch")
+                                 (origin-patches (package-source
+								 linux-libre-arm64-generic))))))))
+
 (define-public linux-libre-arm64-generic-5.10
   (make-linux-libre* linux-libre-5.10-version
                      linux-libre-5.10-gnu-revision
diff --git a/gnu/packages/patches/amlogic-0001-LOCAL-set-meson-gx-cma-pool-to-896MB.patch b/gnu/packages/patches/amlogic-0001-LOCAL-set-meson-gx-cma-pool-to-896MB.patch
new file mode 100644
index 0000000000..cae02b7907
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0001-LOCAL-set-meson-gx-cma-pool-to-896MB.patch
@@ -0,0 +1,28 @@
+From bbbc1a8a588a2f899c67941f054dfeb250233a19 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 13 Apr 2019 05:41:51 +0000
+Subject: [PATCH 01/73] LOCAL: 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 <[email-masked]>
+---
+ 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 023a52005494..ca0d1733d515 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+@@ -58,7 +58,7 @@
+ 		linux,cma {
+ 			compatible = "shared-dma-pool";
+ 			reusable;
+-			size = <0x0 0x10000000>;
++			size = <0x0 0x38000000>;
+ 			alignment = <0x0 0x400000>;
+ 			linux,cma-default;
+ 		};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0002-LOCAL-set-meson-g12-cma-pool-to-896MB.patch b/gnu/packages/patches/amlogic-0002-LOCAL-set-meson-g12-cma-pool-to-896MB.patch
new file mode 100644
index 0000000000..6a69784629
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0002-LOCAL-set-meson-g12-cma-pool-to-896MB.patch
@@ -0,0 +1,28 @@
+From 391e4a8fc138daf6fba77392eb6ebe688f2f6468 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 14 Aug 2019 19:58:14 +0000
+Subject: [PATCH 02/73] LOCAL: 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 <[email-masked]>
+---
+ 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 45947c1031c4..2c56b216d6f9 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 @@
+ 		linux,cma {
+ 			compatible = "shared-dma-pool";
+ 			reusable;
+-			size = <0x0 0x10000000>;
++			size = <0x0 0x38000000>;
+ 			alignment = <0x0 0x400000>;
+ 			linux,cma-default;
+ 		};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0003-LOCAL-arm64-fix-Kodi-sysinfo-CPU-information.patch b/gnu/packages/patches/amlogic-0003-LOCAL-arm64-fix-Kodi-sysinfo-CPU-information.patch
new file mode 100644
index 0000000000..93ab3092e9
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0003-LOCAL-arm64-fix-Kodi-sysinfo-CPU-information.patch
@@ -0,0 +1,31 @@
+From b0f2464452ed2c0cf69e2dee5a1c054fa1b0e6cc Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 13 Apr 2019 05:45:18 +0000
+Subject: [PATCH 03/73] LOCAL: arm64: fix Kodi sysinfo CPU information
+
+This allows the CPU information to show in the Kodi sysinfo screen, e.g.
+
+"ARMv8 Processor rev 4 (v81)" on Amlogic devices
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/kernel/cpuinfo.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
+index d7702f39b4d3..4b6ac49e34b4 100644
+--- a/arch/arm64/kernel/cpuinfo.c
++++ b/arch/arm64/kernel/cpuinfo.c
+@@ -169,8 +169,7 @@ static int c_show(struct seq_file *m, void *v)
+ 		 * "processor".  Give glibc what it expects.
+ 		 */
+ 		seq_printf(m, "processor\t: %d\n", i);
+-		if (compat)
+-			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
++		seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+ 				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
+ 
+ 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0004-LOCAL-arm64-meson-add-Amlogic-Meson-GX-PM-Suspend.patch b/gnu/packages/patches/amlogic-0004-LOCAL-arm64-meson-add-Amlogic-Meson-GX-PM-Suspend.patch
new file mode 100644
index 0000000000..aff6da285e
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0004-LOCAL-arm64-meson-add-Amlogic-Meson-GX-PM-Suspend.patch
@@ -0,0 +1,135 @@
+From d0e70c5cf59999273d7f25ac7153f959a9f12f42 Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <[email-masked]>
+Date: Thu, 3 Nov 2016 15:29:23 +0100
+Subject: [PATCH 04/73] LOCAL: arm64: meson: add Amlogic Meson GX PM Suspend
+
+The Amlogic Meson GX SoCs uses a non-standard argument to the
+PSCI CPU_SUSPEND call to enter system suspend.
+
+Implement such call within platform_suspend_ops.
+
+Signed-off-by: Neil Armstrong <[email-masked]>
+---
+ drivers/firmware/meson/Kconfig       |  6 ++
+ drivers/firmware/meson/Makefile      |  1 +
+ drivers/firmware/meson/meson_gx_pm.c | 86 ++++++++++++++++++++++++++++
+ 3 files changed, 93 insertions(+)
+ create mode 100644 drivers/firmware/meson/meson_gx_pm.c
+
+diff --git a/drivers/firmware/meson/Kconfig b/drivers/firmware/meson/Kconfig
+index f2fdd3756648..d3ead92ac61b 100644
+--- a/drivers/firmware/meson/Kconfig
++++ b/drivers/firmware/meson/Kconfig
+@@ -9,3 +9,9 @@ config MESON_SM
+ 	depends on ARM64_4K_PAGES
+ 	help
+ 	  Say y here to enable the Amlogic secure monitor driver
++
++config MESON_GX_PM
++	bool
++	default ARCH_MESON if ARM64
++	help
++	  Say y here to enable the Amlogic GX SoC Power Management
+diff --git a/drivers/firmware/meson/Makefile b/drivers/firmware/meson/Makefile
+index c6c09483b622..0193cdfee32f 100644
+--- a/drivers/firmware/meson/Makefile
++++ b/drivers/firmware/meson/Makefile
+@@ -1,2 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_MESON_SM) +=	meson_sm.o
++obj-$(CONFIG_MESON_GX_PM) +=	meson_gx_pm.o
+diff --git a/drivers/firmware/meson/meson_gx_pm.c b/drivers/firmware/meson/meson_gx_pm.c
+new file mode 100644
+index 000000000000..c104c2e4c77f
+--- /dev/null
++++ b/drivers/firmware/meson/meson_gx_pm.c
+@@ -0,0 +1,86 @@
++/*
++ * Amlogic Meson GX Power Management
++ *
++ * Copyright (c) 2016 Baylibre, SAS.
++ * Author: Neil Armstrong <[email-masked]>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ */
++
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/suspend.h>
++#include <linux/arm-smccc.h>
++
++#include <uapi/linux/psci.h>
++
++#include <asm/suspend.h>
++
++/*
++ * The Amlogic GX SoCs uses a special argument value to the
++ * PSCI CPU_SUSPEND method to enter SUSPEND_MEM.
++ */
++
++#define MESON_SUSPEND_PARAM	0x0010000
++#define PSCI_FN_NATIVE(version, name)	PSCI_##version##_FN64_##name
++
++static int meson_gx_suspend_finish(unsigned long arg)
++{
++	struct arm_smccc_res res;
++
++	arm_smccc_smc(PSCI_FN_NATIVE(0_2, CPU_SUSPEND), arg,
++		      virt_to_phys(cpu_resume), 0, 0, 0, 0, 0, &res);
++
++	return res.a0;
++}
++
++static int meson_gx_suspend_enter(suspend_state_t state)
++{
++	switch (state) {
++	case PM_SUSPEND_MEM:
++		return cpu_suspend(MESON_SUSPEND_PARAM,
++				   meson_gx_suspend_finish);
++	}
++
++	return -EINVAL;
++}
++
++static const struct platform_suspend_ops meson_gx_pm_ops = {
++		.enter = meson_gx_suspend_enter,
++		.valid = suspend_valid_only_mem,
++};
++
++static const struct of_device_id meson_gx_pm_match[] = {
++	{ .compatible = "amlogic,meson-gx-pm", },
++	{ /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(of, meson_gx_pm_match);
++
++static int meson_gx_pm_probe(struct platform_device *pdev)
++{
++	suspend_set_ops(&meson_gx_pm_ops);
++
++	return 0;
++}
++
++static struct platform_driver meson_gx_pm_driver = {
++	.probe = meson_gx_pm_probe,
++	.driver = {
++		.name = "meson-gx-pm",
++		.of_match_table = meson_gx_pm_match,
++	},
++};
++
++module_platform_driver(meson_gx_pm_driver);
++
++MODULE_AUTHOR("Neil Armstrong <[email-masked]>");
++MODULE_DESCRIPTION("Amlogic Meson GX PM driver");
++MODULE_LICENSE("GPL v2");
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0005-LOCAL-arm64-dts-meson-add-support-for-GX-PM-and-Virt.patch b/gnu/packages/patches/amlogic-0005-LOCAL-arm64-dts-meson-add-support-for-GX-PM-and-Virt.patch
new file mode 100644
index 0000000000..56be695e9c
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0005-LOCAL-arm64-dts-meson-add-support-for-GX-PM-and-Virt.patch
@@ -0,0 +1,41 @@
+From 482d13486412a6b33ceb9e64c87e6394942834e9 Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <[email-masked]>
+Date: Thu, 3 Nov 2016 15:29:25 +0100
+Subject: [PATCH 05/73] LOCAL: arm64: dts: meson: add support for GX PM and
+ Virtual RTC
+
+Signed-off-by: Neil Armstrong <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+index ca0d1733d515..b278a8380f8a 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+@@ -221,6 +221,10 @@
+ 		};
+ 	};
+ 
++	system-suspend {
++		compatible = "amlogic,meson-gx-pm";
++	};
++
+ 	efuse: efuse {
+ 		compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse";
+ 		#address-cells = <1>;
+@@ -459,6 +463,11 @@
+ 				};
+ 			};
+ 
++			vrtc: rtc@a8 {
++				compatible = "amlogic,meson-vrtc";
++				reg = <0x0 0x000a8 0x0 0x4>;
++			};
++
+ 			cec_AO: cec@100 {
+ 				compatible = "amlogic,meson-gx-ao-cec";
+ 				reg = <0x0 0x00100 0x0 0x14>;
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0006-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch b/gnu/packages/patches/amlogic-0006-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch
new file mode 100644
index 0000000000..dea97bfebc
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0006-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch
@@ -0,0 +1,30 @@
+From 411cb7102c7addd30d31b41f21471d57df8e2124 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Thu, 21 Jan 2021 01:35:36 +0000
+Subject: [PATCH 06/73] LOCAL: arm64: dts: meson: add rtc/vrtc aliases to
+ Khadas VIM
+
+Add aliases to ensure the vrtc time (which normally proves first) is /dev/rtc1
+while the onboard rtc chip claims /dev/rtc0.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+index 6ab1cc125b96..24af15e18026 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+@@ -29,6 +29,8 @@
+ 	aliases {
+ 		serial2 = &uart_AO_B;
+ 		ethernet0 = &ethmac;
++		rtc0 = &rtc;
++		rtc1 = &vrtc;
+ 	};
+ 
+ 	gpio-keys-polled {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0007-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch b/gnu/packages/patches/amlogic-0007-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch
new file mode 100644
index 0000000000..a9d254f640
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0007-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Khadas.patch
@@ -0,0 +1,30 @@
+From 1786033be020b8a5ab6a86646135e8df2e294524 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 6 Nov 2021 13:01:08 +0000
+Subject: [PATCH 07/73] LOCAL: arm64: dts: meson: add rtc/vrtc aliases to
+ Khadas VIM2
+
+Add aliases to ensure the vrtc time (which normally proves first) is /dev/rtc1
+while the onboard rtc chip claims /dev/rtc0.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+index f43c45daf7eb..6d396c1be3d6 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+@@ -18,6 +18,8 @@
+ 	aliases {
+ 		serial0 = &uart_AO;
+ 		serial2 = &uart_AO_B;
++		rtc0 = &rtc;
++		rtc1 = &vrtc;
+ 	};
+ 
+ 	chosen {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0008-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch b/gnu/packages/patches/amlogic-0008-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch
new file mode 100644
index 0000000000..9ba8d6137a
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0008-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch
@@ -0,0 +1,32 @@
+From eae65baf2f29a74a7fe9d349501561b50439abfe Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Mon, 1 Feb 2021 19:27:40 +0000
+Subject: [PATCH 08/73] LOCAL: arm64: dts: meson: add rtc/vrtc aliases to Minix
+ NEO U9-H
+
+Add node aliases to prevent meson-vrtc from claiming /dev/rtc0
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts
+index b8ef3bd8b840..0920e7b096f5 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts
+@@ -14,6 +14,11 @@
+ 	compatible = "minix,neo-u9h", "amlogic,s912", "amlogic,meson-gxm";
+ 	model = "Minix Neo U9-H";
+ 
++	aliases {
++		rtc0 = &rtc;
++		rtc1 = &vrtc;
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0009-LOCAL-ALSA-Assign-internal-PCM-chmap-ELD-IEC958-kctl.patch b/gnu/packages/patches/amlogic-0009-LOCAL-ALSA-Assign-internal-PCM-chmap-ELD-IEC958-kctl.patch
new file mode 100644
index 0000000000..ba65fe5e6e
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0009-LOCAL-ALSA-Assign-internal-PCM-chmap-ELD-IEC958-kctl.patch
@@ -0,0 +1,59 @@
+From 04bdcad098193dda5988bb96bfae7178834b13b0 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <[email-masked]>
+Date: Sun, 17 Apr 2022 04:37:48 +0000
+Subject: [PATCH 09/73] LOCAL: ALSA: Assign internal PCM chmap/ELD/IEC958 kctls
+ to device 0
+
+On SoC sound devices utilizing codec2codec DAI links with a HDMI codec
+the kctls for chmap, ELD, IEC958 are currently created using the
+internal PCM device numbers. This causes userspace to not see the
+actual channel mapping.
+
+Affected devices include LibreTech LePotato and Wetek Play 2.
+
+The proper fix would be not create these kctls for internal PCMs and
+instead create them for the real userspace-visible PCMs, somehow
+forwarding the controls between the HDMI codec and the real PCM.
+
+As a workaround, simply use device=0 for all channel map controls and
+SoC HDMI codec controls for internal PCM devices.
+
+Signed-off-by: Anssi Hannula <[email-masked]>
+---
+ sound/core/pcm_lib.c          | 5 ++++-
+ sound/soc/codecs/hdmi-codec.c | 3 ++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 40751e5aff09..1461463dc320 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2514,7 +2514,10 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
+ 		knew.name = "Playback Channel Map";
+ 	else
+ 		knew.name = "Capture Channel Map";
+-	knew.device = pcm->device;
++	if (pcm->internal && pcm->device)
++		dev_info(pcm->card->dev, "workaround active: internal PCM chmap controls mapped to device 0\n");
++	else
++		knew.device = pcm->device;
+ 	knew.count = pcm->streams[stream].substream_count;
+ 	knew.private_value = private_value;
+ 	info->kctl = snd_ctl_new1(&knew, info);
+diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
+index 5679102de91f..aa2ca5078551 100644
+--- a/sound/soc/codecs/hdmi-codec.c
++++ b/sound/soc/codecs/hdmi-codec.c
+@@ -797,7 +797,8 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
+ 		if (!kctl)
+ 			return -ENOMEM;
+ 
+-		kctl->id.device = rtd->pcm->device;
++		if (!rtd->pcm->internal)
++			kctl->id.device = rtd->pcm->device;
+ 		ret = snd_ctl_add(rtd->card->snd_card, kctl);
+ 		if (ret < 0)
+ 			return ret;
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0010-LOCAL-usb-hub-disable-autosuspend-for-Genesys-Logic-.patch b/gnu/packages/patches/amlogic-0010-LOCAL-usb-hub-disable-autosuspend-for-Genesys-Logic-.patch
new file mode 100644
index 0000000000..b899e43d63
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0010-LOCAL-usb-hub-disable-autosuspend-for-Genesys-Logic-.patch
@@ -0,0 +1,34 @@
+From 080a637d2fedf1d550f2fcee2da8520cb2456122 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Mon, 3 Jan 2022 10:44:17 +0000
+Subject: [PATCH 10/73] LOCAL: usb: hub: disable autosuspend for Genesys Logic
+ Hubs
+
+Disable autosuspend in Genesys Logic hubs to allow USB devices on the
+Odroid C2 board to be used. The alternative to this patch is setting
+usbcore.autosuspend=-1 in boot params.
+
+This patch only impacts GXBB devices as GXL/GXM onwards use the newer
+dwc3 core which does not have the problem.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ drivers/usb/core/hub.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index bbab424b0d55..ccfd0b312867 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5797,7 +5797,7 @@ static const struct usb_device_id hub_id_table[] = {
+ 			| USB_DEVICE_ID_MATCH_INT_CLASS,
+       .idVendor = USB_VENDOR_GENESYS_LOGIC,
+       .bInterfaceClass = USB_CLASS_HUB,
+-      .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
++      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
+     { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
+       .bDeviceClass = USB_CLASS_HUB},
+     { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0011-LOCAL-of-partial-revert-of-fdt.c-changes.patch b/gnu/packages/patches/amlogic-0011-LOCAL-of-partial-revert-of-fdt.c-changes.patch
new file mode 100644
index 0000000000..4f23598f6b
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0011-LOCAL-of-partial-revert-of-fdt.c-changes.patch
@@ -0,0 +1,38 @@
+From 31cdc54e582baafbe8e2daf291c35b027081f01d Mon Sep 17 00:00:00 2001
+From: Stefan Agner <[email-masked]>
+Date: Wed, 15 Sep 2021 05:00:45 +0000
+Subject: [PATCH 11/73] LOCAL: 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 <[email-masked]>
+---
+ drivers/of/fdt.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
+index 1c573e7a60bc..f9188a76500d 100644
+--- a/drivers/of/fdt.c
++++ b/drivers/of/fdt.c
+@@ -481,15 +481,6 @@ static int __init early_init_dt_reserve_memory(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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0012-FROMGIT-drm-lima-Fix-opp-clkname-setting-in-case-of-.patch b/gnu/packages/patches/amlogic-0012-FROMGIT-drm-lima-Fix-opp-clkname-setting-in-case-of-.patch
new file mode 100644
index 0000000000..d1abb419ea
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0012-FROMGIT-drm-lima-Fix-opp-clkname-setting-in-case-of-.patch
@@ -0,0 +1,57 @@
+From 7712306891a8e02c0253f4b6f68101cf4e567e3a Mon Sep 17 00:00:00 2001
+From: Erico Nunes <[email-masked]>
+Date: Fri, 18 Nov 2022 03:00:39 +0000
+Subject: [PATCH 12/73] FROMGIT: drm/lima: Fix opp clkname setting in case of
+ missing regulator
+
+Commit d8c32d3971e4 ("drm/lima: Migrate to dev_pm_opp_set_config()")
+introduced a regression as it may undo the clk_names setting in case
+the optional regulator is missing. This resulted in test and performance
+regressions with lima.
+
+Restore the old behavior where clk_names is set separately so it is not
+undone in case of a missing optional regulator.
+
+Fixes: d8c32d3971e4 ("drm/lima: Migrate to dev_pm_opp_set_config()")
+Signed-off-by: Erico Nunes <[email-masked]>
+Acked-by: Viresh Kumar <[email-masked]>
+---
+ drivers/gpu/drm/lima/lima_devfreq.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c
+index 011be7ff51e1..bc8fb4e38d0a 100644
+--- a/drivers/gpu/drm/lima/lima_devfreq.c
++++ b/drivers/gpu/drm/lima/lima_devfreq.c
+@@ -112,11 +112,6 @@ int lima_devfreq_init(struct lima_device *ldev)
+ 	unsigned long cur_freq;
+ 	int ret;
+ 	const char *regulator_names[] = { "mali", NULL };
+-	const char *clk_names[] = { "core", NULL };
+-	struct dev_pm_opp_config config = {
+-		.regulator_names = regulator_names,
+-		.clk_names = clk_names,
+-	};
+ 
+ 	if (!device_property_present(dev, "operating-points-v2"))
+ 		/* Optional, continue without devfreq */
+@@ -124,7 +119,15 @@ int lima_devfreq_init(struct lima_device *ldev)
+ 
+ 	spin_lock_init(&ldevfreq->lock);
+ 
+-	ret = devm_pm_opp_set_config(dev, &config);
++	/*
++	 * clkname is set separately so it is not affected by the optional
++	 * regulator setting which may return error.
++	 */
++	ret = devm_pm_opp_set_clkname(dev, "core");
++	if (ret)
++		return ret;
++
++	ret = devm_pm_opp_set_regulators(dev, regulator_names);
+ 	if (ret) {
+ 		/* Continue if the optional regulator is missing */
+ 		if (ret != -ENODEV)
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0013-FROMGIT-6.1-dt-bindings-arm-amlogic-add-Beelink-GT1-.patch b/gnu/packages/patches/amlogic-0013-FROMGIT-6.1-dt-bindings-arm-amlogic-add-Beelink-GT1-.patch
new file mode 100644
index 0000000000..ff43e9fd70
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0013-FROMGIT-6.1-dt-bindings-arm-amlogic-add-Beelink-GT1-.patch
@@ -0,0 +1,30 @@
+From f159c2cb2327d34823fb0731da4f3e7438fad3a9 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 6 Jul 2022 09:58:31 +0000
+Subject: [PATCH 13/73] FROMGIT(6.1): dt-bindings: arm: amlogic: add Beelink
+ GT1 Ultimate binding
+
+Add the board binding for the Shenzen AZW (Beelink) GT1 Ultimate
+Android Set-Top Box device.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+Acked-by: Rob Herring <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index 61a6cabb375b..3217c069673e 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -120,6 +120,7 @@ properties:
+           - enum:
+               - amlogic,q200
+               - amlogic,q201
++              - azw,gt1-ultimate
+               - khadas,vim2
+               - kingnovel,r-box-pro
+               - libretech,aml-s912-pc
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0014-FROMGIT-6.1-arm64-dts-meson-add-support-for-Beelink-.patch b/gnu/packages/patches/amlogic-0014-FROMGIT-6.1-arm64-dts-meson-add-support-for-Beelink-.patch
new file mode 100644
index 0000000000..80cf1d84a7
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0014-FROMGIT-6.1-arm64-dts-meson-add-support-for-Beelink-.patch
@@ -0,0 +1,141 @@
+From 11d8541da45ed52bd6363b8be424289149cb7b7a Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 6 Jul 2022 09:58:31 +0000
+Subject: [PATCH 14/73] FROMGIT(6.1): arm64: dts: meson: add support for
+ Beelink GT1-Ultimate
+
+The Beelink GT1-Ultimate is based on the Amlogic S912 (Q200)
+reference design with the following specifications:
+
+- 3GB DDR3 RAM
+- 32GB eMMC
+- HDMI 2.1 video
+- S/PDIF optical output
+- 10/100/1000 Ethernet
+- AP6356S Wireless (802.11 a/b/g/n, BT 4.2)
+- 3x USB 2.0 ports
+- IR receiver (internal)
+- 1x micro SD card slot
+- 1x Power LED (white)
+- 1x Reset button (internal)
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+Reviewed-by: Neil Armstrong <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |  1 +
+ .../dts/amlogic/meson-gxm-gt1-ultimate.dts    | 91 +++++++++++++++++++
+ 2 files changed, 92 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxm-gt1-ultimate.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 8773211df50e..641399fcbdd9 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -43,6 +43,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-gt1-ultimate.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-khadas-vim2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-mecool-kiii-pro.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-minix-neo-u9h.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-gt1-ultimate.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-gt1-ultimate.dts
+new file mode 100644
+index 000000000000..2c267884cc16
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxm-gt1-ultimate.dts
+@@ -0,0 +1,91 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) Christian Hewitt <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxm.dtsi"
++#include "meson-gx-p23x-q20x.dtsi"
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++	compatible = "azw,gt1-ultimate", "amlogic,s912", "amlogic,meson-gxm";
++	model = "Beelink GT1 Ultimate";
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-white {
++			color = <LED_COLOR_ID_WHITE>;
++			function = LED_FUNCTION_POWER;
++			gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
++			default-state = "on";
++			panic-indicator;
++		};
++	};
++
++	adc-keys {
++		compatible = "adc-keys";
++		io-channels = <&saradc 0>;
++		io-channel-names = "buttons";
++		keyup-threshold-microvolt = <1710000>;
++
++		button-function {
++			label = "update";
++			linux,code = <KEY_VENDOR>;
++			press-threshold-microvolt = <10000>;
++		};
++	};
++};
++
++&ethmac {
++	pinctrl-0 = <&eth_pins>;
++	pinctrl-names = "default";
++	phy-handle = <&external_phy>;
++	amlogic,tx-delay-ns = <2>;
++	phy-mode = "rgmii";
++};
++
++&external_mdio {
++	external_phy: ethernet-phy@0 {
++		/* Realtek RTL8211F (0x001cc916) */
++		reg = <0>;
++		max-speed = <1000>;
++
++		reset-assert-us = <10000>;
++		reset-deassert-us = <80000>;
++		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
++
++		interrupt-parent = <&gpio_intc>;
++		/* MAC_INTR on GPIOZ_15 */
++		interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-beelink-gs1";
++};
++
++&sd_emmc_a {
++	brcmf: wifi@1 {
++		reg = <1>;
++		compatible = "brcm,bcm4329-fmac";
++	};
++};
++
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "brcm,bcm43438-bt";
++		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		max-speed = <2000000>;
++		clocks = <&wifi32k>;
++		clock-names = "lpo";
++	};
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0015-FROMLIST-v2-arm64-dts-meson-make-dts-use-gpio-fan-ma.patch b/gnu/packages/patches/amlogic-0015-FROMLIST-v2-arm64-dts-meson-make-dts-use-gpio-fan-ma.patch
new file mode 100644
index 0000000000..e531a972f9
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0015-FROMLIST-v2-arm64-dts-meson-make-dts-use-gpio-fan-ma.patch
@@ -0,0 +1,40 @@
+From f1ff5687260210679d811005e7f3fb0ff48a51cc Mon Sep 17 00:00:00 2001
+From: David Heidelberg <[email-masked]>
+Date: Sat, 27 Nov 2021 07:23:35 +0000
+Subject: [PATCH 15/73] FROMLIST(v2): arm64: dts: meson: make dts use gpio-fan
+ matrix instead of array
+
+No functional changes.
+
+Adjust to comply with dt-schema requirements
+and make possible to validate values.
+
+Signed-off-by: David Heidelberg <[email-masked]>
+Acked-by: Martin Blumenstingl <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+index 6d396c1be3d6..9b0c7e9d0620 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+@@ -54,10 +54,11 @@
+ 		gpios = <&gpio GPIODV_14 GPIO_ACTIVE_HIGH
+ 			 &gpio GPIODV_15 GPIO_ACTIVE_HIGH>;
+ 		/* Dummy RPM values since fan is optional */
+-		gpio-fan,speed-map = <0 0
+-				      1 1
+-				      2 2
+-				      3 3>;
++		gpio-fan,speed-map =
++				<0 0>,
++				<1 1>,
++				<2 2>,
++				<3 3>;
+ 		#cooling-cells = <2>;
+ 	};
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0016-FROMLIST-v1-mmc-meson-gx-fix-deferred-probing.patch b/gnu/packages/patches/amlogic-0016-FROMLIST-v1-mmc-meson-gx-fix-deferred-probing.patch
new file mode 100644
index 0000000000..fcbd7b2434
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0016-FROMLIST-v1-mmc-meson-gx-fix-deferred-probing.patch
@@ -0,0 +1,36 @@
+From fe266042ccee82d0997fdc437572de68ff9a1a76 Mon Sep 17 00:00:00 2001
+From: Sergey Shtylyov <[email-masked]>
+Date: Fri, 24 Dec 2021 06:09:57 +0000
+Subject: [PATCH 16/73] 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 <[email-masked]>
+Reviewed-by: Martin Blumenstingl <[email-masked]>
+---
+ 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 fc462995cf94..a2aacbffc3bf 100644
+--- a/drivers/mmc/host/meson-gx-mmc.c
++++ b/drivers/mmc/host/meson-gx-mmc.c
+@@ -1185,8 +1185,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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0017-FROMLIST-v5-dt-bindings-vendor-prefixes-Add-Titan-Mi.patch b/gnu/packages/patches/amlogic-0017-FROMLIST-v5-dt-bindings-vendor-prefixes-Add-Titan-Mi.patch
new file mode 100644
index 0000000000..2ab25b02d0
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0017-FROMLIST-v5-dt-bindings-vendor-prefixes-Add-Titan-Mi.patch
@@ -0,0 +1,34 @@
+From d04e53e0b5cc15aeee4cd078706226ea80d47dee Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Andreas=20F=C3=A4rber?= <[email-masked]>
+Date: Sun, 20 Feb 2022 08:23:12 +0000
+Subject: [PATCH 17/73] FROMLIST(v5): dt-bindings: vendor-prefixes: Add Titan
+ Micro Electronics
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Assign vendor prefix "titanmec", matching their domain name.
+
+Acked-by: Rob Herring <[email-masked]>
+Signed-off-by: Andreas Färber <[email-masked]>
+Signed-off-by: Heiner Kallweit <[email-masked]>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
+index 2f0151e9f6be..7163901e5976 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
+@@ -1291,6 +1291,8 @@ patternProperties:
+     description: Texas Instruments
+   "^tianma,.*":
+     description: Tianma Micro-electronics Co., Ltd.
++  "^titanmec,.*":
++    description: Shenzhen Titan Micro Electronics Co., Ltd.
+   "^tlm,.*":
+     description: Trusted Logic Mobility
+   "^tmt,.*":
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0018-FROMLIST-v5-dt-bindings-auxdisplay-Add-Titan-Micro-E.patch b/gnu/packages/patches/amlogic-0018-FROMLIST-v5-dt-bindings-auxdisplay-Add-Titan-Micro-E.patch
new file mode 100644
index 0000000000..09a49b6a28
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0018-FROMLIST-v5-dt-bindings-auxdisplay-Add-Titan-Micro-E.patch
@@ -0,0 +1,114 @@
+From 1bc9224b52be0df338c4e63e122460df0f651d96 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <[email-masked]>
+Date: Sun, 20 Feb 2022 08:24:47 +0000
+Subject: [PATCH 18/73] FROMLIST(v5): dt-bindings: auxdisplay: Add Titan Micro
+ Electronics TM1628
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add a YAML schema binding for TM1628 auxdisplay
+(7/11-segment LED) controller.
+
+This patch is partially based on previous RFC work from
+Andreas Färber <[email-masked]>.
+
+Co-developed-by: Andreas Färber <[email-masked]>
+Signed-off-by: Andreas Färber <[email-masked]>
+Signed-off-by: Heiner Kallweit <[email-masked]>
+---
+ .../bindings/auxdisplay/titanmec,tm1628.yaml  | 82 +++++++++++++++++++
+ 1 file changed, 82 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/auxdisplay/titanmec,tm1628.yaml
+
+diff --git a/Documentation/devicetree/bindings/auxdisplay/titanmec,tm1628.yaml b/Documentation/devicetree/bindings/auxdisplay/titanmec,tm1628.yaml
+new file mode 100644
+index 000000000000..d9cbbc950aab
+--- /dev/null
++++ b/Documentation/devicetree/bindings/auxdisplay/titanmec,tm1628.yaml
+@@ -0,0 +1,82 @@
++# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/leds/titanmec,tm1628.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Titan Micro Electronics TM1628 LED controller
++
++properties:
++  compatible:
++    enum:
++    - titanmec,tm1628
++
++  reg:
++    maxItems: 1
++
++  grid:
++    description:
++      Mapping of display digit position to grid number.
++      This implicitly defines the display size.
++    $ref: /schemas/types.yaml#/definitions/uint8-array
++    minItems: 1
++    maxItems: 7
++
++  segment-mapping:
++    description:
++      Mapping of 7 segment display segments A-G to bit numbers 1-12.
++    $ref: /schemas/types.yaml#/definitions/uint8-array
++    minItems: 7
++    maxItems: 7
++
++  "#address-cells":
++    const: 2
++
++  "#size-cells":
++    const: 0
++
++required:
++  - compatible
++  - reg
++
++patternProperties:
++  "^.*@[1-7],([1-9]|1[0-6])$":
++    type: object
++    description: |
++      Properties for a single LED.
++
++    properties:
++      reg:
++        description: |
++          1-based grid number, followed by 1-based segment bit number.
++        maxItems: 1
++
++    required:
++      - reg
++
++examples:
++  - |
++    #include <dt-bindings/leds/common.h>
++
++    spi {
++        #address-cells = <1>;
++        #size-cells = <0>;
++
++        led-controller@0 {
++            compatible = "titanmec,tm1628";
++            reg = <0>;
++            spi-3-wire;
++            spi-lsb-first;
++            spi-max-frequency = <500000>;
++            grid = /bits/ 8 <4 3 2 1>;
++            segment-mapping = /bits/ 8 <4 5 6 1 2 3 7>;
++            #address-cells = <2>;
++            #size-cells = <0>;
++
++            alarmn@5,4 {
++                reg = <5 4>;
++                function = LED_FUNCTION_ALARM;
++            };
++        };
++    };
++...
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0019-FROMLIST-v5-docs-ABI-document-tm1628-attribute-displ.patch b/gnu/packages/patches/amlogic-0019-FROMLIST-v5-docs-ABI-document-tm1628-attribute-displ.patch
new file mode 100644
index 0000000000..9c860b4e3e
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0019-FROMLIST-v5-docs-ABI-document-tm1628-attribute-displ.patch
@@ -0,0 +1,31 @@
+From 12d50549e630b703799379595f49c363ac6b8308 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <[email-masked]>
+Date: Sun, 20 Feb 2022 08:26:27 +0000
+Subject: [PATCH 19/73] FROMLIST(v5): docs: ABI: document tm1628 attribute
+ display-text
+
+Document the attribute for reading / writing the text to be displayed on
+the 7 segment display.
+
+Signed-off-by: Heiner Kallweit <[email-masked]>
+---
+ Documentation/ABI/testing/sysfs-devices-auxdisplay-tm1628 | 7 +++++++
+ 1 file changed, 7 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-devices-auxdisplay-tm1628
+
+diff --git a/Documentation/ABI/testing/sysfs-devices-auxdisplay-tm1628 b/Documentation/ABI/testing/sysfs-devices-auxdisplay-tm1628
+new file mode 100644
+index 000000000000..382757e721af
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-devices-auxdisplay-tm1628
+@@ -0,0 +1,7 @@
++What:		/sys/devices/.../display-text
++Date:		February 2022
++Contact:	Heiner Kallweit <[email-masked]>
++Description:
++		The text to be displayed on the 7 segment display.
++		Any printable character is allowed as input, but some
++		can not be displayed in a readable way with 7 segments.
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0020-FROMLIST-v5-auxdisplay-add-support-for-Titanmec-TM16.patch b/gnu/packages/patches/amlogic-0020-FROMLIST-v5-auxdisplay-add-support-for-Titanmec-TM16.patch
new file mode 100644
index 0000000000..7c73e34be7
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0020-FROMLIST-v5-auxdisplay-add-support-for-Titanmec-TM16.patch
@@ -0,0 +1,461 @@
+From 90b0ef46ad6cc8ea91a75d59561f2ce837319c83 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <[email-masked]>
+Date: Mon, 4 Apr 2022 18:51:20 +0000
+Subject: [PATCH 20/73] FROMLIST(v5): auxdisplay: add support for Titanmec
+ TM1628 7 segment display controller
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch adds support for the Titanmec TM1628 7 segment display
+controller. It's based on previous RFC work from Andreas Färber.
+The RFC version placed the driver in the LED subsystem, but this was
+NAK'ed by the LED maintainer. Therefore I moved the driver to
+/drivers/auxdisplay what seems most reasonable to me.
+
+Further changes to the RFC version:
+- Driver can be built also w/o LED class support, for displays that
+  don't have any symbols to be exposed as LED's.
+- Simplified the code and rewrote a lot of it.
+- Driver is now kind of a MVP, but functionality should be sufficient
+  for most use cases.
+- Use the existing 7 segment support in uapi/linux/map_to_7segment.h
+  as suggested by Geert Uytterhoeven.
+
+Note: There's a number of chips from other manufacturers that are
+      almost identical, e.g. FD628, SM1628. Only difference I saw so
+      far is that they partially support other display modes.
+      TM1628: 6x12, 7x11
+      SM1628C: 4x13, 5x12, 6x11, 7x10
+      For typical displays on devices using these chips this
+      difference shouldn't matter.
+
+Successfully tested on a TX3 Mini TV box that has an SM1628C and a
+display with 4 digits and 7 symbols.
+
+Co-developed-by: Andreas Färber <[email-masked]>
+Signed-off-by: Andreas Färber <[email-masked]>
+Signed-off-by: Heiner Kallweit <[email-masked]>
+---
+ drivers/auxdisplay/Kconfig  |  11 ++
+ drivers/auxdisplay/Makefile |   1 +
+ drivers/auxdisplay/tm1628.c | 376 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 388 insertions(+)
+ create mode 100644 drivers/auxdisplay/tm1628.c
+
+diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
+index 64012cda4d12..2764afc5c5d9 100644
+--- a/drivers/auxdisplay/Kconfig
++++ b/drivers/auxdisplay/Kconfig
+@@ -203,6 +203,17 @@ config ARM_CHARLCD
+ 	  line and the Linux version on the second line, but that's
+ 	  still useful.
+ 
++config TM1628
++	tristate "TM1628 driver for LED 7/11 segment displays"
++	depends on SPI
++	depends on OF || COMPILE_TEST
++	help
++	  Say Y to enable support for Titan Micro Electronics TM1628
++	  LED controller.
++
++	  It's a 3-wire SPI device controlling a two-dimensional grid of
++	  LEDs. Dimming is applied to all outputs through an internal PWM.
++
+ menuconfig PARPORT_PANEL
+ 	tristate "Parallel port LCD/Keypad Panel support"
+ 	depends on PARPORT
+diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
+index 6968ed4d3f0a..7728e17e1c5a 100644
+--- a/drivers/auxdisplay/Makefile
++++ b/drivers/auxdisplay/Makefile
+@@ -14,3 +14,4 @@ obj-$(CONFIG_HT16K33)		+= ht16k33.o
+ obj-$(CONFIG_PARPORT_PANEL)	+= panel.o
+ obj-$(CONFIG_LCD2S)		+= lcd2s.o
+ obj-$(CONFIG_LINEDISP)		+= line-display.o
++obj-$(CONFIG_TM1628)		+= tm1628.o
+diff --git a/drivers/auxdisplay/tm1628.c b/drivers/auxdisplay/tm1628.c
+new file mode 100644
+index 000000000000..4d99a7aa077b
+--- /dev/null
++++ b/drivers/auxdisplay/tm1628.c
+@@ -0,0 +1,376 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Titan Micro Electronics TM1628 LED controller
++ *
++ * Copyright (c) 2019 Andreas Färber
++ * Copyright (c) 2022 Heiner Kallweit
++ */
++
++#include <linux/ctype.h>
++#include <linux/delay.h>
++#include <linux/leds.h>
++#include <linux/module.h>
++#include <linux/property.h>
++#include <linux/spi/spi.h>
++#include <uapi/linux/map_to_7segment.h>
++
++#define TM1628_CMD_DISPLAY_MODE		(0 << 6)
++#define TM1628_DISPLAY_MODE_6_12	0x02
++#define TM1628_DISPLAY_MODE_7_11	0x03
++
++#define TM1628_CMD_DATA			(1 << 6)
++#define TM1628_DATA_TEST_MODE		BIT(3)
++#define TM1628_DATA_FIXED_ADDR		BIT(2)
++#define TM1628_DATA_WRITE_DATA		0x00
++#define TM1628_DATA_READ_DATA		0x02
++
++#define TM1628_CMD_DISPLAY_CTRL		(2 << 6)
++#define TM1628_DISPLAY_CTRL_DISPLAY_ON	BIT(3)
++
++#define TM1628_CMD_SET_ADDRESS		(3 << 6)
++
++#define TM1628_BRIGHTNESS_MAX		7
++#define NUM_LED_SEGS			7
++
++/* Physical limits, depending on the mode the chip may support less */
++#define MAX_GRID_SIZE			7
++#define MAX_SEGMENT_NUM			16
++
++struct tm1628_led {
++	struct led_classdev	leddev;
++	struct tm1628		*ctrl;
++	u32			grid;
++	u32			seg;
++};
++
++struct tm1628 {
++	struct spi_device		*spi;
++	__le16				data[MAX_GRID_SIZE];
++	struct mutex			disp_lock;
++	char				text[MAX_GRID_SIZE + 1];
++	u8				segment_mapping[NUM_LED_SEGS];
++	u8				grid[MAX_GRID_SIZE];
++	int				grid_size;
++	struct tm1628_led		leds[];
++};
++
++/* Command 1: Display Mode Setting */
++static int tm1628_set_display_mode(struct spi_device *spi, u8 grid_mode)
++{
++	const u8 cmd = TM1628_CMD_DISPLAY_MODE | grid_mode;
++
++	return spi_write(spi, &cmd, 1);
++}
++
++/* Command 3: Address Setting */
++static int tm1628_set_address(struct spi_device *spi, u8 offset)
++{
++	const u8 cmd = TM1628_CMD_SET_ADDRESS | (offset * sizeof(__le16));
++
++	return spi_write(spi, &cmd, 1);
++}
++
++/* Command 2: Data Setting */
++static int tm1628_write_data(struct spi_device *spi, unsigned int offset,
++			     unsigned int len)
++{
++	struct tm1628 *s = spi_get_drvdata(spi);
++	const u8 cmd = TM1628_CMD_DATA | TM1628_DATA_WRITE_DATA;
++	struct spi_transfer xfers[] = {
++		{
++			.tx_buf = &cmd,
++			.len = 1,
++		},
++		{
++			.tx_buf = (__force void *)(s->data + offset),
++			.len = len * sizeof(__le16),
++		},
++	};
++
++	if (offset + len > MAX_GRID_SIZE) {
++		dev_err(&spi->dev, "Invalid data address offset %u len %u\n",
++			offset, len);
++		return -EINVAL;
++	}
++
++	tm1628_set_address(spi, offset);
++
++	return spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
++}
++
++/* Command 4: Display Control */
++static int tm1628_set_display_ctrl(struct spi_device *spi, bool on)
++{
++	u8 cmd = TM1628_CMD_DISPLAY_CTRL | TM1628_BRIGHTNESS_MAX;
++
++	if (on)
++		cmd |= TM1628_DISPLAY_CTRL_DISPLAY_ON;
++
++	return spi_write(spi, &cmd, 1);
++}
++
++static int tm1628_show_text(struct tm1628 *s)
++{
++	static SEG7_CONVERSION_MAP(map_seg7, MAP_ASCII7SEG_ALPHANUM);
++	int msg_len, i, ret;
++
++	msg_len = strlen(s->text);
++
++	mutex_lock(&s->disp_lock);
++
++	for (i = 0; i < s->grid_size; i++) {
++		int pos = s->grid[i] - 1;
++		int j, char7_raw, char7;
++
++		if (i >= msg_len) {
++			s->data[pos] = 0;
++			continue;
++		}
++
++		char7_raw = map_to_seg7(&map_seg7, s->text[i]);
++
++		for (j = 0, char7 = 0; j < NUM_LED_SEGS; j++) {
++			if (char7_raw & BIT(j))
++				char7 |= BIT(s->segment_mapping[j] - 1);
++		}
++
++		s->data[pos] = cpu_to_le16(char7);
++	}
++
++	ret = tm1628_write_data(s->spi, 0, s->grid_size);
++
++	mutex_unlock(&s->disp_lock);
++
++	return ret;
++}
++
++static int tm1628_led_set_brightness(struct led_classdev *led_cdev,
++				     enum led_brightness brightness)
++{
++	struct tm1628_led *led = container_of(led_cdev, struct tm1628_led, leddev);
++	struct tm1628 *s = led->ctrl;
++	int ret, offset = led->grid - 1;
++	__le16 bit = cpu_to_le16(BIT(led->seg - 1));
++
++	mutex_lock(&s->disp_lock);
++
++	if (brightness == LED_OFF)
++		s->data[offset] &= ~bit;
++	else
++		s->data[offset] |= bit;
++
++	ret = tm1628_write_data(s->spi, offset, 1);
++
++	mutex_unlock(&s->disp_lock);
++
++	return ret;
++}
++
++static enum led_brightness tm1628_led_get_brightness(struct led_classdev *led_cdev)
++{
++	struct tm1628_led *led = container_of(led_cdev, struct tm1628_led, leddev);
++	struct tm1628 *s = led->ctrl;
++	int offset = led->grid - 1;
++	__le16 bit = cpu_to_le16(BIT(led->seg - 1));
++	bool on;
++
++	mutex_lock(&s->disp_lock);
++	on = s->data[offset] & bit;
++	mutex_unlock(&s->disp_lock);
++
++	return on ? LED_ON : LED_OFF;
++}
++
++static int tm1628_register_led(struct tm1628 *s, struct fwnode_handle *node,
++			       u32 grid, u32 seg, struct tm1628_led *led)
++{
++	struct device *dev = &s->spi->dev;
++	struct led_init_data init_data = { .fwnode = node };
++
++	led->ctrl = s;
++	led->grid = grid;
++	led->seg  = seg;
++	led->leddev.max_brightness = LED_ON;
++	led->leddev.brightness_set_blocking = tm1628_led_set_brightness;
++	led->leddev.brightness_get = tm1628_led_get_brightness;
++
++	return devm_led_classdev_register_ext(dev, &led->leddev, &init_data);
++}
++
++static ssize_t display_text_show(struct device *dev, struct device_attribute *attr,
++				 char *buf)
++{
++	struct tm1628 *s = dev_get_drvdata(dev);
++
++	return sysfs_emit(buf, "%s\n", s->text);
++}
++
++static ssize_t display_text_store(struct device *dev, struct device_attribute *attr,
++				  const char *buf, size_t count)
++{
++	struct tm1628 *s = dev_get_drvdata(dev);
++	int ret, i;
++
++	for (i = 0; i < count && i < s->grid_size && isprint(buf[i]); i++)
++		s->text[i] = buf[i];
++
++	s->text[i] = '\0';
++
++	ret = tm1628_show_text(s);
++	if (ret < 0)
++		return ret;
++
++	return count;
++}
++
++static const DEVICE_ATTR_RW(display_text);
++
++static int tm1628_spi_probe(struct spi_device *spi)
++{
++	struct fwnode_handle *child;
++	unsigned int num_leds;
++	struct tm1628 *s;
++	int ret, i;
++
++	num_leds = device_get_child_node_count(&spi->dev);
++
++	s = devm_kzalloc(&spi->dev, struct_size(s, leds, num_leds), GFP_KERNEL);
++	if (!s)
++		return -ENOMEM;
++
++	s->spi = spi;
++	spi_set_drvdata(spi, s);
++
++	mutex_init(&s->disp_lock);
++
++	/* According to TM1628 datasheet */
++	msleep(200);
++
++	/* Clear screen */
++	ret = tm1628_write_data(spi, 0, MAX_GRID_SIZE);
++	if (ret)
++		return ret;
++
++	/* For now we support 6x12 mode only. This should be sufficient for most use cases */
++	ret = tm1628_set_display_mode(spi, TM1628_DISPLAY_MODE_6_12);
++	if (ret)
++		return ret;
++
++	ret = tm1628_set_display_ctrl(spi, true);
++	if (ret)
++		return ret;
++
++	num_leds = 0;
++
++	if (!IS_REACHABLE(CONFIG_LEDS_CLASS))
++		goto no_leds;
++
++	device_for_each_child_node(&spi->dev, child) {
++		u32 reg[2];
++
++		ret = fwnode_property_read_u32_array(child, "reg", reg, 2);
++		if (ret) {
++			dev_err(&spi->dev, "Reading %s reg property failed (%d)\n",
++				fwnode_get_name(child), ret);
++			continue;
++		}
++
++		if (reg[0] == 0 || reg[0] > MAX_GRID_SIZE) {
++			dev_err(&spi->dev, "Invalid grid %u at %s\n",
++				reg[0], fwnode_get_name(child));
++			continue;
++		}
++
++		if (reg[1] == 0 || reg[1] > MAX_SEGMENT_NUM) {
++			dev_err(&spi->dev, "Invalid segment %u at %s\n",
++				reg[1], fwnode_get_name(child));
++			continue;
++		}
++
++		ret = tm1628_register_led(s, child, reg[0], reg[1], s->leds + num_leds);
++		if (ret) {
++			dev_err(&spi->dev, "Failed to register LED %s (%d)\n",
++				fwnode_get_name(child), ret);
++			continue;
++		}
++		num_leds++;
++	}
++
++no_leds:
++	ret = device_property_count_u8(&spi->dev, "titanmec,grid");
++	if (ret < 1 || ret > MAX_GRID_SIZE) {
++		dev_err(&spi->dev, "Invalid display length (%d)\n", ret);
++		return -EINVAL;
++	}
++
++	s->grid_size = ret;
++
++	ret = device_property_read_u8_array(&spi->dev, "titanmec,grid", s->grid, s->grid_size);
++	if (ret < 0)
++		return ret;
++
++	for (i = 0; i < s->grid_size; i++) {
++		if (s->grid[i] < 1 || s->grid[i] > s->grid_size)
++			return -EINVAL;
++	}
++
++	ret = device_property_read_u8_array(&spi->dev, "titanmec,segment-mapping",
++					    s->segment_mapping, NUM_LED_SEGS);
++	if (ret < 0)
++		return ret;
++
++	for (i = 0; i < NUM_LED_SEGS; i++) {
++		if (s->segment_mapping[i] < 1 || s->segment_mapping[i] > MAX_SEGMENT_NUM)
++			return -EINVAL;
++	}
++
++	ret = device_create_file(&spi->dev, &dev_attr_display_text);
++	if (ret)
++		return ret;
++
++	dev_info(&spi->dev, "Configured display with %u digits and %u symbols\n",
++		 s->grid_size, num_leds);
++
++	return 0;
++}
++
++static void tm1628_spi_remove(struct spi_device *spi)
++{
++	device_remove_file(&spi->dev, &dev_attr_display_text);
++	tm1628_set_display_ctrl(spi, false);
++}
++
++static void tm1628_spi_shutdown(struct spi_device *spi)
++{
++	tm1628_set_display_ctrl(spi, false);
++}
++
++static const struct of_device_id tm1628_spi_of_matches[] = {
++	{ .compatible = "titanmec,tm1628" },
++	{}
++};
++MODULE_DEVICE_TABLE(of, tm1628_spi_of_matches);
++
++static const struct spi_device_id tm1628_spi_id_table[] = {
++	{ "tm1628" },
++	{},
++};
++MODULE_DEVICE_TABLE(spi, tm1628_spi_id_table);
++
++static struct spi_driver tm1628_spi_driver = {
++	.probe = tm1628_spi_probe,
++	.remove = tm1628_spi_remove,
++	.shutdown = tm1628_spi_shutdown,
++	.id_table = tm1628_spi_id_table,
++
++	.driver = {
++		.name = "tm1628",
++		.of_match_table = tm1628_spi_of_matches,
++	},
++};
++module_spi_driver(tm1628_spi_driver);
++
++MODULE_DESCRIPTION("TM1628 LED controller driver");
++MODULE_AUTHOR("Andreas Färber <[email-masked]>");
++MODULE_AUTHOR("Heiner Kallweit <[email-masked]>");
++MODULE_LICENSE("GPL");
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0021-FROMLIST-v5-arm64-dts-meson-gxl-s905w-tx3-mini-add-s.patch b/gnu/packages/patches/amlogic-0021-FROMLIST-v5-arm64-dts-meson-gxl-s905w-tx3-mini-add-s.patch
new file mode 100644
index 0000000000..8a9dee74a0
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0021-FROMLIST-v5-arm64-dts-meson-gxl-s905w-tx3-mini-add-s.patch
@@ -0,0 +1,93 @@
+From 42aab91da4a46c2be7e2f0f8ef578621bccc0665 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <[email-masked]>
+Date: Mon, 4 Apr 2022 18:52:34 +0000
+Subject: [PATCH 21/73] FROMLIST(v5): arm64: dts: meson-gxl-s905w-tx3-mini: add
+ support for the 7 segment display
+
+This patch adds support for the 7 segment display of the device.
+
+Signed-off-by: Heiner Kallweit <[email-masked]>
+---
+ .../dts/amlogic/meson-gxl-s905w-tx3-mini.dts  | 59 +++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
+index 6705c2082a78..ae0d8d7b1e19 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
+@@ -10,6 +10,7 @@
+ 
+ #include "meson-gxl-s905x.dtsi"
+ #include "meson-gx-p23x-q20x.dtsi"
++#include <dt-bindings/leds/common.h>
+ 
+ / {
+ 	compatible = "oranth,tx3-mini", "amlogic,s905w", "amlogic,meson-gxl";
+@@ -19,6 +20,64 @@
+ 		device_type = "memory";
+ 		reg = <0x0 0x0 0x0 0x40000000>; /* 1 GiB or 2 GiB */
+ 	};
++
++	spi {
++		compatible = "spi-gpio";
++		sck-gpios = <&gpio GPIODV_27  GPIO_ACTIVE_HIGH>;
++		mosi-gpios = <&gpio GPIODV_26 GPIO_ACTIVE_HIGH>;
++		cs-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>;
++		num-chipselects = <1>;
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		tm1628: led-controller@0 {
++			compatible = "titanmec,tm1628";
++			reg = <0>;
++			spi-3wire;
++			spi-lsb-first;
++			spi-rx-delay-us = <1>;
++			spi-max-frequency = <500000>;
++			#address-cells = <2>;
++			#size-cells = <0>;
++
++			titanmec,segment-mapping = /bits/ 8 <4 5 6 1 2 3 7>;
++			titanmec,grid = /bits/ 8 <4 3 2 1>;
++
++			alarm@5,1 {
++				reg = <5 1>;
++				function = LED_FUNCTION_ALARM;
++			};
++
++			usb@5,2 {
++				reg = <5 2>;
++				function = LED_FUNCTION_USB;
++			};
++			play@5,3 {
++				reg = <5 3>;
++				function = "play";
++			};
++
++			pause@5,4 {
++				reg = <5 4>;
++				function = "pause";
++			};
++
++			colon@5,5 {
++				reg = <5 5>;
++				function = "colon";
++			};
++
++			lan@5,6 {
++				reg = <5 6>;
++				function = LED_FUNCTION_LAN;
++			};
++
++			wlan@5,7 {
++				reg = <5 7>;
++				function = LED_FUNCTION_WLAN;
++			};
++		};
++	};
+ };
+ 
+ &ir {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0022-FROMLIST-v5-MAINTAINERS-Add-entry-for-tm1628-auxdisp.patch b/gnu/packages/patches/amlogic-0022-FROMLIST-v5-MAINTAINERS-Add-entry-for-tm1628-auxdisp.patch
new file mode 100644
index 0000000000..b1b5abfdf5
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0022-FROMLIST-v5-MAINTAINERS-Add-entry-for-tm1628-auxdisp.patch
@@ -0,0 +1,32 @@
+From b302175edf75e8729fe5a5b6dae4bed90525ab8d Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <[email-masked]>
+Date: Mon, 4 Apr 2022 18:53:32 +0000
+Subject: [PATCH 22/73] FROMLIST(v5): MAINTAINERS: Add entry for tm1628
+ auxdisplay driver
+
+Signed-off-by: Heiner Kallweit <[email-masked]>
+---
+ MAINTAINERS | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 72b9654f764c..8889d9dbd71a 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -20481,6 +20481,13 @@ W:	http://sourceforge.net/projects/tlan/
+ F:	Documentation/networking/device_drivers/ethernet/ti/tlan.rst
+ F:	drivers/net/ethernet/ti/tlan.*
+ 
++TM1628 LED CONTROLLER DRIVER
++M:	Heiner Kallweit <[email-masked]>
++S:	Maintained
++F:	Documentation/devicetree/bindings/auxdisplay/titanmec,tm1628.yaml
++F:	Documentation/ABI/testing/sysfs-devices-auxdisplay-tm1628
++F:	drivers/auxdisplay/tm1628.c
++
+ TM6000 VIDEO4LINUX DRIVER
+ M:	Mauro Carvalho Chehab <[email-masked]>
+ L:	[email-masked]
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0023-FROMLIST-v1-drm-bridge-dw_hdmi-fix-preference-of-RGB.patch b/gnu/packages/patches/amlogic-0023-FROMLIST-v1-drm-bridge-dw_hdmi-fix-preference-of-RGB.patch
new file mode 100644
index 0000000000..f2e458215b
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0023-FROMLIST-v1-drm-bridge-dw_hdmi-fix-preference-of-RGB.patch
@@ -0,0 +1,49 @@
+From 0ae242ebcee68a9b02f466b00ff46944390d80cd Mon Sep 17 00:00:00 2001
+From: Guillaume BRUN <[email-masked]>
+Date: Thu, 13 Oct 2022 13:21:53 +0000
+Subject: [PATCH 23/73] FROMLIST(v1): drm: bridge: dw_hdmi: fix preference of
+ RGB modes over YUV420
+
+Cheap monitors sometimes advertise YUV modes they don't really have
+(HDMI specification mandates YUV support so even monitors without actual
+support will often wrongfully advertise it) which results in YUV matches
+and user forum complaints of a red tint to light colour display areas in
+common desktop environments.
+
+Moving the default RGB fall-back before YUV selection results in RGB
+mode matching in most cases, reducing complaints.
+
+Fixes: 6c3c719936da ("drm/bridge: synopsys: dw-hdmi: add bus format negociation")
+Signed-off-by: Guillaume BRUN <[email-masked]>
+Tested-by: Christian Hewitt <[email-masked]>
+---
+ drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+index 40d8ca37f5bc..aa51c61a78c7 100644
+--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+@@ -2720,6 +2720,9 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
+ 	 * if supported. In any case the default RGB888 format is added
+ 	 */
+ 
++	/* Default 8bit RGB fallback */
++	output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
++
+ 	if (max_bpc >= 16 && info->bpc == 16) {
+ 		if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ 			output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
+@@ -2753,9 +2756,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
+ 	if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ 		output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
+ 
+-	/* Default 8bit RGB fallback */
+-	output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
+-
+ 	*num_output_fmts = i;
+ 
+ 	return output_fmts;
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0024-WIP-ASoC-hdmi-codec-reorder-channel-allocation-list.patch b/gnu/packages/patches/amlogic-0024-WIP-ASoC-hdmi-codec-reorder-channel-allocation-list.patch
new file mode 100644
index 0000000000..9a5e6544cc
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0024-WIP-ASoC-hdmi-codec-reorder-channel-allocation-list.patch
@@ -0,0 +1,202 @@
+From 5c71bbe15728d90b905b1539a394a6c78aa3339f Mon Sep 17 00:00:00 2001
+From: Jonas Karlman <[email-masked]>
+Date: Sun, 23 Dec 2018 02:24:38 +0100
+Subject: [PATCH 24/73] 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 <[email-masked]>
+---
+ 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 aa2ca5078551..bed6dba14243 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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0025-WIP-mmc-meson-gx-mmc-set-core-clock-phase-to-270-deg.patch b/gnu/packages/patches/amlogic-0025-WIP-mmc-meson-gx-mmc-set-core-clock-phase-to-270-deg.patch
new file mode 100644
index 0000000000..d94a201911
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0025-WIP-mmc-meson-gx-mmc-set-core-clock-phase-to-270-deg.patch
@@ -0,0 +1,59 @@
+From 9d475abbf29793acc2c085e862ee8abb60c88961 Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <[email-masked]>
+Date: Thu, 14 Jan 2021 17:43:02 +0100
+Subject: [PATCH 25/73] WIP: mmc: meson-gx-mmc: set core clock phase to 270
+ degrees for AXG compatible controllers
+
+Signed-off-by: Neil Armstrong <[email-masked]>
+---
+ 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 a2aacbffc3bf..c16ac828b6f9 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);
+@@ -1328,6 +1330,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 = {
+@@ -1335,6 +1338,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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0026-WIP-arm64-dts-meson-add-Broadcom-WiFi-to-P212-dtsi.patch b/gnu/packages/patches/amlogic-0026-WIP-arm64-dts-meson-add-Broadcom-WiFi-to-P212-dtsi.patch
new file mode 100644
index 0000000000..57afabc348
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0026-WIP-arm64-dts-meson-add-Broadcom-WiFi-to-P212-dtsi.patch
@@ -0,0 +1,32 @@
+From be4a8a8b236626776583abc7c0bc6a0cbe4ecf55 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Thu, 13 Jan 2022 03:50:01 +0000
+Subject: [PATCH 26/73] WIP: arm64: dts: meson: add Broadcom WiFi to P212 dtsi
+
+The P212 has a combined WiFi/BT module. The BT side is already enabled
+in the dtsi but the WiFi side is not. Let's enable the WiFi module.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+index 05cb2f5e5c36..7055057d7942 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+@@ -125,6 +125,11 @@
+ 
+ 	vmmc-supply = <&vddao_3v3>;
+ 	vqmmc-supply = <&vddio_boot>;
++
++	brcmf: wifi@1 {
++		reg = <1>;
++		compatible = "brcm,bcm4329-fmac";
++	};
+ };
+ 
+ /* SD card */
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0027-WIP-arm64-dts-meson-move-pwm_ef-node-in-P212-dtsi.patch b/gnu/packages/patches/amlogic-0027-WIP-arm64-dts-meson-move-pwm_ef-node-in-P212-dtsi.patch
new file mode 100644
index 0000000000..d3fa664966
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0027-WIP-arm64-dts-meson-move-pwm_ef-node-in-P212-dtsi.patch
@@ -0,0 +1,49 @@
+From a4e6681cdab0a1e3518ee3401e2b7ffba0363b90 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Thu, 13 Jan 2022 03:56:12 +0000
+Subject: [PATCH 27/73] WIP: arm64: dts: meson: move pwm_ef node in P212 dtsi
+
+Cosmetic-only change to alpha-sort the pwm_ef node.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-gxl-s905x-p212.dtsi   | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+index 7055057d7942..a150cc0e18ff 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+@@ -97,6 +97,14 @@
+ 	pinctrl-names = "default";
+ };
+ 
++&pwm_ef {
++	status = "okay";
++	pinctrl-0 = <&pwm_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&clkc CLKID_FCLK_DIV4>;
++	clock-names = "clkin0";
++};
++
+ &saradc {
+ 	status = "okay";
+ 	vref-supply = <&vddio_ao18>;
+@@ -170,14 +178,6 @@
+ 	vqmmc-supply = <&vddio_boot>;
+ };
+ 
+-&pwm_ef {
+-	status = "okay";
+-	pinctrl-0 = <&pwm_e_pins>;
+-	pinctrl-names = "default";
+-	clocks = <&clkc CLKID_FCLK_DIV4>;
+-	clock-names = "clkin0";
+-};
+-
+ /* This is connected to the Bluetooth module: */
+ &uart_A {
+ 	status = "okay";
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0028-WIP-arm64-dts-meson-remove-WiFi-BT-nodes-from-Khadas.patch b/gnu/packages/patches/amlogic-0028-WIP-arm64-dts-meson-remove-WiFi-BT-nodes-from-Khadas.patch
new file mode 100644
index 0000000000..a94bc3bfb3
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0028-WIP-arm64-dts-meson-remove-WiFi-BT-nodes-from-Khadas.patch
@@ -0,0 +1,43 @@
+From 96b67dcbffe99d032c38bb393f8f3459b5df04cf Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Thu, 13 Jan 2022 03:58:58 +0000
+Subject: [PATCH 28/73] WIP: arm64: dts: meson: remove WiFi/BT nodes from
+ Khadas VIM1
+
+The Broadcom WiFi/BT SDIO nodes are now inherited from the P212 common dtsi
+so we can remove them from the VIM1 board dts.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../dts/amlogic/meson-gxl-s905x-khadas-vim.dts    | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+index 24af15e18026..5ed1e9313003 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+@@ -221,21 +221,6 @@
+ 
+ &sd_emmc_a {
+ 	max-frequency = <100000000>;
+-
+-	brcmf: wifi@1 {
+-		reg = <1>;
+-		compatible = "brcm,bcm4329-fmac";
+-	};
+-};
+-
+-&uart_A {
+-	bluetooth {
+-		compatible = "brcm,bcm43438-bt";
+-		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+-		max-speed = <2000000>;
+-		clocks = <&wifi32k>;
+-		clock-names = "lpo";
+-	};
+ };
+ 
+ /* This is brought out on the Linux_RX (18) and Linux_TX (19) pins: */
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0029-WIP-arm64-dts-meson-set-p212-p23x-q20x-SDIO-to-100MH.patch b/gnu/packages/patches/amlogic-0029-WIP-arm64-dts-meson-set-p212-p23x-q20x-SDIO-to-100MH.patch
new file mode 100644
index 0000000000..49192c0223
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0029-WIP-arm64-dts-meson-set-p212-p23x-q20x-SDIO-to-100MH.patch
@@ -0,0 +1,109 @@
+From 193209275b80d4510bd47a52c029084b2fedf542 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Tue, 18 Jan 2022 15:09:12 +0000
+Subject: [PATCH 29/73] WIP: arm64: dts: meson: set p212/p23x/q20x SDIO to
+ 100MHz
+
+Amlogic datasheets describe 50MHz max-frequency for SDIO on GXL/GXM but
+real-world tests on an assortment of GXL and GXM boards show noteable
+increases in throughput when max-frequency is 100MHz, so let's use it.
+
+Before results from a p231 device:
+
+Connecting to host 192.168.0.1, port 5201
+Reverse mode, remote host 192.168.0.1 is sending
+[  5] local 192.168.0.41 port 42550 connected to 192.168.0.1 port 5201
+[ ID] Interval           Transfer     Bitrate
+[  5]   0.00-1.00   sec  8.84 MBytes  74.2 Mbits/sec
+[  5]   1.00-2.00   sec  9.60 MBytes  80.5 Mbits/sec
+[  5]   2.00-3.00   sec  9.07 MBytes  76.1 Mbits/sec
+[  5]   3.00-4.00   sec  9.14 MBytes  76.6 Mbits/sec
+[  5]   4.00-5.00   sec  9.26 MBytes  77.7 Mbits/sec
+[  5]   5.00-6.00   sec  9.08 MBytes  76.2 Mbits/sec
+[  5]   6.00-7.00   sec  9.11 MBytes  76.4 Mbits/sec
+[  5]   7.00-8.00   sec  8.65 MBytes  72.5 Mbits/sec
+[  5]   8.00-9.00   sec  9.24 MBytes  77.5 Mbits/sec
+[  5]   9.00-10.00  sec  8.57 MBytes  71.9 Mbits/sec
+- - - - - - - - - - - - - - - - - - - - - - - - -
+[ ID] Interval           Transfer     Bitrate         Retr
+[  5]   0.00-10.27  sec  94.1 MBytes  76.8 Mbits/sec    0             sender
+[  5]   0.00-10.00  sec  90.6 MBytes  76.0 Mbits/sec                  receiver
+
+clock:		50000000 Hz
+actual clock:	50000000 Hz
+vdd:		21 (3.3 ~ 3.4 V)
+bus mode:	2 (push-pull)
+chip select:	0 (don't care)
+power mode:	2 (on)
+bus width:	2 (4 bits)
+timing spec:	2 (sd high-speed)
+signal voltage:	1 (1.80 V)
+driver type:	0 (driver type B)
+
+After results from a p231 device:
+
+Connecting to host 192.168.0.1, port 5201
+Reverse mode, remote host 192.168.0.1 is sending
+[  5] local 192.168.0.41 port 58534 connected to 192.168.0.1 port 5201
+[ ID] Interval           Transfer     Bitrate
+[  5]   0.00-1.00   sec  12.6 MBytes   106 Mbits/sec
+[  5]   1.00-2.00   sec  13.0 MBytes   109 Mbits/sec
+[  5]   2.00-3.00   sec  12.8 MBytes   107 Mbits/sec
+[  5]   3.00-4.00   sec  13.2 MBytes   111 Mbits/sec
+[  5]   4.00-5.00   sec  12.4 MBytes   104 Mbits/sec
+[  5]   5.00-6.00   sec  11.2 MBytes  93.9 Mbits/sec
+[  5]   6.00-7.00   sec  12.3 MBytes   103 Mbits/sec
+[  5]   7.00-8.00   sec  12.3 MBytes   103 Mbits/sec
+[  5]   8.00-9.00   sec  12.5 MBytes   105 Mbits/sec
+[  5]   9.00-10.00  sec  12.3 MBytes   103 Mbits/sec
+- - - - - - - - - - - - - - - - - - - - - - - - -
+[ ID] Interval           Transfer     Bitrate         Retr
+[  5]   0.00-10.22  sec   127 MBytes   104 Mbits/sec    0             sender
+[  5]   0.00-10.00  sec   125 MBytes   105 Mbits/sec                  receiver
+
+clock:		100000000 Hz
+actual clock:	100000000 Hz
+vdd:		21 (3.3 ~ 3.4 V)
+bus mode:	2 (push-pull)
+chip select:	0 (don't care)
+power mode:	2 (on)
+bus width:	2 (4 bits)
+timing spec:	6 (sd uhs SDR104)
+signal voltage:	1 (1.80 V)
+driver type:	0 (driver type B)
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi   | 2 +-
+ arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+index dafc841f7c16..8d315508360d 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+@@ -259,7 +259,7 @@
+ 
+ 	bus-width = <4>;
+ 	cap-sd-highspeed;
+-	max-frequency = <50000000>;
++	max-frequency = <100000000>;
+ 
+ 	non-removable;
+ 	disable-wp;
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+index a150cc0e18ff..b3d7b8613d6d 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+@@ -121,7 +121,7 @@
+ 
+ 	bus-width = <4>;
+ 	cap-sd-highspeed;
+-	max-frequency = <50000000>;
++	max-frequency = <100000000>;
+ 
+ 	non-removable;
+ 	disable-wp;
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0030-WIP-arm64-dts-meson-add-UHS-SDIO-capabilities-to-p21.patch b/gnu/packages/patches/amlogic-0030-WIP-arm64-dts-meson-add-UHS-SDIO-capabilities-to-p21.patch
new file mode 100644
index 0000000000..bafd873cd1
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0030-WIP-arm64-dts-meson-add-UHS-SDIO-capabilities-to-p21.patch
@@ -0,0 +1,47 @@
+From e5a3f942e0191001771ecec4eeb0cfc6312727a1 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 19 Jan 2022 06:45:06 +0000
+Subject: [PATCH 30/73] WIP: arm64: dts: meson: add UHS SDIO capabilities to
+ p212/p23x/q20x
+
+Add UHS capabilities to the SDIO node to enable 100MHz speeds.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi   | 4 ++++
+ arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+index 8d315508360d..b0d008fc5f7a 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+@@ -259,6 +259,10 @@
+ 
+ 	bus-width = <4>;
+ 	cap-sd-highspeed;
++	sd-uhs-sdr12;
++	sd-uhs-sdr25;
++	sd-uhs-sdr50;
++	sd-uhs-sdr104;
+ 	max-frequency = <100000000>;
+ 
+ 	non-removable;
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+index b3d7b8613d6d..6eec4e81592b 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
+@@ -121,6 +121,10 @@
+ 
+ 	bus-width = <4>;
+ 	cap-sd-highspeed;
++	sd-uhs-sdr12;
++	sd-uhs-sdr25;
++	sd-uhs-sdr50;
++	sd-uhs-sdr104;
+ 	max-frequency = <100000000>;
+ 
+ 	non-removable;
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0031-WIP-arm64-dts-meson-remove-SDIO-node-from-Khadas-VIM.patch b/gnu/packages/patches/amlogic-0031-WIP-arm64-dts-meson-remove-SDIO-node-from-Khadas-VIM.patch
new file mode 100644
index 0000000000..dbad30fe68
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0031-WIP-arm64-dts-meson-remove-SDIO-node-from-Khadas-VIM.patch
@@ -0,0 +1,32 @@
+From f9949b67a813b574134869de01224f589e0af092 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Tue, 18 Jan 2022 15:18:32 +0000
+Subject: [PATCH 31/73] WIP: arm64: dts: meson: remove SDIO node from Khadas
+ VIM1
+
+Now that SDIO 100MHz max-frequency is inherited from the p212 dtsi we
+can drop the node from the board dts.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+index 5ed1e9313003..fb0dd920882f 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+@@ -219,10 +219,6 @@
+ 	pinctrl-0 = <&pwm_e_pins>, <&pwm_f_clk_pins>;
+ };
+ 
+-&sd_emmc_a {
+-	max-frequency = <100000000>;
+-};
+-
+ /* This is brought out on the Linux_RX (18) and Linux_TX (19) pins: */
+ &uart_AO {
+ 	status = "okay";
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0032-WIP-arm64-dts-meson-add-audio-playback-to-S905X-P212.patch b/gnu/packages/patches/amlogic-0032-WIP-arm64-dts-meson-add-audio-playback-to-S905X-P212.patch
new file mode 100644
index 0000000000..bf2e35bd24
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0032-WIP-arm64-dts-meson-add-audio-playback-to-S905X-P212.patch
@@ -0,0 +1,109 @@
+From 841690704fda49df673b17cd7847f8fc6d14026c Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Thu, 13 Jan 2022 04:30:44 +0000
+Subject: [PATCH 32/73] WIP: arm64: dts: meson: add audio playback to
+ S905X-P212 dts
+
+Add support for the HDMI and Analogue i2s audio outputs.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-gxl-s905x-p212.dts | 70 +++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
+index 2602940c2077..c2bc7cec476d 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
+@@ -7,11 +7,19 @@
+ /dts-v1/;
+ 
+ #include "meson-gxl-s905x-p212.dtsi"
++#include <dt-bindings/sound/meson-aiu.h>
+ 
+ / {
+ 	compatible = "amlogic,p212", "amlogic,s905x", "amlogic,meson-gxl";
+ 	model = "Amlogic Meson GXL (S905X) P212 Development Board";
+ 
++	dio2133: analog-amplifier {
++		compatible = "simple-audio-amplifier";
++		sound-name-prefix = "AU2";
++		VCC-supply = <&hdmi_5v>;
++		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
++	};
++
+ 	cvbs-connector {
+ 		compatible = "composite-video-connector";
+ 
+@@ -32,6 +40,68 @@
+ 			};
+ 		};
+ 	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "S905X-P212";
++		audio-aux-devs = <&dio2133>;
++		audio-widgets = "Line", "Lineout";
++		audio-routing = "AU2 INL", "ACODEC LOLN",
++				"AU2 INR", "ACODEC LORN",
++				"Lineout", "AU2 OUTL",
++				"Lineout", "AU2 OUTR";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++
++			codec-1 {
++				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
++			};
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&acodec>;
++			};
++		};
++	};
++};
++
++&acodec {
++	AVDD-supply = <&vddio_ao18>;
++	status = "okay";
++};
++
++&aiu {
++	status = "okay";
+ };
+ 
+ &cec_AO {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0033-WIP-drivers-meson-vdec-remove-redundant-if-statement.patch b/gnu/packages/patches/amlogic-0033-WIP-drivers-meson-vdec-remove-redundant-if-statement.patch
new file mode 100644
index 0000000000..e7caa7b5f9
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0033-WIP-drivers-meson-vdec-remove-redundant-if-statement.patch
@@ -0,0 +1,29 @@
+From b07432a29e196337c9e9506a0b1ece3a2c5d2944 Mon Sep 17 00:00:00 2001
+From: benjamin545 <[email-masked]>
+Date: Thu, 15 Jul 2021 14:32:33 -0400
+Subject: [PATCH 33/73] 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 86ccc8937afc..7b15fc54efe4 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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0034-WIP-drivers-meson-vdec-improve-mmu-and-fbc-handling-.patch b/gnu/packages/patches/amlogic-0034-WIP-drivers-meson-vdec-improve-mmu-and-fbc-handling-.patch
new file mode 100644
index 0000000000..8d0ded1e11
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0034-WIP-drivers-meson-vdec-improve-mmu-and-fbc-handling-.patch
@@ -0,0 +1,586 @@
+From 44bcd5abdcc043dbabd7af356ab7b81972b806d3 Mon Sep 17 00:00:00 2001
+From: benjamin545 <[email-masked]>
+Date: Thu, 15 Jul 2021 16:32:39 -0400
+Subject: [PATCH 34/73] 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 7b15fc54efe4..5d2273d53d02 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 7d2a75653250..d684057509bf 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)
+ {
+@@ -440,7 +448,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,
+@@ -448,25 +456,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 4bf3e61d081b..1a711679d26a 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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0035-WIP-drivers-meson-vdec-add-HEVC-decode-codec.patch b/gnu/packages/patches/amlogic-0035-WIP-drivers-meson-vdec-add-HEVC-decode-codec.patch
new file mode 100644
index 0000000000..9df9e57908
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0035-WIP-drivers-meson-vdec-add-HEVC-decode-codec.patch
@@ -0,0 +1,1609 @@
+From 9c91e0c4fb4deb050b4a8b4fc0b338c3145814b5 Mon Sep 17 00:00:00 2001
+From: benjamin545 <[email-masked]>
+Date: Thu, 15 Jul 2021 17:08:42 -0400
+Subject: [PATCH 35/73] 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 <[email-masked]>
++ * 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 <[email-masked]>
++ */
++
++#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 5d2273d53d02..df5956c6141d 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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0036-WIP-drivers-meson-vdec-add-handling-to-HEVC-decoder-.patch b/gnu/packages/patches/amlogic-0036-WIP-drivers-meson-vdec-add-handling-to-HEVC-decoder-.patch
new file mode 100644
index 0000000000..f2e74412f9
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0036-WIP-drivers-meson-vdec-add-handling-to-HEVC-decoder-.patch
@@ -0,0 +1,157 @@
+From 01c7b71f758342efe824f09988a122f1060e3834 Mon Sep 17 00:00:00 2001
+From: benjamin545 <[email-masked]>
+Date: Mon, 2 Aug 2021 15:18:40 -0400
+Subject: [PATCH 36/73] 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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0037-WIP-drivers-meson-vdec-add-HEVC-support-to-GXBB.patch b/gnu/packages/patches/amlogic-0037-WIP-drivers-meson-vdec-add-HEVC-support-to-GXBB.patch
new file mode 100644
index 0000000000..98b62c648e
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0037-WIP-drivers-meson-vdec-add-HEVC-support-to-GXBB.patch
@@ -0,0 +1,39 @@
+From 514962e3e5743b5d0e1b9add082b27f1a17d535d Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 21 Nov 2021 19:12:07 +0000
+Subject: [PATCH 37/73] WIP: drivers: meson: vdec: add HEVC support to GXBB
+
+It's not clear whether the GXL firmware is the same one used with GXBB
+but let's try it and see!
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ drivers/staging/media/meson/vdec/vdec_platform.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/staging/media/meson/vdec/vdec_platform.c b/drivers/staging/media/meson/vdec/vdec_platform.c
+index 8592cb3aaea9..810039a02b44 100644
+--- a/drivers/staging/media/meson/vdec/vdec_platform.c
++++ b/drivers/staging/media/meson/vdec/vdec_platform.c
+@@ -16,6 +16,18 @@
+ 
+ static const struct amvdec_format vdec_formats_gxbb[] = {
+ 	{
++		.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,
+ 		.max_buffers = 24,
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0038-WIP-drivers-meson-vdec-check-if-parser-has-really-pa.patch b/gnu/packages/patches/amlogic-0038-WIP-drivers-meson-vdec-check-if-parser-has-really-pa.patch
new file mode 100644
index 0000000000..0f31839874
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0038-WIP-drivers-meson-vdec-check-if-parser-has-really-pa.patch
@@ -0,0 +1,51 @@
+From 8d43f5852bdc1a6925e45c57de499ad61547cde1 Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <[email-masked]>
+Date: Mon, 22 Nov 2021 09:15:21 +0000
+Subject: [PATCH 38/73] WIP: drivers: meson: vdec: check if parser has really
+ parser before marking input buffer as error
+
+Signed-off-by: Neil Armstrong <[email-masked]>
+---
+ 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 df5956c6141d..06f627b141fb 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
+@@ -354,15 +355,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.17.1
+
diff --git a/gnu/packages/patches/amlogic-0039-WIP-arm64-dts-meson-radxa-zero-add-support-for-the-u.patch b/gnu/packages/patches/amlogic-0039-WIP-arm64-dts-meson-radxa-zero-add-support-for-the-u.patch
new file mode 100644
index 0000000000..bbc5419b83
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0039-WIP-arm64-dts-meson-radxa-zero-add-support-for-the-u.patch
@@ -0,0 +1,94 @@
+From 2e5d82b4f096bb5abe901f491e1612a23b332c5d Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Tue, 17 Aug 2021 16:16:43 +0000
+Subject: [PATCH 39/73] WIP: arm64: dts: meson: radxa-zero: add support for the
+ usb type-c controller
+
+Radxa Zero uses an FUSB302 type-c controller, so lets enable it.
+
+NB: Polarity swapping via GPIO is not implemented in the current driver
+(see drivers/usb/typec/tcpm/fusb302.c) so it is not possible to handle
+GPIOAO_6 for USB3 polarity control.
+
+Suggested-by: Neil Armstrong <[email-masked]>
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../dts/amlogic/meson-g12a-radxa-zero.dts     | 44 +++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts
+index e3bb6df42ff3..5e3dc013409f 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts
+@@ -60,6 +60,14 @@
+ 		clock-names = "ext_clock";
+ 	};
+ 
++	typec2_vbus: regulator-typec2_vbus {
++		compatible = "regulator-fixed";
++		regulator-name = "TYPEC2_VBUS";
++		regulator-min-microvolt = <5000000>;
++		regulator-max-microvolt = <5000000>;
++		vin-supply = <&ao_5v>;
++	};
++
+ 	ao_5v: regulator-ao_5v {
+ 		compatible = "regulator-fixed";
+ 		regulator-name = "AO_5V";
+@@ -191,6 +199,18 @@
+ 	};
+ };
+ 
++&ao_pinctrl {
++	/* Ensure the TYPE C controller irq pin is not driven by the SoC */
++	fusb302_irq_pins: fusb302_irq {
++		mux {
++			groups = "GPIOAO_5";
++			function = "gpio_aobus";
++			bias-pull-up;
++			output-disable;
++		};
++	};
++};
++
+ &arb {
+ 	status = "okay";
+ };
+@@ -278,6 +298,22 @@
+ 	pinctrl-names = "default";
+ };
+ 
++&i2c_AO {
++	fusb302@22 {
++		compatible = "fcs,fusb302";
++		reg = <0x22>;
++
++		pinctrl-0 = <&fusb302_irq_pins>;
++		pinctrl-names = "default";
++		interrupt-parent = <&gpio_intc>;
++		interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
++
++		vbus-supply = <&typec2_vbus>;
++
++		status = "okay";
++	};
++};
++
+ &pwm_AO_cd {
+ 	pinctrl-0 = <&pwm_ao_d_e_pins>;
+ 	pinctrl-names = "default";
+@@ -403,3 +439,11 @@
+ 	status = "okay";
+ 	dr_mode = "host";
+ };
++
++&usb2_phy0 {
++	phy-supply = <&typec2_vbus>;
++};
++
++&usb3_pcie_phy {
++	phy-supply = <&typec2_vbus>;
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0040-WIP-dt-bindings-arm-amlogic-add-support-for-Radxa-Ze.patch b/gnu/packages/patches/amlogic-0040-WIP-dt-bindings-arm-amlogic-add-support-for-Radxa-Ze.patch
new file mode 100644
index 0000000000..7cec22b8fa
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0040-WIP-dt-bindings-arm-amlogic-add-support-for-Radxa-Ze.patch
@@ -0,0 +1,29 @@
+From 0fb9861b7c3cc0a598ef0ad6544c3ef3ebc1e3cc Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 16 Feb 2022 07:27:07 +0000
+Subject: [PATCH 40/73] WIP: dt-bindings: arm: amlogic: add support for Radxa
+ Zero2
+
+The Radxa Zero2 is a small form-factor SBC using the Amlogic
+A311D chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index 3217c069673e..ea4f016082c4 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -153,6 +153,7 @@ properties:
+         items:
+           - enum:
+               - khadas,vim3
++              - radxa,zero2
+           - const: amlogic,a311d
+           - const: amlogic,g12b
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0041-WIP-arm64-dts-meson-add-support-for-Radxa-Zero2.patch b/gnu/packages/patches/amlogic-0041-WIP-arm64-dts-meson-add-support-for-Radxa-Zero2.patch
new file mode 100644
index 0000000000..d5cfdc5ea0
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0041-WIP-arm64-dts-meson-add-support-for-Radxa-Zero2.patch
@@ -0,0 +1,547 @@
+From 92ce99d7dc9d6aca6bcebbdb99b032b32ec39f81 Mon Sep 17 00:00:00 2001
+From: Yuntian Zhang <[email-masked]>
+Date: Fri, 14 Jan 2022 15:50:02 +0000
+Subject: [PATCH 41/73] WIP: arm64: dts: meson: add support for Radxa Zero2
+
+Radxa Zero2 is a small form factor SBC based on the Amlogic A311D
+chipset that ships in a number of eMMC configurations:
+
+- Amlogic A311D (Quad A73 + Dual A53) CPU
+- 4GB LPDDR4 RAM
+- 32/64/128GB eMMC
+- Mali G52-MP4 GPU
+- HDMI 2.1 output (micro)
+- BCM4345 WiFi (2.4/5GHz a/b/g/n/ac) and BT 5.0
+- 1x USB 2.0 port - Type C (OTG)
+- 1x USB 3.0 port - Type C (Host)
+- 1x micro SD Card slot
+- 40 Pin GPIO header
+
+Signed-off-by: Yuntian Zhang <[email-masked]>
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../dts/amlogic/meson-g12b-radxa-zero2.dts    | 499 ++++++++++++++++++
+ 2 files changed, 500 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 641399fcbdd9..5eaaeb620a17 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2-plus.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-radxa-zero2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-ugoos-am6.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-kii-pro.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts
+new file mode 100644
+index 000000000000..fefa6f2b7abf
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts
+@@ -0,0 +1,499 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2019 BayLibre, SAS
++ * Author: Neil Armstrong <[email-masked]>
++ * Copyright (c) 2019 Christian Hewitt <[email-masked]>
++ * Copyright (c) 2022 Radxa Limited
++ * Author: Yuntian Zhang <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-g12b-a311d.dtsi"
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/gpio/meson-g12a-gpio.h>
++#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
++
++/ {
++	compatible = "radxa,zero2", "amlogic,a311d", "amlogic,g12b";
++	model = "Radxa Zero2";
++
++	aliases {
++		serial0 = &uart_AO;
++		serial2 = &uart_A;
++	};
++
++	chosen {
++		stdout-path = "serial0:115200n8";
++	};
++
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x80000000>;
++	};
++
++	gpio-keys-polled {
++		compatible = "gpio-keys-polled";
++		poll-interval = <100>;
++		power-button {
++			label = "power";
++			linux,code = <KEY_POWER>;
++			gpios = <&gpio_ao GPIOAO_3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
++		};
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-green {
++			color = <LED_COLOR_ID_GREEN>;
++			function = LED_FUNCTION_STATUS;
++			gpios = <&gpio GPIOA_12 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "heartbeat";
++		};
++	};
++
++	cvbs-connector {
++		status = "disabled";
++		compatible = "composite-video-connector";
++
++		port {
++			cvbs_connector_in: endpoint {
++				remote-endpoint = <&cvbs_vdac_out>;
++			};
++		};
++	};
++
++	hdmi-connector {
++		compatible = "hdmi-connector";
++		type = "a";
++
++		port {
++			hdmi_connector_in: endpoint {
++				remote-endpoint = <&hdmi_tx_tmds_out>;
++			};
++		};
++	};
++
++	emmc_pwrseq: emmc-pwrseq {
++		compatible = "mmc-pwrseq-emmc";
++		reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
++	};
++
++	sdio_pwrseq: sdio-pwrseq {
++		compatible = "mmc-pwrseq-simple";
++		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
++		clocks = <&wifi32k>;
++		clock-names = "ext_clock";
++	};
++
++	ao_5v: regulator-ao_5v {
++		compatible = "regulator-fixed";
++		regulator-name = "AO_5V";
++		regulator-min-microvolt = <5000000>;
++		regulator-max-microvolt = <5000000>;
++		regulator-always-on;
++	};
++
++	vcc_1v8: regulator-vcc_1v8 {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_1V8";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++		vin-supply = <&vcc_3v3>;
++		regulator-always-on;
++	};
++
++	vcc_3v3: regulator-vcc_3v3 {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_3V3";
++		regulator-min-microvolt = <3300000>;
++		regulator-max-microvolt = <3300000>;
++		vin-supply = <&vddao_3v3>;
++		regulator-always-on;
++		/* FIXME: actually controlled by VDDCPU_B_EN */
++	};
++
++	vddao_1v8: regulator-vddao_1v8 {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDIO_AO1V8";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++		vin-supply = <&vddao_3v3>;
++		regulator-always-on;
++	};
++
++	vddao_3v3: regulator-vddao_3v3 {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDAO_3V3";
++		regulator-min-microvolt = <3300000>;
++		regulator-max-microvolt = <3300000>;
++		vin-supply = <&ao_5v>;
++		regulator-always-on;
++	};
++	
++	vddcpu_a: regulator-vddcpu-a {
++		/*
++		 * MP8756GD Regulator.
++		 */
++		compatible = "pwm-regulator";
++
++		regulator-name = "VDDCPU_A";
++		regulator-min-microvolt = <730000>;
++		regulator-max-microvolt = <1022000>;
++
++		pwm-supply = <&ao_5v>;
++
++		pwms = <&pwm_ab 0 1250 0>;
++		pwm-dutycycle-range = <100 0>;
++
++		regulator-boot-on;
++		regulator-always-on;
++	};
++
++	vddcpu_b: regulator-vddcpu-b {
++		/*
++		 * Silergy SY8120B1ABC Regulator.
++		 */
++		compatible = "pwm-regulator";
++
++		regulator-name = "VDDCPU_B";
++		regulator-min-microvolt = <730000>;
++		regulator-max-microvolt = <1022000>;
++
++		pwm-supply = <&ao_5v>;
++
++		pwms = <&pwm_AO_cd 1 1250 0>;
++		pwm-dutycycle-range = <100 0>;
++
++		regulator-boot-on;
++		regulator-always-on;
++	};
++
++	sound {
++		compatible = "amlogic,axg-sound-card";
++		model = "RADXA-ZERO2";
++		audio-aux-devs = <&tdmout_b>;
++		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
++				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
++				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
++				"TDM_B Playback", "TDMOUT_B OUT";
++
++		assigned-clocks = <&clkc CLKID_MPLL2>,
++				  <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&frddr_a>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&frddr_b>;
++		};
++
++		dai-link-2 {
++			sound-dai = <&frddr_c>;
++		};
++
++		/* 8ch hdmi interface */
++		dai-link-3 {
++			sound-dai = <&tdmif_b>;
++			dai-format = "i2s";
++			dai-tdm-slot-tx-mask-0 = <1 1>;
++			dai-tdm-slot-tx-mask-1 = <1 1>;
++			dai-tdm-slot-tx-mask-2 = <1 1>;
++			dai-tdm-slot-tx-mask-3 = <1 1>;
++			mclk-fs = <256>;
++
++			codec {
++				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
++			};
++		};
++
++		/* hdmi glue */
++		dai-link-4 {
++			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
++
++			codec {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++
++	wifi32k: wifi32k {
++		compatible = "pwm-clock";
++		#clock-cells = <0>;
++		clock-frequency = <32768>;
++		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
++	};
++};
++
++&arb {
++	status = "okay";
++};
++
++&cec_AO {
++	pinctrl-0 = <&cec_ao_a_h_pins>;
++	pinctrl-names = "default";
++	status = "disabled";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&cecb_AO {
++	pinctrl-0 = <&cec_ao_b_h_pins>;
++	pinctrl-names = "default";
++	status = "okay";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&clkc_audio {
++	status = "okay";
++};
++
++&cpu0 {
++	cpu-supply = <&vddcpu_b>;
++	operating-points-v2 = <&cpu_opp_table_0>;
++	clocks = <&clkc CLKID_CPU_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu1 {
++	cpu-supply = <&vddcpu_b>;
++	operating-points-v2 = <&cpu_opp_table_0>;
++	clocks = <&clkc CLKID_CPU_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu100 {
++	cpu-supply = <&vddcpu_a>;
++	operating-points-v2 = <&cpub_opp_table_1>;
++	clocks = <&clkc CLKID_CPUB_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu101 {
++	cpu-supply = <&vddcpu_a>;
++	operating-points-v2 = <&cpub_opp_table_1>;
++	clocks = <&clkc CLKID_CPUB_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu102 {
++	cpu-supply = <&vddcpu_a>;
++	operating-points-v2 = <&cpub_opp_table_1>;
++	clocks = <&clkc CLKID_CPUB_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu103 {
++	cpu-supply = <&vddcpu_a>;
++	operating-points-v2 = <&cpub_opp_table_1>;
++	clocks = <&clkc CLKID_CPUB_CLK>;
++	clock-latency = <50000>;
++};
++
++&cvbs_vdac_port {
++	cvbs_vdac_out: endpoint {
++		remote-endpoint = <&cvbs_connector_in>;
++	};
++};
++
++&frddr_a {
++	status = "okay";
++};
++
++&frddr_b {
++	status = "okay";
++};
++
++&frddr_c {
++	status = "okay";
++};
++
++&gpio {
++	gpio-line-names =
++		/* GPIOZ */
++		"PIN_27", "PIN_28", "PIN_7", "PIN_11", "PIN_13", "PIN_15", "PIN_18", "PIN_40",
++		"", "", "", "", "", "", "", "",
++		/* GPIOH */
++		"", "", "", "", "PIN_19", "PIN_21", "PIN_24", "PIN_23",
++		"",
++		/* BOOT */
++		"", "", "", "", "", "", "", "",
++		"", "", "", "", "EMMC_PWRSEQ", "", "", "",
++		/* GPIOC */
++		"", "", "", "", "", "", "SD_CD", "PIN_36",
++		/* GPIOA */
++		"PIN_32", "PIN_12", "PIN_35", "", "", "PIN_38", "", "",
++		"", "", "", "", "LED_GREEN", "PIN_31", "PIN_3", "PIN_5",
++		/* GPIOX */
++		"", "", "", "", "", "", "SDIO_PWRSEQ", "",
++		"", "", "", "", "", "", "", "",
++		"", "BT_SHUTDOWN", "", "";
++};
++
++&gpio_ao {
++	gpio-line-names =
++		/* GPIOAO */
++		"PIN_8", "PIN_10", "", "BTN_POWER", "", "", "", "PIN_29",
++		"PIN_33", "PIN_37", "FAN", "",
++		/* GPIOE */
++		"", "", "";
++};
++
++&hdmi_tx {
++	status = "okay";
++	pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
++	pinctrl-names = "default";
++	hdmi-supply = <&ao_5v>;
++};
++
++&hdmi_tx_tmds_port {
++	hdmi_tx_tmds_out: endpoint {
++		remote-endpoint = <&hdmi_connector_in>;
++	};
++};
++
++&ir {
++	status = "disabled";
++	pinctrl-0 = <&remote_input_ao_pins>;
++	pinctrl-names = "default";
++};
++
++&pwm_ab {
++	pinctrl-0 = <&pwm_a_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&xtal>;
++	clock-names = "clkin0";
++	status = "okay";
++};
++
++&pwm_ef {
++	pinctrl-0 = <&pwm_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&xtal>;
++	clock-names = "clkin2";
++	status = "okay";
++};
++
++&pwm_AO_cd {
++	pinctrl-0 = <&pwm_ao_d_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&xtal>;
++	clock-names = "clkin4";
++	status = "okay";
++};
++
++&saradc {
++	status = "okay";
++	vref-supply = <&vddao_1v8>;
++};
++
++/* SDIO */
++&sd_emmc_a {
++	status = "okay";
++	pinctrl-0 = <&sdio_pins>;
++	pinctrl-1 = <&sdio_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++	#address-cells = <1>;
++	#size-cells = <0>;
++
++	bus-width = <4>;
++	cap-sd-highspeed;
++	max-frequency = <100000000>;
++
++	non-removable;
++	disable-wp;
++
++	/* WiFi firmware requires power to be kept while in suspend */
++	keep-power-in-suspend;
++
++	mmc-pwrseq = <&sdio_pwrseq>;
++
++	vmmc-supply = <&vddao_3v3>;
++	vqmmc-supply = <&vddao_1v8>;
++
++	brcmf: wifi@1 {
++		reg = <1>;
++		compatible = "brcm,bcm4329-fmac";
++	};
++};
++
++/* SD card */
++&sd_emmc_b {
++	status = "okay";
++	pinctrl-0 = <&sdcard_c_pins>;
++	pinctrl-1 = <&sdcard_clk_gate_c_pins>;
++	pinctrl-names = "default", "clk-gate";
++
++	bus-width = <4>;
++	cap-sd-highspeed;
++	max-frequency = <50000000>;
++	disable-wp;
++
++	cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
++	vmmc-supply = <&vddao_3v3>;
++	vqmmc-supply = <&vddao_3v3>;
++};
++
++/* eMMC */
++&sd_emmc_c {
++	status = "okay";
++	pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>;
++	pinctrl-1 = <&emmc_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++
++	bus-width = <8>;
++	cap-mmc-highspeed;
++	mmc-ddr-1_8v;
++	mmc-hs200-1_8v;
++	max-frequency = <200000000>;
++	disable-wp;
++
++	mmc-pwrseq = <&emmc_pwrseq>;
++	vmmc-supply = <&vcc_3v3>;
++	vqmmc-supply = <&vcc_1v8>;
++};
++
++&tdmif_b {
++	status = "okay";
++};
++
++&tdmout_b {
++	status = "okay";
++};
++
++&tohdmitx {
++	status = "okay";
++};
++
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "brcm,bcm43438-bt";
++		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		max-speed = <2000000>;
++		clocks = <&wifi32k>;
++		clock-names = "lpo";
++	};
++};
++
++&uart_AO {
++	status = "okay";
++	pinctrl-0 = <&uart_ao_a_pins>;
++	pinctrl-names = "default";
++};
++
++&usb {
++	status = "okay";
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0042-WIP-arm64-dts-meson-add-audio-playback-to-p201.patch b/gnu/packages/patches/amlogic-0042-WIP-arm64-dts-meson-add-audio-playback-to-p201.patch
new file mode 100644
index 0000000000..71d20739fc
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0042-WIP-arm64-dts-meson-add-audio-playback-to-p201.patch
@@ -0,0 +1,70 @@
+From f0102e5d910b47aa4f46e2757a8e4b9cd820ae7c Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Fri, 15 May 2020 07:52:47 +0000
+Subject: [PATCH 42/73] WIP: arm64: dts: meson: add audio playback to p201
+
+Add initial audio support limited to HDMI i2s.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-gxbb-p201.dts      | 40 +++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
+index 150a82f3b2d7..22bd0070146b 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
+@@ -8,10 +8,50 @@
+ /dts-v1/;
+ 
+ #include "meson-gxbb-p20x.dtsi"
++#include <dt-bindings/sound/meson-aiu.h>
+ 
+ / {
+ 	compatible = "amlogic,p201", "amlogic,meson-gxbb";
+ 	model = "Amlogic Meson GXBB P201 Development Board";
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "P201";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++};
++
++&aiu {
++	status = "okay";
+ };
+ 
+ &ethmac {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0043-WIP-arm64-dts-meson-add-audio-playback-to-p200.patch b/gnu/packages/patches/amlogic-0043-WIP-arm64-dts-meson-add-audio-playback-to-p200.patch
new file mode 100644
index 0000000000..cb6f03aa95
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0043-WIP-arm64-dts-meson-add-audio-playback-to-p200.patch
@@ -0,0 +1,99 @@
+From cbba90f273a4af2f08f6286bca65c49b96ff44d4 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Fri, 15 May 2020 07:56:15 +0000
+Subject: [PATCH 43/73] WIP: arm64: dts: meson: add audio playback to p200
+
+Add initial support limited to HDMI i2s and SPDIF (LPCM).
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-gxbb-p200.dts      | 61 +++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
+index 3c93d1898b40..27b3ab20f070 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
+@@ -9,11 +9,19 @@
+ 
+ #include "meson-gxbb-p20x.dtsi"
+ #include <dt-bindings/input/input.h>
++#include <dt-bindings/sound/meson-aiu.h>
+ 
+ / {
+ 	compatible = "amlogic,p200", "amlogic,meson-gxbb";
+ 	model = "Amlogic Meson GXBB P200 Development Board";
+ 
++	spdif_dit: audio-codec-0 {
++		#sound-dai-cells = <0>;
++		compatible = "linux,spdif-dit";
++		status = "okay";
++		sound-name-prefix = "DIT";
++	};
++
+ 	avdd18_usb_adc: regulator-avdd18_usb_adc {
+ 		compatible = "regulator-fixed";
+ 		regulator-name = "AVDD18_USB_ADC";
+@@ -57,6 +65,59 @@
+ 			press-threshold-microvolt = <0>; /* 0% */
+ 		};
+ 	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "P200";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
++
++			codec-0 {
++				sound-dai = <&spdif_dit>;
++			};
++		};
++
++		dai-link-4 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++};
++
++&aiu {
++	status = "okay";
++	pinctrl-0 = <&spdif_out_y_pins>;
++	pinctrl-names = "default";
+ };
+ 
+ &ethmac {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0044-WIP-arm64-dts-meson-add-audio-playback-to-u200.patch b/gnu/packages/patches/amlogic-0044-WIP-arm64-dts-meson-add-audio-playback-to-u200.patch
new file mode 100644
index 0000000000..362809b82f
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0044-WIP-arm64-dts-meson-add-audio-playback-to-u200.patch
@@ -0,0 +1,191 @@
+From e708a7770bd3d6f557bf31b7fa921af5e38d68ff Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 17 May 2020 05:00:55 +0000
+Subject: [PATCH 44/73] WIP: arm64: dts: meson: add audio playback to u200
+
+Add initial support limited to HDMI i2s and SPDIF (LPCM).
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-g12a-u200.dts      | 130 ++++++++++++++++++
+ 1 file changed, 130 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+index 4b5d11e56364..61a85c27a463 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+@@ -8,6 +8,7 @@
+ #include "meson-g12a.dtsi"
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/gpio/meson-g12a-gpio.h>
++#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+ 
+ / {
+ 	compatible = "amlogic,u200", "amlogic,g12a";
+@@ -18,6 +19,13 @@
+ 		ethernet0 = &ethmac;
+ 	};
+ 
++	spdif_dit: audio-codec-1 {
++		#sound-dai-cells = <0>;
++		compatible = "linux,spdif-dit";
++		status = "okay";
++		sound-name-prefix = "DIT";
++	};
++
+ 	chosen {
+ 		stdout-path = "serial0:115200n8";
+ 	};
+@@ -147,6 +155,90 @@
+ 		regulator-boot-on;
+ 		regulator-always-on;
+ 	};
++
++	sound {
++		compatible = "amlogic,axg-sound-card";
++		model = "U200";
++		audio-aux-devs = <&tdmout_b>;
++		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
++				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
++				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
++				"TDM_B Playback", "TDMOUT_B OUT",
++				"SPDIFOUT IN 0", "FRDDR_A OUT 3",
++				"SPDIFOUT IN 1", "FRDDR_B OUT 3",
++				"SPDIFOUT IN 2", "FRDDR_C OUT 3";
++
++		assigned-clocks = <&clkc CLKID_MPLL2>,
++				  <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&frddr_a>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&frddr_b>;
++		};
++
++		dai-link-2 {
++			sound-dai = <&frddr_c>;
++		};
++
++		/* 8ch hdmi interface */
++		dai-link-3 {
++			sound-dai = <&tdmif_b>;
++			dai-format = "i2s";
++			dai-tdm-slot-tx-mask-0 = <1 1>;
++			dai-tdm-slot-tx-mask-1 = <1 1>;
++			dai-tdm-slot-tx-mask-2 = <1 1>;
++			dai-tdm-slot-tx-mask-3 = <1 1>;
++			mclk-fs = <256>;
++
++			codec {
++				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
++			};
++		};
++
++		/* spdif hdmi or toslink interface */
++		dai-link-4 {
++			sound-dai = <&spdifout>;
++
++			codec-0 {
++				sound-dai = <&spdif_dit>;
++			};
++
++			codec-1 {
++				sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>;
++			};
++		};
++
++		/* spdif hdmi interface */
++		dai-link-5 {
++			sound-dai = <&spdifout_b>;
++
++			codec {
++				sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>;
++			};
++		};
++
++		/* hdmi glue */
++		dai-link-6 {
++			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
++
++			codec {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++};
++
++&arb {
++	status = "okay";
+ };
+ 
+ &cec_AO {
+@@ -163,6 +255,10 @@
+ 	hdmi-phandle = <&hdmi_tx>;
+ };
+ 
++&clkc_audio {
++	status = "okay";
++};
++
+ &cpu0 {
+ 	cpu-supply = <&vddcpu>;
+ 	operating-points-v2 = <&cpu_opp_table>;
+@@ -203,6 +299,18 @@
+ 	phy-mode = "rmii";
+ };
+ 
++&frddr_a {
++	status = "okay";
++};
++
++&frddr_b {
++	status = "okay";
++};
++
++&frddr_c {
++	status = "okay";
++};
++
+ &hdmi_tx {
+ 	status = "okay";
+ 	pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+@@ -288,6 +396,28 @@
+ 	vqmmc-supply = <&flash_1v8>;
+ };
+ 
++&spdifout {
++	pinctrl-0 = <&spdif_out_h_pins>;
++	pinctrl-names = "default";
++	status = "okay";
++};
++
++&spdifout_b {
++	status = "okay";
++};
++
++&tdmif_b {
++	status = "okay";
++};
++
++&tdmout_b {
++	status = "okay";
++};
++
++&tohdmitx {
++	status = "okay";
++};
++
+ &uart_AO {
+ 	status = "okay";
+ 	pinctrl-0 = <&uart_ao_a_pins>;
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0045-WIP-arm64-dts-meson-add-Headphone-output-to-Beelink-.patch b/gnu/packages/patches/amlogic-0045-WIP-arm64-dts-meson-add-Headphone-output-to-Beelink-.patch
new file mode 100644
index 0000000000..f2ebf4575a
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0045-WIP-arm64-dts-meson-add-Headphone-output-to-Beelink-.patch
@@ -0,0 +1,215 @@
+From fece5cdfd0a0be48e8b78294fc9242216761d13e Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 27 Nov 2021 13:50:06 +0000
+Subject: [PATCH 45/73] WIP: arm64: dts: meson: add Headphone output to Beelink
+ GT-King
+
+Add support for the Headphone audio DAC built-in to the S922X chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-g12b-gtking.dts    | 120 +++++++++++++++++-
+ 1 file changed, 113 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts
+index 5d96c1449050..a441975cbfb0 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts
+@@ -8,6 +8,7 @@
+ /dts-v1/;
+ 
+ #include "meson-g12b-w400.dtsi"
++#include <dt-bindings/sound/meson-g12a-toacodec.h>
+ #include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+ 
+ / {
+@@ -29,14 +30,37 @@
+ 	sound {
+ 		compatible = "amlogic,axg-sound-card";
+ 		model = "GTKING";
+-		audio-aux-devs = <&tdmout_b>;
++		audio-widgets = "Line", "Lineout";
++		audio-aux-devs = <&tdmout_b>, <&tdmout_c>,
++				 <&tdmin_a>, <&tdmin_b>, <&tdmin_c>;
+ 		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+ 				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
+ 				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
+ 				"TDM_B Playback", "TDMOUT_B OUT",
++				"TDMOUT_C IN 0", "FRDDR_A OUT 2",
++				"TDMOUT_C IN 1", "FRDDR_B OUT 2",
++				"TDMOUT_C IN 2", "FRDDR_C OUT 2",
++				"TDM_C Playback", "TDMOUT_C OUT",
++				"TDMIN_A IN 4", "TDM_B Loopback",
++				"TDMIN_B IN 4", "TDM_B Loopback",
++				"TDMIN_C IN 4", "TDM_B Loopback",
++				"TDMIN_A IN 5", "TDM_C Loopback",
++				"TDMIN_B IN 5", "TDM_C Loopback",
++				"TDMIN_C IN 5", "TDM_C Loopback",
++				"TODDR_A IN 0", "TDMIN_A OUT",
++				"TODDR_B IN 0", "TDMIN_A OUT",
++				"TODDR_C IN 0", "TDMIN_A OUT",
++				"TODDR_A IN 1", "TDMIN_B OUT",
++				"TODDR_B IN 1", "TDMIN_B OUT",
++				"TODDR_C IN 1", "TDMIN_B OUT",
++				"TODDR_A IN 2", "TDMIN_C OUT",
++				"TODDR_B IN 2", "TDMIN_C OUT",
++				"TODDR_C IN 2", "TDMIN_C OUT",
+ 				"SPDIFOUT IN 0", "FRDDR_A OUT 3",
+ 				"SPDIFOUT IN 1", "FRDDR_B OUT 3",
+-				"SPDIFOUT IN 2", "FRDDR_C OUT 3";
++				"SPDIFOUT IN 2", "FRDDR_C OUT 3",
++				"Lineout", "ACODEC LOLP",
++				"Lineout", "ACODEC LORP";
+ 
+ 		assigned-clocks = <&clkc CLKID_MPLL2>,
+ 				  <&clkc CLKID_MPLL0>,
+@@ -59,8 +83,20 @@
+ 			sound-dai = <&frddr_c>;
+ 		};
+ 
+-		/* 8ch hdmi interface */
+ 		dai-link-3 {
++			sound-dai = <&toddr_a>;
++		};
++
++		dai-link-4 {
++			sound-dai = <&toddr_b>;
++		};
++
++		dai-link-5 {
++			sound-dai = <&toddr_c>;
++		};
++
++		/* 8ch hdmi interface */
++		dai-link-6 {
+ 			sound-dai = <&tdmif_b>;
+ 			dai-format = "i2s";
+ 			dai-tdm-slot-tx-mask-0 = <1 1>;
+@@ -69,13 +105,17 @@
+ 			dai-tdm-slot-tx-mask-3 = <1 1>;
+ 			mclk-fs = <256>;
+ 
+-			codec {
++			codec-0 {
+ 				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+ 			};
++
++			codec-1 {
++				sound-dai = <&toacodec TOACODEC_IN_B>;
++			};
+ 		};
+ 
+ 		/* spdif hdmi or toslink interface */
+-		dai-link-4 {
++		dai-link-7 {
+ 			sound-dai = <&spdifout>;
+ 
+ 			codec-0 {
+@@ -88,7 +128,7 @@
+ 		};
+ 
+ 		/* spdif hdmi interface */
+-		dai-link-5 {
++		dai-link-8 {
+ 			sound-dai = <&spdifout_b>;
+ 
+ 			codec {
+@@ -96,17 +136,47 @@
+ 			};
+ 		};
+ 
++		/* i2s jack output interface */
++		dai-link-9 {
++			sound-dai = <&tdmif_c>;
++			dai-format = "i2s";
++			dai-tdm-slot-tx-mask-0 = <1 1>;
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>;
++			};
++
++			codec-1 {
++				sound-dai = <&toacodec TOACODEC_IN_C>;
++			};
++		};
++
+ 		/* hdmi glue */
+-		dai-link-6 {
++		dai-link-10 {
+ 			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+ 
+ 			codec {
+ 				sound-dai = <&hdmi_tx>;
+ 			};
+ 		};
++
++		/* acodec glue */
++		dai-link-11 {
++			sound-dai = <&toacodec TOACODEC_OUT>;
++
++			codec {
++				sound-dai = <&acodec>;
++			};
++		};
+ 	};
+ };
+ 
++&acodec {
++	AVDD-supply = <&vddao_1v8>;
++	status = "okay";
++};
++
+ &arb {
+ 	status = "okay";
+ };
+@@ -154,10 +224,46 @@
+ 	status = "okay";
+ };
+ 
++&tdmif_c {
++	status = "okay";
++};
++
++&tdmin_a {
++	status = "okay";
++};
++
++&tdmin_b {
++	status = "okay";
++};
++
++&tdmin_c {
++	status = "okay";
++};
++
+ &tdmout_b {
+ 	status = "okay";
+ };
+ 
++&tdmout_c {
++	status = "okay";
++};
++
++&toacodec {
++	status = "okay";
++};
++
++&toddr_a {
++	status = "okay";
++};
++
++&toddr_b {
++	status = "okay";
++};
++
++&toddr_c {
++	status = "okay";
++};
++
+ &tohdmitx {
+ 	status = "okay";
+ };
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0046-WIP-dt-bindings-arm-amlogic-add-support-for-the-Tani.patch b/gnu/packages/patches/amlogic-0046-WIP-dt-bindings-arm-amlogic-add-support-for-the-Tani.patch
new file mode 100644
index 0000000000..2a04ed8038
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0046-WIP-dt-bindings-arm-amlogic-add-support-for-the-Tani.patch
@@ -0,0 +1,29 @@
+From 363f2d99c9a9f49cabbef2818edb4df61a3f86cf Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 29 Feb 2020 15:13:02 +0000
+Subject: [PATCH 46/73] WIP: dt-bindings: arm: amlogic: add support for the
+ Tanix TX5 Max
+
+The Oranth (Tanix) TX5 Max is based on the Amlogic U200 reference
+board with an S905X2 chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index ea4f016082c4..ba74854cd6b1 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -145,6 +145,7 @@ properties:
+           - enum:
+               - amediatech,x96-max
+               - amlogic,u200
++              - oranth,tx5-max
+               - radxa,zero
+               - seirobotics,sei510
+           - const: amlogic,g12a
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0047-WIP-arm64-dts-meson-add-support-for-the-Tanix-TX5-Ma.patch b/gnu/packages/patches/amlogic-0047-WIP-arm64-dts-meson-add-support-for-the-Tanix-TX5-Ma.patch
new file mode 100644
index 0000000000..0eabc13b6a
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0047-WIP-arm64-dts-meson-add-support-for-the-Tanix-TX5-Ma.patch
@@ -0,0 +1,529 @@
+From b12f0b01cc049a365480902807c6a1db0980f587 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 20 Oct 2019 04:06:59 +0000
+Subject: [PATCH 47/73] WIP: arm64: dts: meson: add support for the Tanix TX5
+ Max
+
+The Tanix TX5 Max is based on the Amlogic U200 reference design
+using the S905X2 chipset. Hardware specification:
+
+- 4GB LPDDR4 RAM
+- 32GB eMMC storage
+- 10/100/1000 Base-T Ethernet using External RGMII PHY
+- 802.11 a/b/g/b/ac + BT 4.1 sdio wireless
+- HDMI 2.0 (4k@60p) video
+- Composite video + 2-channel audio output on 3.5mm jack
+- S/PDIF audio output
+- 1x USB 3.0
+- 1x USB 2.0
+- 1x micro SD card slot
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../dts/amlogic/meson-g12a-tanix-tx5max.dts   | 481 ++++++++++++++++++
+ 2 files changed, 482 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 5eaaeb620a17..51a3b84bda1e 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j100.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-axg-s400.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12a-radxa-zero.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12a-sei510.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-g12a-tanix-tx5max.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12a-u200.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12a-x96-max.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts
+new file mode 100644
+index 000000000000..0e55427ca398
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts
+@@ -0,0 +1,481 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2018 BayLibre SAS. All rights reserved.
++ */
++
++/dts-v1/;
++
++#include "meson-g12a.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/gpio/meson-g12a-gpio.h>
++#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
++
++/ {
++	compatible = "oranth,tx5-max", "amlogic,g12a";
++	model = "Tanix TX5 Max";
++
++	aliases {
++		serial0 = &uart_AO;
++		ethernet0 = &ethmac;
++	};
++
++	spdif_dit: audio-codec-1 {
++		#sound-dai-cells = <0>;
++		compatible = "linux,spdif-dit";
++		status = "okay";
++		sound-name-prefix = "DIT";
++	};
++
++	chosen {
++		stdout-path = "serial0:115200n8";
++	};
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x40000000>;
++	};
++
++	cvbs-connector {
++		compatible = "composite-video-connector";
++
++		port {
++			cvbs_connector_in: endpoint {
++				remote-endpoint = <&cvbs_vdac_out>;
++			};
++		};
++	};
++
++	hdmi-connector {
++		compatible = "hdmi-connector";
++		type = "a";
++
++		port {
++			hdmi_connector_in: endpoint {
++				remote-endpoint = <&hdmi_tx_tmds_out>;
++			};
++		};
++	};
++
++	emmc_pwrseq: emmc-pwrseq {
++		compatible = "mmc-pwrseq-emmc";
++		reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
++	};
++
++	sdio_pwrseq: sdio-pwrseq {
++		compatible = "mmc-pwrseq-simple";
++		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
++		clocks = <&wifi32k>;
++		clock-names = "ext_clock";
++	};
++
++	flash_1v8: regulator-flash_1v8 {
++		compatible = "regulator-fixed";
++		regulator-name = "FLASH_1V8";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++		vin-supply = <&vcc_3v3>;
++		regulator-always-on;
++	};
++
++	dc_in: regulator-dc_in {
++		compatible = "regulator-fixed";
++		regulator-name = "DC_IN";
++		regulator-min-microvolt = <5000000>;
++		regulator-max-microvolt = <5000000>;
++		regulator-always-on;
++	};
++
++	vcc_1v8: regulator-vcc_1v8 {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_1V8";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++		vin-supply = <&vcc_3v3>;
++		regulator-always-on;
++	};
++
++	vcc_3v3: regulator-vcc_3v3 {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_3V3";
++		regulator-min-microvolt = <3300000>;
++		regulator-max-microvolt = <3300000>;
++		vin-supply = <&vddao_3v3>;
++		regulator-always-on;
++		/* FIXME: actually controlled by VDDCPU_B_EN */
++	};
++
++	vcc_5v: regulator-vcc_5v {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_5V";
++		regulator-min-microvolt = <5000000>;
++		regulator-max-microvolt = <5000000>;
++		vin-supply = <&dc_in>;
++
++		gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>;
++		enable-active-low;
++	};
++
++	vddao_1v8: regulator-vddao_1v8 {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDAO_1V8";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++		vin-supply = <&vddao_3v3>;
++		regulator-always-on;
++	};
++
++	vddao_3v3: regulator-vddao_3v3 {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDAO_3V3";
++		regulator-min-microvolt = <3300000>;
++		regulator-max-microvolt = <3300000>;
++		vin-supply = <&dc_in>;
++		regulator-always-on;
++	};
++
++	vddcpu: regulator-vddcpu {
++		compatible = "pwm-regulator";
++
++		regulator-name = "VDDCPU";
++		regulator-min-microvolt = <721000>;
++		regulator-max-microvolt = <1022000>;
++
++		vin-supply = <&dc_in>;
++
++		pwms = <&pwm_AO_cd 1 1250 0>;
++		pwm-dutycycle-range = <100 0>;
++
++		regulator-boot-on;
++		regulator-always-on;
++	};
++
++	wifi32k: wifi32k {
++		compatible = "pwm-clock";
++		#clock-cells = <0>;
++		clock-frequency = <32768>;
++		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
++	};
++
++	sound {
++		compatible = "amlogic,axg-sound-card";
++		model = "TANIX-TX5MAX";
++		audio-aux-devs = <&tdmout_b>;
++		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
++				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
++				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
++				"TDM_B Playback", "TDMOUT_B OUT",
++				"SPDIFOUT IN 0", "FRDDR_A OUT 3",
++				"SPDIFOUT IN 1", "FRDDR_B OUT 3",
++				"SPDIFOUT IN 2", "FRDDR_C OUT 3";
++
++		assigned-clocks = <&clkc CLKID_MPLL2>,
++				  <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&frddr_a>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&frddr_b>;
++		};
++
++		dai-link-2 {
++			sound-dai = <&frddr_c>;
++		};
++
++		/* 8ch hdmi interface */
++		dai-link-3 {
++			sound-dai = <&tdmif_b>;
++			dai-format = "i2s";
++			dai-tdm-slot-tx-mask-0 = <1 1>;
++			dai-tdm-slot-tx-mask-1 = <1 1>;
++			dai-tdm-slot-tx-mask-2 = <1 1>;
++			dai-tdm-slot-tx-mask-3 = <1 1>;
++			mclk-fs = <256>;
++
++			codec {
++				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
++			};
++		};
++
++		/* spdif hdmi or toslink interface */
++		dai-link-4 {
++			sound-dai = <&spdifout>;
++
++			codec-0 {
++				sound-dai = <&spdif_dit>;
++			};
++
++			codec-1 {
++				sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>;
++			};
++		};
++
++		/* spdif hdmi interface */
++		dai-link-5 {
++			sound-dai = <&spdifout_b>;
++
++			codec {
++				sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>;
++			};
++		};
++
++		/* hdmi glue */
++		dai-link-6 {
++			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
++
++			codec {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++};
++
++&arb {
++	status = "okay";
++};
++
++&cec_AO {
++	pinctrl-0 = <&cec_ao_a_h_pins>;
++	pinctrl-names = "default";
++	status = "disabled";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&cecb_AO {
++	pinctrl-0 = <&cec_ao_b_h_pins>;
++	pinctrl-names = "default";
++	status = "okay";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&clkc_audio {
++	status = "okay";
++};
++
++&cpu0 {
++	cpu-supply = <&vddcpu>;
++	operating-points-v2 = <&cpu_opp_table>;
++	clocks = <&clkc CLKID_CPU_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu1 {
++	cpu-supply = <&vddcpu>;
++	operating-points-v2 = <&cpu_opp_table>;
++	clocks = <&clkc CLKID_CPU_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu2 {
++	cpu-supply = <&vddcpu>;
++	operating-points-v2 = <&cpu_opp_table>;
++	clocks = <&clkc CLKID_CPU_CLK>;
++	clock-latency = <50000>;
++};
++
++&cpu3 {
++	cpu-supply = <&vddcpu>;
++	operating-points-v2 = <&cpu_opp_table>;
++	clocks = <&clkc CLKID_CPU_CLK>;
++	clock-latency = <50000>;
++};
++
++&cvbs_vdac_port {
++	cvbs_vdac_out: endpoint {
++		remote-endpoint = <&cvbs_connector_in>;
++	};
++};
++
++&frddr_a {
++	status = "okay";
++};
++
++&frddr_b {
++	status = "okay";
++};
++
++&frddr_c {
++	status = "okay";
++};
++
++&hdmi_tx {
++	status = "okay";
++	pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
++	pinctrl-names = "default";
++	hdmi-supply = <&vcc_5v>;
++};
++
++&hdmi_tx_tmds_port {
++	hdmi_tx_tmds_out: endpoint {
++		remote-endpoint = <&hdmi_connector_in>;
++	};
++};
++
++&ir {
++	status = "okay";
++	pinctrl-0 = <&remote_input_ao_pins>;
++	pinctrl-names = "default";
++	linux,rc-map-name = "rc-tx5max";
++};
++
++&pwm_AO_cd {
++	pinctrl-0 = <&pwm_ao_d_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&xtal>;
++	clock-names = "clkin1";
++	status = "okay";
++};
++
++&ext_mdio {
++	external_phy: ethernet-phy@0 {
++		/* Realtek RTL8211F (0x001cc916) */
++		reg = <0>;
++		max-speed = <1000>;
++		eee-broken-1000t;
++
++		reset-assert-us = <10000>;
++		reset-deassert-us = <80000>;
++		reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
++
++		interrupt-parent = <&gpio_intc>;
++		/* MAC_INTR on GPIOZ_14 */
++		interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
++	};
++};
++
++&ethmac {
++	pinctrl-0 = <&eth_pins>, <&eth_rgmii_pins>;
++	pinctrl-names = "default";
++	status = "okay";
++	phy-mode = "rgmii";
++	phy-handle = <&external_phy>;
++	amlogic,tx-delay-ns = <2>;
++};
++
++&pwm_ef {
++	status = "okay";
++	pinctrl-0 = <&pwm_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&xtal>;
++	clock-names = "clkin0";
++};
++
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "brcm,bcm43438-bt";
++		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		max-speed = <2000000>;
++		clocks = <&wifi32k>;
++		clock-names = "lpo";
++	};
++};
++
++&uart_AO {
++	status = "okay";
++	pinctrl-0 = <&uart_ao_a_pins>;
++	pinctrl-names = "default";
++};
++
++&usb {
++	status = "okay";
++	dr_mode = "host";
++};
++
++/* SDIO */
++&sd_emmc_a {
++	status = "okay";
++	pinctrl-0 = <&sdio_pins>;
++	pinctrl-1 = <&sdio_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++	#address-cells = <1>;
++	#size-cells = <0>;
++
++	bus-width = <4>;
++	cap-sd-highspeed;
++	sd-uhs-sdr50;
++	max-frequency = <100000000>;
++
++	non-removable;
++	disable-wp;
++
++	/* WiFi firmware requires power to be kept while in suspend */
++	keep-power-in-suspend;
++
++	mmc-pwrseq = <&sdio_pwrseq>;
++
++	vmmc-supply = <&vddao_3v3>;
++	vqmmc-supply = <&vddao_1v8>;
++
++	brcmf: wifi@1 {
++		reg = <1>;
++		compatible = "brcm,bcm4329-fmac";
++	};
++};
++
++/* SD card */
++&sd_emmc_b {
++	status = "okay";
++	pinctrl-0 = <&sdcard_c_pins>;
++	pinctrl-1 = <&sdcard_clk_gate_c_pins>;
++	pinctrl-names = "default", "clk-gate";
++
++	bus-width = <4>;
++	cap-sd-highspeed;
++	max-frequency = <100000000>;
++	disable-wp;
++
++	cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
++	vmmc-supply = <&vddao_3v3>;
++	vqmmc-supply = <&vddao_3v3>;
++};
++
++/* eMMC */
++&sd_emmc_c {
++	status = "okay";
++	pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>;
++	pinctrl-1 = <&emmc_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++
++	bus-width = <8>;
++	cap-mmc-highspeed;
++	max-frequency = <100000000>;
++	non-removable;
++	disable-wp;
++
++	mmc-pwrseq = <&emmc_pwrseq>;
++	vmmc-supply = <&vcc_3v3>;
++	vqmmc-supply = <&flash_1v8>;
++};
++
++&spdifout {
++	pinctrl-0 = <&spdif_out_h_pins>;
++	pinctrl-names = "default";
++	status = "okay";
++};
++
++&spdifout_b {
++	status = "okay";
++};
++
++&tdmif_b {
++	status = "okay";
++};
++
++&tdmout_b {
++	status = "okay";
++};
++
++&tohdmitx {
++	status = "okay";
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0048-WIP-arm64-dts-meson-add-multiple-MeCool-device-trees.patch b/gnu/packages/patches/amlogic-0048-WIP-arm64-dts-meson-add-multiple-MeCool-device-trees.patch
new file mode 100644
index 0000000000..fb946dd526
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0048-WIP-arm64-dts-meson-add-multiple-MeCool-device-trees.patch
@@ -0,0 +1,215 @@
+From 9246eb3763b8fc6837b6041cd6c1441fcf12eddc Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Mon, 21 Oct 2019 03:58:06 +0000
+Subject: [PATCH 48/73] WIP: arm64: dts: meson: add multiple MeCool device
+ trees
+
+This adds initial device trees for a range of MeCool devices based on various
+Amlogic GXBB, GXL and GXM reference designs. The current purpose is to allow
+devices to be associated with their respective IR remote keymaps. It also
+prepares for the addition of DVB support in the future.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          | 11 ++++++
+ .../dts/amlogic/meson-gxbb-mecool-ki-plus.dts | 34 +++++++++++++++++++
+ .../dts/amlogic/meson-gxbb-mecool-kii-pro.dts | 34 +++++++++++++++++++
+ .../meson-gxl-s905d-mecool-ki-plus.dts        | 21 ++++++++++++
+ .../amlogic/meson-gxl-s905d-mecool-ki-pro.dts | 16 +++++++++
+ .../meson-gxl-s905d-mecool-m8s-plus.dts       | 16 +++++++++
+ 6 files changed, 132 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 51a3b84bda1e..1caed487c074 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -17,6 +17,8 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-radxa-zero2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-ugoos-am6.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-kii-pro.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-ki-plus.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-kii-pro.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb
+@@ -30,12 +32,21 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-play2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-libretech-ac.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-p241.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-libretech-pc.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-ki-plus.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-ki-pro.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-kii-pro.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-m8s-plus.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-phicomm-n1.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-sml5442tw.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-vero4k-plus.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-hwacom-amazetv.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-khadas-vim.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-jethome-jethub-j80.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-p281.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-tx3-mini.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts
+new file mode 100644
+index 000000000000..cb422633a8f9
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts
+@@ -0,0 +1,34 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/*
++ * Author: Christian Hewitt <[email-masked]>
++ */
++
++#include "meson-gxbb-p201.dts"
++
++/ {
++	compatible = "videostrong,gxbb-ki-plus", "amlogic,meson-gxbb";
++	model = "MeCool KI Plus";
++
++	clock: meson_clock {
++		compatible = "amlogic, gxbb-clock";
++		reg = <0x0 0xc883c000 0x0 0x1000>,
++		      <0x0 0xc8100000 0x0 0x1000>;
++		#clock-cells = <1>;
++		#reset-cells = <1>;
++		sys_max = <1536000000>;
++	};
++
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x40000000>;
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-mecool-ki-plus";
++};
++
++&usb_pwr {
++	gpio = <>;
++};
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts
+new file mode 100644
+index 000000000000..0dbcf0f7dbd9
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts
+@@ -0,0 +1,34 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/*
++ * Author: Christian Hewitt <[email-masked]>
++ */
++
++#include "meson-gxbb-p201.dts"
++
++/ {
++	compatible = "videostrong,gxbb-kii-pro", "amlogic,meson-gxbb";
++	model = "MeCool KII Pro";
++
++	clock: meson_clock {
++		compatible = "amlogic, gxbb-clock";
++		reg = <0x0 0xc883c000 0x0 0x1000>,
++		      <0x0 0xc8100000 0x0 0x1000>;
++		#clock-cells = <1>;
++		#reset-cells = <1>;
++		sys_max = <1536000000>;
++	};
++
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x40000000>;
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-mecool-kii-pro";
++};
++
++&usb_pwr {
++	gpio = <>;
++};
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts
+new file mode 100644
+index 000000000000..b4aed5d0dbdf
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts
+@@ -0,0 +1,21 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/*
++ * Author: Christian Hewitt <[email-masked]>
++ */
++
++#include "meson-gxl-s905d-p231.dts"
++
++/ {
++	compatible = "videostrong,gxl-ki-plus", "amlogic,s905d", "amlogic,meson-gxl";
++	model = "MeCool KI Plus";
++
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x40000000>;
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-mecool-ki-plus";
++};
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts
+new file mode 100644
+index 000000000000..af695620728c
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts
+@@ -0,0 +1,16 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/*
++ * Author: Christian Hewitt <[email-masked]>
++ */
++
++#include "meson-gxl-s905d-p230.dts"
++
++/ {
++	compatible = "videostrong,gxl-ki-pro", "amlogic,s905d", "amlogic,meson-gxl";
++	model = "MeCool KI Pro";
++};
++
++&ir {
++	linux,rc-map-name = "rc-mecool-ki-pro";
++};
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts
+new file mode 100644
+index 000000000000..3ddcf59d2649
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts
+@@ -0,0 +1,16 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/*
++ * Author: Christian Hewitt <[email-masked]>
++ */
++
++#include "meson-gxl-s905d-p231.dts"
++
++/ {
++	compatible = "videostrong,gxl-kii-pro", "amlogic,s905d", "amlogic,meson-gxl";
++	model = "MeCool M8S Plus";
++};
++
++&ir {
++	linux,rc-map-name = "rc-mecool-m8s-plus";
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0049-WIP-dt-bindings-arm-amlogic-add-support-for-Minix-NE.patch b/gnu/packages/patches/amlogic-0049-WIP-dt-bindings-arm-amlogic-add-support-for-Minix-NE.patch
new file mode 100644
index 0000000000..e0c2a0887a
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0049-WIP-dt-bindings-arm-amlogic-add-support-for-Minix-NE.patch
@@ -0,0 +1,29 @@
+From a5736b0b8811d7cad0c79fde2768b6cef819e35d Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 11 Apr 2021 05:50:13 +0000
+Subject: [PATCH 49/73] WIP: dt-bindings: arm: amlogic: add support for Minix
+ NEO-U1
+
+The Minix NEO-U1 is an Android STB based on the Amlogic P200 (GXBB)
+reference design with an S905 chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index ba74854cd6b1..7e801f208863 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -58,6 +58,7 @@ properties:
+               - amlogic,p201
+               - friendlyarm,nanopi-k2
+               - hardkernel,odroid-c2
++              - minix,neo-u1
+               - nexbox,a95x
+               - videostrong,kii-pro
+               - wetek,hub
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0050-WIP-arm64-dts-meson-add-initial-device-tree-for-Mini.patch b/gnu/packages/patches/amlogic-0050-WIP-arm64-dts-meson-add-initial-device-tree-for-Mini.patch
new file mode 100644
index 0000000000..c6f6efb259
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0050-WIP-arm64-dts-meson-add-initial-device-tree-for-Mini.patch
@@ -0,0 +1,241 @@
+From b2e02da33d49e72e3b3f126f6df87608be02443c Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 11 Apr 2021 05:52:14 +0000
+Subject: [PATCH 50/73] WIP: arm64: dts: meson: add initial device-tree for
+ Minix NEO-U1
+
+The Minix NEO-U1 is an Android STB based on the Amlogic P200 (GXBB)
+reference design with an S905-H chip and the following specs:
+
+- 2GB DDR3 RAM
+- 16GB eMMC
+- 10/100/1000 Base-T Ethernet
+- AP6356 Wireless (802.11 b/g/n/ac, BT 5.0)
+- HDMI 2.1 video
+- S/PDIF optical output
+- ES8323 DAC
+- 3x USB 2.0 port
+- 1x USB micro OTG port
+- RTC chip (hym8563)
+- IR receiver
+- 1x Power LED (white)
+- 1x Update/Reset button (underside)
+- 1x micro SD card slot
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../dts/amlogic/meson-gxbb-minix-neo-u1.dts   | 189 ++++++++++++++++++
+ 2 files changed, 190 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 1caed487c074..fd0d7d68f8e6 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -19,6 +19,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-ugoos-am6.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-kii-pro.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-ki-plus.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-kii-pro.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-minix-neo-u1.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts
+new file mode 100644
+index 000000000000..5343e90f9f34
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts
+@@ -0,0 +1,189 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2021 Christian Hewitt <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxbb-p20x.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/sound/meson-aiu.h>
++
++/ {
++	compatible = "minix,neo-u1", "amlogic,meson-gxbb";
++	model = "Minix NEO U1";
++
++	aliases {
++		rtc0 = &rtc;
++	};
++
++	spdif_dit: audio-codec-0 {
++		#sound-dai-cells = <0>;
++		compatible = "linux,spdif-dit";
++		status = "okay";
++		sound-name-prefix = "DIT";
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-status {
++			color = <LED_COLOR_ID_WHITE>;
++			function = LED_FUNCTION_STATUS;
++			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
++			default-state = "on";
++		};
++	};
++
++	gpio-keys-polled {
++		compatible = "gpio-keys-polled";
++		#address-cells = <1>;
++		#size-cells = <0>;
++		poll-interval = <20>;
++
++		button-reset {
++			label = "reset";
++			linux,code = <KEY_POWER>;
++			gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
++		};
++	};
++
++	avdd18_usb_adc: regulator-avdd18_usb_adc {
++		compatible = "regulator-fixed";
++		regulator-name = "AVDD18_USB_ADC";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "MINIX-NEO";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
++
++			codec-0 {
++				sound-dai = <&spdif_dit>;
++			};
++		};
++
++		dai-link-4 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++};
++
++&aiu {
++	status = "okay";
++	pinctrl-0 = <&spdif_out_y_pins>;
++	pinctrl-names = "default";
++};
++
++&ethmac {
++	status = "okay";
++	pinctrl-0 = <&eth_rgmii_pins>;
++	pinctrl-names = "default";
++
++	phy-handle = <&eth_phy0>;
++	phy-mode = "rgmii";
++
++	amlogic,tx-delay-ns = <2>;
++
++	mdio {
++		compatible = "snps,dwmac-mdio";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		eth_phy0: ethernet-phy@0 {
++			/* Realtek RTL8211F (0x001cc916) */
++			reg = <0>;
++
++			reset-assert-us = <10000>;
++			reset-deassert-us = <80000>;
++			reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
++
++			interrupt-parent = <&gpio_intc>;
++			/* MAC_INTR on GPIOZ_15 */
++			interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
++		};
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-minix-neo";
++};
++
++&i2c_A {
++	status = "okay";
++	pinctrl-0 = <&i2c_a_pins>;
++	pinctrl-names = "default";
++};
++
++&i2c_B {
++	status = "okay";
++	pinctrl-0 = <&i2c_b_pins>;
++	pinctrl-names = "default";
++
++	rtc: rtc@51 {
++		status = "okay";
++		compatible = "haoyu,hym8563";
++		reg = <0x51>;
++		#clock-cells = <0>;
++		clock-frequency = <32768>;
++		clock-output-names = "xin32k";
++		wakeup-source;
++	};
++};
++
++&saradc {
++	status = "okay";
++	vref-supply = <&avdd18_usb_adc>;
++};
++
++/* This is connected to the Bluetooth module: */
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "bcm43438-bt";
++		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		max-speed = <2000000>;
++		clocks = <&wifi32k>;
++		clock-names = "lpo";
++	};
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0051-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch b/gnu/packages/patches/amlogic-0051-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch
new file mode 100644
index 0000000000..1edd7177e1
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0051-LOCAL-arm64-dts-meson-add-rtc-vrtc-aliases-to-Minix-.patch
@@ -0,0 +1,28 @@
+From c543938e8b30003ef31501248601b9cd5d15270e Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Fri, 19 Aug 2022 21:32:21 +0000
+Subject: [PATCH 51/73] LOCAL: arm64: dts: meson: add rtc/vrtc aliases to Minix
+ NEO-U1
+
+Add node aliases to prevent meson-vrtc from claiming /dev/rtc0
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts
+index 5343e90f9f34..5900ee92ca28 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts
+@@ -17,6 +17,7 @@
+ 
+ 	aliases {
+ 		rtc0 = &rtc;
++		rtc1 = &vrtc;
+ 	};
+ 
+ 	spdif_dit: audio-codec-0 {
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0052-WIP-media-rc-add-keymap-for-Beelink-Mini-MXIII-remot.patch b/gnu/packages/patches/amlogic-0052-WIP-media-rc-add-keymap-for-Beelink-Mini-MXIII-remot.patch
new file mode 100644
index 0000000000..c578f8f223
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0052-WIP-media-rc-add-keymap-for-Beelink-Mini-MXIII-remot.patch
@@ -0,0 +1,117 @@
+From a85233ca2209fa517b3b68c6563f940591481501 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 8 Dec 2021 15:33:47 +0000
+Subject: [PATCH 52/73] WIP: media: rc: add keymap for Beelink Mini MXIII
+ remote
+
+Add a keymap and bindings for the simple IR (NEC) remote used with
+the Beelink Mini MXIII Android STB device.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../devicetree/bindings/media/rc.yaml         |  1 +
+ drivers/media/rc/keymaps/Makefile             |  1 +
+ drivers/media/rc/keymaps/rc-beelink-mxiii.c   | 54 +++++++++++++++++++
+ include/media/rc-map.h                        |  1 +
+ 4 files changed, 57 insertions(+)
+ create mode 100644 drivers/media/rc/keymaps/rc-beelink-mxiii.c
+
+diff --git a/Documentation/devicetree/bindings/media/rc.yaml b/Documentation/devicetree/bindings/media/rc.yaml
+index b11d14ab89c4..1121006b9fbe 100644
+--- a/Documentation/devicetree/bindings/media/rc.yaml
++++ b/Documentation/devicetree/bindings/media/rc.yaml
+@@ -39,6 +39,7 @@ properties:
+       - rc-avertv-303
+       - rc-azurewave-ad-tu700
+       - rc-beelink-gs1
++      - rc-beelink-mxiii
+       - rc-behold
+       - rc-behold-columbus
+       - rc-budget-ci-old
+diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
+index f513ff5caf4e..f3bf9878d72c 100644
+--- a/drivers/media/rc/keymaps/Makefile
++++ b/drivers/media/rc/keymaps/Makefile
+@@ -22,6 +22,7 @@ obj-$(CONFIG_RC_MAP) += \
+ 			rc-avertv-303.o \
+ 			rc-azurewave-ad-tu700.o \
+ 			rc-beelink-gs1.o \
++			rc-beelink-mxiii.o \
+ 			rc-behold-columbus.o \
+ 			rc-behold.o \
+ 			rc-budget-ci-old.o \
+diff --git a/drivers/media/rc/keymaps/rc-beelink-mxiii.c b/drivers/media/rc/keymaps/rc-beelink-mxiii.c
+new file mode 100644
+index 000000000000..09b77295e0a3
+--- /dev/null
++++ b/drivers/media/rc/keymaps/rc-beelink-mxiii.c
+@@ -0,0 +1,54 @@
++// SPDX-License-Identifier: GPL-2.0+
++//
++// Copyright (C) 2019 Christian Hewitt <[email-masked]>
++
++#include <media/rc-map.h>
++#include <linux/module.h>
++
++//
++// Keytable for the Beelink Mini MXIII remote control
++//
++
++static struct rc_map_table beelink_mxiii[] = {
++	{ 0xb2dc, KEY_POWER },
++
++	{ 0xb288, KEY_MUTE },
++	{ 0xb282, KEY_HOME },
++
++	{ 0xb2ca, KEY_UP },
++	{ 0xb299, KEY_LEFT },
++	{ 0xb2ce, KEY_OK },
++	{ 0xb2c1, KEY_RIGHT },
++	{ 0xb2d2, KEY_DOWN },
++
++	{ 0xb2c5, KEY_MENU },
++	{ 0xb29a, KEY_BACK },
++
++	{ 0xb281, KEY_VOLUMEDOWN },
++	{ 0xb280, KEY_VOLUMEUP },
++};
++
++static struct rc_map_list beelink_mxiii_map = {
++	.map = {
++		.scan     = beelink_mxiii,
++		.size     = ARRAY_SIZE(beelink_mxiii),
++		.rc_proto = RC_PROTO_NEC,
++		.name     = RC_MAP_BEELINK_MXIII,
++	}
++};
++
++static int __init init_rc_map_beelink_mxiii(void)
++{
++	return rc_map_register(&beelink_mxiii_map);
++}
++
++static void __exit exit_rc_map_beelink_mxiii(void)
++{
++	rc_map_unregister(&beelink_mxiii_map);
++}
++
++module_init(init_rc_map_beelink_mxiii)
++module_exit(exit_rc_map_beelink_mxiii)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Christian Hewitt <[email-masked]");
+diff --git a/include/media/rc-map.h b/include/media/rc-map.h
+index 793b54342dff..e4ddb3586d05 100644
+--- a/include/media/rc-map.h
++++ b/include/media/rc-map.h
+@@ -225,6 +225,7 @@ struct rc_map *rc_map_get(const char *name);
+ #define RC_MAP_AVERTV_303                "rc-avertv-303"
+ #define RC_MAP_AZUREWAVE_AD_TU700        "rc-azurewave-ad-tu700"
+ #define RC_MAP_BEELINK_GS1               "rc-beelink-gs1"
++#define RC_MAP_BEELINK_MXIII             "rc-beelink-mxiii"
+ #define RC_MAP_BEHOLD                    "rc-behold"
+ #define RC_MAP_BEHOLD_COLUMBUS           "rc-behold-columbus"
+ #define RC_MAP_BUDGET_CI_OLD             "rc-budget-ci-old"
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0053-WIP-dt-bindings-arm-amlogic-add-support-for-Beelink-.patch b/gnu/packages/patches/amlogic-0053-WIP-dt-bindings-arm-amlogic-add-support-for-Beelink-.patch
new file mode 100644
index 0000000000..923bf69bfe
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0053-WIP-dt-bindings-arm-amlogic-add-support-for-Beelink-.patch
@@ -0,0 +1,29 @@
+From 91747a7ed34a46cef82739d8d77645c281eda1cf Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 8 Dec 2021 15:28:50 +0000
+Subject: [PATCH 53/73] WIP: dt-bindings: arm: amlogic: add support for Beelink
+ Mini MXIII
+
+The Beelink Mini MXIII is an Android STB based on the Amlogic P200
+(GXBB) reference design with an S905 chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index 7e801f208863..096c3cfadeb0 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -56,6 +56,7 @@ properties:
+           - enum:
+               - amlogic,p200
+               - amlogic,p201
++              - beelink,mini-mxiii
+               - friendlyarm,nanopi-k2
+               - hardkernel,odroid-c2
+               - minix,neo-u1
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0054-WIP-arm64-dts-meson-add-support-for-Beelink-Mini-MXI.patch b/gnu/packages/patches/amlogic-0054-WIP-arm64-dts-meson-add-support-for-Beelink-Mini-MXI.patch
new file mode 100644
index 0000000000..9e92246517
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0054-WIP-arm64-dts-meson-add-support-for-Beelink-Mini-MXI.patch
@@ -0,0 +1,209 @@
+From 242be8590b9bb9462c4cced8613f0a7fb141f62d Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 8 Dec 2021 15:26:00 +0000
+Subject: [PATCH 54/73] WIP: arm64: dts: meson: add support for Beelink Mini
+ MXIII
+
+This is a GXBB board that ships in two variants, one with
+a Broadcom SDIO module, and a second with RTL8723BS.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../amlogic/meson-gxbb-beelink-mini-mxiii.dts | 172 ++++++++++++++++++
+ 2 files changed, 173 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index fd0d7d68f8e6..2fb679aa6105 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -17,6 +17,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-radxa-zero2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-ugoos-am6.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-kii-pro.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-beelink-mini-mxiii.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-ki-plus.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-kii-pro.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-minix-neo-u1.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts
+new file mode 100644
+index 000000000000..3d99ca93e1d5
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts
+@@ -0,0 +1,172 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2021 Christian Hewitt <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxbb-p20x.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/sound/meson-aiu.h>
++
++/ {
++	compatible = "beelink,mini-mxiii", "amlogic,meson-gxbb";
++	model = "Beelink Mini MXIII";
++
++	spdif_dit: audio-codec-0 {
++		#sound-dai-cells = <0>;
++		compatible = "linux,spdif-dit";
++		status = "okay";
++		sound-name-prefix = "DIT";
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-power {
++			/* Red in Standby */
++			color = <LED_COLOR_ID_GREEN>;
++			function = LED_FUNCTION_POWER;
++			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
++			default-state = "on";
++		};
++	};
++
++	gpio-keys-polled {
++		compatible = "gpio-keys-polled";
++		#address-cells = <1>;
++		#size-cells = <0>;
++		poll-interval = <20>;
++
++		button-reset {
++			label = "reset";
++			linux,code = <KEY_POWER>;
++			gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
++		};
++	};
++
++	avdd18_usb_adc: regulator-avdd18_usb_adc {
++		compatible = "regulator-fixed";
++		regulator-name = "AVDD18_USB_ADC";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "MINI-MXIII";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>;
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>;
++
++			codec-0 {
++				sound-dai = <&spdif_dit>;
++			};
++		};
++
++		dai-link-4 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++	};
++};
++
++&aiu {
++	status = "okay";
++	pinctrl-0 = <&spdif_out_y_pins>;
++	pinctrl-names = "default";
++};
++
++&ethmac {
++	status = "okay";
++	pinctrl-0 = <&eth_rgmii_pins>;
++	pinctrl-names = "default";
++
++	phy-handle = <&eth_phy0>;
++	phy-mode = "rgmii";
++
++	amlogic,tx-delay-ns = <2>;
++
++	mdio {
++		compatible = "snps,dwmac-mdio";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		eth_phy0: ethernet-phy@0 {
++			/* Realtek RTL8211F (0x001cc916) */
++			reg = <0>;
++
++			reset-assert-us = <10000>;
++			reset-deassert-us = <80000>;
++			reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
++
++			interrupt-parent = <&gpio_intc>;
++			/* MAC_INTR on GPIOZ_15 */
++			interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
++		};
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-beelink-mxiii";
++};
++
++&saradc {
++	status = "okay";
++	vref-supply = <&avdd18_usb_adc>;
++};
++
++/* Realtek Wireless SDIO Module */
++&sd_emmc_a {
++	/delete-node/ brcmf;
++
++	rtl8723bs: wifi@1 {
++		reg = <1>;
++		compatible = "realtek,rtl8723bs";
++	};
++};
++
++/* Connected to the Bluetooth module */
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "realtek,rtl8723bs-bt";
++		enable-gpios = <&gpio GPIOX_20 GPIO_ACTIVE_HIGH>;
++		host-wake-gpios = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>;
++	};
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0055-WIP-media-rc-add-keymap-for-MeCool-M8S-Pro-W-remote.patch b/gnu/packages/patches/amlogic-0055-WIP-media-rc-add-keymap-for-MeCool-M8S-Pro-W-remote.patch
new file mode 100644
index 0000000000..52182001bc
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0055-WIP-media-rc-add-keymap-for-MeCool-M8S-Pro-W-remote.patch
@@ -0,0 +1,138 @@
+From e8701365b030f23a1237df631201bd99b16e4230 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 16 Jan 2022 08:48:02 +0000
+Subject: [PATCH 55/73] WIP: media: rc: add keymap for MeCool M8S Pro W remote
+
+Add a keymap and bindings for the simple IR (NEC) remote used with
+the MeCool M8S Pro W Android STB device.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../devicetree/bindings/media/rc.yaml         |  1 +
+ drivers/media/rc/keymaps/Makefile             |  2 +
+ .../media/rc/keymaps/rc-mecool-m8s-pro-w.c    | 75 +++++++++++++++++++
+ include/media/rc-map.h                        |  1 +
+ 4 files changed, 79 insertions(+)
+ create mode 100644 drivers/media/rc/keymaps/rc-mecool-m8s-pro-w.c
+
+diff --git a/Documentation/devicetree/bindings/media/rc.yaml b/Documentation/devicetree/bindings/media/rc.yaml
+index 1121006b9fbe..5e3039e71312 100644
+--- a/Documentation/devicetree/bindings/media/rc.yaml
++++ b/Documentation/devicetree/bindings/media/rc.yaml
+@@ -94,6 +94,7 @@ properties:
+       - rc-manli
+       - rc-mecool-kii-pro
+       - rc-mecool-kiii-pro
++      - rc-mecool-m8s-pro-w
+       - rc-medion-x10
+       - rc-medion-x10-digitainer
+       - rc-medion-x10-or2x
+diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
+index f3bf9878d72c..ef48a6bbeca4 100644
+--- a/drivers/media/rc/keymaps/Makefile
++++ b/drivers/media/rc/keymaps/Makefile
+@@ -75,6 +75,8 @@ obj-$(CONFIG_RC_MAP) += \
+ 			rc-manli.o \
+ 			rc-mecool-kiii-pro.o \
+ 			rc-mecool-kii-pro.o \
++			rc-mecool-m8s-pro-w.o \
++			rc-medion-x10.o \
+ 			rc-medion-x10-digitainer.o \
+ 			rc-medion-x10.o \
+ 			rc-medion-x10-or2x.o \
+diff --git a/drivers/media/rc/keymaps/rc-mecool-m8s-pro-w.c b/drivers/media/rc/keymaps/rc-mecool-m8s-pro-w.c
+new file mode 100644
+index 000000000000..9024b999d5a9
+--- /dev/null
++++ b/drivers/media/rc/keymaps/rc-mecool-m8s-pro-w.c
+@@ -0,0 +1,75 @@
++// SPDX-License-Identifier: GPL-2.0+
++//
++// Copyright (C) 2022 Christian Hewitt <[email-masked]>
++
++#include <media/rc-map.h>
++#include <linux/module.h>
++
++//
++// Keytable for the MeCool M8S Pro W remote control
++//
++
++static struct rc_map_table mecool_m8s_pro_w[] = {
++
++	{ 0x59, KEY_POWER },
++
++	// TV CONTROLS
++
++	{ 0x08, KEY_PREVIOUS },
++	{ 0x0b, KEY_NEXT },
++	{ 0x18, KEY_TEXT }, // INTERNET
++	{ 0x19, KEY_MUTE },
++	{ 0x13, KEY_VOLUMEUP },
++	{ 0x17, KEY_VOLUMEDOWN },
++
++	{ 0x0d, KEY_HOME },
++	{ 0x05, KEY_BACK },
++
++	{ 0x06, KEY_UP },
++	{ 0x5a, KEY_LEFT },
++	{ 0x1b, KEY_RIGHT },
++	{ 0x1a, KEY_ENTER },
++	{ 0x16, KEY_DOWN },
++
++	{ 0x45, KEY_MENU },
++	{ 0x12, KEY_CONTEXT_MENU }, // MOUSE
++
++	{ 0x52, KEY_NUMERIC_1 },
++	{ 0x50, KEY_NUMERIC_2 },
++	{ 0x10, KEY_NUMERIC_3 },
++	{ 0x56, KEY_NUMERIC_4 },
++	{ 0x54, KEY_NUMERIC_5 },
++	{ 0x14, KEY_NUMERIC_6 },
++	{ 0x4e, KEY_NUMERIC_7 },
++	{ 0x4c, KEY_NUMERIC_8 },
++	{ 0x0c, KEY_NUMERIC_9 },
++	{ 0x22, KEY_INFO }, // SEARCH
++	{ 0x0f, KEY_NUMERIC_0 },
++	{ 0x51, KEY_BACKSPACE },
++
++};
++
++static struct rc_map_list mecool_m8s_pro_w_map = {
++	.map = {
++		.scan     = mecool_m8s_pro_w,
++		.size     = ARRAY_SIZE(mecool_m8s_pro_w),
++		.rc_proto = RC_PROTO_NEC,
++		.name     = RC_MAP_MECOOL_M8S_PRO_W,
++	}
++};
++
++static int __init init_rc_map_mecool_m8s_pro_w(void)
++{
++	return rc_map_register(&mecool_m8s_pro_w_map);
++}
++
++static void __exit exit_rc_map_mecool_m8s_pro_w(void)
++{
++	rc_map_unregister(&mecool_m8s_pro_w_map);
++}
++
++module_init(init_rc_map_mecool_m8s_pro_w)
++module_exit(exit_rc_map_mecool_m8s_pro_w)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Christian Hewitt <[email-masked]");
+diff --git a/include/media/rc-map.h b/include/media/rc-map.h
+index e4ddb3586d05..9b6f09a6fd3a 100644
+--- a/include/media/rc-map.h
++++ b/include/media/rc-map.h
+@@ -281,6 +281,7 @@ struct rc_map *rc_map_get(const char *name);
+ #define RC_MAP_MANLI                     "rc-manli"
+ #define RC_MAP_MECOOL_KII_PRO            "rc-mecool-kii-pro"
+ #define RC_MAP_MECOOL_KIII_PRO           "rc-mecool-kiii-pro"
++#define RC_MAP_MECOOL_M8S_PRO_W          "rc-mecool-m8s-pro-w"
+ #define RC_MAP_MEDION_X10                "rc-medion-x10"
+ #define RC_MAP_MEDION_X10_DIGITAINER     "rc-medion-x10-digitainer"
+ #define RC_MAP_MEDION_X10_OR2X           "rc-medion-x10-or2x"
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0056-WIP-dt-bindings-arm-amlogic-add-support-for-MeCool-M.patch b/gnu/packages/patches/amlogic-0056-WIP-dt-bindings-arm-amlogic-add-support-for-MeCool-M.patch
new file mode 100644
index 0000000000..3358726bd6
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0056-WIP-dt-bindings-arm-amlogic-add-support-for-MeCool-M.patch
@@ -0,0 +1,29 @@
+From cac91ad1445e0da6b9f51e5e4b3d29e6bd361b7e Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 16 Jan 2022 08:15:36 +0000
+Subject: [PATCH 56/73] WIP: dt-bindings: arm: amlogic: add support for MeCool
+ M8S Pro W
+
+The MeCool M8S Pro W is an Android STB based on the Amlogic P281
+(GXL) reference design with an S905W chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index 096c3cfadeb0..954d536f6c56 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -89,6 +89,7 @@ properties:
+               - amlogic,p281
+               - oranth,tx3-mini
+               - jethome,jethub-j80
++              - videostrong,gxl-m8s-pro-w
+           - const: amlogic,s905w
+           - const: amlogic,meson-gxl
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0057-WIP-arm64-dts-meson-add-support-for-MeCool-M8S-Pro-W.patch b/gnu/packages/patches/amlogic-0057-WIP-arm64-dts-meson-add-support-for-MeCool-M8S-Pro-W.patch
new file mode 100644
index 0000000000..2f37f7cbd9
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0057-WIP-arm64-dts-meson-add-support-for-MeCool-M8S-Pro-W.patch
@@ -0,0 +1,66 @@
+From 282f373fa348d80178c8849853bf2919d4ab7d5d Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 16 Jan 2022 08:17:41 +0000
+Subject: [PATCH 57/73] WIP: arm64: dts: meson: add support for MeCool M8S Pro
+ W
+
+MeCool M8S Pro W is an Android STB based on the Amlogic P281 (GXL)
+reference design with an S905W chip and the following specs:
+
+- 2GB DDR3 RAM
+- 16GB eMMC
+- 10/100 Base-T Ethernet
+- SSV6051P Wireless (802.11 b/g/n)
+- HDMI 2.0 video
+- 1x 3.5mm AV jack
+- 2x USB 2.0 port
+- IR receiver
+- 1x Power LED (blue)
+- 1x Update/Reset button (underside)
+- 1x micro SD card slot
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../meson-gxl-s905w-mecool-m8s-pro-w.dts      | 30 +++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts
+new file mode 100644
+index 000000000000..a5bbe7315471
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts
+@@ -0,0 +1,30 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2018 Martin Blumenstingl <[email-masked]>.
++ * Based on meson-gxl-s905d-p231.dts:
++ * - Copyright (c) 2016 Endless Computers, Inc.
++ *   Author: Carlo Caione <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxl-s905x.dtsi"
++#include "meson-gx-p23x-q20x.dtsi"
++
++/ {
++	compatible = "videostrong,gxl-m8s-pro-w", "amlogic,s905w", "amlogic,meson-gxl";
++	model = "MeCool M8S Pro W";
++
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x80000000>;
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-mecool-m8s-pro-w";
++};
++
++&usb {
++	dr_mode = "host";
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0058-WIP-dt-bindings-arm-amlogic-add-Vero-4K-binding.patch b/gnu/packages/patches/amlogic-0058-WIP-dt-bindings-arm-amlogic-add-Vero-4K-binding.patch
new file mode 100644
index 0000000000..5aca6a7b41
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0058-WIP-dt-bindings-arm-amlogic-add-Vero-4K-binding.patch
@@ -0,0 +1,27 @@
+From f8a3f8723b9996495a87676b66ab33d2ccde6152 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 19 Jan 2022 02:40:20 +0000
+Subject: [PATCH 58/73] WIP: dt-bindings: arm: amlogic: add Vero 4K binding
+
+Add the board binding for the OSMC Vero 4K STB device
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index 954d536f6c56..ef943bf50944 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -102,6 +102,7 @@ properties:
+               - libretech,aml-s905x-cc
+               - libretech,aml-s905x-cc-v2
+               - nexbox,a95x
++              - osmc,vero4k
+           - const: amlogic,s905x
+           - const: amlogic,meson-gxl
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0059-WIP-arm64-dts-meson-add-support-for-OSMC-Vero-4K.patch b/gnu/packages/patches/amlogic-0059-WIP-arm64-dts-meson-add-support-for-OSMC-Vero-4K.patch
new file mode 100644
index 0000000000..71d2d1de7a
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0059-WIP-arm64-dts-meson-add-support-for-OSMC-Vero-4K.patch
@@ -0,0 +1,230 @@
+From b9752455be81fbca3fad373b608b643e48f99df0 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 19 Jan 2022 04:06:17 +0000
+Subject: [PATCH 59/73] WIP: arm64: dts: meson: add support for OSMC Vero 4K
+
+The OSMC Vero 4K device is based on the Amlogic S905X (P212) reference
+design with the following specifications:
+
+- 2GB DDR4 RAM
+- 16GB eMMC
+- HDMI 2.1 video
+- S/PDIF optical output
+- AV output
+- 10/100 Ethernet
+- AP6255 Wireless (802.11 a/b/g/n/ac, BT 4.2)
+- 2x USB 2.0 ports (1x OTG)
+- IR receiver (internal)
+- IR extender port (external)
+- 1x micro SD card slot
+- 1x Power LED (red)
+- 1x Reset button (in AV jack)
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../dts/amlogic/meson-gxl-s905x-vero4k.dts    | 180 ++++++++++++++++++
+ 2 files changed, 181 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 2fb679aa6105..de102b395dd3 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -49,6 +49,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-vero4k.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-jethome-jethub-j80.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-p281.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-tx3-mini.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts
+new file mode 100644
+index 000000000000..6196153e424d
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts
+@@ -0,0 +1,180 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Author: Christian Hewitt <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxl-s905x-p212.dtsi"
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/sound/meson-aiu.h>
++
++/ {
++	compatible = "osmc,vero4k", "amlogic,s905x", "amlogic,meson-gxl";
++	model = "OSMC Vero 4K";
++
++	reserved-memory {
++		/* 32 MiB reserved for ARM Trusted Firmware (BL32) */
++		secmon_reserved_bl32: secmon@5300000 {
++			reg = <0x0 0x05300000 0x0 0x2000000>;
++			no-map;
++		};
++	};
++
++	gpio-keys-polled {
++		compatible = "gpio-keys-polled";
++		#address-cells = <1>;
++		#size-cells = <0>;
++		poll-interval = <20>;
++
++		button@0 {
++			label = "power";
++			linux,code = <KEY_POWER>;
++			gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
++		};
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-standby {
++			color = <LED_COLOR_ID_RED>;
++			function = LED_FUNCTION_POWER;
++			gpios = <&gpio GPIODV_24 GPIO_ACTIVE_LOW>;
++			default-state = "off";
++			panic-indicator;
++		};
++	};
++
++	dio2133: analog-amplifier {
++		compatible = "simple-audio-amplifier";
++		sound-name-prefix = "AU2";
++		VCC-supply = <&hdmi_5v>;
++		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
++	};
++
++	cvbs-connector {
++		compatible = "composite-video-connector";
++
++		port {
++			cvbs_connector_in: endpoint {
++				remote-endpoint = <&cvbs_vdac_out>;
++			};
++		};
++	};
++
++	hdmi-connector {
++		compatible = "hdmi-connector";
++		type = "a";
++
++		port {
++			hdmi_connector_in: endpoint {
++				remote-endpoint = <&hdmi_tx_tmds_out>;
++			};
++		};
++	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "VERO4K";
++		audio-aux-devs = <&dio2133>;
++		audio-widgets = "Line", "Lineout";
++		audio-routing = "AU2 INL", "ACODEC LOLN",
++				"AU2 INR", "ACODEC LORN",
++				"Lineout", "AU2 OUTL",
++				"Lineout", "AU2 OUTR";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++
++			codec-1 {
++				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
++			};
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&acodec>;
++			};
++		};
++	};
++};
++
++&acodec {
++	AVDD-supply = <&vddio_ao18>;
++	status = "okay";
++};
++
++&aiu {
++	status = "okay";
++};
++
++&cec_AO {
++	status = "okay";
++	pinctrl-0 = <&ao_cec_pins>;
++	pinctrl-names = "default";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&cvbs_vdac_port {
++	cvbs_vdac_out: endpoint {
++		remote-endpoint = <&cvbs_connector_in>;
++	};
++};
++
++&ethmac {
++        phy-mode = "rmii";
++        phy-handle = <&internal_phy>;
++};
++
++&hdmi_tx {
++	status = "okay";
++	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
++	pinctrl-names = "default";
++	hdmi-supply = <&hdmi_5v>;
++};
++
++&hdmi_tx_tmds_port {
++	hdmi_tx_tmds_out: endpoint {
++		remote-endpoint = <&hdmi_connector_in>;
++	};
++};
++
++&internal_phy {
++        pinctrl-0 = <&eth_link_led_pins>, <&eth_act_led_pins>;
++        pinctrl-names = "default";
++};
++
++/* This UART is brought out to the DB9 connector */
++&uart_AO {
++	status = "okay";
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0060-WIP-arm64-dts-meson-add-RTL8822CS-bluetooth-to-X96-A.patch b/gnu/packages/patches/amlogic-0060-WIP-arm64-dts-meson-add-RTL8822CS-bluetooth-to-X96-A.patch
new file mode 100644
index 0000000000..436a1b95a6
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0060-WIP-arm64-dts-meson-add-RTL8822CS-bluetooth-to-X96-A.patch
@@ -0,0 +1,37 @@
+From 595907b3cf75fd7c4e1378e2b1e0f603d6b72fd9 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Tue, 12 Apr 2022 11:21:21 +0000
+Subject: [PATCH 60/73] WIP: arm64: dts: meson: add RTL8822CS bluetooth to
+ X96-Air
+
+Add the uart_A/bluetooth node for the RTL8822CS chip.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-sm1-x96-air-gbit.dts     | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts
+index 7e1a74046ba5..66e53c25bfb4 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts
+@@ -131,3 +131,16 @@
+ &tohdmitx {
+ 	status = "okay";
+ };
++
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "realtek,rtl8822cs-bt";
++		enable-gpios  = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		host-wake-gpios = <&gpio GPIOX_18 GPIO_ACTIVE_HIGH>;
++	};
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0061-WIP-media-rc-add-keymap-for-Venz-V10-remote.patch b/gnu/packages/patches/amlogic-0061-WIP-media-rc-add-keymap-for-Venz-V10-remote.patch
new file mode 100644
index 0000000000..8d0f28c8dc
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0061-WIP-media-rc-add-keymap-for-Venz-V10-remote.patch
@@ -0,0 +1,154 @@
+From 420bb2b17660a31cb5928df4cb38b8236c07db49 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 10 Apr 2022 11:51:38 +0000
+Subject: [PATCH 61/73] WIP: media: rc: add keymap for Venz V10 remote
+
+Add a keymap and bindings for the IR (NEC) remote used with
+the Venz V10 Android STB device.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../devicetree/bindings/media/rc.yaml         |  1 +
+ drivers/media/rc/keymaps/Makefile             |  1 +
+ drivers/media/rc/keymaps/rc-venz-v10.c        | 92 +++++++++++++++++++
+ include/media/rc-map.h                        |  1 +
+ 4 files changed, 95 insertions(+)
+ create mode 100644 drivers/media/rc/keymaps/rc-venz-v10.c
+
+diff --git a/Documentation/devicetree/bindings/media/rc.yaml b/Documentation/devicetree/bindings/media/rc.yaml
+index 5e3039e71312..f441a35ce7f4 100644
+--- a/Documentation/devicetree/bindings/media/rc.yaml
++++ b/Documentation/devicetree/bindings/media/rc.yaml
+@@ -151,6 +151,7 @@ properties:
+       - rc-videomate-tv-pvr
+       - rc-videostrong-kii-pro
+       - rc-vega-s9x
++      - rc-venz-v10
+       - rc-wetek-hub
+       - rc-wetek-play2
+       - rc-winfast
+diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
+index ef48a6bbeca4..77d8b5a69815 100644
+--- a/drivers/media/rc/keymaps/Makefile
++++ b/drivers/media/rc/keymaps/Makefile
+@@ -128,6 +128,7 @@ obj-$(CONFIG_RC_MAP) += \
+ 			rc-twinhan1027.o \
+ 			rc-twinhan-dtv-cab-ci.o \
+ 			rc-vega-s9x.o \
++			rc-venz-v10.o \
+ 			rc-videomate-m1f.o \
+ 			rc-videomate-s350.o \
+ 			rc-videomate-tv-pvr.o \
+diff --git a/drivers/media/rc/keymaps/rc-venz-v10.c b/drivers/media/rc/keymaps/rc-venz-v10.c
+new file mode 100644
+index 000000000000..f0a99a31a1d7
+--- /dev/null
++++ b/drivers/media/rc/keymaps/rc-venz-v10.c
+@@ -0,0 +1,92 @@
++// SPDX-License-Identifier: GPL-2.0+
++//
++// Copyright (C) 2022 Christian Hewitt <[email-masked]>
++
++#include <media/rc-map.h>
++#include <linux/module.h>
++
++//
++// Keytable for the Venz V10 remote control
++//
++
++static struct rc_map_table venz_v10[] = {
++	{ 0x847912, KEY_POWER },
++	{ 0x847903, KEY_MUTE },
++
++	{ 0x847921, KEY_EPG },
++	{ 0x847922, KEY_ZOOMIN },
++	{ 0x847923, KEY_ZOOMOUT },
++	{ 0x847924, KEY_SCREEN }, // LAUNCHER
++
++	// UP
++	// DOWN
++	// LEFT
++	// RIGHT
++
++	{ 0x847904, KEY_FAVORITES }, // TV-SYS
++	{ 0x84790a, KEY_INFO }, // RATIO
++	{ 0x84791f, KEY_LANGUAGE }, // TRACK
++	{ 0x84791e, KEY_SUBTITLE }, // SUB-T
++
++	{ 0x847929, KEY_RED },
++	{ 0x847930, KEY_GREEN },
++	{ 0x847931, KEY_YELLOW },
++	{ 0x847932, KEY_BLUE },
++
++	{ 0x847906, KEY_HOME },
++	{ 0x84791b, KEY_CONFIG },
++
++	{ 0x847905, KEY_UP },
++	{ 0x847907, KEY_LEFT },
++	{ 0x847908, KEY_OK },
++	{ 0x847909, KEY_RIGHT },
++	{ 0x847900, KEY_DOWN },
++
++	{ 0x847920, KEY_CONTEXT_MENU },
++	{ 0x84791a, KEY_BACK },
++
++	{ 0x847910, KEY_VOLUMEUP },
++	{ 0x84790f, KEY_VOLUMEDOWN },
++	{ 0x847919, KEY_PLAYPAUSE },
++	{ 0x84791c, KEY_STOP },
++	{ 0x84791d, KEY_PREVIOUS },
++	{ 0x847928, KEY_NEXT },
++
++	{ 0x84790b, KEY_1 },
++	{ 0x84790c, KEY_2 },
++	{ 0x84790d, KEY_3 },
++	{ 0x84790e, KEY_4 },
++	{ 0x847911, KEY_5 },
++	{ 0x847927, KEY_6 },
++	{ 0x847913, KEY_7 },
++	{ 0x847914, KEY_8 },
++	{ 0x847915, KEY_9 },
++	{ 0x847916, KEY_MENU }, // MOUSE
++	{ 0x847917, KEY_0 },
++	{ 0x847918, KEY_DELETE },
++};
++
++static struct rc_map_list venz_v10_map = {
++	.map = {
++		.scan     = venz_v10,
++		.size     = ARRAY_SIZE(venz_v10),
++		.rc_proto = RC_PROTO_NEC,
++		.name     = RC_MAP_VENZ_V10,
++	}
++};
++
++static int __init init_rc_map_venz_v10(void)
++{
++	return rc_map_register(&venz_v10_map);
++}
++
++static void __exit exit_rc_map_venz_v10(void)
++{
++	rc_map_unregister(&venz_v10_map);
++}
++
++module_init(init_rc_map_venz_v10)
++module_exit(exit_rc_map_venz_v10)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Christian Hewitt <[email-masked]");
+diff --git a/include/media/rc-map.h b/include/media/rc-map.h
+index 9b6f09a6fd3a..43d254930daa 100644
+--- a/include/media/rc-map.h
++++ b/include/media/rc-map.h
+@@ -333,6 +333,7 @@ struct rc_map *rc_map_get(const char *name);
+ #define RC_MAP_TT_1500                   "rc-tt-1500"
+ #define RC_MAP_TWINHAN_DTV_CAB_CI        "rc-twinhan-dtv-cab-ci"
+ #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
++#define RC_MAP_VENZ_V10                  "rc-venz-v10"
+ #define RC_MAP_VEGA_S9X                  "rc-vega-s9x"
+ #define RC_MAP_VIDEOMATE_K100            "rc-videomate-k100"
+ #define RC_MAP_VIDEOMATE_S350            "rc-videomate-s350"
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0062-WIP-dt-bindings-arm-amlogic-add-S905L-and-Venz-V10-b.patch b/gnu/packages/patches/amlogic-0062-WIP-dt-bindings-arm-amlogic-add-S905L-and-Venz-V10-b.patch
new file mode 100644
index 0000000000..1fdcc47097
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0062-WIP-dt-bindings-arm-amlogic-add-S905L-and-Venz-V10-b.patch
@@ -0,0 +1,34 @@
+From 2e6341669bc34a64c264db1137369cdb31a4ee5f Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 9 Apr 2022 06:27:50 +0000
+Subject: [PATCH 62/73] WIP: dt-bindings: arm: amlogic: add S905L and Venz V10
+ bindings
+
+Add SOC bindings for S905L devices and the board binding for Venz V10.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index ef943bf50944..47a9ec09a81a 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -83,6 +83,13 @@ properties:
+           - const: amlogic,s805x
+           - const: amlogic,meson-gxl
+ 
++      - description: Boards with the Amlogic Meson GXL S905L SoC
++        items:
++          - enum:
++              - venz,v10
++          - const: amlogic,s905l
++          - const: amlogic,meson-gxl
++
+       - description: Boards with the Amlogic Meson GXL S905W SoC
+         items:
+           - enum:
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0063-WIP-arm64-dts-meson-add-support-for-Venz-V10.patch b/gnu/packages/patches/amlogic-0063-WIP-arm64-dts-meson-add-support-for-Venz-V10.patch
new file mode 100644
index 0000000000..81344f3441
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0063-WIP-arm64-dts-meson-add-support-for-Venz-V10.patch
@@ -0,0 +1,373 @@
+From 3eafb34fd8bdff426583e2fb85dfd82fb69564ca Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sat, 9 Apr 2022 06:21:58 +0000
+Subject: [PATCH 63/73] WIP: arm64: dts: meson: add support for Venz V10
+
+The Venz V10 is an Android STB based on the Amlogic P212 (GXL)
+reference design with an S905L chip and the following specs:
+
+- 1GB DDR3 RAM
+- 8GB eMMC
+- 10/100 Base-T Ethernet
+- RTL8189ES Wireless (802.11 b/g/n)
+- HDMI 2.0b video
+- 1x 3.5mm AV jack
+- 2x USB 2.0 port
+- IR receiver
+- 1x Update/Reset button (underside)
+- 1x micro SD card slot
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../dts/amlogic/meson-gxl-s905l-venz-v10.dts  | 326 ++++++++++++++++++
+ 2 files changed, 327 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index de102b395dd3..751e1be7be1b 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -43,6 +43,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-phicomm-n1.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-sml5442tw.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-vero4k-plus.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905l-venz-v10.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-hwacom-amazetv.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-khadas-vim.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts
+new file mode 100644
+index 000000000000..553377fce051
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts
+@@ -0,0 +1,326 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2016 Endless Computers, Inc.
++ * Author: Carlo Caione <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxl-s905x.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/sound/meson-aiu.h>
++
++/ {
++	compatible = "venz,v10", "amlogic,s905l", "amlogic,meson-gxl";
++	model = "Venz V10";
++
++	aliases {
++		serial0 = &uart_AO;
++		ethernet0 = &ethmac;
++		wlan0 = &rtl8189;
++	};
++
++	chosen {
++		stdout-path = "serial0:115200n8";
++	};
++
++	memory@0 {
++		device_type = "memory";
++		reg = <0x0 0x0 0x0 0x80000000>;
++	};
++
++	dio2133: analog-amplifier {
++		compatible = "simple-audio-amplifier";
++		sound-name-prefix = "AU2";
++		VCC-supply = <&hdmi_5v>;
++		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-standby {
++			color = <LED_COLOR_ID_BLUE>;
++			function = LED_FUNCTION_POWER;
++			gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
++			default-state = "on";
++                };
++        };
++
++	cvbs-connector {
++		compatible = "composite-video-connector";
++
++		port {
++			cvbs_connector_in: endpoint {
++				remote-endpoint = <&cvbs_vdac_out>;
++			};
++		};
++	};
++
++	hdmi-connector {
++		compatible = "hdmi-connector";
++		type = "a";
++
++		port {
++			hdmi_connector_in: endpoint {
++				remote-endpoint = <&hdmi_tx_tmds_out>;
++			};
++		};
++	};
++
++	hdmi_5v: regulator-hdmi-5v {
++		compatible = "regulator-fixed";
++
++		regulator-name = "HDMI_5V";
++		regulator-min-microvolt = <5000000>;
++		regulator-max-microvolt = <5000000>;
++
++		gpio = <&gpio GPIOH_3 GPIO_ACTIVE_HIGH>;
++		enable-active-high;
++		regulator-always-on;
++	};
++
++	vddio_boot: regulator-vddio_boot {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDIO_BOOT";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++	};
++
++	vddao_3v3: regulator-vddao_3v3 {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDAO_3V3";
++		regulator-min-microvolt = <3300000>;
++		regulator-max-microvolt = <3300000>;
++	};
++
++	vddio_ao18: regulator-vddio_ao18 {
++		compatible = "regulator-fixed";
++		regulator-name = "VDDIO_AO18";
++		regulator-min-microvolt = <1800000>;
++		regulator-max-microvolt = <1800000>;
++	};
++
++	vcc_3v3: regulator-vcc_3v3 {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_3V3";
++		regulator-min-microvolt = <3300000>;
++		regulator-max-microvolt = <3300000>;
++	};
++
++	emmc_pwrseq: emmc-pwrseq {
++		compatible = "mmc-pwrseq-emmc";
++		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
++	};
++
++	wifi32k: wifi32k {
++		compatible = "pwm-clock";
++		#clock-cells = <0>;
++		clock-frequency = <32768>;
++		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
++	};
++
++	sdio_pwrseq: sdio-pwrseq {
++		compatible = "mmc-pwrseq-simple";
++		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
++		clocks = <&wifi32k>;
++		clock-names = "ext_clock";
++	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "VENZ-V10";
++		audio-aux-devs = <&dio2133>;
++		audio-widgets = "Line", "Lineout";
++		audio-routing = "AU2 INL", "ACODEC LOLN",
++				"AU2 INR", "ACODEC LORN",
++				"Lineout", "AU2 OUTL",
++				"Lineout", "AU2 OUTR";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++
++			codec-1 {
++				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
++			};
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&acodec>;
++			};
++		};
++	};
++};
++
++&acodec {
++	AVDD-supply = <&vddio_ao18>;
++	status = "okay";
++};
++
++&aiu {
++	status = "okay";
++};
++
++&cec_AO {
++	status = "okay";
++	pinctrl-0 = <&ao_cec_pins>;
++	pinctrl-names = "default";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&cvbs_vdac_port {
++	cvbs_vdac_out: endpoint {
++		remote-endpoint = <&cvbs_connector_in>;
++	};
++};
++
++&ethmac {
++	status = "okay";
++};
++
++&hdmi_tx {
++	status = "okay";
++	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
++	pinctrl-names = "default";
++	hdmi-supply = <&hdmi_5v>;
++};
++
++&hdmi_tx_tmds_port {
++	hdmi_tx_tmds_out: endpoint {
++		remote-endpoint = <&hdmi_connector_in>;
++	};
++};
++
++&ir {
++	status = "okay";
++	pinctrl-0 = <&remote_input_ao_pins>;
++	pinctrl-names = "default";
++	linux,rc-map-name = "rc-venz-v10";
++};
++
++&pwm_ef {
++	status = "okay";
++	pinctrl-0 = <&pwm_e_pins>;
++	pinctrl-names = "default";
++	clocks = <&clkc CLKID_FCLK_DIV4>;
++	clock-names = "clkin0";
++};
++
++&saradc {
++	status = "okay";
++	vref-supply = <&vddio_ao18>;
++};
++
++/* Wireless SDIO Module */
++&sd_emmc_a {
++	status = "okay";
++	pinctrl-0 = <&sdio_pins>;
++	pinctrl-1 = <&sdio_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++	#address-cells = <1>;
++	#size-cells = <0>;
++
++	bus-width = <4>;
++	cap-sd-highspeed;
++	max-frequency = <100000000>;
++
++	non-removable;
++	disable-wp;
++
++	/* WiFi firmware requires power to be kept while in suspend */
++	keep-power-in-suspend;
++
++	mmc-pwrseq = <&sdio_pwrseq>;
++
++	vmmc-supply = <&vddao_3v3>;
++	vqmmc-supply = <&vddio_boot>;
++
++	rtl8189: wifi@1 {
++		reg = <1>;
++	};
++};
++
++/* SD card */
++&sd_emmc_b {
++	status = "okay";
++	pinctrl-0 = <&sdcard_pins>;
++	pinctrl-1 = <&sdcard_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++
++	bus-width = <4>;
++	cap-sd-highspeed;
++	max-frequency = <50000000>;
++	disable-wp;
++
++	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
++
++	vmmc-supply = <&vddao_3v3>;
++	vqmmc-supply = <&vddio_boot>;
++};
++
++/* eMMC */
++&sd_emmc_c {
++	status = "okay";
++	pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
++	pinctrl-1 = <&emmc_clk_gate_pins>;
++	pinctrl-names = "default", "clk-gate";
++
++	bus-width = <8>;
++	cap-mmc-highspeed;
++	max-frequency = <200000000>;
++	non-removable;
++	disable-wp;
++	mmc-ddr-1_8v;
++	mmc-hs200-1_8v;
++
++	mmc-pwrseq = <&emmc_pwrseq>;
++	vmmc-supply = <&vcc_3v3>;
++	vqmmc-supply = <&vddio_boot>;
++};
++
++/* This UART is brought out to the DB9 connector */
++&uart_AO {
++	status = "okay";
++	pinctrl-0 = <&uart_ao_a_pins>;
++	pinctrl-names = "default";
++};
++
++&usb {
++	status = "okay";
++	dr_mode = "host";
++};
++
++&usb2_phy0 {
++	/* HDMI_5V is the supply for the USB VBUS */
++	phy-supply = <&hdmi_5v>;
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0064-WIP-dt-bindings-vendor-prefixes-add-tbee-prefix.patch b/gnu/packages/patches/amlogic-0064-WIP-dt-bindings-vendor-prefixes-add-tbee-prefix.patch
new file mode 100644
index 0000000000..1114a95827
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0064-WIP-dt-bindings-vendor-prefixes-add-tbee-prefix.patch
@@ -0,0 +1,29 @@
+From d36e778a5f52586b7a3bbea4ff1b17a261b222ea Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 6 Jul 2022 05:15:41 +0000
+Subject: [PATCH 64/73] WIP: dt-bindings: vendor-prefixes: add tbee prefix
+
+QUIDBox, Lda. are the Portuguese manufacturer of 'TBee' branded
+Android Set-Top Box devices.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
+index 7163901e5976..51dc9317db26 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
+@@ -1251,6 +1251,8 @@ patternProperties:
+   "^synopsys,.*":
+     description: Synopsys, Inc. (deprecated, use snps)
+     deprecated: true
++  "^tbee,.*":
++    description: QUIDBox Lda.
+   "^tbs,.*":
+     description: TBS Technologies
+   "^tbs-biometrics,.*":
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0065-WIP-dt-bindings-arm-amlogic-add-TBee-Box-binding.patch b/gnu/packages/patches/amlogic-0065-WIP-dt-bindings-arm-amlogic-add-TBee-Box-binding.patch
new file mode 100644
index 0000000000..a7c4e49430
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0065-WIP-dt-bindings-arm-amlogic-add-TBee-Box-binding.patch
@@ -0,0 +1,27 @@
+From 747c7ac68e792e26a165b49a07cf5b05d37843e5 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 6 Jul 2022 05:05:11 +0000
+Subject: [PATCH 65/73] WIP: dt-bindings: arm: amlogic: add TBee Box binding
+
+Add the board binding for the TBee Box.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index 47a9ec09a81a..a17daa64ba31 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -110,6 +110,7 @@ properties:
+               - libretech,aml-s905x-cc-v2
+               - nexbox,a95x
+               - osmc,vero4k
++              - tbee,box
+           - const: amlogic,s905x
+           - const: amlogic,meson-gxl
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0066-WIP-arm64-dts-meson-add-support-for-TBee-Box.patch b/gnu/packages/patches/amlogic-0066-WIP-arm64-dts-meson-add-support-for-TBee-Box.patch
new file mode 100644
index 0000000000..6e9c24debf
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0066-WIP-arm64-dts-meson-add-support-for-TBee-Box.patch
@@ -0,0 +1,201 @@
+From 806ac3731dd4e2e35ab71c393e77e0a29f702b39 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 6 Jul 2022 05:23:12 +0000
+Subject: [PATCH 66/73] WIP: arm64: dts: meson: add support for TBee Box
+
+The TBee Box is an Android STB based on the Amlogic P212 (GXL)
+reference design with an S905X chip and the following specs:
+
+- 2GB DDR3 RAM
+- 16GB eMMC
+- 10/100 Base-T Ethernet
+- QCA9377 Wireless (802.11 a/b/g/n, Bluetooth 4.0)
+- HDMI 2.0b video
+- 3x USB 2.0 ports
+- 1x USB WebCam (Sonix Technology)
+- IR receiver
+- 1x Update/Reset button (underside)
+- 1x Power LED (blue, front)
+- 1x SD card slot (full-size)
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |   1 +
+ .../boot/dts/amlogic/meson-gxl-s905x-tbee.dts | 153 ++++++++++++++++++
+ 2 files changed, 154 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 751e1be7be1b..3e216a8e3b2a 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-tbee.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-vero4k.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-jethome-jethub-j80.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-p281.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts
+new file mode 100644
+index 000000000000..3584d87c1916
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts
+@@ -0,0 +1,153 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2016 Endless Computers, Inc.
++ * Author: Carlo Caione <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxl-s905x-p212.dtsi"
++#include <dt-bindings/sound/meson-aiu.h>
++
++/ {
++	compatible = "tbee,box", "amlogic,s905x", "amlogic,meson-gxl";
++	model = "TBee-Box";
++
++	dio2133: analog-amplifier {
++		compatible = "simple-audio-amplifier";
++		sound-name-prefix = "AU2";
++		VCC-supply = <&hdmi_5v>;
++		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
++	};
++
++	cvbs-connector {
++		compatible = "composite-video-connector";
++
++		port {
++			cvbs_connector_in: endpoint {
++				remote-endpoint = <&cvbs_vdac_out>;
++			};
++		};
++	};
++
++	hdmi-connector {
++		compatible = "hdmi-connector";
++		type = "a";
++
++		port {
++			hdmi_connector_in: endpoint {
++				remote-endpoint = <&hdmi_tx_tmds_out>;
++			};
++		};
++	};
++
++	sound {
++		compatible = "amlogic,gx-sound-card";
++		model = "TBEE-BOX";
++		audio-aux-devs = <&dio2133>;
++		audio-widgets = "Line", "Lineout";
++		audio-routing = "AU2 INL", "ACODEC LOLN",
++				"AU2 INR", "ACODEC LORN",
++				"Lineout", "AU2 OUTL",
++				"Lineout", "AU2 OUTR";
++		assigned-clocks = <&clkc CLKID_MPLL0>,
++				  <&clkc CLKID_MPLL1>,
++				  <&clkc CLKID_MPLL2>;
++		assigned-clock-parents = <0>, <0>, <0>;
++		assigned-clock-rates = <294912000>,
++				       <270950400>,
++				       <393216000>;
++		status = "okay";
++
++		dai-link-0 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
++		};
++
++		dai-link-1 {
++			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
++			dai-format = "i2s";
++			mclk-fs = <256>;
++
++			codec-0 {
++				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
++			};
++
++			codec-1 {
++				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
++			};
++		};
++
++		dai-link-2 {
++			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&hdmi_tx>;
++			};
++		};
++
++		dai-link-3 {
++			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
++
++			codec-0 {
++				sound-dai = <&acodec>;
++			};
++		};
++	};
++};
++
++&acodec {
++	AVDD-supply = <&vddio_ao18>;
++	status = "okay";
++};
++
++&aiu {
++	status = "okay";
++};
++
++&cec_AO {
++	status = "okay";
++	pinctrl-0 = <&ao_cec_pins>;
++	pinctrl-names = "default";
++	hdmi-phandle = <&hdmi_tx>;
++};
++
++&cvbs_vdac_port {
++	cvbs_vdac_out: endpoint {
++		remote-endpoint = <&cvbs_connector_in>;
++	};
++};
++
++&hdmi_tx {
++	status = "okay";
++	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
++	pinctrl-names = "default";
++	hdmi-supply = <&hdmi_5v>;
++};
++
++&hdmi_tx_tmds_port {
++	hdmi_tx_tmds_out: endpoint {
++		remote-endpoint = <&hdmi_connector_in>;
++	};
++};
++
++/* This is connected to the Bluetooth module: */
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "qcom,qca9377-bt";
++		enable-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		max-speed = <2000000>;
++		clocks = <&wifi32k>;
++		clock-names = "lpo";
++	};
++};
++
++/* This UART is brought out to the DB9 connector */
++&uart_AO {
++	status = "okay";
++};
++
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0067-WIP-dt-bindings-arm-amlogic-add-Beelink-GT1-binding.patch b/gnu/packages/patches/amlogic-0067-WIP-dt-bindings-arm-amlogic-add-Beelink-GT1-binding.patch
new file mode 100644
index 0000000000..85d4139983
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0067-WIP-dt-bindings-arm-amlogic-add-Beelink-GT1-binding.patch
@@ -0,0 +1,28 @@
+From ea9f2cf8516daabd388706eea334220525b0bd96 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Sun, 24 Jul 2022 08:50:28 +0000
+Subject: [PATCH 67/73] WIP: dt-bindings: arm: amlogic: add Beelink GT1 binding
+
+Add the board binding for the Shenzen AZW (Beelink) GT1 Android
+Set-Top Box device.
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
+index a17daa64ba31..8f7908bb3fee 100644
+--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
+@@ -132,6 +132,7 @@ properties:
+           - enum:
+               - amlogic,q200
+               - amlogic,q201
++              - azw,gt1
+               - azw,gt1-ultimate
+               - khadas,vim2
+               - kingnovel,r-box-pro
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0068-WIP-arm64-dts-meson-add-support-for-Beelink-GT1.patch b/gnu/packages/patches/amlogic-0068-WIP-arm64-dts-meson-add-support-for-Beelink-GT1.patch
new file mode 100644
index 0000000000..47d0c1a403
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0068-WIP-arm64-dts-meson-add-support-for-Beelink-GT1.patch
@@ -0,0 +1,139 @@
+From 128d4f0b7fed865b7b6210cec0d7946ccca19042 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 6 Jul 2022 10:01:03 +0000
+Subject: [PATCH 68/73] WIP: arm64: dts: meson: add support for Beelink GT1
+
+The Beelink GT1 is based on the Amlogic S912 (Q200) reference
+design with the following specifications:
+
+- 2GB DDR3 RAM
+- 16GB eMMC
+- HDMI 2.1 video
+- S/PDIF optical output
+- 10/100/1000 Ethernet
+- QCA9377 Wireless (802.11 a/b/g/n, BT 4.0)
+- 2x USB 2.0 ports
+- IR receiver (internal)
+- 1x micro SD card slot
+- 1x Power LED (white)
+- 1x Reset button (underneath)
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/Makefile          |  1 +
+ arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts | 91 +++++++++++++++++++
+ 2 files changed, 92 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts
+
+diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
+index 3e216a8e3b2a..dc5167a86685 100644
+--- a/arch/arm64/boot/dts/amlogic/Makefile
++++ b/arch/arm64/boot/dts/amlogic/Makefile
+@@ -61,6 +61,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-gt1.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-gt1-ultimate.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-khadas-vim2.dtb
+ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-mecool-kiii-pro.dtb
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts
+new file mode 100644
+index 000000000000..3c8d73599ce6
+--- /dev/null
++++ b/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts
+@@ -0,0 +1,91 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) Christian Hewitt <[email-masked]>
++ */
++
++/dts-v1/;
++
++#include "meson-gxm.dtsi"
++#include "meson-gx-p23x-q20x.dtsi"
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++	compatible = "azw,gt1", "amlogic,s912", "amlogic,meson-gxm";
++	model = "Beelink GT1";
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-white {
++			color = <LED_COLOR_ID_WHITE>;
++			function = LED_FUNCTION_POWER;
++			gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
++			default-state = "on";
++			panic-indicator;
++		};
++	};
++
++	adc-keys {
++		compatible = "adc-keys";
++		io-channels = <&saradc 0>;
++		io-channel-names = "buttons";
++		keyup-threshold-microvolt = <1710000>;
++
++		button-function {
++			label = "update";
++			linux,code = <KEY_VENDOR>;
++			press-threshold-microvolt = <10000>;
++		};
++	};
++};
++
++&ethmac {
++	pinctrl-0 = <&eth_pins>;
++	pinctrl-names = "default";
++	phy-handle = <&external_phy>;
++	amlogic,tx-delay-ns = <2>;
++	phy-mode = "rgmii";
++};
++
++&external_mdio {
++	external_phy: ethernet-phy@0 {
++		/* Realtek RTL8211F (0x001cc916) */
++		reg = <0>;
++		max-speed = <1000>;
++
++		reset-assert-us = <10000>;
++		reset-deassert-us = <80000>;
++		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
++
++		interrupt-parent = <&gpio_intc>;
++		/* MAC_INTR on GPIOZ_15 */
++		interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
++	};
++};
++
++&ir {
++	linux,rc-map-name = "rc-beelink-gs1";
++};
++
++&sd_emmc_a {
++	/* QCA9377 WiFi */
++	wifi: wifi@1 {
++		reg = <1>;
++	};
++};
++
++&uart_A {
++	status = "okay";
++	pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
++	pinctrl-names = "default";
++	uart-has-rtscts;
++
++	bluetooth {
++		compatible = "qcom,qca9377-bt";
++		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
++		max-speed = <2000000>;
++		clocks = <&wifi32k>;
++		clock-names = "lpo";
++	};
++};
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0069-WIP-arm64-dts-meson-add-vcc_5v-regulator-to-WeTek-dt.patch b/gnu/packages/patches/amlogic-0069-WIP-arm64-dts-meson-add-vcc_5v-regulator-to-WeTek-dt.patch
new file mode 100644
index 0000000000..89a0010c50
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0069-WIP-arm64-dts-meson-add-vcc_5v-regulator-to-WeTek-dt.patch
@@ -0,0 +1,34 @@
+From 479af13691d399bbb6782713658a312a9800b65d Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 27 Jul 2022 10:27:10 +0000
+Subject: [PATCH 69/73] WIP: arm64: dts: meson: add vcc_5v regulator to WeTek
+ dtsi
+
+Add the vcc_5v regulator used by the audio DAC chip
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
+index 94dafb955301..caa63f5edf03 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
+@@ -71,6 +71,13 @@
+ 		regulator-always-on;
+ 	};
+ 
++	vcc_5v: regulator-vcc_5v {
++		compatible = "regulator-fixed";
++		regulator-name = "VCC_5V";
++		regulator-min-microvolt = <5000000>;
++		regulator-max-microvolt = <5000000>;
++	};
++
+ 	vcc_3v3: regulator-vcc_3v3 {
+ 		compatible = "regulator-fixed";
+ 		regulator-name = "VCC_3V3";
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0070-WIP-arm64-dts-meson-add-audio-lineout-to-WeTek-Play2.patch b/gnu/packages/patches/amlogic-0070-WIP-arm64-dts-meson-add-audio-lineout-to-WeTek-Play2.patch
new file mode 100644
index 0000000000..67db7e2e66
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0070-WIP-arm64-dts-meson-add-audio-lineout-to-WeTek-Play2.patch
@@ -0,0 +1,56 @@
+From 51142747fd8747c558922b6ef8cbbe453986c7b2 Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Wed, 27 Jul 2022 13:39:23 +0000
+Subject: [PATCH 70/73] WIP: arm64: dts: meson: add audio lineout to WeTek
+ Play2
+
+Add support for the ES7134LV headphone output on the WeTek Play2
+
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ .../boot/dts/amlogic/meson-gxbb-wetek-play2.dts   | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
+index 505ffcd8eb76..e206d658d157 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
+@@ -21,6 +21,13 @@
+ 		sound-name-prefix = "DIT";
+ 	};
+ 
++	i2s_codec: audio-codec-1 {
++		#sound-dai-cells = <0>;
++		compatible = "everest,es7134";
++		VDD-supply = <&vcc_5v>;
++		status = "okay";
++	};
++
+ 	leds {
+ 		led-wifi {
+ 			label = "wetek-play:wifi-status";
+@@ -74,6 +81,10 @@
+ 			codec-0 {
+ 				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+ 			};
++
++			codec-1 {
++				sound-dai = <&i2s_codec>;
++			};
+ 		};
+ 
+ 		dai-link-3 {
+@@ -96,7 +107,9 @@
+ 
+ &aiu {
+ 	status = "okay";
+-	pinctrl-0 = <&spdif_out_y_pins>;
++	pinctrl-0 = <&i2s_am_clk_pins>, <&i2s_out_ao_clk_pins>,
++		    <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_ao_pins>,
++		    <&spdif_out_y_pins>;
+ 	pinctrl-names = "default";
+ };
+ 
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0071-WIP-arm64-dts-amlogic-fix-cvbs-disable-on-WeTek-Hub.patch b/gnu/packages/patches/amlogic-0071-WIP-arm64-dts-amlogic-fix-cvbs-disable-on-WeTek-Hub.patch
new file mode 100644
index 0000000000..9d51b757b4
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0071-WIP-arm64-dts-amlogic-fix-cvbs-disable-on-WeTek-Hub.patch
@@ -0,0 +1,35 @@
+From 860b75b686b8cbff5090e4db07964e51d48ed90c Mon Sep 17 00:00:00 2001
+From: Christian Hewitt <[email-masked]>
+Date: Fri, 29 Jul 2022 08:29:20 +0000
+Subject: [PATCH 71/73] WIP: arm64: dts: amlogic: fix cvbs disable on WeTek Hub
+
+The original submission in commit d537d289de06 ("ARM64: dts: meson-gxbb:
+Add support for WeTek Hub and Play") shows cvbs output as disabled, but
+this appears to have been dropped accidentally when moving WeTek boards
+to a common dtsi. The Hub does not have cvbs hardware so let's fix and
+reinstate the disable.
+
+Fixes fb72c03e0e32 ("ARM64: dts: meson-gxbb-wetek: add a wetek specific dtsi to cleanup hub and play2")
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
+index 58733017eda8..23bea3fe9501 100644
+--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
+@@ -13,6 +13,10 @@
+ 	compatible = "wetek,hub", "amlogic,meson-gxbb";
+ 	model = "WeTek Hub";
+ 
++	cvbs-connector {
++		status = "disabled";
++	};
++
+ 	sound {
+ 		compatible = "amlogic,gx-sound-card";
+ 		model = "WETEK-HUB";
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0072-WIP-ASoC-dt-bindings-add-compatible-for-es8323-i2c.patch b/gnu/packages/patches/amlogic-0072-WIP-ASoC-dt-bindings-add-compatible-for-es8323-i2c.patch
new file mode 100644
index 0000000000..6d85fe4abe
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0072-WIP-ASoC-dt-bindings-add-compatible-for-es8323-i2c.patch
@@ -0,0 +1,34 @@
+From 577af8787454fffa1a6cc387f14d564282c8b244 Mon Sep 17 00:00:00 2001
+From: Romain Perier <[email-masked]>
+Date: Sun, 14 Aug 2022 04:21:16 +0000
+Subject: [PATCH 72/73] WIP: ASoC: dt-bindings: add compatible for es8323-i2c
+
+Add a compatible for the everest,es8323 audio codec used with a number
+of Amlogic and Rockchip board devices.
+
+Signed-off-by: Romain Perier <[email-masked]>
+Signed-off-by: Christian Hewitt <[email-masked]>
+Acked-by: Rob Herring <[email-masked]>
+---
+ Documentation/devicetree/bindings/sound/es8328.txt | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/sound/es8328.txt b/Documentation/devicetree/bindings/sound/es8328.txt
+index 33fbf058c997..86b6d6e99732 100644
+--- a/Documentation/devicetree/bindings/sound/es8328.txt
++++ b/Documentation/devicetree/bindings/sound/es8328.txt
+@@ -4,7 +4,10 @@ This device supports both I2C and SPI.
+ 
+ Required properties:
+ 
+-  - compatible  : Should be "everest,es8328" or "everest,es8388"
++  - compatible  : Should be one of the following:
++	- "everest,es8323"
++	- "everest,es8328"
++	- "everest,es8388"
+   - DVDD-supply : Regulator providing digital core supply voltage 1.8 - 3.6V
+   - AVDD-supply : Regulator providing analog supply voltage 3.3V
+   - PVDD-supply : Regulator providing digital IO supply voltage 1.8 - 3.6V
+-- 
+2.17.1
+
diff --git a/gnu/packages/patches/amlogic-0073-WIP-ASoC-codecs-add-support-for-ES8323.patch b/gnu/packages/patches/amlogic-0073-WIP-ASoC-codecs-add-support-for-ES8323.patch
new file mode 100644
index 0000000000..e9b5d4f3f6
--- /dev/null
+++ b/gnu/packages/patches/amlogic-0073-WIP-ASoC-codecs-add-support-for-ES8323.patch
@@ -0,0 +1,37 @@
+From 7c7014c03b5bbbec7231836f836a26b0237f31cf Mon Sep 17 00:00:00 2001
+From: Romain Perier <[email-masked]>
+Date: Sun, 14 Aug 2022 04:29:32 +0000
+Subject: [PATCH 73/73] WIP: ASoC: codecs: add support for ES8323
+
+The ES8323 is compatible with the existing ES8328 codec driver, so add
+compatibles allowing it to be used.
+
+Signed-off-by: Romain Perier <[email-masked]>
+Signed-off-by: Christian Hewitt <[email-masked]>
+---
+ sound/soc/codecs/es8328-i2c.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c
+index 68072e99fcc7..57c7de5cfa05 100644
+--- a/sound/soc/codecs/es8328-i2c.c
++++ b/sound/soc/codecs/es8328-i2c.c
+@@ -16,6 +16,7 @@
+ #include "es8328.h"
+ 
+ static const struct i2c_device_id es8328_id[] = {
++	{ "es8323", 0 },
+ 	{ "es8328", 0 },
+ 	{ "es8388", 0 },
+ 	{ }
+@@ -23,6 +24,7 @@ static const struct i2c_device_id es8328_id[] = {
+ MODULE_DEVICE_TABLE(i2c, es8328_id);
+ 
+ static const struct of_device_id es8328_of_match[] = {
++	{ .compatible = "everest,es8323", },
+ 	{ .compatible = "everest,es8328", },
+ 	{ .compatible = "everest,es8388", },
+ 	{ }
+-- 
+2.17.1
+
-- 
2.38.1