Merge pull request #3405 from LibreELEC/allwinner

Add Allwinner project
This commit is contained in:
CvH 2019-04-14 14:32:57 +02:00 committed by GitHub
commit afae8c6a20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 29068 additions and 28 deletions

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv)
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
# setup alsa (especially the mixer config)
@ -114,6 +115,13 @@ else
# NVidia CK804 sound devices
mixer $card 'IEC958 Playback AC97-SPSA' 100%
# Allwinner H3 Analog
mixer $card 'Line Out' 0db on
# Allwinner A64 Analog
mixer $card Headphone 0db on
mixer $card 'AIF1 Slot 0 Digital DAC' on
fi
exit 0

View File

@ -0,0 +1,27 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="gpu-sunxi-midgard"
PKG_VERSION="r22p0-01rel0"
PKG_SHA256="02f80e777dc945d645fce888afc926555ec61b70079c1da289bf1a3a9544452f"
PKG_ARCH="arm aarch64"
PKG_LICENSE="GPL"
PKG_SITE="https://developer.arm.com/products/software/mali-drivers/"
PKG_URL="https://developer.arm.com/-/media/Files/downloads/mali-drivers/kernel/mali-midgard-gpu/TX011-SW-99002-$PKG_VERSION.tgz"
PKG_DEPENDS_TARGET="toolchain linux"
PKG_NEED_UNPACK="$LINUX_DEPENDS"
PKG_LONGDESC="gpu-sunxi-midgard: Linux drivers for Mali GPUs found in Allwinner SoCs"
PKG_TOOLCHAIN="manual"
PKG_IS_KERNEL_PKG="yes"
make_target() {
kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/product/kernel/drivers/gpu/arm/midgard/ \
EXTRA_CFLAGS="-DCONFIG_MALI_PLATFORM_DEVICETREE -DCONFIG_MALI_BACKEND=gpu -DCONFIG_MALI_DEVFREQ" CONFIG_MALI_DEVFREQ=y \
CONFIG_MALI_MIDGARD=m CONFIG_MALI_PLATFORM_DEVICETREE=y CONFIG_MALI_BACKEND=gpu modules
}
makeinstall_target() {
kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/product/kernel/drivers/gpu/arm/midgard/ \
INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \
modules_install
}

View File

@ -0,0 +1,89 @@
diff -Nur a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2018-03-06 18:05:25.000000000 +0100
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2018-04-04 22:26:50.310273475 +0200
@@ -3225,6 +3225,20 @@
}
#endif /* LINUX_VERSION_CODE >= 3, 12, 0 */
+ kbdev->mali_rst = of_reset_control_get_by_index(kbdev->dev->of_node, 0);
+ if (IS_ERR(kbdev->mali_rst)) {
+ dev_err(kbdev->dev, "Couldn't get mali reset line\n");
+ err = PTR_ERR(kbdev->mali_rst);
+ goto fail;
+ }
+
+ kbdev->bus_clk = of_clk_get(kbdev->dev->of_node, 1);
+ if (IS_ERR(kbdev->bus_clk)) {
+ dev_err(kbdev->dev, "Couldn't get the mali bus clock\n");
+ err = PTR_ERR(kbdev->bus_clk);
+ goto fail;
+ }
+
kbdev->clock = of_clk_get(kbdev->dev->of_node, 0);
if (IS_ERR_OR_NULL(kbdev->clock)) {
err = PTR_ERR(kbdev->clock);
@@ -3236,6 +3250,8 @@
dev_info(kbdev->dev, "Continuing without Mali clock control\n");
/* Allow probe to continue without clock. */
} else {
+ reset_control_deassert(kbdev->mali_rst);
+ clk_prepare_enable(kbdev->bus_clk);
err = clk_prepare_enable(kbdev->clock);
if (err) {
dev_err(kbdev->dev,
@@ -3268,6 +3284,16 @@
kbdev->clock = NULL;
}
+if (kbdev->bus_clk) {
+ clk_put(kbdev->bus_clk);
+ kbdev->bus_clk = NULL;
+}
+
+if (kbdev->mali_rst) {
+ reset_control_put(kbdev->mali_rst);
+ kbdev->mali_rst = NULL;
+}
+
#ifdef CONFIG_REGULATOR
if (NULL != kbdev->regulator) {
regulator_put(kbdev->regulator);
@@ -3293,6 +3319,18 @@
kbdev->clock = NULL;
}
+ if (kbdev->bus_clk) {
+ clk_disable_unprepare(kbdev->bus_clk);
+ clk_put(kbdev->bus_clk);
+ kbdev->bus_clk = NULL;
+ }
+
+ if (kbdev->mali_rst) {
+ reset_control_assert(kbdev->mali_rst);
+ reset_control_put(kbdev->mali_rst);
+ kbdev->mali_rst = NULL;
+ }
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \
&& defined(CONFIG_REGULATOR)
if (kbdev->regulator) {
diff -Nur a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h 2018-03-06 18:05:25.000000000 +0100
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_defs.h 2018-04-04 22:05:56.017916193 +0200
@@ -68,6 +68,7 @@
#endif /* CONFIG_MALI_DEVFREQ */
#include <linux/clk.h>
+#include <linux/reset.h>
#include <linux/regulator/consumer.h>
#if defined(CONFIG_PM_RUNTIME) || \
@@ -1434,6 +1435,8 @@
} irqs[3];
struct clk *clock;
+ struct clk *bus_clk;
+ struct reset_control *mali_rst;
#ifdef CONFIG_REGULATOR
struct regulator *regulator;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
From ee7f0a678fff8316ec0be973f1b3780a63f50942 Mon Sep 17 00:00:00 2001
From: Myy Miouyouyou <myy@miouyouyou.fr>
Date: Mon, 11 Dec 2017 21:04:56 +0100
Subject: [PATCH] gpu: arm: Midgard: setup_timer() -> timer_setup()
This patch is due the changes provoked by series of commit ending
at 513ae785c63c30741e46f43960213d4ae5382ec0, and removing the
setup_timer macros.
The previous patches replaced made sure that timers were all set
up with setup_timer and replaced setup_timer calls by timer_setup
calls.
This changed was introduced in the 4.15-rc1.
Signed-off-by: Myy Miouyouyou <myy@miouyouyou.fr>
---
drivers/gpu/arm/midgard/mali_kbase.h | 2 +-
drivers/gpu/arm/midgard/mali_kbase_context.c | 4 ++--
drivers/gpu/arm/midgard/mali_kbase_softjobs.c | 4 ++--
drivers/gpu/arm/midgard/mali_kbase_tlstream.c | 6 ++----
4 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase.h b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase.h
index a4ceab9e0..27bde3b71 100644
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase.h
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase.h
@@ -213,7 +213,7 @@ int kbase_soft_event_update(struct kbase_context *kctx,
bool kbase_replay_process(struct kbase_jd_atom *katom);
-void kbasep_soft_job_timeout_worker(unsigned long data);
+void kbasep_soft_job_timeout_worker(struct timer_list *t);
void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt);
/* api used internally for register access. Contains validation and tracing */
diff --git a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_context.c b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_context.c
index f43db48fd..589df768c 100644
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_context.c
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_context.c
@@ -165,9 +165,9 @@ kbase_create_context(struct kbase_device *kbdev, bool is_compat)
mutex_init(&kctx->vinstr_cli_lock);
- setup_timer(&kctx->soft_job_timeout,
+ timer_setup(&kctx->soft_job_timeout,
kbasep_soft_job_timeout_worker,
- (uintptr_t)kctx);
+ 0);
return kctx;
diff --git a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c
index 127ada07f..019edf562 100644
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c
@@ -370,9 +370,9 @@ static void kbase_fence_debug_timeout(struct kbase_jd_atom *katom)
}
#endif /* CONFIG_MALI_FENCE_DEBUG */
-void kbasep_soft_job_timeout_worker(unsigned long data)
+void kbasep_soft_job_timeout_worker(struct timer_list *t)
{
- struct kbase_context *kctx = (struct kbase_context *)data;
+ struct kbase_context *kctx = from_timer(kctx, t, soft_job_timeout);
u32 timeout_ms = (u32)atomic_read(
&kctx->kbdev->js_data.soft_job_timeout_ms);
struct timer_list *timer = &kctx->soft_job_timeout;
diff --git a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_tlstream.c b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_tlstream.c
index d01aa23b2..11d8b59c7 100644
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_tlstream.c
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_tlstream.c
@@ -1042,13 +1042,11 @@ static void kbasep_tlstream_flush_stream(enum tl_stream_type stype)
* Timer is executed periodically to check if any of the stream contains
* buffer ready to be submitted to user space.
*/
-static void kbasep_tlstream_autoflush_timer_callback(unsigned long data)
+static void kbasep_tlstream_autoflush_timer_callback(struct timer_list *unused)
{
enum tl_stream_type stype;
int rcode;
- CSTD_UNUSED(data);
-
for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) {
struct tl_stream *stream = tl_stream[stype];
unsigned long flags;
@@ -1371,7 +1369,7 @@ int kbase_tlstream_init(void)
/* Initialize autoflush timer. */
atomic_set(&autoflush_timer_active, 0);
- setup_timer(&autoflush_timer,
+ timer_setup(&autoflush_timer,
kbasep_tlstream_autoflush_timer_callback,
0);
--
2.14.1

View File

@ -0,0 +1,35 @@
From 44a5ba2e969adfb64c84f294c16490194988dcc7 Mon Sep 17 00:00:00 2001
From: Myy Miouyouyou <myy@miouyouyou.fr>
Date: Sun, 24 Dec 2017 19:30:12 +0100
Subject: [PATCH] drivers: gpu: Arm: Midgard: Replace ACCESS_ONCE by READ_ONCE
The ACCESS_ONCE macro has now been removed in the 4.15.0-rc4,
and every ACCESS_ONCE call has been replaced by either READ_ONCE or
WRITE_ONCE calls.
Since the Midgard GPU drivers are not mainlined, the change
needs to be applied manually.
See commit b899a850431e2dd0943205a63a68573f3e312d0d and its parents,
for more informations.
Signed-off-by: Myy Miouyouyou <myy@miouyouyou.fr>
---
drivers/gpu/arm/midgard/mali_kbase_mem.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
index e9a8d5dd6..eac685699 100644
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem.h
@@ -591,7 +591,7 @@ void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages,
*/
static inline size_t kbase_mem_pool_size(struct kbase_mem_pool *pool)
{
- return ACCESS_ONCE(pool->cur_size);
+ return READ_ONCE(pool->cur_size);
}
/**
--
2.14.1

View File

@ -0,0 +1,32 @@
From 47e8aad9419ff8843a373c3e5aa2c9d261d8cd07 Mon Sep 17 00:00:00 2001
From: Myy Miouyouyou <myy@miouyouyou.fr>
Date: Mon, 23 Apr 2018 20:54:13 +0200
Subject: [PATCH] gpu: arm: midgard: Remove sys_close references
sys_close is now replaced by ksys_close in an effort to remove
in-kernel system calls references.
See 2ca2a09d6215fd9621aa3e2db7cc9428a61f2911 and
https://lkml.org/lkml/2018/3/25/93 for more details.
Signed-off-by: Myy Miouyouyou <myy@miouyouyou.fr>
---
drivers/gpu/arm/midgard/mali_kbase_sync.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h b/drivers/gpu/arm/midgard/mali_kbase_sync.h
index de72147d..33b58059 100644
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_sync.h
@@ -156,7 +156,7 @@ void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom);
*/
static inline void kbase_sync_fence_close_fd(int fd)
{
- sys_close(fd);
+ ksys_close(fd);
}
/**
--
2.14.1

View File

@ -0,0 +1,60 @@
diff -Nur a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c c/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c 2018-12-01 17:49:08.000000000 +0100
+++ c/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c 2018-12-01 20:27:42.057964019 +0100
@@ -1668,6 +1668,7 @@
struct kbase_cpu_mapping *map = vma->vm_private_data;
pgoff_t rel_pgoff;
size_t i;
+ int ret = VM_FAULT_SIGBUS;
pgoff_t addr;
KBASE_DEBUG_ASSERT(map);
@@ -1693,9 +1694,9 @@
addr = (pgoff_t)(vmf->address >> PAGE_SHIFT);
#endif
while (i < map->alloc->nents && (addr < vma->vm_end >> PAGE_SHIFT)) {
- int ret = vm_insert_pfn(vma, addr << PAGE_SHIFT,
+ ret = vmf_insert_pfn(vma, addr << PAGE_SHIFT,
PFN_DOWN(as_phys_addr_t(map->alloc->pages[i])));
- if (ret < 0 && ret != -EBUSY)
+ if (unlikely(ret & VM_FAULT_ERROR))
goto locked_bad_fault;
i++; addr++;
@@ -1707,7 +1708,7 @@
locked_bad_fault:
kbase_gpu_vm_unlock(map->kctx);
- return VM_FAULT_SIGBUS;
+ return ret;
}
const struct vm_operations_struct kbase_vm_ops = {
@@ -1776,10 +1777,11 @@
phys_addr_t phys;
phys = as_phys_addr_t(page_array[i + start_off]);
- err = vm_insert_pfn(vma, addr, PFN_DOWN(phys));
- if (WARN_ON(err))
+ err = vmf_insert_pfn(vma, addr, PFN_DOWN(phys));
+ if (unlikely(WARN_ON(err & VM_FAULT_ERROR)))
break;
+ err = 0;
addr += PAGE_SIZE;
}
} else {
diff -Nur a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c c/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c 2018-01-13 23:26:00.000000000 +0100
+++ c/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_smc.c 2018-12-01 20:03:30.071690693 +0100
@@ -27,6 +27,10 @@
#include <linux/compiler.h>
+#ifndef __asmeq
+#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
+#endif
+
static noinline u64 invoke_smc_fid(u64 function_id,
u64 arg0, u64 arg1, u64 arg2)
{

View File

@ -0,0 +1,30 @@
diff -Nur a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2018-12-01 21:10:15.000000000 +0100
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_core_linux.c 2018-12-01 23:28:48.956901556 +0100
@@ -3815,12 +3815,18 @@
"Continuing without Mali regulator control\n");
/* Allow probe to continue without regulator */
}
+ err = regulator_enable(kbdev->regulator);
+ if (err) {
+ dev_err(kbdev->dev, "Failed to enable regulator\n");
+ return err;
+ }
#endif /* LINUX_VERSION_CODE >= 3, 12, 0 */
kbdev->mali_rst = of_reset_control_get_by_index(kbdev->dev->of_node, 0);
if (IS_ERR(kbdev->mali_rst)) {
dev_err(kbdev->dev, "Couldn't get mali reset line\n");
err = PTR_ERR(kbdev->mali_rst);
+ kbdev->mali_rst = NULL;
goto fail;
}
@@ -3828,6 +3834,7 @@
if (IS_ERR(kbdev->bus_clk)) {
dev_err(kbdev->dev, "Couldn't get the mali bus clock\n");
err = PTR_ERR(kbdev->bus_clk);
+ kbdev->bus_clk = NULL;
goto fail;
}

View File

@ -0,0 +1,15 @@
diff -Nur a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c
--- a/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c 2019-02-09 23:20:20.000000000 +0100
+++ b/driver/product/kernel/drivers/gpu/arm/midgard/mali_kbase_gpuprops.c 2019-02-10 08:26:47.874751287 +0100
@@ -243,7 +243,11 @@
/* Populate the base_gpu_props structure */
kbase_gpuprops_update_core_props_gpu_id(gpu_props);
gpu_props->core_props.log2_program_counter_size = KBASE_GPU_PC_SIZE_LOG2;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ gpu_props->core_props.gpu_available_memory_size = totalram_pages() << PAGE_SHIFT;
+#else
gpu_props->core_props.gpu_available_memory_size = totalram_pages << PAGE_SHIFT;
+#endif
for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++)
gpu_props->core_props.texture_features[i] = gpu_props->raw_props.texture_features[i];

View File

@ -0,0 +1,28 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="gpu-sunxi"
PKG_VERSION="r9p0-01rel0"
PKG_SHA256="7a67127341d17640c1fff5dad80258fb2a37c8a2121b81525fe2327e4532ce2b"
PKG_ARCH="arm aarch64"
PKG_LICENSE="GPL"
PKG_SITE="https://developer.arm.com/products/software/mali-drivers/utgard-kernel"
PKG_URL="https://developer.arm.com/-/media/Files/downloads/mali-drivers/kernel/mali-utgard-gpu/DX910-SW-99002-$PKG_VERSION.tgz"
PKG_DEPENDS_TARGET="toolchain linux"
PKG_NEED_UNPACK="$LINUX_DEPENDS"
PKG_LONGDESC="gpu-sunxi: Linux drivers for Mali GPUs found in Allwinner SoCs"
PKG_TOOLCHAIN="manual"
PKG_IS_KERNEL_PKG="yes"
make_target() {
kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/src/devicedrv/mali/ \
MALI_PLATFORM_FILES=platform/sunxi/sunxi.c \
EXTRA_CFLAGS="-DMALI_FAKE_PLATFORM_DEVICE=1 -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH" \
CONFIG_MALI400=m
}
makeinstall_target() {
kernel_make -C $(kernel_path) M=$PKG_BUILD/driver/src/devicedrv/mali/ \
INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) INSTALL_MOD_STRIP=1 DEPMOD=: \
modules_install
}

View File

@ -0,0 +1,426 @@
From 2b56fc78a4acbffbdebf5b690035d1ba70ef592c Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Tue, 29 Nov 2016 10:18:40 +0100
Subject: [PATCH 4/4] mali: Add sunxi platform
Add a platform for the Mali GPU integrated in the Allwinner SoCs.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
src/devicedrv/mali/platform/sunxi/sunxi.c | 404 +++++++++++++++++++++++
1 file changed, 404 insertions(+)
create mode 100644 src/devicedrv/mali/platform/sunxi/sunxi.c
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/sunxi/sunxi.c
@@ -0,0 +1,410 @@
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/cma.h>
+#include <linux/delay.h>
+#include <linux/dma-contiguous.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include <linux/clk/clk-conf.h>
+
+#include <linux/mali/mali_utgard.h>
+
+#include "mali_kernel_linux.h"
+
+struct mali {
+ struct clk *bus_clk;
+ struct clk *core_clk;
+
+ struct reset_control *reset;
+
+ struct platform_device *dev;
+};
+
+struct mali *mali;
+
+struct resource *mali_create_mp1_resources(unsigned long address,
+ int irq_gp, int irq_gpmmu,
+ int irq_pp0, int irq_ppmmu0,
+ int *len)
+{
+ struct resource target[] = {
+ MALI_GPU_RESOURCES_MALI400_MP1_PMU(address,
+ irq_gp, irq_gpmmu,
+ irq_pp0, irq_ppmmu0)
+ };
+ struct resource *res;
+
+ res = kzalloc(sizeof(target), GFP_KERNEL);
+ if (!res)
+ return NULL;
+
+ memcpy(res, target, sizeof(target));
+
+ *len = ARRAY_SIZE(target);
+
+ return res;
+}
+
+struct resource *mali_create_mp2_resources(unsigned long address,
+ int irq_gp, int irq_gpmmu,
+ int irq_pp0, int irq_ppmmu0,
+ int irq_pp1, int irq_ppmmu1,
+ int *len)
+{
+ struct resource target[] = {
+ MALI_GPU_RESOURCES_MALI400_MP2_PMU(address,
+ irq_gp, irq_gpmmu,
+ irq_pp0, irq_ppmmu0,
+ irq_pp1, irq_ppmmu1)
+ };
+ struct resource *res;
+
+ res = kzalloc(sizeof(target), GFP_KERNEL);
+ if (!res)
+ return NULL;
+
+ memcpy(res, target, sizeof(target));
+
+ *len = ARRAY_SIZE(target);
+
+ return res;
+}
+
+struct resource *mali_create_450mp4_resources(unsigned long address,
+ int irq_gp, int irq_gpmmu,
+ int irq_pp0, int irq_ppmmu0,
+ int irq_pp1, int irq_ppmmu1,
+ int irq_pp2, int irq_ppmmu2,
+ int irq_pp3, int irq_ppmmu3,
+ int irq_pp, int *len)
+{
+ struct resource target[] = {
+ MALI_GPU_RESOURCES_MALI450_MP4(address,
+ irq_gp, irq_gpmmu,
+ irq_pp0, irq_ppmmu0,
+ irq_pp1, irq_ppmmu1,
+ irq_pp2, irq_ppmmu2,
+ irq_pp3, irq_ppmmu3,
+ irq_pp)
+ };
+ struct resource *res;
+
+ res = kzalloc(sizeof(target), GFP_KERNEL);
+ if (!res)
+ return NULL;
+
+ memcpy(res, target, sizeof(target));
+
+ *len = ARRAY_SIZE(target);
+
+ return res;
+}
+
+static const struct of_device_id mali_dt_ids[] = {
+ { .compatible = "allwinner,sun4i-a10-mali" },
+ { .compatible = "allwinner,sun7i-a20-mali" },
+ { .compatible = "allwinner,sun8i-h3-mali" },
+ { .compatible = "allwinner,sun50i-a64-mali" },
+ { .compatible = "allwinner,sun50i-h5-mali" },
+ { .compatible = "arm,mali-400" },
+ { .compatible = "arm,mali-450" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mali_dt_ids);
+
+static struct mali_gpu_device_data mali_gpu_data = {
+ .max_job_runtime = 60000,
+};
+int mali_platform_device_register(void)
+{
+ int irq_gp, irq_gpmmu;
+ int irq_pp0, irq_ppmmu0;
+ int irq_pp1 = -EINVAL, irq_ppmmu1 = -EINVAL;
+ int irq_pp2 = -EINVAL, irq_ppmmu2 = -EINVAL;
+ int irq_pp3 = -EINVAL, irq_ppmmu3 = -EINVAL;
+ int irq_pp = -EINVAL;
+ int irq_pmu;
+ struct resource *mali_res = NULL, res;
+ struct device_node *np;
+ struct device *dev;
+ int ret, len;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ mali_gpu_data.shared_mem_size = totalram_pages() * PAGE_SIZE;
+#else
+ mali_gpu_data.shared_mem_size = totalram_pages * PAGE_SIZE;
+#endif
+
+ np = of_find_matching_node(NULL, mali_dt_ids);
+ if (!np) {
+ pr_err("Couldn't find the mali node\n");
+ return -ENODEV;
+ }
+
+ mali = kzalloc(sizeof(*mali), GFP_KERNEL);
+ if (!mali) {
+ ret = -ENOMEM;
+ goto err_put_node;
+ }
+
+ ret = of_clk_set_defaults(np, false);
+ if (ret) {
+ pr_err("Couldn't set clock defaults\n");
+ goto err_free_mem;
+ }
+
+ mali->bus_clk = of_clk_get_by_name(np, "bus");
+ if (IS_ERR(mali->bus_clk)) {
+ pr_err("Couldn't retrieve our bus clock\n");
+ ret = PTR_ERR(mali->bus_clk);
+ goto err_free_mem;
+ }
+ clk_prepare_enable(mali->bus_clk);
+
+ mali->core_clk = of_clk_get_by_name(np, "core");
+ if (IS_ERR(mali->core_clk)) {
+ pr_err("Couldn't retrieve our module clock\n");
+ ret = PTR_ERR(mali->core_clk);
+ goto err_put_bus;
+ }
+ clk_prepare_enable(mali->core_clk);
+
+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mali") ||
+ of_device_is_compatible(np, "allwinner,sun7i-a20-mali") ||
+ of_device_is_compatible(np, "allwinner,sun8i-h3-mali") ||
+ of_device_is_compatible(np, "allwinner,sun50i-a64-mali") ||
+ of_device_is_compatible(np, "allwinner,sun50i-h5-mali")) {
+ mali->reset = of_reset_control_get(np, NULL);
+ if (IS_ERR(mali->reset)) {
+ pr_err("Couldn't retrieve our reset handle\n");
+ ret = PTR_ERR(mali->reset);
+ goto err_put_mod;
+ }
+ reset_control_deassert(mali->reset);
+ }
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret) {
+ pr_err("Couldn't retrieve our base address\n");
+ goto err_put_reset;
+ }
+
+ irq_gp = of_irq_get_byname(np, "gp");
+ if (irq_gp < 0) {
+ pr_err("Couldn't retrieve our GP interrupt\n");
+ ret = irq_gp;
+ goto err_put_reset;
+ }
+
+ irq_gpmmu = of_irq_get_byname(np, "gpmmu");
+ if (irq_gpmmu < 0) {
+ pr_err("Couldn't retrieve our GP MMU interrupt\n");
+ ret = irq_gpmmu;
+ goto err_put_reset;
+ }
+
+ irq_pp0 = of_irq_get_byname(np, "pp0");
+ if (irq_pp0 < 0) {
+ pr_err("Couldn't retrieve our PP0 interrupt %d\n", irq_pp0);
+ ret = irq_pp0;
+ goto err_put_reset;
+ }
+
+ irq_ppmmu0 = of_irq_get_byname(np, "ppmmu0");
+ if (irq_ppmmu0 < 0) {
+ pr_err("Couldn't retrieve our PP0 MMU interrupt\n");
+ ret = irq_ppmmu0;
+ goto err_put_reset;
+ }
+
+ irq_pp1 = of_irq_get_byname(np, "pp1");
+ irq_ppmmu1 = of_irq_get_byname(np, "ppmmu1");
+ if ((irq_pp1 < 0) ^ (irq_ppmmu1 < 0 )) {
+ pr_err("Couldn't retrieve our PP1 interrupts\n");
+ ret = (irq_pp1 < 0) ? irq_pp1 : irq_ppmmu1;
+ goto err_put_reset;
+ }
+
+ if (of_device_is_compatible(np, "allwinner,sun50i-h5-mali")) {
+ irq_pp2 = of_irq_get_byname(np, "pp2");
+ if (irq_pp2 < 0) {
+ pr_err("Couldn't retrieve our PP2 interrupt\n");
+ ret = irq_pp2;
+ goto err_put_reset;
+ }
+
+ irq_ppmmu2 = of_irq_get_byname(np, "ppmmu2");
+ if (irq_ppmmu2 < 0) {
+ pr_err("Couldn't retrieve our PP2 interrupts\n");
+ ret = irq_ppmmu2;
+ goto err_put_reset;
+ }
+
+ irq_pp3 = of_irq_get_byname(np, "pp3");
+ if (irq_pp3 < 0) {
+ pr_err("Couldn't retrieve our PP3 interrupt\n");
+ ret = irq_pp3;
+ goto err_put_reset;
+ }
+
+ irq_ppmmu3 = of_irq_get_byname(np, "ppmmu3");
+ if (irq_ppmmu3 < 0) {
+ pr_err("Couldn't retrieve our PP3 interrupts\n");
+ ret = irq_ppmmu3;
+ goto err_put_reset;
+ }
+
+ irq_pp = of_irq_get_byname(np, "pp");
+ if (irq_pp < 0) {
+ pr_err("Couldn't retrieve our PP broadcast interrupt\n");
+ ret = irq_pp;
+ goto err_put_reset;
+ }
+ } else {
+ irq_pmu = of_irq_get_byname(np, "pmu");
+ if (irq_pmu < 0) {
+ pr_err("Couldn't retrieve our PMU interrupt\n");
+ ret = irq_pmu;
+ goto err_put_reset;
+ }
+ }
+
+ mali->dev = platform_device_alloc("mali-utgard", 0);
+ if (!mali->dev) {
+ pr_err("Couldn't create platform device\n");
+ ret = -EINVAL;
+ goto err_put_reset;
+ }
+ dev = &mali->dev->dev;
+ dev_set_name(dev, "mali-utgard");
+ dev->of_node = np;
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ dev->dma_mask = &dev->coherent_dma_mask;
+ dev->bus = &platform_bus_type;
+
+ ret = of_reserved_mem_device_init(&mali->dev->dev);
+ if (ret && ret != -ENODEV) {
+ pr_err("Couldn't claim our reserved memory region\n");
+ goto err_free_mem_region;
+ }
+
+ if (of_device_is_compatible(np, "allwinner,sun50i-h5-mali"))
+ mali_res = mali_create_450mp4_resources(res.start,
+ irq_gp, irq_gpmmu,
+ irq_pp0, irq_ppmmu0,
+ irq_pp1, irq_ppmmu1,
+ irq_pp2, irq_ppmmu2,
+ irq_pp3, irq_ppmmu3,
+ irq_pp, &len);
+ else if ((irq_pp1 >= 0) && (irq_ppmmu1 >= 0))
+ mali_res = mali_create_mp2_resources(res.start,
+ irq_gp, irq_gpmmu,
+ irq_pp0, irq_ppmmu0,
+ irq_pp1, irq_ppmmu1,
+ &len);
+ else
+ mali_res = mali_create_mp1_resources(res.start,
+ irq_gp, irq_gpmmu,
+ irq_pp0, irq_ppmmu0,
+ &len);
+
+ if (!mali_res) {
+ pr_err("Couldn't create target resources\n");
+ ret = -EINVAL;
+ goto err_free_mem_region;
+ }
+
+ clk_register_clkdev(mali->core_clk, "clk_mali", NULL);
+
+ ret = platform_device_add_resources(mali->dev, mali_res, len);
+ kfree(mali_res);
+ if (ret) {
+ pr_err("Couldn't add our resources\n");
+ goto err_free_mem_region;
+ }
+
+ ret = platform_device_add_data(mali->dev, &mali_gpu_data,
+ sizeof(mali_gpu_data));
+ if (ret) {
+ pr_err("Couldn't add our platform data\n");
+ goto err_free_mem_region;
+ }
+
+ ret = platform_device_add(mali->dev);
+ if (ret) {
+ pr_err("Couldn't add our device\n");
+ goto err_free_mem_region;
+ }
+
+#ifdef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+ pm_runtime_set_autosuspend_delay(&mali->dev->dev, 1000);
+ pm_runtime_use_autosuspend(&mali->dev->dev);
+#endif
+ pm_runtime_enable(&mali->dev->dev);
+#endif
+
+ pr_info("Allwinner sunXi mali glue initialized\n");
+
+ return 0;
+
+err_free_mem_region:
+ of_reserved_mem_device_release(dev);
+ platform_device_put(mali->dev);
+err_put_reset:
+ if (!IS_ERR_OR_NULL(mali->reset)) {
+ reset_control_assert(mali->reset);
+ reset_control_put(mali->reset);
+ }
+err_put_mod:
+ clk_disable_unprepare(mali->core_clk);
+ clk_put(mali->core_clk);
+err_put_bus:
+ clk_disable_unprepare(mali->bus_clk);
+ clk_put(mali->bus_clk);
+err_free_mem:
+ kfree(mali);
+err_put_node:
+ of_node_put(np);
+ return ret;
+}
+
+int mali_platform_device_unregister(void)
+{
+ struct device *dev = &mali->dev->dev;
+
+#ifdef CONFIG_PM_RUNTIME
+ pm_runtime_disable(dev);
+#endif
+
+ of_reserved_mem_device_release(dev);
+
+ platform_device_del(mali->dev);
+ of_node_put(dev->of_node);
+ platform_device_put(mali->dev);
+
+ if (!IS_ERR_OR_NULL(mali->reset)) {
+ reset_control_assert(mali->reset);
+ reset_control_put(mali->reset);
+ }
+
+ clk_disable_unprepare(mali->core_clk);
+ clk_put(mali->core_clk);
+
+ clk_disable_unprepare(mali->bus_clk);
+ clk_put(mali->bus_clk);
+
+ kfree(mali);
+
+ return 0;
+}

View File

@ -0,0 +1,155 @@
From 246fdac477cf109c354011c1ae0a7a8d928cb504 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 12 Mar 2018 23:02:55 +0100
Subject: [PATCH] v4.16 build fix
---
.../driver/src/devicedrv/mali/common/mali_control_timer.c | 2 +-
src/devicedrv/mali/common/mali_group.c | 8 ++++---
src/devicedrv/mali/common/mali_osk_types.h | 8 ++++++-
.../devicedrv/mali/linux/mali_memory_os_alloc.c | 6 +++++
.../driver/src/devicedrv/mali/linux/mali_memory_secure.c | 4 ++++
src/devicedrv/mali/linux/mali_osk_timers.c | 20 +++++++++++-----
11 files changed, 84 insertions(+), 14 deletions(-)
diff --git a/driver/src/devicedrv/mali/common/mali_control_timer.c b/driver/src/devicedrv/mali/common/mali_control_timer.c
index 1296ffe..bfe975f 100644
--- a/driver/src/devicedrv/mali/common/mali_control_timer.c
+++ b/driver/src/devicedrv/mali/common/mali_control_timer.c
@@ -28,7 +28,7 @@ void mali_control_timer_add(u32 timeout)
_mali_osk_timer_add(mali_control_timer, _mali_osk_time_mstoticks(timeout));
}
-static void mali_control_timer_callback(void *arg)
+static void mali_control_timer_callback(struct timer_list *t)
{
if (mali_utilization_enabled()) {
struct mali_gpu_utilization_data *util_data = NULL;
diff --git a/driver/src/devicedrv/mali/common/mali_group.c b/driver/src/devicedrv/mali/common/mali_group.c
index e9005e1..4a43753 100644
--- a/driver/src/devicedrv/mali/common/mali_group.c
+++ b/driver/src/devicedrv/mali/common/mali_group.c
@@ -44,7 +44,7 @@ int mali_max_job_runtime = MALI_MAX_JOB_RUNTIME_DEFAULT;
static void mali_group_bottom_half_mmu(void *data);
static void mali_group_bottom_half_gp(void *data);
static void mali_group_bottom_half_pp(void *data);
-static void mali_group_timeout(void *data);
+static void mali_group_timeout(struct timer_list *t);
static void mali_group_reset_pp(struct mali_group *group);
static void mali_group_reset_mmu(struct mali_group *group);
@@ -1761,9 +1761,11 @@ static void mali_group_bottom_half_pp(void *data)
0xFFFFFFFF, 0);
}
-static void mali_group_timeout(void *data)
+static void mali_group_timeout(struct timer_list *t)
{
- struct mali_group *group = (struct mali_group *)data;
+ _mali_osk_timer_t *tim = container_of(t, _mali_osk_timer_t, timer);
+ struct mali_group *group = container_of(&tim, struct mali_group, timeout_timer);
+
MALI_DEBUG_ASSERT_POINTER(group);
MALI_DEBUG_PRINT(2, ("Group: timeout handler for %s at %u\n",
diff --git a/driver/src/devicedrv/mali/common/mali_osk_types.h b/driver/src/devicedrv/mali/common/mali_osk_types.h
index 03161cf..c9d0fec 100644
--- a/driver/src/devicedrv/mali/common/mali_osk_types.h
+++ b/driver/src/devicedrv/mali/common/mali_osk_types.h
@@ -50,6 +50,7 @@ typedef unsigned long long u64;
#include <linux/types.h>
#endif
+#include <linux/timer.h>
/** @brief Mali Boolean type which uses MALI_TRUE and MALI_FALSE
*/
typedef unsigned long mali_bool;
@@ -395,7 +396,12 @@ typedef struct _mali_osk_notification_t_struct {
* by any callers of _mali_osk_timer_del(). Otherwise, a deadlock may occur.
*
* @param arg Function-specific data */
-typedef void (*_mali_osk_timer_callback_t)(void *arg);
+typedef void (*_mali_osk_timer_callback_t)(struct timer_list *t);
+
+
+struct _mali_osk_timer_t_struct {
+ struct timer_list timer;
+};
/** @brief Private type for Timer Callback Objects */
typedef struct _mali_osk_timer_t_struct _mali_osk_timer_t;
diff --git a/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c b/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c
index 5fe1270..92c245a 100644
--- a/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c
+++ b/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c
@@ -202,7 +202,9 @@ int mali_mem_os_alloc_pages(mali_mem_os_mem *os_mem, u32 size)
/* Allocate new pages, if needed. */
for (i = 0; i < remaining; i++) {
dma_addr_t dma_addr;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+ gfp_t flags = __GFP_ZERO | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
gfp_t flags = __GFP_ZERO | __GFP_RETRY_MAYFAIL | __GFP_NOWARN | __GFP_COLD;
#else
gfp_t flags = __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD;
diff --git a/driver/src/devicedrv/mali/linux/mali_memory_secure.c b/driver/src/devicedrv/mali/linux/mali_memory_secure.c
index 2836b1b..4f55fa5 100644
--- a/driver/src/devicedrv/mali/linux/mali_memory_secure.c
+++ b/driver/src/devicedrv/mali/linux/mali_memory_secure.c
@@ -13,7 +13,11 @@
#include "mali_memory_secure.h"
#include "mali_osk.h"
#include <linux/mutex.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
+#include <linux/dma-direct.h>
+#else
#include <linux/dma-mapping.h>
+#endif
#include <linux/dma-buf.h>
_mali_osk_errcode_t mali_mem_secure_attach_dma_buf(mali_mem_secure *secure_mem, u32 size, int mem_fd)
diff --git a/driver/src/devicedrv/mali/linux/mali_osk_timers.c b/driver/src/devicedrv/mali/linux/mali_osk_timers.c
index e5d7238..701051a 100644
--- a/driver/src/devicedrv/mali/linux/mali_osk_timers.c
+++ b/driver/src/devicedrv/mali/linux/mali_osk_timers.c
@@ -18,16 +18,25 @@
#include "mali_osk.h"
#include "mali_kernel_common.h"
-struct _mali_osk_timer_t_struct {
- struct timer_list timer;
-};
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
+
+#define TIMER_DATA_TYPE unsigned long
+#define TIMER_FUNC_TYPE void (*)(TIMER_DATA_TYPE)
+
+static inline void timer_setup(struct timer_list *timer,
+ void (*callback)(struct timer_list *),
+ unsigned int flags)
+{
+ __setup_timer(timer, (TIMER_FUNC_TYPE)callback,
+ (TIMER_DATA_TYPE)timer, flags);
+}
+#endif
typedef void (*timer_timeout_function_t)(unsigned long);
_mali_osk_timer_t *_mali_osk_timer_init(void)
{
_mali_osk_timer_t *t = (_mali_osk_timer_t *)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL);
- if (NULL != t) init_timer(&t->timer);
return t;
}
@@ -65,8 +74,7 @@ mali_bool _mali_osk_timer_pending(_mali_osk_timer_t *tim)
void _mali_osk_timer_setcallback(_mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data)
{
MALI_DEBUG_ASSERT_POINTER(tim);
- tim->timer.data = (unsigned long)data;
- tim->timer.function = (timer_timeout_function_t)callback;
+ timer_setup(&tim->timer, callback, 0);
}
void _mali_osk_timer_term(_mali_osk_timer_t *tim)

View File

@ -0,0 +1,128 @@
diff -Nur a/driver/src/devicedrv/mali/linux/mali_memory_block_alloc.c b/driver/src/devicedrv/mali/linux/mali_memory_block_alloc.c
--- a/driver/src/devicedrv/mali/linux/mali_memory_block_alloc.c 2018-09-13 08:52:20.000000000 +0200
+++ b/driver/src/devicedrv/mali/linux/mali_memory_block_alloc.c 2018-12-08 12:22:51.978513336 +0100
@@ -309,9 +309,9 @@
list_for_each_entry(m_page, &block_mem->pfns, list) {
MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK);
- ret = vm_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page));
+ ret = vmf_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page));
- if (unlikely(0 != ret)) {
+ if (unlikely(ret & VM_FAULT_ERROR)) {
return -EFAULT;
}
addr += _MALI_OSK_MALI_PAGE_SIZE;
diff -Nur a/driver/src/devicedrv/mali/linux/mali_memory_cow.c b/driver/src/devicedrv/mali/linux/mali_memory_cow.c
--- a/driver/src/devicedrv/mali/linux/mali_memory_cow.c 2018-09-13 08:52:20.000000000 +0200
+++ b/driver/src/devicedrv/mali/linux/mali_memory_cow.c 2018-12-08 12:27:17.681815893 +0100
@@ -532,10 +532,10 @@
* flush which makes it way slower than remap_pfn_range or vm_insert_pfn.
ret = vm_insert_page(vma, addr, page);
*/
- ret = vm_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page));
+ ret = vmf_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page));
- if (unlikely(0 != ret)) {
- return ret;
+ if (unlikely(ret & VM_FAULT_ERROR)) {
+ return -EFAULT;
}
addr += _MALI_OSK_MALI_PAGE_SIZE;
}
@@ -569,9 +569,9 @@
list_for_each_entry(m_page, &cow->pages, list) {
if ((count >= offset) && (count < offset + num)) {
- ret = vm_insert_pfn(vma, vaddr, _mali_page_node_get_pfn(m_page));
+ ret = vmf_insert_pfn(vma, vaddr, _mali_page_node_get_pfn(m_page));
- if (unlikely(0 != ret)) {
+ if (unlikely(ret & VM_FAULT_ERROR)) {
if (count == offset) {
return _MALI_OSK_ERR_FAULT;
} else {
diff -Nur a/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c b/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c
--- a/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c 2018-12-08 12:15:38.000000000 +0100
+++ b/driver/src/devicedrv/mali/linux/mali_memory_os_alloc.c 2018-12-08 12:30:37.730811640 +0100
@@ -376,9 +376,9 @@
ret = vm_insert_page(vma, addr, page);
*/
page = m_page->page;
- ret = vm_insert_pfn(vma, addr, page_to_pfn(page));
+ ret = vmf_insert_pfn(vma, addr, page_to_pfn(page));
- if (unlikely(0 != ret)) {
+ if (unlikely(ret & VM_FAULT_ERROR)) {
return -EFAULT;
}
addr += _MALI_OSK_MALI_PAGE_SIZE;
@@ -414,16 +414,11 @@
vm_end -= _MALI_OSK_MALI_PAGE_SIZE;
if (mapping_page_num > 0) {
- ret = vm_insert_pfn(vma, vm_end, page_to_pfn(m_page->page));
+ ret = vmf_insert_pfn(vma, vm_end, page_to_pfn(m_page->page));
- if (unlikely(0 != ret)) {
- /*will return -EBUSY If the page has already been mapped into table, but it's OK*/
- if (-EBUSY == ret) {
- break;
- } else {
- MALI_DEBUG_PRINT(1, ("OS Mem: mali_mem_os_resize_cpu_map_locked failed, ret = %d, offset is %d,page_count is %d\n",
- ret, offset + mapping_page_num, os_mem->count));
- }
+ if (unlikely(ret & VM_FAULT_ERROR)) {
+ MALI_DEBUG_PRINT(1, ("OS Mem: mali_mem_os_resize_cpu_map_locked failed, ret = %d, offset is %d,page_count is %d\n",
+ ret, offset + mapping_page_num, os_mem->count));
return _MALI_OSK_ERR_FAULT;
}
} else {
@@ -437,16 +432,11 @@
list_for_each_entry(m_page, &os_mem->pages, list) {
if (count >= offset) {
- ret = vm_insert_pfn(vma, vstart, page_to_pfn(m_page->page));
+ ret = vmf_insert_pfn(vma, vstart, page_to_pfn(m_page->page));
- if (unlikely(0 != ret)) {
- /*will return -EBUSY If the page has already been mapped into table, but it's OK*/
- if (-EBUSY == ret) {
- break;
- } else {
- MALI_DEBUG_PRINT(1, ("OS Mem: mali_mem_os_resize_cpu_map_locked failed, ret = %d, count is %d, offset is %d,page_count is %d\n",
- ret, count, offset, os_mem->count));
- }
+ if (unlikely(ret & VM_FAULT_ERROR)) {
+ MALI_DEBUG_PRINT(1, ("OS Mem: mali_mem_os_resize_cpu_map_locked failed, ret = %d, count is %d, offset is %d,page_count is %d\n",
+ ret, count, offset, os_mem->count));
return _MALI_OSK_ERR_FAULT;
}
}
diff -Nur a/driver/src/devicedrv/mali/linux/mali_memory_secure.c b/driver/src/devicedrv/mali/linux/mali_memory_secure.c
--- a/driver/src/devicedrv/mali/linux/mali_memory_secure.c 2018-12-08 12:15:38.000000000 +0100
+++ b/driver/src/devicedrv/mali/linux/mali_memory_secure.c 2018-12-08 12:31:05.461174554 +0100
@@ -132,9 +132,9 @@
MALI_DEBUG_ASSERT(0 == size % _MALI_OSK_MALI_PAGE_SIZE);
for (j = 0; j < size / _MALI_OSK_MALI_PAGE_SIZE; j++) {
- ret = vm_insert_pfn(vma, addr, PFN_DOWN(phys));
+ ret = vmf_insert_pfn(vma, addr, PFN_DOWN(phys));
- if (unlikely(0 != ret)) {
+ if (unlikely(ret & VM_FAULT_ERROR)) {
return -EFAULT;
}
addr += _MALI_OSK_MALI_PAGE_SIZE;
diff -Nur a/driver/src/devicedrv/mali/linux/mali_osk_time.c b/driver/src/devicedrv/mali/linux/mali_osk_time.c
--- a/driver/src/devicedrv/mali/linux/mali_osk_time.c 2018-09-13 08:52:20.000000000 +0200
+++ b/driver/src/devicedrv/mali/linux/mali_osk_time.c 2018-12-08 12:32:12.632086846 +0100
@@ -53,7 +53,5 @@
u64 _mali_osk_boot_time_get_ns(void)
{
- struct timespec tsval;
- get_monotonic_boottime(&tsval);
- return (u64)timespec_to_ns(&tsval);
+ return (u64)ktime_to_ns(ktime_get_boottime());
}

View File

@ -0,0 +1,35 @@
diff -Nur a/driver/src/devicedrv/mali/linux/mali_ukk_mem.c b/driver/src/devicedrv/mali/linux/mali_ukk_mem.c
--- a/driver/src/devicedrv/mali/linux/mali_ukk_mem.c 2018-09-13 08:52:20.000000000 +0200
+++ b/driver/src/devicedrv/mali/linux/mali_ukk_mem.c 2019-02-09 20:10:06.867561465 +0100
@@ -207,10 +207,17 @@
kargs.ctx = (uintptr_t)session_data;
/* Check if we can access the buffers */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ if (!access_ok(kargs.dest, kargs.size)
+ || !access_ok(kargs.src, kargs.size)) {
+ return -EINVAL;
+ }
+#else
if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
|| !access_ok(VERIFY_READ, kargs.src, kargs.size)) {
return -EINVAL;
}
+#endif
/* Check if size wraps */
if ((kargs.size + kargs.dest) <= kargs.dest
@@ -266,8 +273,13 @@
goto err_exit;
user_buffer = (void __user *)(uintptr_t)kargs.buffer;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ if (!access_ok(user_buffer, kargs.size))
+ goto err_exit;
+#else
if (!access_ok(VERIFY_WRITE, user_buffer, kargs.size))
goto err_exit;
+#endif
/* allocate temporary buffer (kernel side) to store mmu page table info */
if (kargs.size <= 0)

View File

@ -44,6 +44,13 @@ else
PKG_FFMPEG_RKMPP="--disable-rkmpp"
fi
if [ "$PROJECT" = "Allwinner" ]; then
PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libdrm systemd" # systemd is needed for libudev
PKG_FFMPEG_V4L2_REQUEST="--enable-v4l2-request --enable-libudev --enable-libdrm"
else
PKG_FFMPEG_V4L2_REQUEST="--disable-v4l2-request --disable-libudev"
fi
if build_with_debug; then
PKG_FFMPEG_DEBUG="--enable-debug --disable-stripping"
else
@ -138,6 +145,7 @@ configure_target() {
$PKG_FFMPEG_VDPAU \
$PKG_FFMPEG_RPI \
$PKG_FFMPEG_RKMPP \
$PKG_FFMPEG_V4L2_REQUEST \
--enable-runtime-cpudetect \
--disable-hardcoded-tables \
--disable-encoders \

View File

@ -0,0 +1,54 @@
From 7ab07a6b9a8ac8a91213bcbba4a63dc9db03cb53 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 3 Dec 2018 23:48:04 +0100
Subject: [PATCH 1/6] avutil: add av_buffer_pool_reclaim()
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
libavutil/buffer.c | 13 +++++++++++++
libavutil/buffer.h | 5 +++++
2 files changed, 18 insertions(+)
diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index 8d1aa5fa84..9c5d530c7a 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -272,6 +272,19 @@ static void buffer_pool_free(AVBufferPool *pool)
av_freep(&pool);
}
+void av_buffer_pool_reclaim(AVBufferPool *pool)
+{
+ ff_mutex_lock(&pool->mutex);
+ while (pool->pool) {
+ BufferPoolEntry *buf = pool->pool;
+ pool->pool = buf->next;
+
+ buf->free(buf->opaque, buf->data);
+ av_freep(&buf);
+ }
+ ff_mutex_unlock(&pool->mutex);
+}
+
void av_buffer_pool_uninit(AVBufferPool **ppool)
{
AVBufferPool *pool;
diff --git a/libavutil/buffer.h b/libavutil/buffer.h
index 73b6bd0b14..fab745f853 100644
--- a/libavutil/buffer.h
+++ b/libavutil/buffer.h
@@ -266,6 +266,11 @@ AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
AVBufferRef* (*alloc)(void *opaque, int size),
void (*pool_free)(void *opaque));
+/**
+ * Free all available buffers in a buffer pool.
+ */
+ void av_buffer_pool_reclaim(AVBufferPool *pool);
+
/**
* Mark the pool as being available for freeing. It will actually be freed only
* once all the allocated buffers associated with the pool are released. Thus it
--
2.21.0

View File

@ -0,0 +1,247 @@
From de3bcf7557503e5d61b43cdc32d0844deab1c295 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH 3/6] Add V4L2 request API mpeg2 hwaccel
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/hwaccels.h | 1 +
libavcodec/mpeg12dec.c | 6 ++
libavcodec/v4l2_request_mpeg2.c | 154 ++++++++++++++++++++++++++++++++
5 files changed, 165 insertions(+)
create mode 100644 libavcodec/v4l2_request_mpeg2.c
diff --git a/configure b/configure
index ed587ec05e..c93d67056d 100755
--- a/configure
+++ b/configure
@@ -2846,6 +2846,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2"
mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
mpeg2_nvdec_hwaccel_deps="nvdec"
mpeg2_nvdec_hwaccel_select="mpeg2video_decoder"
+mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request"
+mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder"
mpeg2_vaapi_hwaccel_deps="vaapi"
mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
mpeg2_vdpau_hwaccel_deps="vdpau"
@@ -6237,6 +6239,7 @@ check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;"
check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_header sys/videoio.h
test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 48f6e06545..9b945e3f64 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -871,6 +871,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o
+OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL) += v4l2_request_mpeg2.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 7d73da8676..ef54de2a3b 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -47,6 +47,7 @@ extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel;
extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel;
extern const AVHWAccel ff_mpeg2_nvdec_hwaccel;
extern const AVHWAccel ff_mpeg2_dxva2_hwaccel;
+extern const AVHWAccel ff_mpeg2_v4l2request_hwaccel;
extern const AVHWAccel ff_mpeg2_vaapi_hwaccel;
extern const AVHWAccel ff_mpeg2_vdpau_hwaccel;
extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel;
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 83e537884b..305127bc94 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1156,6 +1156,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
#endif
#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
AV_PIX_FMT_VIDEOTOOLBOX,
+#endif
+#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
+ AV_PIX_FMT_DRM_PRIME,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
@@ -2941,6 +2944,9 @@ AVCodec ff_mpeg2video_decoder = {
#endif
#if CONFIG_MPEG2_XVMC_HWACCEL
HWACCEL_XVMC(mpeg2),
+#endif
+#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(mpeg2),
#endif
NULL
},
diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
new file mode 100644
index 0000000000..782b9c2471
--- /dev/null
+++ b/libavcodec/v4l2_request_mpeg2.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hwaccel.h"
+#include "mpegvideo.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsMPEG2 {
+ struct v4l2_ctrl_mpeg2_slice_params slice_params;
+ struct v4l2_ctrl_mpeg2_quantization quantization;
+} V4L2RequestControlsMPEG2;
+
+static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const MpegEncContext *s = avctx->priv_data;
+ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
+
+ controls->slice_params = (struct v4l2_ctrl_mpeg2_slice_params) {
+ .bit_size = 0,
+ .data_bit_offset = 0,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
+ .quantiser_scale_code = s->qscale >> 1,
+
+ .sequence = {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
+ .horizontal_size = s->width,
+ .vertical_size = s->height,
+ .vbv_buffer_size = req->output.size,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
+ .profile_and_level_indication = 0,
+ .progressive_sequence = s->progressive_sequence,
+ .chroma_format = s->chroma_format,
+ },
+
+ .picture = {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
+ .picture_coding_type = s->pict_type,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
+ .f_code[0][0] = s->mpeg_f_code[0][0],
+ .f_code[0][1] = s->mpeg_f_code[0][1],
+ .f_code[1][0] = s->mpeg_f_code[1][0],
+ .f_code[1][1] = s->mpeg_f_code[1][1],
+ .intra_dc_precision = s->intra_dc_precision,
+ .picture_structure = s->picture_structure,
+ .top_field_first = s->top_field_first,
+ .frame_pred_frame_dct = s->frame_pred_frame_dct,
+ .concealment_motion_vectors = s->concealment_motion_vectors,
+ .q_scale_type = s->q_scale_type,
+ .intra_vlc_format = s->intra_vlc_format,
+ .alternate_scan = s->alternate_scan,
+ .repeat_first_field = s->repeat_first_field,
+ .progressive_frame = s->progressive_frame,
+ },
+ };
+
+ switch (s->pict_type) {
+ case AV_PICTURE_TYPE_B:
+ controls->slice_params.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f);
+ // fall-through
+ case AV_PICTURE_TYPE_P:
+ controls->slice_params.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f);
+ }
+
+ controls->quantization = (struct v4l2_ctrl_mpeg2_quantization) {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
+ .load_intra_quantiser_matrix = 1,
+ .load_non_intra_quantiser_matrix = 1,
+ .load_chroma_intra_quantiser_matrix = 1,
+ .load_chroma_non_intra_quantiser_matrix = 1,
+ };
+
+ for (int i = 0; i < 64; i++) {
+ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ controls->quantization.intra_quantiser_matrix[i] = s->intra_matrix[n];
+ controls->quantization.non_intra_quantiser_matrix[i] = s->inter_matrix[n];
+ controls->quantization.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n];
+ controls->quantization.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n];
+ }
+
+ return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f);
+}
+
+static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const MpegEncContext *s = avctx->priv_data;
+
+ return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size);
+}
+
+static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx)
+{
+ const MpegEncContext *s = avctx->priv_data;
+ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+ .ptr = &controls->quantization,
+ .size = sizeof(controls->quantization),
+ },
+ };
+
+ controls->slice_params.bit_size = req->output.used * 8;
+
+ return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_mpeg2_init(AVCodecContext *avctx)
+{
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0);
+}
+
+const AVHWAccel ff_mpeg2_v4l2request_hwaccel = {
+ .name = "mpeg2_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_MPEG2VIDEO,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_mpeg2_start_frame,
+ .decode_slice = v4l2_request_mpeg2_decode_slice,
+ .end_frame = v4l2_request_mpeg2_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2),
+ .init = v4l2_request_mpeg2_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.21.0

View File

@ -0,0 +1,475 @@
From bc1ed76cbc2dad2ec308801552e2398fc2de0a07 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH 4/6] Add V4L2 request API h264 hwaccel
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/h264_slice.c | 4 +
libavcodec/h264dec.c | 3 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_h264.c | 368 +++++++++++++++++++++++++++++++++
6 files changed, 380 insertions(+)
create mode 100644 libavcodec/v4l2_request_h264.c
diff --git a/configure b/configure
index c93d67056d..296ca78ce7 100755
--- a/configure
+++ b/configure
@@ -2804,6 +2804,8 @@ h264_dxva2_hwaccel_deps="dxva2"
h264_dxva2_hwaccel_select="h264_decoder"
h264_nvdec_hwaccel_deps="nvdec"
h264_nvdec_hwaccel_select="h264_decoder"
+h264_v4l2request_hwaccel_deps="v4l2_request h264_v4l2_request"
+h264_v4l2request_hwaccel_select="h264_decoder"
h264_vaapi_hwaccel_deps="vaapi"
h264_vaapi_hwaccel_select="h264_decoder"
h264_vdpau_hwaccel_deps="vdpau"
@@ -6239,6 +6241,7 @@ check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;"
check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE_RAW;"
check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_header sys/videoio.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 9b945e3f64..2bdfaabb5f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -852,6 +852,7 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o
+OBJS-$(CONFIG_H264_V4L2REQUEST_HWACCEL) += v4l2_request_h264.o
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index f78f9f87b0..688d6c4ac2 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -758,6 +758,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
(CONFIG_H264_D3D11VA_HWACCEL * 2) + \
CONFIG_H264_NVDEC_HWACCEL + \
+ CONFIG_H264_V4L2REQUEST_HWACCEL + \
CONFIG_H264_VAAPI_HWACCEL + \
CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
CONFIG_H264_VDPAU_HWACCEL)
@@ -842,6 +843,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
#endif
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
+#endif
+#if CONFIG_H264_V4L2REQUEST_HWACCEL
+ *fmt++ = AV_PIX_FMT_DRM_PRIME;
#endif
if (h->avctx->codec->pix_fmts)
choices = h->avctx->codec->pix_fmts;
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 33e1056d87..3ccfa60621 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -1078,6 +1078,9 @@ AVCodec ff_h264_decoder = {
#endif
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
HWACCEL_VIDEOTOOLBOX(h264),
+#endif
+#if CONFIG_H264_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(h264),
#endif
NULL
},
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index ef54de2a3b..003200edea 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -27,6 +27,7 @@ extern const AVHWAccel ff_h264_d3d11va_hwaccel;
extern const AVHWAccel ff_h264_d3d11va2_hwaccel;
extern const AVHWAccel ff_h264_dxva2_hwaccel;
extern const AVHWAccel ff_h264_nvdec_hwaccel;
+extern const AVHWAccel ff_h264_v4l2request_hwaccel;
extern const AVHWAccel ff_h264_vaapi_hwaccel;
extern const AVHWAccel ff_h264_vdpau_hwaccel;
extern const AVHWAccel ff_h264_videotoolbox_hwaccel;
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
new file mode 100644
index 0000000000..a5c56d81c3
--- /dev/null
+++ b/libavcodec/v4l2_request_h264.c
@@ -0,0 +1,368 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "h264dec.h"
+#include "hwaccel.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsH264 {
+ struct v4l2_ctrl_h264_sps sps;
+ struct v4l2_ctrl_h264_pps pps;
+ struct v4l2_ctrl_h264_scaling_matrix scaling_matrix;
+ struct v4l2_ctrl_h264_decode_params decode_params;
+ struct v4l2_ctrl_h264_slice_params slice_params;
+} V4L2RequestControlsH264;
+
+static void fill_weight_factors(struct v4l2_h264_weight_factors *factors, int list, const H264SliceContext *sl)
+{
+ for (int i = 0; i < sl->ref_count[list]; i++) {
+ if (sl->pwt.luma_weight_flag[list]) {
+ factors->luma_weight[i] = sl->pwt.luma_weight[i][list][0];
+ factors->luma_offset[i] = sl->pwt.luma_weight[i][list][1];
+ } else {
+ factors->luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom;
+ factors->luma_offset[i] = 0;
+ }
+ for (int j = 0; j < 2; j++) {
+ if (sl->pwt.chroma_weight_flag[list]) {
+ factors->chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0];
+ factors->chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1];
+ } else {
+ factors->chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom;
+ factors->chroma_offset[i][j] = 0;
+ }
+ }
+ }
+}
+
+static void fill_dpb_entry(struct v4l2_h264_dpb_entry *entry, const H264Picture *pic)
+{
+ entry->reference_ts = ff_v4l2_request_get_capture_timestamp(pic->f);
+ entry->frame_num = pic->frame_num;
+ entry->pic_num = pic->pic_id;
+ entry->flags = V4L2_H264_DPB_ENTRY_FLAG_VALID;
+ if (pic->reference)
+ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_ACTIVE;
+ if (pic->long_ref)
+ entry->flags |= V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM;
+ entry->top_field_order_cnt = pic->field_poc[0];
+ entry->bottom_field_order_cnt = pic->field_poc[1];
+}
+
+static void fill_dpb(struct v4l2_ctrl_h264_decode_params *decode, const H264Context *h)
+{
+ int entries = 0;
+
+ for (int i = 0; i < h->short_ref_count; i++) {
+ const H264Picture *pic = h->short_ref[i];
+ if (pic)
+ fill_dpb_entry(&decode->dpb[entries++], pic);
+ }
+
+ if (!h->long_ref_count)
+ return;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(h->long_ref); i++) {
+ const H264Picture *pic = h->long_ref[i];
+ if (pic)
+ fill_dpb_entry(&decode->dpb[entries++], pic);
+ }
+}
+
+static uint8_t get_dpb_index(struct v4l2_ctrl_h264_decode_params *decode, const H264Ref *ref)
+{
+ uint64_t timestamp;
+
+ if (!ref->parent)
+ return 0;
+
+ timestamp = ff_v4l2_request_get_capture_timestamp(ref->parent->f);
+
+ for (uint8_t i = 0; i < FF_ARRAY_ELEMS(decode->dpb); i++) {
+ struct v4l2_h264_dpb_entry *entry = &decode->dpb[i];
+ if ((entry->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID) &&
+ entry->reference_ts == timestamp)
+ // TODO: signal reference type, possible using top 2 bits
+ return i | ((ref->reference & 3) << 6);
+ }
+
+ return 0;
+}
+
+static void fill_sps(struct v4l2_ctrl_h264_sps *ctrl, const H264Context *h)
+{
+ const SPS *sps = h->ps.sps;
+
+ *ctrl = (struct v4l2_ctrl_h264_sps) {
+ .profile_idc = sps->profile_idc,
+ .constraint_set_flags = sps->constraint_set_flags,
+ .level_idc = sps->level_idc,
+ .seq_parameter_set_id = sps->sps_id,
+ .chroma_format_idc = sps->chroma_format_idc,
+ .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
+ .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
+ .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
+ .pic_order_cnt_type = sps->poc_type,
+ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
+ .max_num_ref_frames = sps->ref_frame_count,
+ .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
+ //.offset_for_ref_frame[255] - not required? not set by libva-v4l2-request - copy sps->offset_for_ref_frame
+ .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
+ .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
+ .pic_width_in_mbs_minus1 = h->mb_width - 1,
+ .pic_height_in_map_units_minus1 = sps->frame_mbs_only_flag ? h->mb_height - 1 : h->mb_height / 2 - 1,
+ };
+
+ if (sps->residual_color_transform_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE;
+ if (sps->transform_bypass)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS;
+ if (sps->delta_pic_order_always_zero_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO;
+ if (sps->gaps_in_frame_num_allowed_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED;
+ if (sps->frame_mbs_only_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY;
+ if (sps->mb_aff)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD;
+ if (sps->direct_8x8_inference_flag)
+ ctrl->flags |= V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE;
+}
+
+static void fill_pps(struct v4l2_ctrl_h264_pps *ctrl, const H264Context *h)
+{
+ const PPS *pps = h->ps.pps;
+ const H264SliceContext *sl = &h->slice_ctx[0];
+
+ *ctrl = (struct v4l2_ctrl_h264_pps) {
+ .pic_parameter_set_id = sl->pps_id,
+ .seq_parameter_set_id = pps->sps_id,
+ .num_slice_groups_minus1 = pps->slice_group_count - 1,
+ .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
+ .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
+ .weighted_bipred_idc = pps->weighted_bipred_idc,
+ .pic_init_qp_minus26 = pps->init_qp - 26,
+ .pic_init_qs_minus26 = pps->init_qs - 26,
+ .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
+ .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
+ };
+
+ if (pps->cabac)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE;
+ if (pps->pic_order_present)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT;
+ if (pps->weighted_pred)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_WEIGHTED_PRED;
+ if (pps->deblocking_filter_parameters_present)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT;
+ if (pps->constrained_intra_pred)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED;
+ if (pps->redundant_pic_cnt_present)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT;
+ if (pps->transform_8x8_mode)
+ ctrl->flags |= V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE;
+}
+
+static int v4l2_request_h264_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const H264Context *h = avctx->priv_data;
+ const PPS *pps = h->ps.pps;
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+
+ fill_sps(&controls->sps, h);
+ fill_pps(&controls->pps, h);
+
+ memcpy(controls->scaling_matrix.scaling_list_4x4, pps->scaling_matrix4, sizeof(controls->scaling_matrix.scaling_list_4x4));
+ memcpy(controls->scaling_matrix.scaling_list_8x8, pps->scaling_matrix8, sizeof(controls->scaling_matrix.scaling_list_8x8));
+
+ controls->decode_params = (struct v4l2_ctrl_h264_decode_params) {
+ .num_slices = 0,
+ .nal_ref_idc = h->nal_ref_idc,
+ //.ref_pic_list_p0[32] - not required? not set by libva-v4l2-request
+ //.ref_pic_list_b0[32] - not required? not set by libva-v4l2-request
+ //.ref_pic_list_b1[32] - not required? not set by libva-v4l2-request
+ .top_field_order_cnt = h->cur_pic_ptr->field_poc[0],
+ .bottom_field_order_cnt = h->cur_pic_ptr->field_poc[1],
+ };
+
+ if (h->picture_idr)
+ controls->decode_params.flags |= V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC;
+
+ fill_dpb(&controls->decode_params, h);
+
+ return ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
+}
+
+static int v4l2_request_h264_end_frame(AVCodecContext *avctx)
+{
+ const H264Context *h = avctx->priv_data;
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->cur_pic_ptr->f->data[0];
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SPS,
+ .ptr = &controls->sps,
+ .size = sizeof(controls->sps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_PPS,
+ .ptr = &controls->pps,
+ .size = sizeof(controls->pps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
+ .ptr = &controls->scaling_matrix,
+ .size = sizeof(controls->scaling_matrix),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
+ .ptr = &controls->decode_params,
+ .size = sizeof(controls->decode_params),
+ },
+ };
+
+ controls->slice_params.size = req->output.used;
+
+ return ff_v4l2_request_decode_frame(avctx, h->cur_pic_ptr->f, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const H264Context *h = avctx->priv_data;
+ const PPS *pps = h->ps.pps;
+ const H264SliceContext *sl = &h->slice_ctx[0];
+ V4L2RequestControlsH264 *controls = h->cur_pic_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->cur_pic_ptr->f->data[0];
+ int i, count;
+
+ // HACK: trigger decode per slice
+ if (req->output.used) {
+ v4l2_request_h264_end_frame(avctx);
+ ff_v4l2_request_reset_frame(avctx, h->cur_pic_ptr->f);
+ }
+
+ controls->decode_params.num_slices++;
+
+ controls->slice_params = (struct v4l2_ctrl_h264_slice_params) {
+ /* Size in bytes, including header */
+ .size = 0,
+ /* Offset in bits to slice_data() from the beginning of this slice. */
+ .header_bit_size = get_bits_count(&sl->gb),
+
+ .first_mb_in_slice = sl->first_mb_addr,
+ .slice_type = ff_h264_get_slice_type(sl),
+ .pic_parameter_set_id = sl->pps_id,
+ .colour_plane_id = 0, /* what is this? */
+ .frame_num = h->poc.frame_num,
+ .idr_pic_id = 0, /* what is this? */
+ .pic_order_cnt_lsb = sl->poc_lsb,
+ .delta_pic_order_cnt_bottom = sl->delta_poc_bottom,
+ .delta_pic_order_cnt0 = sl->delta_poc[0],
+ .delta_pic_order_cnt1 = sl->delta_poc[1],
+ .redundant_pic_cnt = sl->redundant_pic_count,
+
+ /* Size in bits of dec_ref_pic_marking() syntax element. */
+ .dec_ref_pic_marking_bit_size = 0,
+ /* Size in bits of pic order count syntax. */
+ .pic_order_cnt_bit_size = 0,
+
+ .cabac_init_idc = sl->cabac_init_idc,
+ .slice_qp_delta = sl->qscale - pps->init_qp,
+ .slice_qs_delta = 0, /* XXX not implemented by FFmpeg */
+ .disable_deblocking_filter_idc = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter,
+ .slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2,
+ .slice_beta_offset_div2 = sl->slice_beta_offset / 2,
+ .slice_group_change_cycle = 0, /* what is this? */
+
+ .num_ref_idx_l0_active_minus1 = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0,
+ .num_ref_idx_l1_active_minus1 = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0,
+ };
+
+ if (FIELD_PICTURE(h))
+ controls->slice_params.flags |= V4L2_H264_SLICE_FLAG_FIELD_PIC;
+ if (h->picture_structure == PICT_BOTTOM_FIELD)
+ controls->slice_params.flags |= V4L2_H264_SLICE_FLAG_BOTTOM_FIELD;
+ if (sl->slice_type == AV_PICTURE_TYPE_B && sl->direct_spatial_mv_pred)
+ controls->slice_params.flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED;
+
+ controls->slice_params.pred_weight_table.chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom;
+ controls->slice_params.pred_weight_table.luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom;
+
+ count = sl->list_count > 0 ? sl->ref_count[0] : 0;
+ for (i = 0; i < count; i++)
+ controls->slice_params.ref_pic_list0[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[0][i]);
+ if (count)
+ fill_weight_factors(&controls->slice_params.pred_weight_table.weight_factors[0], 0, sl);
+
+ count = sl->list_count > 1 ? sl->ref_count[1] : 0;
+ for (i = 0; i < count; i++)
+ controls->slice_params.ref_pic_list1[i] = get_dpb_index(&controls->decode_params, &sl->ref_list[1][i]);
+ if (count)
+ fill_weight_factors(&controls->slice_params.pred_weight_table.weight_factors[1], 1, sl);
+
+ return ff_v4l2_request_append_output_buffer(avctx, h->cur_pic_ptr->f, buffer, size);
+}
+
+static int v4l2_request_h264_init(AVCodecContext *avctx)
+{
+ const H264Context *h = avctx->priv_data;
+ struct v4l2_ctrl_h264_sps sps;
+ struct v4l2_ctrl_h264_pps pps;
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_SPS,
+ .ptr = &sps,
+ .size = sizeof(sps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_PPS,
+ .ptr = &pps,
+ .size = sizeof(pps),
+ },
+ };
+
+ fill_sps(&sps, h);
+ fill_pps(&pps, h);
+
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_H264_SLICE_RAW, 2 * 1024 * 1024, control, FF_ARRAY_ELEMS(control));
+}
+
+const AVHWAccel ff_h264_v4l2request_hwaccel = {
+ .name = "h264_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_H264,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_h264_start_frame,
+ .decode_slice = v4l2_request_h264_decode_slice,
+ .end_frame = v4l2_request_h264_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsH264),
+ .init = v4l2_request_h264_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.21.0

View File

@ -0,0 +1,503 @@
From 25065e4e219c6bd688e6b62e40be74f1cfa08e72 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 22:32:16 +0100
Subject: [PATCH 5/6] Add V4L2 request API hevc hwaccel
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/hevcdec.c | 10 +
libavcodec/hwaccels.h | 1 +
libavcodec/v4l2_request_hevc.c | 391 +++++++++++++++++++++++++++++++++
5 files changed, 406 insertions(+)
create mode 100644 libavcodec/v4l2_request_hevc.c
diff --git a/configure b/configure
index 296ca78ce7..9252ca5794 100755
--- a/configure
+++ b/configure
@@ -2820,6 +2820,8 @@ hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
hevc_dxva2_hwaccel_select="hevc_decoder"
hevc_nvdec_hwaccel_deps="nvdec"
hevc_nvdec_hwaccel_select="hevc_decoder"
+hevc_v4l2request_hwaccel_deps="v4l2_request hevc_v4l2_request"
+hevc_v4l2request_hwaccel_select="hevc_decoder"
hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC"
hevc_vaapi_hwaccel_select="hevc_decoder"
hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC"
@@ -6242,6 +6244,7 @@ check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
check_cc h264_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_H264_SLICE_RAW;"
+check_cc hevc_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC_SLICE;"
check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_header sys/videoio.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 2bdfaabb5f..a4c959e0f5 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -860,6 +860,7 @@ OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o
OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o
+OBJS-$(CONFIG_HEVC_V4L2REQUEST_HWACCEL) += v4l2_request_hevc.o
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o
OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o
OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index c8877626d2..df33433150 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -362,6 +362,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \
CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \
CONFIG_HEVC_NVDEC_HWACCEL + \
+ CONFIG_HEVC_V4L2REQUEST_HWACCEL + \
CONFIG_HEVC_VAAPI_HWACCEL + \
CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \
CONFIG_HEVC_VDPAU_HWACCEL)
@@ -388,6 +389,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
+#endif
+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
+ *fmt++ = AV_PIX_FMT_DRM_PRIME;
#endif
break;
case AV_PIX_FMT_YUV420P10:
@@ -406,6 +410,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
#if CONFIG_HEVC_NVDEC_HWACCEL
*fmt++ = AV_PIX_FMT_CUDA;
+#endif
+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
+ *fmt++ = AV_PIX_FMT_DRM_PRIME;
#endif
break;
case AV_PIX_FMT_YUV420P12:
@@ -3556,6 +3563,9 @@ AVCodec ff_hevc_decoder = {
#endif
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
HWACCEL_VIDEOTOOLBOX(hevc),
+#endif
+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(hevc),
#endif
NULL
},
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 003200edea..d183675abe 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -35,6 +35,7 @@ extern const AVHWAccel ff_hevc_d3d11va_hwaccel;
extern const AVHWAccel ff_hevc_d3d11va2_hwaccel;
extern const AVHWAccel ff_hevc_dxva2_hwaccel;
extern const AVHWAccel ff_hevc_nvdec_hwaccel;
+extern const AVHWAccel ff_hevc_v4l2request_hwaccel;
extern const AVHWAccel ff_hevc_vaapi_hwaccel;
extern const AVHWAccel ff_hevc_vdpau_hwaccel;
extern const AVHWAccel ff_hevc_videotoolbox_hwaccel;
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
new file mode 100644
index 0000000000..300c1866ce
--- /dev/null
+++ b/libavcodec/v4l2_request_hevc.c
@@ -0,0 +1,391 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hevcdec.h"
+#include "hwaccel.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsHEVC {
+ struct v4l2_ctrl_hevc_sps sps;
+ struct v4l2_ctrl_hevc_pps pps;
+ struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix;
+ struct v4l2_ctrl_hevc_slice_params slice_params;
+} V4L2RequestControlsHEVC;
+
+static void v4l2_request_hevc_fill_pred_table(const HEVCContext *h, struct v4l2_hevc_pred_weight_table *table)
+{
+ int32_t luma_weight_denom, chroma_weight_denom;
+ const SliceHeader *sh = &h->sh;
+
+ if (sh->slice_type == HEVC_SLICE_I ||
+ (sh->slice_type == HEVC_SLICE_P && !h->ps.pps->weighted_pred_flag) ||
+ (sh->slice_type == HEVC_SLICE_B && !h->ps.pps->weighted_bipred_flag))
+ return;
+
+ table->luma_log2_weight_denom = sh->luma_log2_weight_denom;
+
+ if (h->ps.sps->chroma_format_idc)
+ table->delta_chroma_log2_weight_denom = sh->chroma_log2_weight_denom - sh->luma_log2_weight_denom;
+
+ luma_weight_denom = (1 << sh->luma_log2_weight_denom);
+ chroma_weight_denom = (1 << sh->chroma_log2_weight_denom);
+
+ for (int i = 0; i < 15 && i < sh->nb_refs[L0]; i++) {
+ table->delta_luma_weight_l0[i] = sh->luma_weight_l0[i] - luma_weight_denom;
+ table->luma_offset_l0[i] = sh->luma_offset_l0[i];
+ table->delta_chroma_weight_l0[i][0] = sh->chroma_weight_l0[i][0] - chroma_weight_denom;
+ table->delta_chroma_weight_l0[i][1] = sh->chroma_weight_l0[i][1] - chroma_weight_denom;
+ table->chroma_offset_l0[i][0] = sh->chroma_offset_l0[i][0];
+ table->chroma_offset_l0[i][1] = sh->chroma_offset_l0[i][1];
+ }
+
+ if (sh->slice_type != HEVC_SLICE_B)
+ return;
+
+ for (int i = 0; i < 15 && i < sh->nb_refs[L1]; i++) {
+ table->delta_luma_weight_l1[i] = sh->luma_weight_l1[i] - luma_weight_denom;
+ table->luma_offset_l1[i] = sh->luma_offset_l1[i];
+ table->delta_chroma_weight_l1[i][0] = sh->chroma_weight_l1[i][0] - chroma_weight_denom;
+ table->delta_chroma_weight_l1[i][1] = sh->chroma_weight_l1[i][1] - chroma_weight_denom;
+ table->chroma_offset_l1[i][0] = sh->chroma_offset_l1[i][0];
+ table->chroma_offset_l1[i][1] = sh->chroma_offset_l1[i][1];
+ }
+}
+
+static int find_frame_rps_type(const HEVCContext *h, uint64_t timestamp)
+{
+ const HEVCFrame *frame;
+ int i;
+
+ for (i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
+ frame = h->rps[ST_CURR_BEF].ref[i];
+ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame))
+ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE;
+ }
+
+ for (i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
+ frame = h->rps[ST_CURR_AFT].ref[i];
+ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame))
+ return V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER;
+ }
+
+ for (i = 0; i < h->rps[LT_CURR].nb_refs; i++) {
+ frame = h->rps[LT_CURR].ref[i];
+ if (frame && timestamp == ff_v4l2_request_get_capture_timestamp(frame->frame))
+ return V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR;
+ }
+
+ return 0;
+}
+
+static uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame,
+ struct v4l2_ctrl_hevc_slice_params *slice_params)
+{
+ uint64_t timestamp;
+
+ if (!frame)
+ return 0;
+
+ timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame);
+
+ for (uint8_t i = 0; i < slice_params->num_active_dpb_entries; i++) {
+ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[i];
+ if (entry->timestamp == timestamp)
+ return i;
+ }
+
+ return 0;
+}
+
+static void v4l2_request_hevc_fill_slice_params(const HEVCContext *h,
+ struct v4l2_ctrl_hevc_slice_params *slice_params)
+{
+ const HEVCFrame *pic = h->ref;
+ const SliceHeader *sh = &h->sh;
+ int i, entries = 0;
+ RefPicList *rpl;
+
+ *slice_params = (struct v4l2_ctrl_hevc_slice_params) {
+ .bit_size = 0,
+ .data_bit_offset = get_bits_count(&h->HEVClc->gb),
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
+ .nal_unit_type = h->nal_unit_type,
+ .nuh_temporal_id_plus1 = h->temporal_id + 1,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .slice_type = sh->slice_type,
+ .colour_plane_id = sh->colour_plane_id,
+ .slice_pic_order_cnt = pic->poc,
+ .slice_sao_luma_flag = sh->slice_sample_adaptive_offset_flag[0],
+ .slice_sao_chroma_flag = sh->slice_sample_adaptive_offset_flag[1],
+ .slice_temporal_mvp_enabled_flag = sh->slice_temporal_mvp_enabled_flag,
+ .num_ref_idx_l0_active_minus1 = sh->nb_refs[L0] ? sh->nb_refs[L0] - 1 : 0,
+ .num_ref_idx_l1_active_minus1 = sh->nb_refs[L1] ? sh->nb_refs[L1] - 1 : 0,
+ .mvd_l1_zero_flag = sh->mvd_l1_zero_flag,
+ .cabac_init_flag = sh->cabac_init_flag,
+ .collocated_from_l0_flag = sh->collocated_list == L0 ? 1 : 0,
+ .collocated_ref_idx = sh->slice_temporal_mvp_enabled_flag ? sh->collocated_ref_idx : 0,
+ .five_minus_max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ? 0 : 5 - sh->max_num_merge_cand,
+ .use_integer_mv_flag = 0,
+ .slice_qp_delta = sh->slice_qp_delta,
+ .slice_cb_qp_offset = sh->slice_cb_qp_offset,
+ .slice_cr_qp_offset = sh->slice_cr_qp_offset,
+ .slice_act_y_qp_offset = 0,
+ .slice_act_cb_qp_offset = 0,
+ .slice_act_cr_qp_offset = 0,
+ .slice_deblocking_filter_disabled_flag = sh->disable_deblocking_filter_flag,
+ .slice_beta_offset_div2 = sh->beta_offset / 2,
+ .slice_tc_offset_div2 = sh->tc_offset / 2,
+ .slice_loop_filter_across_slices_enabled_flag = sh->slice_loop_filter_across_slices_enabled_flag,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
+ .pic_struct = h->sei.picture_timing.picture_struct,
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ .num_rps_poc_st_curr_before = h->rps[ST_CURR_BEF].nb_refs,
+ .num_rps_poc_st_curr_after = h->rps[ST_CURR_AFT].nb_refs,
+ .num_rps_poc_lt_curr = h->rps[LT_CURR].nb_refs,
+
+ .slice_segment_addr = sh->slice_segment_addr,
+ .first_slice_segment_in_pic_flag = sh->first_slice_in_pic_flag,
+ };
+
+ for (i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
+ const HEVCFrame *frame = &h->DPB[i];
+ if (frame != pic && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
+ struct v4l2_hevc_dpb_entry *entry = &slice_params->dpb[entries++];
+
+ entry->timestamp = ff_v4l2_request_get_capture_timestamp(frame->frame);
+ entry->rps = find_frame_rps_type(h, entry->timestamp);
+ entry->field_pic = frame->frame->interlaced_frame;
+
+ /* TODO: Interleaved: Get the POC for each field. */
+ entry->pic_order_cnt[0] = frame->poc;
+ entry->pic_order_cnt[1] = frame->poc;
+ }
+ }
+
+ slice_params->num_active_dpb_entries = entries;
+
+ if (sh->slice_type != HEVC_SLICE_I) {
+ rpl = &h->ref->refPicList[0];
+ for (i = 0; i < rpl->nb_refs; i++)
+ slice_params->ref_idx_l0[i] = get_ref_pic_index(h, rpl->ref[i], slice_params);
+ }
+
+ if (sh->slice_type == HEVC_SLICE_B) {
+ rpl = &h->ref->refPicList[1];
+ for (i = 0; i < rpl->nb_refs; i++)
+ slice_params->ref_idx_l1[i] = get_ref_pic_index(h, rpl->ref[i], slice_params);
+ }
+
+ v4l2_request_hevc_fill_pred_table(h, &slice_params->pred_weight_table);
+
+ slice_params->num_entry_point_offsets = sh->num_entry_point_offsets;
+ if (slice_params->num_entry_point_offsets > 256) {
+ slice_params->num_entry_point_offsets = 256;
+ av_log(NULL, AV_LOG_ERROR, "%s: Currently only 256 entry points are supported, but slice has %d entry points.\n", __func__, sh->num_entry_point_offsets);
+ }
+
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++)
+ slice_params->entry_point_offset_minus1[i] = sh->entry_point_offset[i] - 1;
+}
+
+static int v4l2_request_hevc_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ const HEVCSPS *sps = h->ps.sps;
+ const HEVCPPS *pps = h->ps.pps;
+ const ScalingList *sl = pps->scaling_list_data_present_flag ?
+ &pps->scaling_list :
+ sps->scaling_list_enable_flag ?
+ &sps->scaling_list : NULL;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
+ controls->sps = (struct v4l2_ctrl_hevc_sps) {
+ .chroma_format_idc = sps->chroma_format_idc,
+ .separate_colour_plane_flag = sps->separate_colour_plane_flag,
+ .pic_width_in_luma_samples = sps->width,
+ .pic_height_in_luma_samples = sps->height,
+ .bit_depth_luma_minus8 = sps->bit_depth - 8,
+ .bit_depth_chroma_minus8 = sps->bit_depth - 8,
+ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
+ .sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1,
+ .sps_max_num_reorder_pics = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
+ .sps_max_latency_increase_plus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_latency_increase + 1,
+ .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3,
+ .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size,
+ .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2,
+ .log2_diff_max_min_luma_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size,
+ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
+ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
+ .scaling_list_enabled_flag = sps->scaling_list_enable_flag,
+ .amp_enabled_flag = sps->amp_enabled_flag,
+ .sample_adaptive_offset_enabled_flag = sps->sao_enabled,
+ .pcm_enabled_flag = sps->pcm_enabled_flag,
+ .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
+ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
+ .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
+ .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
+ .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag,
+ .num_short_term_ref_pic_sets = sps->nb_st_rps,
+ .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
+ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
+ .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag,
+ .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag,
+ };
+
+ if (sl) {
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 16; j++)
+ controls->scaling_matrix.scaling_list_4x4[i][j] = sl->sl[0][i][j];
+ for (int j = 0; j < 64; j++) {
+ controls->scaling_matrix.scaling_list_8x8[i][j] = sl->sl[1][i][j];
+ controls->scaling_matrix.scaling_list_16x16[i][j] = sl->sl[2][i][j];
+ if (i < 2)
+ controls->scaling_matrix.scaling_list_32x32[i][j] = sl->sl[3][i * 3][j];
+ }
+ controls->scaling_matrix.scaling_list_dc_coef_16x16[i] = sl->sl_dc[0][i];
+ if (i < 2)
+ controls->scaling_matrix.scaling_list_dc_coef_32x32[i] = sl->sl_dc[1][i * 3];
+ }
+ }
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
+ controls->pps = (struct v4l2_ctrl_hevc_pps) {
+ .dependent_slice_segment_flag = pps->dependent_slice_segments_enabled_flag,
+ .output_flag_present_flag = pps->output_flag_present_flag,
+ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
+ .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag,
+ .cabac_init_present_flag = pps->cabac_init_present_flag,
+ .init_qp_minus26 = pps->pic_init_qp_minus26,
+ .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
+ .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
+ .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
+ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
+ .pps_cb_qp_offset = pps->cb_qp_offset,
+ .pps_cr_qp_offset = pps->cr_qp_offset,
+ .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag,
+ .weighted_pred_flag = pps->weighted_pred_flag,
+ .weighted_bipred_flag = pps->weighted_bipred_flag,
+ .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag,
+ .tiles_enabled_flag = pps->tiles_enabled_flag,
+ .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
+ .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
+ .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag,
+ .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
+ .pps_disable_deblocking_filter_flag = pps->disable_dbf,
+ .pps_beta_offset_div2 = pps->beta_offset / 2,
+ .pps_tc_offset_div2 = pps->tc_offset / 2,
+ .lists_modification_present_flag = pps->lists_modification_present_flag,
+ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
+ .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag,
+ .scaling_list_enable_flag = pps->scaling_list_data_present_flag, // pps_scaling_list_data_present_flag
+ };
+
+ if (pps->tiles_enabled_flag) {
+ controls->pps.num_tile_columns_minus1 = pps->num_tile_columns - 1;
+ controls->pps.num_tile_rows_minus1 = pps->num_tile_rows - 1;
+
+ av_log(avctx, AV_LOG_DEBUG, "%s: avctx=%p tiles_enabled_flag=%d num_tile_columns=%d num_tile_rows=%d\n", __func__, avctx, pps->tiles_enabled_flag, pps->num_tile_columns, pps->num_tile_rows);
+
+ for (int i = 0; i < pps->num_tile_columns; i++)
+ controls->pps.column_width_minus1[i] = pps->column_width[i] - 1;
+
+ for (int i = 0; i < pps->num_tile_rows; i++)
+ controls->pps.row_height_minus1[i] = pps->row_height[i] - 1;
+ }
+
+ return ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+}
+
+static int v4l2_request_hevc_end_frame(AVCodecContext *avctx)
+{
+ const HEVCContext *h = avctx->priv_data;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0];
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS,
+ .ptr = &controls->sps,
+ .size = sizeof(controls->sps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS,
+ .ptr = &controls->pps,
+ .size = sizeof(controls->pps),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
+ .ptr = &controls->scaling_matrix,
+ .size = sizeof(controls->scaling_matrix),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params),
+ },
+ };
+
+ controls->slice_params.bit_size = req->output.used * 8;
+
+ return ff_v4l2_request_decode_frame(avctx, h->ref->frame, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_hevc_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ V4L2RequestControlsHEVC *controls = h->ref->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)h->ref->frame->data[0];
+
+ // HACK: trigger decode per slice
+ if (req->output.used) {
+ v4l2_request_hevc_end_frame(avctx);
+ ff_v4l2_request_reset_frame(avctx, h->ref->frame);
+ }
+
+ v4l2_request_hevc_fill_slice_params(h, &controls->slice_params);
+
+ return ff_v4l2_request_append_output_buffer(avctx, h->ref->frame, buffer, size);
+}
+
+static int v4l2_request_hevc_init(AVCodecContext *avctx)
+{
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_HEVC_SLICE, 2 * 1024 * 1024, NULL, 0);
+}
+
+const AVHWAccel ff_hevc_v4l2request_hwaccel = {
+ .name = "hevc_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_HEVC,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_hevc_start_frame,
+ .decode_slice = v4l2_request_hevc_decode_slice,
+ .end_frame = v4l2_request_hevc_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsHEVC),
+ .init = v4l2_request_hevc_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.21.0

View File

@ -0,0 +1,546 @@
From 583677006f15ee59600f6f30f5e79aa5f81935b9 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 14 Feb 2019 23:20:05 +0100
Subject: [PATCH 6/6] Add and use private linux headers for V4L2 request API
ctrls
---
libavcodec/h264-ctrls.h | 192 +++++++++++++++++++++++++++++++
libavcodec/hevc-ctrls.h | 197 ++++++++++++++++++++++++++++++++
libavcodec/mpeg2-ctrls.h | 82 +++++++++++++
libavcodec/v4l2_request_h264.c | 1 +
libavcodec/v4l2_request_hevc.c | 1 +
libavcodec/v4l2_request_mpeg2.c | 1 +
6 files changed, 474 insertions(+)
create mode 100644 libavcodec/h264-ctrls.h
create mode 100644 libavcodec/hevc-ctrls.h
create mode 100644 libavcodec/mpeg2-ctrls.h
diff --git a/libavcodec/h264-ctrls.h b/libavcodec/h264-ctrls.h
new file mode 100644
index 0000000000..e2f83b3cdb
--- /dev/null
+++ b/libavcodec/h264-ctrls.h
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the H.264 state controls for use with stateless H.264
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _H264_CTRLS_H_
+#define _H264_CTRLS_H_
+
+/*
+ * This is put insanely high to avoid conflicting with controls that
+ * would be added during the phase where those controls are not
+ * stable. It should be fixed eventually.
+ */
+#define V4L2_CID_MPEG_VIDEO_H264_SPS (V4L2_CID_MPEG_BASE+1000)
+#define V4L2_CID_MPEG_VIDEO_H264_PPS (V4L2_CID_MPEG_BASE+1001)
+#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (V4L2_CID_MPEG_BASE+1002)
+#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (V4L2_CID_MPEG_BASE+1003)
+#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_H264_SPS 0x0110
+#define V4L2_CTRL_TYPE_H264_PPS 0x0111
+#define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112
+#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113
+#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114
+
+#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01
+#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02
+#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04
+#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08
+#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10
+#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20
+
+#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01
+#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02
+#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04
+#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08
+#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10
+#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20
+#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40
+
+struct v4l2_ctrl_h264_sps {
+ __u8 profile_idc;
+ __u8 constraint_set_flags;
+ __u8 level_idc;
+ __u8 seq_parameter_set_id;
+ __u8 chroma_format_idc;
+ __u8 bit_depth_luma_minus8;
+ __u8 bit_depth_chroma_minus8;
+ __u8 log2_max_frame_num_minus4;
+ __u8 pic_order_cnt_type;
+ __u8 log2_max_pic_order_cnt_lsb_minus4;
+ __u8 max_num_ref_frames;
+ __u8 num_ref_frames_in_pic_order_cnt_cycle;
+ __s32 offset_for_ref_frame[255];
+ __s32 offset_for_non_ref_pic;
+ __s32 offset_for_top_to_bottom_field;
+ __u16 pic_width_in_mbs_minus1;
+ __u16 pic_height_in_map_units_minus1;
+ __u32 flags;
+};
+
+#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001
+#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002
+#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004
+#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008
+#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010
+#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020
+#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040
+#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080
+
+struct v4l2_ctrl_h264_pps {
+ __u8 pic_parameter_set_id;
+ __u8 seq_parameter_set_id;
+ __u8 num_slice_groups_minus1;
+ __u8 num_ref_idx_l0_default_active_minus1;
+ __u8 num_ref_idx_l1_default_active_minus1;
+ __u8 weighted_bipred_idc;
+ __s8 pic_init_qp_minus26;
+ __s8 pic_init_qs_minus26;
+ __s8 chroma_qp_index_offset;
+ __s8 second_chroma_qp_index_offset;
+ __u16 flags;
+};
+
+struct v4l2_ctrl_h264_scaling_matrix {
+ __u8 scaling_list_4x4[6][16];
+ __u8 scaling_list_8x8[6][64];
+};
+
+struct v4l2_h264_weight_factors {
+ __s16 luma_weight[32];
+ __s16 luma_offset[32];
+ __s16 chroma_weight[32][2];
+ __s16 chroma_offset[32][2];
+};
+
+struct v4l2_h264_pred_weight_table {
+ __u16 luma_log2_weight_denom;
+ __u16 chroma_log2_weight_denom;
+ struct v4l2_h264_weight_factors weight_factors[2];
+};
+
+#define V4L2_H264_SLICE_TYPE_P 0
+#define V4L2_H264_SLICE_TYPE_B 1
+#define V4L2_H264_SLICE_TYPE_I 2
+#define V4L2_H264_SLICE_TYPE_SP 3
+#define V4L2_H264_SLICE_TYPE_SI 4
+
+#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01
+#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02
+#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04
+#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08
+
+struct v4l2_ctrl_h264_slice_params {
+ /* Size in bytes, including header */
+ __u32 size;
+ /* Offset in bits to slice_data() from the beginning of this slice. */
+ __u32 header_bit_size;
+
+ __u16 first_mb_in_slice;
+ __u8 slice_type;
+ __u8 pic_parameter_set_id;
+ __u8 colour_plane_id;
+ __u8 redundant_pic_cnt;
+ __u16 frame_num;
+ __u16 idr_pic_id;
+ __u16 pic_order_cnt_lsb;
+ __s32 delta_pic_order_cnt_bottom;
+ __s32 delta_pic_order_cnt0;
+ __s32 delta_pic_order_cnt1;
+
+ struct v4l2_h264_pred_weight_table pred_weight_table;
+ /* Size in bits of dec_ref_pic_marking() syntax element. */
+ __u32 dec_ref_pic_marking_bit_size;
+ /* Size in bits of pic order count syntax. */
+ __u32 pic_order_cnt_bit_size;
+
+ __u8 cabac_init_idc;
+ __s8 slice_qp_delta;
+ __s8 slice_qs_delta;
+ __u8 disable_deblocking_filter_idc;
+ __s8 slice_alpha_c0_offset_div2;
+ __s8 slice_beta_offset_div2;
+ __u8 num_ref_idx_l0_active_minus1;
+ __u8 num_ref_idx_l1_active_minus1;
+ __u32 slice_group_change_cycle;
+
+ /*
+ * Entries on each list are indices into
+ * v4l2_ctrl_h264_decode_params.dpb[].
+ */
+ __u8 ref_pic_list0[32];
+ __u8 ref_pic_list1[32];
+
+ __u32 flags;
+};
+
+#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01
+#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02
+#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04
+
+struct v4l2_h264_dpb_entry {
+ __u64 reference_ts;
+ __u16 frame_num;
+ __u16 pic_num;
+ /* Note that field is indicated by v4l2_buffer.field */
+ __s32 top_field_order_cnt;
+ __s32 bottom_field_order_cnt;
+ __u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */
+};
+
+#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
+
+struct v4l2_ctrl_h264_decode_params {
+ struct v4l2_h264_dpb_entry dpb[16];
+ __u16 num_slices;
+ __u16 nal_ref_idc;
+ __u8 ref_pic_list_p0[32];
+ __u8 ref_pic_list_b0[32];
+ __u8 ref_pic_list_b1[32];
+ __s32 top_field_order_cnt;
+ __s32 bottom_field_order_cnt;
+ __u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */
+};
+
+#endif
diff --git a/libavcodec/hevc-ctrls.h b/libavcodec/hevc-ctrls.h
new file mode 100644
index 0000000000..c8c61079c6
--- /dev/null
+++ b/libavcodec/hevc-ctrls.h
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the HEVC state controls for use with stateless HEVC
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _HEVC_CTRLS_H_
+#define _HEVC_CTRLS_H_
+
+#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 645)
+#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 646)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 647)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 648)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_HEVC_SPS 0x0115
+#define V4L2_CTRL_TYPE_HEVC_PPS 0x0116
+#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0117
+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0118
+
+#define V4L2_HEVC_SLICE_TYPE_B 0
+#define V4L2_HEVC_SLICE_TYPE_P 1
+#define V4L2_HEVC_SLICE_TYPE_I 2
+
+struct v4l2_ctrl_hevc_sps {
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
+ __u8 chroma_format_idc;
+ __u8 separate_colour_plane_flag;
+ __u16 pic_width_in_luma_samples;
+ __u16 pic_height_in_luma_samples;
+ __u8 bit_depth_luma_minus8;
+ __u8 bit_depth_chroma_minus8;
+ __u8 log2_max_pic_order_cnt_lsb_minus4;
+ __u8 sps_max_dec_pic_buffering_minus1;
+ __u8 sps_max_num_reorder_pics;
+ __u8 sps_max_latency_increase_plus1;
+ __u8 log2_min_luma_coding_block_size_minus3;
+ __u8 log2_diff_max_min_luma_coding_block_size;
+ __u8 log2_min_luma_transform_block_size_minus2;
+ __u8 log2_diff_max_min_luma_transform_block_size;
+ __u8 max_transform_hierarchy_depth_inter;
+ __u8 max_transform_hierarchy_depth_intra;
+ __u8 scaling_list_enabled_flag;
+ __u8 amp_enabled_flag;
+ __u8 sample_adaptive_offset_enabled_flag;
+ __u8 pcm_enabled_flag;
+ __u8 pcm_sample_bit_depth_luma_minus1;
+ __u8 pcm_sample_bit_depth_chroma_minus1;
+ __u8 log2_min_pcm_luma_coding_block_size_minus3;
+ __u8 log2_diff_max_min_pcm_luma_coding_block_size;
+ __u8 pcm_loop_filter_disabled_flag;
+ __u8 num_short_term_ref_pic_sets;
+ __u8 long_term_ref_pics_present_flag;
+ __u8 num_long_term_ref_pics_sps;
+ __u8 sps_temporal_mvp_enabled_flag;
+ __u8 strong_intra_smoothing_enabled_flag;
+};
+
+struct v4l2_ctrl_hevc_pps {
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
+ __u8 dependent_slice_segment_flag;
+ __u8 output_flag_present_flag;
+ __u8 num_extra_slice_header_bits;
+ __u8 sign_data_hiding_enabled_flag;
+ __u8 cabac_init_present_flag;
+ __s8 init_qp_minus26;
+ __u8 constrained_intra_pred_flag;
+ __u8 transform_skip_enabled_flag;
+ __u8 cu_qp_delta_enabled_flag;
+ __u8 diff_cu_qp_delta_depth;
+ __s8 pps_cb_qp_offset;
+ __s8 pps_cr_qp_offset;
+ __u8 pps_slice_chroma_qp_offsets_present_flag;
+ __u8 weighted_pred_flag;
+ __u8 weighted_bipred_flag;
+ __u8 transquant_bypass_enabled_flag;
+ __u8 tiles_enabled_flag;
+ __u8 entropy_coding_sync_enabled_flag;
+ __u8 num_tile_columns_minus1;
+ __u8 num_tile_rows_minus1;
+ __u8 column_width_minus1[20];
+ __u8 row_height_minus1[22];
+ __u8 loop_filter_across_tiles_enabled_flag;
+ __u8 pps_loop_filter_across_slices_enabled_flag;
+ __u8 deblocking_filter_override_enabled_flag;
+ __u8 pps_disable_deblocking_filter_flag;
+ __s8 pps_beta_offset_div2;
+ __s8 pps_tc_offset_div2;
+ __u8 lists_modification_present_flag;
+ __u8 log2_parallel_merge_level_minus2;
+ __u8 slice_segment_header_extension_present_flag;
+ __u8 scaling_list_enable_flag;
+};
+
+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01
+#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02
+#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03
+
+#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16
+
+struct v4l2_hevc_dpb_entry {
+ __u64 timestamp;
+ __u8 rps;
+ __u8 field_pic;
+ __u16 pic_order_cnt[2];
+ __u8 padding[2];
+};
+
+struct v4l2_hevc_pred_weight_table {
+ __u8 luma_log2_weight_denom;
+ __s8 delta_chroma_log2_weight_denom;
+
+ __s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+ __s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+
+ __s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+ __s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
+
+ __u8 padding[2];
+};
+
+struct v4l2_ctrl_hevc_slice_params {
+ __u32 bit_size;
+ __u32 data_bit_offset;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
+ __u8 nal_unit_type;
+ __u8 nuh_temporal_id_plus1;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ __u8 slice_type;
+ __u8 colour_plane_id;
+ __u16 slice_pic_order_cnt;
+ __u8 slice_sao_luma_flag;
+ __u8 slice_sao_chroma_flag;
+ __u8 slice_temporal_mvp_enabled_flag;
+ __u8 num_ref_idx_l0_active_minus1;
+ __u8 num_ref_idx_l1_active_minus1;
+ __u8 mvd_l1_zero_flag;
+ __u8 cabac_init_flag;
+ __u8 collocated_from_l0_flag;
+ __u8 collocated_ref_idx;
+ __u8 five_minus_max_num_merge_cand;
+ __u8 use_integer_mv_flag;
+ __s8 slice_qp_delta;
+ __s8 slice_cb_qp_offset;
+ __s8 slice_cr_qp_offset;
+ __s8 slice_act_y_qp_offset;
+ __s8 slice_act_cb_qp_offset;
+ __s8 slice_act_cr_qp_offset;
+ __u8 slice_deblocking_filter_disabled_flag;
+ __s8 slice_beta_offset_div2;
+ __s8 slice_tc_offset_div2;
+ __u8 slice_loop_filter_across_slices_enabled_flag;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
+ __u8 pic_struct;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
+ struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __u8 num_active_dpb_entries;
+ __u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+ __u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
+
+ __u8 num_rps_poc_st_curr_before;
+ __u8 num_rps_poc_st_curr_after;
+ __u8 num_rps_poc_lt_curr;
+
+ /* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
+ struct v4l2_hevc_pred_weight_table pred_weight_table;
+
+ __u32 slice_segment_addr;
+ __u32 num_entry_point_offsets;
+ __u32 entry_point_offset_minus1[256];
+ __u8 first_slice_segment_in_pic_flag;
+
+ __u8 padding;
+};
+
+struct v4l2_ctrl_hevc_scaling_matrix {
+ __u8 scaling_list_4x4[6][16];
+ __u8 scaling_list_8x8[6][64];
+ __u8 scaling_list_16x16[6][64];
+ __u8 scaling_list_32x32[2][64];
+ __u8 scaling_list_dc_coef_16x16[6];
+ __u8 scaling_list_dc_coef_32x32[2];
+};
+
+#endif
diff --git a/libavcodec/mpeg2-ctrls.h b/libavcodec/mpeg2-ctrls.h
new file mode 100644
index 0000000000..6601455b3d
--- /dev/null
+++ b/libavcodec/mpeg2-ctrls.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the MPEG2 state controls for use with stateless MPEG-2
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _MPEG2_CTRLS_H_
+#define _MPEG2_CTRLS_H_
+
+#define V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS (V4L2_CID_MPEG_BASE+250)
+#define V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION (V4L2_CID_MPEG_BASE+251)
+
+/* enum v4l2_ctrl_type type values */
+#define V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS 0x0103
+#define V4L2_CTRL_TYPE_MPEG2_QUANTIZATION 0x0104
+
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_I 1
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_P 2
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_B 3
+#define V4L2_MPEG2_PICTURE_CODING_TYPE_D 4
+
+struct v4l2_mpeg2_sequence {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
+ __u16 horizontal_size;
+ __u16 vertical_size;
+ __u32 vbv_buffer_size;
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
+ __u16 profile_and_level_indication;
+ __u8 progressive_sequence;
+ __u8 chroma_format;
+};
+
+struct v4l2_mpeg2_picture {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
+ __u8 picture_coding_type;
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
+ __u8 f_code[2][2];
+ __u8 intra_dc_precision;
+ __u8 picture_structure;
+ __u8 top_field_first;
+ __u8 frame_pred_frame_dct;
+ __u8 concealment_motion_vectors;
+ __u8 q_scale_type;
+ __u8 intra_vlc_format;
+ __u8 alternate_scan;
+ __u8 repeat_first_field;
+ __u16 progressive_frame;
+};
+
+struct v4l2_ctrl_mpeg2_slice_params {
+ __u32 bit_size;
+ __u32 data_bit_offset;
+ __u64 backward_ref_ts;
+ __u64 forward_ref_ts;
+
+ struct v4l2_mpeg2_sequence sequence;
+ struct v4l2_mpeg2_picture picture;
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
+ __u32 quantiser_scale_code;
+};
+
+struct v4l2_ctrl_mpeg2_quantization {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
+ __u8 load_intra_quantiser_matrix;
+ __u8 load_non_intra_quantiser_matrix;
+ __u8 load_chroma_intra_quantiser_matrix;
+ __u8 load_chroma_non_intra_quantiser_matrix;
+
+ __u8 intra_quantiser_matrix[64];
+ __u8 non_intra_quantiser_matrix[64];
+ __u8 chroma_intra_quantiser_matrix[64];
+ __u8 chroma_non_intra_quantiser_matrix[64];
+};
+
+#endif
diff --git a/libavcodec/v4l2_request_h264.c b/libavcodec/v4l2_request_h264.c
index a5c56d81c3..a5dbc08a8d 100644
--- a/libavcodec/v4l2_request_h264.c
+++ b/libavcodec/v4l2_request_h264.c
@@ -19,6 +19,7 @@
#include "h264dec.h"
#include "hwaccel.h"
#include "v4l2_request.h"
+#include "h264-ctrls.h"
typedef struct V4L2RequestControlsH264 {
struct v4l2_ctrl_h264_sps sps;
diff --git a/libavcodec/v4l2_request_hevc.c b/libavcodec/v4l2_request_hevc.c
index 300c1866ce..7c7948cfbf 100644
--- a/libavcodec/v4l2_request_hevc.c
+++ b/libavcodec/v4l2_request_hevc.c
@@ -19,6 +19,7 @@
#include "hevcdec.h"
#include "hwaccel.h"
#include "v4l2_request.h"
+#include "hevc-ctrls.h"
typedef struct V4L2RequestControlsHEVC {
struct v4l2_ctrl_hevc_sps sps;
diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
index 782b9c2471..37a4eae62c 100644
--- a/libavcodec/v4l2_request_mpeg2.c
+++ b/libavcodec/v4l2_request_mpeg2.c
@@ -19,6 +19,7 @@
#include "hwaccel.h"
#include "mpegvideo.h"
#include "v4l2_request.h"
+#include "mpeg2-ctrls.h"
typedef struct V4L2RequestControlsMPEG2 {
struct v4l2_ctrl_mpeg2_slice_params slice_params;
--
2.21.0

View File

@ -0,0 +1,26 @@
# table pine64, type: NEC
0x404000 KEY_NUMERIC_0
0x404001 KEY_NUMERIC_1
0x404002 KEY_NUMERIC_2
0x404003 KEY_NUMERIC_3
0x404004 KEY_NUMERIC_4
0x404005 KEY_NUMERIC_5
0x404006 KEY_NUMERIC_6
0x404007 KEY_NUMERIC_7
0x404008 KEY_NUMERIC_8
0x404009 KEY_NUMERIC_9
0x40400a KEY_MUTE
0x40400b KEY_UP
0x40400c KEY_BACKSPACE
0x40400d KEY_OK
0x40400e KEY_DOWN
0x404010 KEY_LEFT
0x404011 KEY_RIGHT
0x404017 KEY_VOLUMEDOWN
0x404018 KEY_VOLUMEUP
0x40401a KEY_HOME
0x40401d KEY_MENU
0x40401f KEY_WWW
0x404045 KEY_BACK
0x404047 KEY_INFO
0x40404d KEY_POWER

View File

@ -0,0 +1,21 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2018-present Team LibreELEC
PKG_NAME="atf"
PKG_VERSION="v2.1"
PKG_SHA256="7c4c00a4f28d3cfbb235fd1a1fb28c4d2fc1d657c9301686e7d8824ef575d059"
PKG_ARCH="arm aarch64"
PKG_LICENSE="BSD-3c"
PKG_SITE="https://github.com/ARM-software/arm-trusted-firmware"
PKG_URL="https://github.com/ARM-software/arm-trusted-firmware/archive/$PKG_VERSION.tar.gz"
PKG_LONGDESC="ARM Trusted Firmware is a reference implementation of secure world software, including a Secure Monitor executing at Exception Level 3 and various Arm interface standards."
PKG_TOOLCHAIN="manual"
PKG_IS_KERNEL_PKG="yes"
make_target() {
CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" CFLAGS="" make PLAT=$ATF_PLATFORM bl31
}
post_make_target() {
cp -av build/$ATF_PLATFORM/release/bl31.bin .
}

View File

@ -11,6 +11,8 @@ PKG_LONGDESC="Das U-Boot is a cross-platform bootloader for embedded systems."
PKG_IS_KERNEL_PKG="yes"
PKG_STAMP="$UBOOT_SYSTEM"
[ -n "$ATF_PLATFORM" ] && PKG_DEPENDS_TARGET+=" atf"
PKG_NEED_UNPACK="$PROJECT_DIR/$PROJECT/bootloader"
[ -n "$DEVICE" ] && PKG_NEED_UNPACK+=" $PROJECT_DIR/$PROJECT/devices/$DEVICE/bootloader"
@ -24,8 +26,8 @@ case "$PROJECT" in
PKG_NEED_UNPACK+=" $(get_pkg_directory rkbin)"
;;
*)
PKG_VERSION="2018.09"
PKG_SHA256="839bf23cfe8ce613a77e583a60375179d0ad324e92c82fbdd07bebf0fd142268"
PKG_VERSION="2019.01"
PKG_SHA256="50bd7e5a466ab828914d080d5f6a432345b500e8fba1ad3b7b61e95e60d51c22"
PKG_URL="http://ftp.denx.de/pub/u-boot/u-boot-$PKG_VERSION.tar.bz2"
;;
esac
@ -36,9 +38,10 @@ make_target() {
echo "see './scripts/uboot_helper' for more information"
else
[ "${BUILD_WITH_DEBUG}" = "yes" ] && PKG_DEBUG=1 || PKG_DEBUG=0
[ -n "$ATF_PLATFORM" ] && cp -av $(get_build_dir atf)/bl31.bin .
DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm make mrproper
DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm make $($ROOT/$SCRIPTS/uboot_helper $PROJECT $DEVICE $UBOOT_SYSTEM config)
DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm make HOSTCC="$HOST_CC" HOSTSTRIP="true"
DEBUG=${PKG_DEBUG} CROSS_COMPILE="$TARGET_KERNEL_PREFIX" LDFLAGS="" ARCH=arm _python_sysroot="$TOOLCHAIN" _python_prefix=/ _python_exec_prefix=/ make HOSTCC="$HOST_CC" HOSTLDFLAGS="-L$TOOLCHAIN/lib" HOSTSTRIP="true"
fi
}

View File

@ -1,25 +0,0 @@
diff --git a/dts/Kconfig b/dts/Kconfig
index 0cef225ba9..e4e3455d4c 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -13,7 +13,6 @@ config PYLIBFDT
config DTOC
bool
- select PYLIBFDT
config BINMAN
bool
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index dbc338653b..04f3c5935c 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -10,7 +10,7 @@ import struct
import sys
import fdt_util
-import libfdt
+from pylibfdt import libfdt
from libfdt import QUIET_NOTFOUND
# This deals with a device tree, presenting it as an assortment of Node and

View File

@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
cp -av u-boot-sunxi-with-spl.bin $INSTALL/usr/share/bootloader

View File

@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
if [ -f "$RELEASE_DIR/3rdparty/bootloader/u-boot-sunxi-with-spl.bin" ]; then
echo "Writing U-Boot to $(basename $DISK)"
dd if="$RELEASE_DIR/3rdparty/bootloader/u-boot-sunxi-with-spl.bin" of="$DISK" bs=1K seek=8 conv=fsync,notrunc >"$SAVE_ERROR" 2>&1 || show_error
fi

View File

@ -0,0 +1,38 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
[ -z "$BOOT_ROOT" ] && BOOT_ROOT="/flash"
[ -z "$BOOT_PART" ] && BOOT_PART=$(df "$BOOT_ROOT" | tail -1 | awk {' print $1 '})
if [ -z "$BOOT_DISK" ]; then
case $BOOT_PART in
/dev/sd[a-z][0-9]*)
BOOT_DISK=$(echo $BOOT_PART | sed -e "s,[0-9]*,,g")
;;
/dev/mmcblk*)
BOOT_DISK=$(echo $BOOT_PART | sed -e "s,p[0-9]*,,g")
;;
esac
fi
# mount $BOOT_ROOT r/w
mount -o remount,rw $BOOT_ROOT
# update Device Tree Blobs
for all_dtb in /flash/*.dtb; do
dtb=$(basename $all_dtb)
if [ -f $SYSTEM_ROOT/usr/share/bootloader/$dtb ]; then
echo "*** updating Device Tree Blob: $dtb ..."
cp -p $SYSTEM_ROOT/usr/share/bootloader/$dtb $BOOT_ROOT
fi
done
# update bootloader files
if [ -f $SYSTEM_ROOT/usr/share/bootloader/u-boot-sunxi-with-spl.bin ]; then
echo "*** updating U-Boot on: $BOOT_DISK ..."
dd if=$SYSTEM_ROOT/usr/share/bootloader/u-boot-sunxi-with-spl.bin of="$BOOT_DISK" bs=1k seek=8 conv=fsync &>/dev/null
fi
# mount $BOOT_ROOT r/o
sync
mount -o remount,ro $BOOT_ROOT

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
mkdir -p $RELEASE_DIR/3rdparty/bootloader
if [ -n "$UBOOT_SYSTEM" ]; then
cp -a $(get_build_dir $BOOTLOADER)/u-boot-sunxi-with-spl.bin $RELEASE_DIR/3rdparty/bootloader
fi
cp -a $(get_build_dir linux)/arch/$TARGET_KERNEL_ARCH/boot/dts/allwinner/sun50i-a64-*.dtb $RELEASE_DIR/3rdparty/bootloader

View File

@ -0,0 +1,36 @@
#
# Configuration for H3 analog output
#
<confdir:pcm/front.conf>
sun50i-a64-audi.pcm.front.0 {
@args [ CARD ]
@args.CARD {
type string
}
type hooks
slave.pcm {
type hw
card $CARD
}
hooks.0 {
type ctl_elems
hook_args [
{
name "Line Out Playback Volume"
lock true
preserve true
optional false
value 31
}
{
name "Line Out Playback Switch"
lock true
preserve true
optional false
value [ on on ]
}
]
}
}

View File

@ -0,0 +1,35 @@
################################################################################
# setup system defaults
################################################################################
# The TARGET_CPU variable controls which processor should be targeted for
# generated code.
case $TARGET_ARCH in
aarch64)
TARGET_CPU="cortex-a53"
TARGET_CPU_FLAGS="+crc+crypto"
TARGET_FEATURES="64bit"
TARGET_KERNEL_ARCH="arm64"
;;
arm)
TARGET_KERNEL_ARCH="arm64"
TARGET_PATCH_ARCH="aarch64"
TARGET_FLOAT="hard"
TARGET_CPU="cortex-a53"
TARGET_CPU_FLAGS="+crc"
TARGET_FPU="crypto-neon-fp-armv8"
TARGET_FEATURES="32bit"
;;
esac
# Kernel target
KERNEL_TARGET="Image"
# ATF platform
ATF_PLATFORM="sun50i_a64"
# additional drivers to install:
ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS gpu-sunxi"
# Mali GPU family
MALI_FAMILY="400"

View File

@ -0,0 +1,48 @@
Date: Sun, 3 Dec 2017 11:43:08 -0800
Subject: [PATCH] Add A64 HDMI sound node
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 29 +++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 0f69f35939755..0b44018361cbf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -727,6 +727,36 @@
status = "disabled";
};
+ i2s2: i2s@1c22800 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-i2s";
+ reg = <0x01c22800 0x400>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 27>;
+ resets = <&ccu RST_BUS_I2S2>;
+ dma-names = "tx";
+ allwinner,playback-channels = <8>;
+ };
+
+ sound_hdmi: sound_hdmi {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "allwinner-hdmi";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s2>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ };
+ };
+
rtc: rtc@1f00000 {
compatible = "allwinner,sun6i-a31-rtc";
reg = <0x01f00000 0x54>;

View File

@ -0,0 +1,11 @@
diff -Nur a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 2018-11-17 18:26:20.000000000 +0100
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 2018-11-17 19:29:15.132911602 +0100
@@ -892,6 +892,7 @@
};
hdmi: hdmi@1ee0000 {
+ #sound-dai-cells = <0>;
compatible = "allwinner,sun50i-a64-dw-hdmi",
"allwinner,sun8i-a83t-dw-hdmi";
reg = <0x01ee0000 0x10000>;

View File

@ -0,0 +1,135 @@
From c642dca33a893b38770003f92de5708b2ef82878 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 10 Jan 2019 20:00:25 +0100
Subject: [PATCH 1/4] media: dt: bindings: sunxi-ir: Add A64 compatible
A64 IR is compatible with A13, so add A64 compatible with A13 as a
fallback.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/media/sunxi-ir.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt
index 278098987edb..ecac6964b69b 100644
--- a/Documentation/devicetree/bindings/media/sunxi-ir.txt
+++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt
@@ -1,7 +1,10 @@
Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
Required properties:
-- compatible : "allwinner,sun4i-a10-ir" or "allwinner,sun5i-a13-ir"
+- compatible : value must be one of:
+ * "allwinner,sun4i-a10-ir"
+ * "allwinner,sun5i-a13-ir"
+ * "allwinner,sun50i-a64-ir", "allwinner,sun5i-a13-ir"
- clocks : list of clock specifiers, corresponding to
entries in clock-names property;
- clock-names : should contain "apb" and "ir" entries;
--
2.20.1
From 85923b765bbd31be033a7b7d8bf0018accb386dd Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 10 Jan 2019 20:50:15 +0100
Subject: [PATCH 2/4] arm64: dts: allwinner: a64: Add IR pinmux
IR on A64 has a dedicated pin. Add pinmux setting for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 839b2ae88583..86ff1d3a4ffa 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -1043,6 +1043,11 @@
function = "s_i2c";
};
+ r_ir_pins: ir-pins {
+ pins = "PL11";
+ function = "s_cir_rx";
+ };
+
r_pwm_pin: pwm {
pins = "PL10";
function = "s_pwm";
--
2.20.1
From 943855104927268a641bd4f5f35c0592398e39ec Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 10 Jan 2019 20:19:32 +0100
Subject: [PATCH 3/4] arm64: dts: allwinner: a64: Add IR node
IR is similar to that in A13 and can use same driver.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 86ff1d3a4ffa..8238caedd90e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -1004,6 +1004,17 @@
status = "disabled";
};
+ r_ir: ir@1f02000 {
+ compatible = "allwinner,sun50i-a64-ir",
+ "allwinner,sun5i-a13-ir";
+ reg = <0x01f02000 0x400>;
+ clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_APB0_IR>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
r_i2c: i2c@1f02400 {
compatible = "allwinner,sun50i-a64-i2c",
"allwinner,sun6i-a31-i2c";
--
2.20.1
From 3020e7d85fe574cda8e6803330ffd75fffdbbf6b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 10 Jan 2019 20:25:18 +0100
Subject: [PATCH 4/4] arm64: dts: allwinner: a64: Orange Pi Win: Enable IR
OrangePi Win board contains IR receiver. Enable it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
index b0c64f75792c..c6c759511f5e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
@@ -144,6 +144,12 @@
};
};
+&r_ir {
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_ir_pins>;
+ status = "okay";
+};
+
&mdio {
ext_rgmii_phy: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
--
2.20.1

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
mkdir -p $RELEASE_DIR/3rdparty/bootloader
if [ -n "$UBOOT_SYSTEM" ]; then
cp -a $(get_build_dir $BOOTLOADER)/u-boot-sunxi-with-spl.bin $RELEASE_DIR/3rdparty/bootloader
fi
cp -a $(get_build_dir linux)/arch/$TARGET_KERNEL_ARCH/boot/dts/sun8i-h3-*.dtb $RELEASE_DIR/3rdparty/bootloader

View File

@ -0,0 +1,36 @@
#
# Configuration for H3 analog output
#
<confdir:pcm/front.conf>
H3_Audio_Codec.pcm.front.0 {
@args [ CARD ]
@args.CARD {
type string
}
type hooks
slave.pcm {
type hw
card $CARD
}
hooks.0 {
type ctl_elems
hook_args [
{
name "Line Out Playback Volume"
lock true
preserve true
optional false
value 31
}
{
name "Line Out Playback Switch"
lock true
preserve true
optional false
value [ on on ]
}
]
}
}

View File

@ -0,0 +1,44 @@
################################################################################
# setup system defaults
################################################################################
# The TARGET_CPU variable controls which processor should be targeted for
# generated code.
case $TARGET_ARCH in
arm)
# TARGET_CPU:
# arm2 arm250 arm3 arm6 arm60 arm600 arm610 arm620 arm7 arm7m arm7d
# arm7dm arm7di arm7dmi arm70 arm700 arm700i arm710 arm710c
# arm7100 arm720 arm7500 arm7500fe arm7tdmi arm7tdmi-s arm710t
# arm720t arm740t strongarm strongarm110 strongarm1100
# strongarm1110 arm8 arm810 arm9 arm9e arm920 arm920t arm922t
# arm946e-s arm966e-s arm968e-s arm926ej-s arm940t arm9tdmi
# arm10tdmi arm1020t arm1026ej-s arm10e arm1020e arm1022e
# arm1136j-s arm1136jf-s mpcore mpcorenovfp arm1156t2-s
# arm1176jz-s arm1176jzf-s cortex-a8 cortex-a9 cortex-r4
# cortex-r4f cortex-m3 cortex-m1 xscale iwmmxt iwmmxt2 ep9312.
TARGET_CPU="cortex-a7"
# TARGET_FLOAT:
# Specifies which floating-point ABI to use. Permissible values are:
# soft softfp hard
TARGET_FLOAT="hard"
# TARGET_FPU:
# This specifies what floating point hardware (or hardware emulation) is
# available on the target. Permissible names are:
# fpa fpe2 fpe3 maverick vfp vfpv3 vfpv3-fp16 vfpv3-d16 vfpv3-d16-fp16
# vfpv3xd vfpv3xd-fp16 neon neon-fp16 vfpv4 vfpv4-d16 fpv4-sp-d16
# neon-vfpv4.
TARGET_FPU="neon-vfpv4"
;;
esac
# Kernel target
KERNEL_TARGET="zImage"
# additional drivers to install:
ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS gpu-sunxi"
# Mali GPU family
MALI_FAMILY="400"

View File

@ -0,0 +1,56 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 8aa2befc..d3d70eac 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -53,6 +53,23 @@
#address-cells = <1>;
#size-cells = <1>;
+ sound_hdmi: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "allwinner-hdmi";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s2>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ };
+ };
+
clocks {
#address-cells = <1>;
#size-cells = <1>;
@@ -631,6 +648,19 @@
status = "disabled";
};
+ i2s2: i2s@1c22800 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-i2s";
+ reg = <0x01c22800 0x400>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 27>;
+ resets = <&ccu RST_BUS_I2S2>;
+ dma-names = "tx";
+ allwinner,playback-channels = <8>;
+ };
+
codec: codec@1c22c00 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun8i-h3-codec";
@@ -110,6 +126,7 @@
};
hdmi: hdmi@1ee0000 {
+ #sound-dai-cells = <0>;
compatible = "allwinner,sun8i-h3-dw-hdmi",
"allwinner,sun8i-a83t-dw-hdmi";
reg = <0x01ee0000 0x10000>;

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
mkdir -p $RELEASE_DIR/3rdparty/bootloader
if [ -n "$UBOOT_SYSTEM" ]; then
cp -a $(get_build_dir $BOOTLOADER)/u-boot-sunxi-with-spl.bin $RELEASE_DIR/3rdparty/bootloader
fi
cp -a $(get_build_dir linux)/arch/$TARGET_KERNEL_ARCH/boot/dts/allwinner/sun50i-h6-*.dtb $RELEASE_DIR/3rdparty/bootloader

View File

@ -0,0 +1,35 @@
################################################################################
# setup system defaults
################################################################################
# The TARGET_CPU variable controls which processor should be targeted for
# generated code.
case $TARGET_ARCH in
aarch64)
TARGET_CPU="cortex-a53"
TARGET_CPU_FLAGS="+crc+crypto"
TARGET_FEATURES="64bit"
TARGET_KERNEL_ARCH="arm64"
;;
arm)
TARGET_KERNEL_ARCH="arm64"
TARGET_PATCH_ARCH="aarch64"
TARGET_FLOAT="hard"
TARGET_CPU="cortex-a53"
TARGET_CPU_FLAGS="+crc"
TARGET_FPU="crypto-neon-fp-armv8"
TARGET_FEATURES="32bit"
;;
esac
# Kernel target
KERNEL_TARGET="Image"
# ATF platform
ATF_PLATFORM="sun50i_h6"
# additional drivers to install:
ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS gpu-sunxi-midgard"
# Mali GPU family
MALI_FAMILY="t720"

View File

@ -0,0 +1,111 @@
diff -Nur a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi 2018-03-28 20:27:22.000000000 +0200
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi 2018-04-16 19:28:43.842331161 +0200
@@ -35,6 +35,72 @@
};
};
+ gpu_opp_table: opp_table1 {
+ compatible = "operating-points-v2",
+ "operating-points-v2-mali";
+
+ opp@756000000 {
+ opp-hz = /bits/ 64 <756000000>;
+ opp-microvolt = <1040000>;
+ };
+ opp@624000000 {
+ opp-hz = /bits/ 64 <624000000>;
+ opp-microvolt = <950000>;
+ };
+ opp@576000000 {
+ opp-hz = /bits/ 64 <576000000>;
+ opp-microvolt = <930000>;
+ };
+ opp@540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ opp-microvolt = <910000>;
+ };
+ opp@504000000 {
+ opp-hz = /bits/ 64 <504000000>;
+ opp-microvolt = <890000>;
+ };
+ opp@456000000 {
+ opp-hz = /bits/ 64 <456000000>;
+ opp-microvolt = <870000>;
+ };
+ opp@432000000 {
+ opp-hz = /bits/ 64 <432000000>;
+ opp-microvolt = <860000>;
+ };
+ opp@420000000 {
+ opp-hz = /bits/ 64 <420000000>;
+ opp-microvolt = <850000>;
+ };
+ opp@408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <840000>;
+ };
+ opp@384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-microvolt = <830000>;
+ };
+ opp@360000000 {
+ opp-hz = /bits/ 64 <360000000>;
+ opp-microvolt = <820000>;
+ };
+ opp@336000000 {
+ opp-hz = /bits/ 64 <336000000>;
+ opp-microvolt = <810000>;
+ };
+ opp@312000000 {
+ opp-hz = /bits/ 64 <312000000>;
+ opp-microvolt = <810000>;
+ };
+ opp@264000000 {
+ opp-hz = /bits/ 64 <264000000>;
+ opp-microvolt = <810000>;
+ };
+ opp@216000000 {
+ opp-hz = /bits/ 64 <216000000>;
+ opp-microvolt = <810000>;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -162,6 +228,20 @@
};
};
+ gpu: gpu@1800000 {
+ compatible = "arm,malit720", "arm,malit72x", "arm,malit7xx", "arm,mali-midgard";
+ reg = <0x01800000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "JOB", "MMU", "GPU";
+
+ clocks = <&ccu CLK_GPU>, <&ccu CLK_BUS_GPU>;
+ clock-names = "clk_mali", "clk_bus_mali";
+ resets = <&ccu RST_BUS_GPU>;
+ operating-points-v2 = <&gpu_opp_table>;
+ };
+
syscon: syscon@3000000 {
compatible = "allwinner,sun50i-h6-system-controller",
"syscon";
diff -Nur a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts 2018-03-28 20:27:22.000000000 +0200
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts 2018-04-14 15:34:15.545094216 +0200
@@ -89,6 +89,10 @@
status = "okay";
};
+&gpu {
+ mali-supply = <&reg_dcdcc>;
+};
+
&hdmi {
status = "okay";
};

View File

@ -0,0 +1,13 @@
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index 8a81f764abd0..46b72f2ed5cd 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -288,7 +288,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
0, 3, /* M */
24, 1, /* mux */
BIT(31), /* gate */
- 0);
+ CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
0x67c, BIT(0), 0);

View File

@ -0,0 +1,240 @@
From ed19ec00d4d62a74857ad9c2ea1dbf9671ac3580 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 28 Jan 2019 19:36:54 +0100
Subject: [PATCH 1/6] dt-bindings: media: cedrus: Add H6 compatible
This adds a compatible for H6. H6 VPU supports 10-bit HEVC decoding and
additional AFBC output format for HEVC.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/media/cedrus.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/media/cedrus.txt b/Documentation/devicetree/bindings/media/cedrus.txt
index bce0705df953..20c82fb0c343 100644
--- a/Documentation/devicetree/bindings/media/cedrus.txt
+++ b/Documentation/devicetree/bindings/media/cedrus.txt
@@ -13,6 +13,7 @@ Required properties:
- "allwinner,sun8i-h3-video-engine"
- "allwinner,sun50i-a64-video-engine"
- "allwinner,sun50i-h5-video-engine"
+ - "allwinner,sun50i-h6-video-engine"
- reg : register base and length of VE;
- clocks : list of clock specifiers, corresponding to entries in
the clock-names property;
--
2.20.1
From bb6b00e1225a5b382b723d3c2190429e15a4c607 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 28 Jan 2019 19:45:38 +0100
Subject: [PATCH 2/6] media: cedrus: Add a quirk for not setting DMA offset
H6 VPU doesn't work if DMA offset is set.
Add a quirk for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.h | 3 +++
drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index 4aedd24a9848..c57c04b41d2e 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -28,6 +28,8 @@
#define CEDRUS_CAPABILITY_UNTILED BIT(0)
+#define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0)
+
enum cedrus_codec {
CEDRUS_CODEC_MPEG2,
@@ -91,6 +93,7 @@ struct cedrus_dec_ops {
struct cedrus_variant {
unsigned int capabilities;
+ unsigned int quirks;
};
struct cedrus_dev {
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 0acf219a8c91..fbfff7c1c771 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -177,7 +177,8 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
*/
#ifdef PHYS_PFN_OFFSET
- dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET;
+ if (!(variant->quirks & CEDRUS_QUIRK_NO_DMA_OFFSET))
+ dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET;
#endif
ret = of_reserved_mem_device_init(dev->dev);
--
2.20.1
From 744c66f8c328ef40b6fb246f8b9f2daa9cce4d9d Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 28 Jan 2019 19:47:33 +0100
Subject: [PATCH 3/6] media: cedrus: Add support for H6
H6 has improved VPU. It supports 10-bit HEVC decoding and AFBC output
format for HEVC.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index ff11cbeba205..b98add3cdedd 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -396,6 +396,11 @@ static const struct cedrus_variant sun50i_h5_cedrus_variant = {
.capabilities = CEDRUS_CAPABILITY_UNTILED,
};
+static const struct cedrus_variant sun50i_h6_cedrus_variant = {
+ .capabilities = CEDRUS_CAPABILITY_UNTILED | CEDRUS_CAPABILITY_H265_DEC,
+ .quirks = CEDRUS_QUIRK_NO_DMA_OFFSET,
+};
+
static const struct of_device_id cedrus_dt_match[] = {
{
.compatible = "allwinner,sun4i-a10-video-engine",
@@ -425,6 +430,10 @@ static const struct of_device_id cedrus_dt_match[] = {
.compatible = "allwinner,sun50i-h5-video-engine",
.data = &sun50i_h5_cedrus_variant,
},
+ {
+ .compatible = "allwinner,sun50i-h6-video-engine",
+ .data = &sun50i_h6_cedrus_variant,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, cedrus_dt_match);
--
2.20.1
From b4ca53c594950b80d71ac320b3505a303e7f6092 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 28 Jan 2019 20:05:47 +0100
Subject: [PATCH 4/6] dt-bindings: sram: sunxi: Add compatible for the H6 SRAM
C1
This introduces a new compatible for the H6 SRAM C1 section, that is
compatible with the SRAM C1 section as found on the A10.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/sram/sunxi-sram.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sram/sunxi-sram.txt b/Documentation/devicetree/bindings/sram/sunxi-sram.txt
index ab5a70bb9a64..380246a805f2 100644
--- a/Documentation/devicetree/bindings/sram/sunxi-sram.txt
+++ b/Documentation/devicetree/bindings/sram/sunxi-sram.txt
@@ -63,6 +63,7 @@ The valid sections compatible for H5 are:
The valid sections compatible for H6 are:
- allwinner,sun50i-h6-sram-c, allwinner,sun50i-a64-sram-c
+ - allwinner,sun50i-h6-sram-c1, allwinner,sun4i-a10-sram-c1
The valid sections compatible for F1C100s are:
- allwinner,suniv-f1c100s-sram-d, allwinner,sun4i-a10-sram-d
--
2.20.1
From 6a505c910b90581b2a980e52f9b6fcb03d234cb7 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 28 Jan 2019 19:53:30 +0100
Subject: [PATCH 5/6] arm64: dts: allwinner: h6: Add support for the SRAM C1
section
Add a node for H6 SRAM C1 section.
Manual calls it VE SRAM, but for consistency with older SoCs, SRAM C1
name is used.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index d93a7add67e7..247dc0a5ce89 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -167,6 +167,20 @@
reg = <0x0000 0x1e000>;
};
};
+
+ sram_c1: sram@1a00000 {
+ compatible = "mmio-sram";
+ reg = <0x01a00000 0x200000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x01a00000 0x200000>;
+
+ ve_sram: sram-section@0 {
+ compatible = "allwinner,sun50i-h6-sram-c1",
+ "allwinner,sun4i-a10-sram-c1";
+ reg = <0x000000 0x200000>;
+ };
+ };
};
ccu: clock@3001000 {
--
2.20.1
From c1b3128ac98c05c0afde4e6e065d6b1f2ae1dfa7 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 28 Jan 2019 19:59:27 +0100
Subject: [PATCH 6/6] arm64: dts: allwinner: h6: Add Video Engine node
This adds the Video engine node for H6. It can use whole DRAM range so
there is no need for reserved memory node.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 247dc0a5ce89..de4b7a1f1012 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -146,6 +146,17 @@
};
};
+ video-codec@1c0e000 {
+ compatible = "allwinner,sun50i-h6-video-engine";
+ reg = <0x01c0e000 0x2000>;
+ clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
+ <&ccu CLK_MBUS_VE>;
+ clock-names = "ahb", "mod", "ram";
+ resets = <&ccu RST_BUS_VE>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ allwinner,sram = <&ve_sram 1>;
+ };
+
syscon: syscon@3000000 {
compatible = "allwinner,sun50i-h6-system-control",
"allwinner,sun50i-a64-system-control";
--
2.20.1

View File

@ -0,0 +1,658 @@
From f04472a823847403fd9ea34915803c21b8c27175 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 26 Jan 2019 09:47:17 +0100
Subject: [PATCH 01/12] dt-bindings: arm64: allwinner: h6: Add binding for DMA
controller
DMA in H6 is similar to other DMA controller, except it is first which
supports more than 32 request sources and has 16 channels. It also needs
additional clock to be enabled.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/dma/sun6i-dma.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 7fccc20d8331..cae31f4e77ba 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -28,12 +28,17 @@ Example:
};
------------------------------------------------------------------------------
-For A64 DMA controller:
+For A64 and H6 DMA controller:
Required properties:
-- compatible: "allwinner,sun50i-a64-dma"
+- compatible: Must be one of
+ "allwinner,sun50i-a64-dma"
+ "allwinner,sun50i-h6-dma"
- dma-channels: Number of DMA channels supported by the controller.
Refer to Documentation/devicetree/bindings/dma/dma.txt
+- clocks: In addition to parent AHB clock, it should also contain mbus
+ clock (H6 only)
+- clock-names: Should contain "bus" and "mbus" (H6 only)
- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
Optional properties:
--
2.20.1
From 638f21d14b0f22c7e9709edb4ac7b52f0e2a744e Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 26 Jan 2019 09:55:38 +0100
Subject: [PATCH 02/12] dmaengine: sun6i: Add a quirk for additional mbus clock
H6 DMA controller needs additional mbus clock to be enabled.
Add a quirk for it and handle it accordingly.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 0cd13f17fc11..761555080325 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -129,6 +129,7 @@ struct sun6i_dma_config {
u32 dst_burst_lengths;
u32 src_addr_widths;
u32 dst_addr_widths;
+ bool mbus_clk;
};
/*
@@ -182,6 +183,7 @@ struct sun6i_dma_dev {
struct dma_device slave;
void __iomem *base;
struct clk *clk;
+ struct clk *clk_mbus;
int irq;
spinlock_t lock;
struct reset_control *rstc;
@@ -1208,6 +1210,14 @@ static int sun6i_dma_probe(struct platform_device *pdev)
return PTR_ERR(sdc->clk);
}
+ if (sdc->cfg->mbus_clk) {
+ sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
+ if (IS_ERR(sdc->clk_mbus)) {
+ dev_err(&pdev->dev, "No mbus clock specified\n");
+ return PTR_ERR(sdc->clk_mbus);
+ }
+ }
+
sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(sdc->rstc)) {
dev_err(&pdev->dev, "No reset controller specified\n");
@@ -1312,11 +1322,19 @@ static int sun6i_dma_probe(struct platform_device *pdev)
goto err_reset_assert;
}
+ if (sdc->cfg->mbus_clk) {
+ ret = clk_prepare_enable(sdc->clk_mbus);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't enable mbus clock\n");
+ goto err_clk_disable;
+ }
+ }
+
ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
dev_name(&pdev->dev), sdc);
if (ret) {
dev_err(&pdev->dev, "Cannot request IRQ\n");
- goto err_clk_disable;
+ goto err_mbus_clk_disable;
}
ret = dma_async_device_register(&sdc->slave);
@@ -1341,6 +1359,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
dma_async_device_unregister(&sdc->slave);
err_irq_disable:
sun6i_kill_tasklet(sdc);
+err_mbus_clk_disable:
+ clk_disable_unprepare(sdc->clk_mbus);
err_clk_disable:
clk_disable_unprepare(sdc->clk);
err_reset_assert:
@@ -1359,6 +1379,7 @@ static int sun6i_dma_remove(struct platform_device *pdev)
sun6i_kill_tasklet(sdc);
+ clk_disable_unprepare(sdc->clk_mbus);
clk_disable_unprepare(sdc->clk);
reset_control_assert(sdc->rstc);
--
2.20.1
From 74a1f9f2f199e9b23ce0b9710efabbaee82f5605 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 26 Jan 2019 12:51:35 +0100
Subject: [PATCH 03/12] dmaengine: sun6i: Add a quirk for setting DRQ fields
H6 DMA has more than 32 possible DRQs. That means that current maximum
of 31 DRQs is not enough anymore.
Add a quirk which will set source and destination DRQ number.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/dma/sun6i-dma.c | 48 ++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 20 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 761555080325..9dd23b76d841 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,15 +68,15 @@
#define DMA_CHAN_LLI_ADDR 0x08
#define DMA_CHAN_CUR_CFG 0x0c
-#define DMA_CHAN_MAX_DRQ 0x1f
-#define DMA_CHAN_CFG_SRC_DRQ(x) ((x) & DMA_CHAN_MAX_DRQ)
+#define DMA_CHAN_MAX_DRQ_A31 0x1f
+#define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
#define DMA_CHAN_CFG_SRC_IO_MODE BIT(5)
#define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5)
#define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
#define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
-#define DMA_CHAN_CFG_DST_DRQ(x) (DMA_CHAN_CFG_SRC_DRQ(x) << 16)
+#define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
#define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16)
#define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
#define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
@@ -125,6 +125,7 @@ struct sun6i_dma_config {
*/
void (*clock_autogate_enable)(struct sun6i_dma_dev *);
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+ void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
u32 src_burst_lengths;
u32 dst_burst_lengths;
u32 src_addr_widths;
@@ -311,6 +312,12 @@ static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
}
+static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_DRQ_A31(src_drq) |
+ DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -634,14 +641,13 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
burst = convert_burst(8);
width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
- v_lli->cfg = DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_LINEAR_MODE |
+ v_lli->cfg = DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
DMA_CHAN_CFG_SRC_WIDTH(width) |
DMA_CHAN_CFG_DST_WIDTH(width);
sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
+ sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, DRQ_SDRAM);
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
@@ -695,9 +701,8 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
v_lli->dst = sconfig->dst_addr;
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -710,9 +715,8 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
v_lli->dst = sg_dma_address(sg);
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE |
- DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_IO_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -780,17 +784,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
v_lli->dst = sconfig->dst_addr;
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
} else {
v_lli->src = sconfig->src_addr;
v_lli->dst = buf_addr + period_len * i;
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE |
- DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_IO_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
}
prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
@@ -1055,6 +1057,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_requests = 30,
.nr_max_vchans = 53,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1076,6 +1079,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_vchans = 37,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1092,6 +1096,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_vchans = 39,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1115,6 +1120,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans = 34,
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1134,6 +1140,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
static struct sun6i_dma_config sun50i_a64_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1157,6 +1164,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.nr_max_vchans = 24,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1272,8 +1280,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
if (ret && !sdc->max_request) {
dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
- DMA_CHAN_MAX_DRQ);
- sdc->max_request = DMA_CHAN_MAX_DRQ;
+ DMA_CHAN_MAX_DRQ_A31);
+ sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
}
/*
--
2.20.1
From 20465d9f33a6686cc283f5874428d80fbce29f46 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 26 Jan 2019 13:35:02 +0100
Subject: [PATCH 04/12] dmaengine: sun6i: Add a quirk for setting mode fields
H6 DMA has mode fields in different position than any other currently
supported DMA controller.
Add a quirk for that.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/dma/sun6i-dma.c | 46 ++++++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 9dd23b76d841..6a37f8bb39b1 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -70,15 +70,13 @@
#define DMA_CHAN_CUR_CFG 0x0c
#define DMA_CHAN_MAX_DRQ_A31 0x1f
#define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
-#define DMA_CHAN_CFG_SRC_IO_MODE BIT(5)
-#define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5)
+#define DMA_CHAN_CFG_SRC_MODE_A31(x) (((x) & 0x1) << 5)
#define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
#define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
#define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
-#define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16)
-#define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
+#define DMA_CHAN_CFG_DST_MODE_A31(x) (DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
#define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
@@ -98,6 +96,8 @@
#define LLI_LAST_ITEM 0xfffff800
#define NORMAL_WAIT 8
#define DRQ_SDRAM 1
+#define LINEAR_MODE 0
+#define IO_MODE 1
/* forward declaration */
struct sun6i_dma_dev;
@@ -126,6 +126,7 @@ struct sun6i_dma_config {
void (*clock_autogate_enable)(struct sun6i_dma_dev *);
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
+ void (*set_mode)(u32 *p_cfg, s8 src_mode, s8 dst_mode);
u32 src_burst_lengths;
u32 dst_burst_lengths;
u32 src_addr_widths;
@@ -318,6 +319,12 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
}
+static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
+ DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -641,13 +648,12 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
burst = convert_burst(8);
width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
- v_lli->cfg = DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_WIDTH(width) |
+ v_lli->cfg = DMA_CHAN_CFG_SRC_WIDTH(width) |
DMA_CHAN_CFG_DST_WIDTH(width);
sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, DRQ_SDRAM);
+ sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, LINEAR_MODE);
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
@@ -699,10 +705,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
if (dir == DMA_MEM_TO_DEV) {
v_lli->src = sg_dma_address(sg);
v_lli->dst = sconfig->dst_addr;
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
+ sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -713,10 +718,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
} else {
v_lli->src = sconfig->src_addr;
v_lli->dst = sg_dma_address(sg);
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
+ sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -782,17 +786,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
if (dir == DMA_MEM_TO_DEV) {
v_lli->src = buf_addr + period_len * i;
v_lli->dst = sconfig->dst_addr;
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
+ sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE);
} else {
v_lli->src = sconfig->src_addr;
v_lli->dst = buf_addr + period_len * i;
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
+ sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE);
}
prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
@@ -1058,6 +1060,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_vchans = 53,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1080,6 +1083,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1097,6 +1101,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1121,6 +1126,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1141,6 +1147,7 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1165,6 +1172,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
--
2.20.1
From 7d4d497a1c5395d452930fdf0177f82520c09066 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 26 Jan 2019 13:50:24 +0100
Subject: [PATCH 05/12] dmaengine: sun6i: Add support for H6 DMA
H6 DMA has more than 32 supported DRQs, which means that configuration
register is slightly rearranged. It also needs additional clock to be
enabled.
Add support for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 6a37f8bb39b1..eceedd139651 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -69,14 +69,19 @@
#define DMA_CHAN_CUR_CFG 0x0c
#define DMA_CHAN_MAX_DRQ_A31 0x1f
+#define DMA_CHAN_MAX_DRQ_H6 0x3f
#define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
+#define DMA_CHAN_CFG_SRC_DRQ_H6(x) ((x) & DMA_CHAN_MAX_DRQ_H6)
#define DMA_CHAN_CFG_SRC_MODE_A31(x) (((x) & 0x1) << 5)
+#define DMA_CHAN_CFG_SRC_MODE_H6(x) (((x) & 0x1) << 8)
#define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
#define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
#define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_DRQ_H6(x) (DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
#define DMA_CHAN_CFG_DST_MODE_A31(x) (DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_MODE_H6(x) (DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
#define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
@@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
}
+static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
+ DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
+}
+
static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
{
*p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
}
+static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
+ DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
};
+/*
+ * The H6 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_h6_dma_cfg = {
+ .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+ .set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_h6,
+ .set_mode = sun6i_set_mode_h6,
+ .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .mbus_clk = true,
+};
+
/*
* The V3s have only 8 physical channels, a maximum DRQ port id of 23,
* and a total of 24 usable source and destination endpoints.
@@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
+ { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun6i_dma_match);
@@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
if (ret && !sdc->max_request) {
dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
- DMA_CHAN_MAX_DRQ_A31);
- sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
+ DMA_CHAN_MAX_DRQ_H6);
+ sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
}
/*
--
2.20.1
From b9d20d1b5577e4d73b47b9303798484f6699cfd4 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 26 Jan 2019 14:20:21 +0100
Subject: [PATCH 06/12] arm64: dts: allwinner: h6: Add DMA node
H6 has DMA controller which supports 16 channels.
Add a node for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index d93a7add67e7..62a0eae77639 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -178,6 +178,18 @@
#reset-cells = <1>;
};
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun50i-h6-dma";
+ reg = <0x03002000 0x1000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ dma-channels = <16>;
+ dma-requests = <46>;
+ resets = <&ccu RST_BUS_DMA>;
+ #dma-cells = <1>;
+ };
+
gic: interrupt-controller@3021000 {
compatible = "arm,gic-400";
reg = <0x03021000 0x1000>,
--
2.20.1

View File

@ -0,0 +1,142 @@
From 026ec1598d98a0bd45785a44a74ddb7063d2f776 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 22 Jan 2019 20:16:58 +0100
Subject: [PATCH] AW H6 I2S WIP
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 31 ++++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 8 ++---
sound/soc/sunxi/sun4i-i2s.c | 12 ++++----
3 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 62a0eae77639..f1c53aec6523 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -95,6 +95,23 @@
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
+ sound_hdmi: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "allwinner-hdmi";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ };
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -357,6 +374,19 @@
};
};
+ i2s1: i2s@5091000 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-i2s";
+ reg = <0x05091000 0x1000>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 4>;
+ resets = <&ccu RST_BUS_I2S1>;
+ dma-names = "tx";
+ allwinner,playback-channels = <8>;
+ };
+
usb2otg: usb@5100000 {
compatible = "allwinner,sun50i-h6-musb",
"allwinner,sun8i-a33-musb";
@@ -440,6 +470,7 @@
};
hdmi: hdmi@6000000 {
+ #sound-dai-cells = <0>;
compatible = "allwinner,sun50i-h6-dw-hdmi";
reg = <0x06000000 0x10000>;
reg-io-width = <1>;
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index 139e8389615c..bdb33266a3de 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -504,7 +504,7 @@ static struct ccu_div i2s3_clk = {
.hw.init = CLK_HW_INIT_PARENTS("i2s3",
audio_parents,
&ccu_div_ops,
- 0),
+ CLK_SET_RATE_PARENT),
},
};
@@ -517,7 +517,7 @@ static struct ccu_div i2s0_clk = {
.hw.init = CLK_HW_INIT_PARENTS("i2s0",
audio_parents,
&ccu_div_ops,
- 0),
+ CLK_SET_RATE_PARENT),
},
};
@@ -530,7 +530,7 @@ static struct ccu_div i2s1_clk = {
.hw.init = CLK_HW_INIT_PARENTS("i2s1",
audio_parents,
&ccu_div_ops,
- 0),
+ CLK_SET_RATE_PARENT),
},
};
@@ -543,7 +543,7 @@ static struct ccu_div i2s2_clk = {
.hw.init = CLK_HW_INIT_PARENTS("i2s2",
audio_parents,
&ccu_div_ops,
- 0),
+ CLK_SET_RATE_PARENT),
},
};
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index d5ec1a20499d..f286b8bfcfb3 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -108,12 +108,12 @@
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0)
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1)
-#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44
+#define SUN8I_I2S_TX_CHAN_MAP_REG 0x48
#define SUN8I_I2S_TX_CHAN_SEL_REG 0x34
-#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12)
-#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12)
-#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4)
-#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4)
+#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(21, 20)
+#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 20)
+#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(15, 0)
+#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 0)
#define SUN8I_I2S_RX_CHAN_SEL_REG 0x54
#define SUN8I_I2S_RX_CHAN_MAP_REG 0x58
@@ -946,7 +946,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
.field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5),
.field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31),
- .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2),
+ .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 16, 19),
.field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2),
};
--
2.21.0

View File

@ -0,0 +1,25 @@
From 18c9a269e2b744ee84f32de9d5c6c66857725ef8 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 12:56:53 +0100
Subject: [PATCH 20/20] cedrus increase frequency
---
drivers/staging/media/sunxi/cedrus/cedrus_hw.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index b43c77d54b95..70677571f3d3 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -16,7 +16,7 @@
#ifndef _CEDRUS_HW_H_
#define _CEDRUS_HW_H_
-#define CEDRUS_CLOCK_RATE_DEFAULT 402000000
+#define CEDRUS_CLOCK_RATE_DEFAULT 600000000
int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
void cedrus_engine_disable(struct cedrus_dev *dev);
--
2.20.0

View File

@ -0,0 +1,20 @@
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index caea5a9f8f1d..ba4ce576b471 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -48,8 +48,13 @@ static enum drm_mode_status
sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- /* This is max for HDMI 2.0b (4K@60Hz) */
- if (mode->clock > 594000)
+ /*
+ * Controller support maximum of 594 MHz, which correlates to
+ * 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
+ * 340 MHz scrambling has to be enabled. Because scrambling is
+ * not yet implemented, just limit to 340 MHz for now.
+ */
+ if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
return MODE_OK;

View File

@ -0,0 +1,96 @@
From 9413130f5b213551519c97482462a6daea9a5343 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 2 Apr 2019 19:32:01 +0200
Subject: [PATCH 1/2] clk: sunxi-ng: h6: Change CEC clock parent
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index daf78966555e..33980067b06e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -656,6 +656,8 @@ static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
{ .index = 1, .div = 36621 },
};
+
+#define SUN50I_H6_HDMI_CEC_CLK_REG 0xb10
static struct ccu_mux hdmi_cec_clk = {
.enable = BIT(31),
@@ -1200,6 +1202,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
val &= ~(GENMASK(21, 16) | BIT(0));
writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG);
+ /*
+ * First clock parent (osc32K) is unusable for CEC. But since there
+ * is no good way to force parent switch (both run with same frequency),
+ * just set second clock parent here.
+ */
+ val = readl(reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+
return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
}
--
2.21.0
From eab64a1ccf6b7cda339fdfdbfa9e1973e4cc0c85 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 2 Apr 2019 21:15:45 +0200
Subject: [PATCH 2/2] clk: sunxi-ng: h6: Allow video & vpu clocks to change
parent rate
Video related clocks need to set rate as close as possible to the
requested one, so they should be able to change parent clock rate.
VPU clock sometimes has to be set to higher than default parent clock
rate. This is requ
Add CLK_SET_RATE_PARENT flag to tcon-lcd0, tcon-tv0 and ve.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index 33980067b06e..3c32d7798f27 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -311,7 +311,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
0, 3, /* M */
24, 1, /* mux */
BIT(31), /* gate */
- 0);
+ CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
0x69c, BIT(0), 0);
@@ -691,7 +691,7 @@ static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0",
tcon_lcd0_parents, 0xb60,
24, 3, /* mux */
BIT(31), /* gate */
- 0);
+ CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb3",
0xb7c, BIT(0), 0);
@@ -706,7 +706,7 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
8, 2, /* P */
24, 3, /* mux */
BIT(31), /* gate */
- 0);
+ CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
0xb9c, BIT(0), 0);
--
2.21.0

View File

@ -0,0 +1,608 @@
diff --git a/arch/arm/dts/sun50i-h6-pine-h64.dts b/arch/arm/dts/sun50i-h6-pine-h64.dts
index ceffc40810..bdb8470fc8 100644
--- a/arch/arm/dts/sun50i-h6-pine-h64.dts
+++ b/arch/arm/dts/sun50i-h6-pine-h64.dts
@@ -14,6 +14,7 @@
compatible = "pine64,pine-h64", "allwinner,sun50i-h6";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -21,6 +22,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -39,6 +51,56 @@
gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
};
};
+
+ reg_usb_vbus: vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ startup-delay-us = <100000>;
+ gpio = <&r_pio 0 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-supply = <&reg_aldo2>;
+ allwinner,rx-delay-ps = <200>;
+ allwinner,tx-delay-ps = <200>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&de {
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
};
&mmc0 {
@@ -46,6 +108,7 @@
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
status = "okay";
};
@@ -56,6 +119,15 @@
vqmmc-supply = <&reg_bldo2>;
non-removable;
cap-mmc-hw-reset;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci3 {
status = "okay";
};
@@ -83,6 +155,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-ac200";
+ regulator-enable-ramp-delay = <100000>;
};
reg_aldo3: aldo3 {
@@ -183,3 +256,14 @@
pinctrl-0 = <&uart0_ph_pins>;
status = "okay";
};
+
+&usb2otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb2phy {
+ usb0_vbus-supply = <&reg_usb_vbus>;
+ usb3_vbus-supply = <&reg_usb_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h6.dtsi b/arch/arm/dts/sun50i-h6.dtsi
index cfa5fffcf6..c9e861a50a 100644
--- a/arch/arm/dts/sun50i-h6.dtsi
+++ b/arch/arm/dts/sun50i-h6.dtsi
@@ -6,8 +6,11 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/sun50i-h6-ccu.h>
#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
#include <dt-bindings/reset/sun50i-h6-ccu.h>
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
/ {
interrupt-parent = <&gic>;
@@ -19,34 +22,40 @@
#size-cells = <0>;
cpu0: cpu@0 {
- compatible = "arm,cortex-a53", "arm,armv8";
+ compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0>;
enable-method = "psci";
};
cpu1: cpu@1 {
- compatible = "arm,cortex-a53", "arm,armv8";
+ compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <1>;
enable-method = "psci";
};
cpu2: cpu@2 {
- compatible = "arm,cortex-a53", "arm,armv8";
+ compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <2>;
enable-method = "psci";
};
cpu3: cpu@3 {
- compatible = "arm,cortex-a53", "arm,armv8";
+ compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <3>;
enable-method = "psci";
};
};
+ de: display-engine {
+ compatible = "allwinner,sun50i-h6-display-engine";
+ allwinner,pipelines = <&mixer0>;
+ status = "disabled";
+ };
+
iosc: internal-osc-clk {
#clock-cells = <0>;
compatible = "fixed-clock";
@@ -92,6 +101,88 @@
#size-cells = <1>;
ranges;
+ display-engine@1000000 {
+ compatible = "allwinner,sun50i-h6-de3",
+ "allwinner,sun50i-a64-de2";
+ reg = <0x1000000 0x400000>;
+ allwinner,sram = <&de2_sram 1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1000000 0x400000>;
+
+ display_clocks: clock@0 {
+ compatible = "allwinner,sun50i-h6-de3-clk";
+ reg = <0x0 0x10000>;
+ clocks = <&ccu CLK_DE>,
+ <&ccu CLK_BUS_DE>;
+ clock-names = "mod",
+ "bus";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ mixer0: mixer@100000 {
+ compatible = "allwinner,sun50i-h6-de3-mixer-0";
+ reg = <0x100000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus",
+ "mod";
+ resets = <&display_clocks RST_MIXER0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ reg = <1>;
+
+ mixer0_out_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+ };
+ };
+ };
+ };
+ };
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun50i-h6-system-control",
+ "allwinner,sun50i-a64-system-control";
+ reg = <0x03000000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ sram_c: sram@28000 {
+ compatible = "mmio-sram";
+ reg = <0x00028000 0x1e000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00028000 0x1e000>;
+
+ de2_sram: sram-section@0 {
+ compatible = "allwinner,sun50i-h6-sram-c",
+ "allwinner,sun50i-a64-sram-c";
+ reg = <0x0000 0x1e000>;
+ };
+ };
+
+ sram_c1: sram@1a00000 {
+ compatible = "mmio-sram";
+ reg = <0x01a00000 0x200000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x01a00000 0x200000>;
+
+ ve_sram: sram-section@0 {
+ compatible = "allwinner,sun50i-h6-sram-c1",
+ "allwinner,sun4i-a10-sram-c1";
+ reg = <0x000000 0x200000>;
+ };
+ };
+ };
+
ccu: clock@3001000 {
compatible = "allwinner,sun50i-h6-ccu";
reg = <0x03001000 0x1000>;
@@ -101,17 +192,6 @@
#reset-cells = <1>;
};
- gic: interrupt-controller@3021000 {
- compatible = "arm,gic-400";
- reg = <0x03021000 0x1000>,
- <0x03022000 0x2000>,
- <0x03024000 0x2000>,
- <0x03026000 0x2000>;
- interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
- interrupt-controller;
- #interrupt-cells = <3>;
- };
-
pio: pinctrl@300b000 {
compatible = "allwinner,sun50i-h6-pinctrl";
reg = <0x0300b000 0x400>;
@@ -126,6 +206,19 @@
interrupt-controller;
#interrupt-cells = <3>;
+ ext_rgmii_pins: rgmii_pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4",
+ "PD5", "PD7", "PD8", "PD9", "PD10",
+ "PD11", "PD12", "PD13", "PD19", "PD20";
+ function = "emac";
+ drive-strength = <40>;
+ };
+
+ hdmi_pins: hdmi-pins {
+ pins = "PH8", "PH9", "PH10";
+ function = "hdmi";
+ };
+
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2", "PF3",
"PF4", "PF5";
@@ -149,6 +242,17 @@
};
};
+ gic: interrupt-controller@3021000 {
+ compatible = "arm,gic-400";
+ reg = <0x03021000 0x1000>,
+ <0x03022000 0x2000>,
+ <0x03024000 0x2000>,
+ <0x03026000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
mmc0: mmc@4020000 {
compatible = "allwinner,sun50i-h6-mmc",
"allwinner,sun50i-a64-mmc";
@@ -235,6 +339,250 @@
status = "disabled";
};
+ emac: ethernet@5020000 {
+ compatible = "allwinner,sun50i-h6-emac",
+ "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x05020000 0x10000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ usb2otg: usb@5100000 {
+ compatible = "allwinner,sun50i-h6-musb",
+ "allwinner,sun8i-a33-musb";
+ reg = <0x05100000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ phys = <&usb2phy 0>;
+ phy-names = "usb";
+ extcon = <&usb2phy 0>;
+ status = "disabled";
+ };
+
+ usb2phy: phy@5100400 {
+ compatible = "allwinner,sun50i-h6-usb-phy";
+ reg = <0x05100400 0x24>,
+ <0x05101800 0x4>,
+ <0x05311800 0x4>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu3";
+ clocks = <&ccu CLK_USB_PHY0>,
+ <&ccu CLK_USB_PHY3>;
+ clock-names = "usb0_phy",
+ "usb3_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY3>;
+ reset-names = "usb0_reset",
+ "usb3_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@5101000 {
+ compatible = "allwinner,sun50i-h6-ehci", "generic-ehci";
+ reg = <0x05101000 0x100>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ status = "disabled";
+ };
+
+ ohci0: usb@5101400 {
+ compatible = "allwinner,sun50i-h6-ohci", "generic-ohci";
+ reg = <0x05101400 0x100>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ status = "disabled";
+ };
+
+ ehci3: usb@5311000 {
+ compatible = "allwinner,sun50i-h6-ehci", "generic-ehci";
+ reg = <0x05311000 0x100>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI3>,
+ <&ccu CLK_BUS_EHCI3>,
+ <&ccu CLK_USB_OHCI3>;
+ resets = <&ccu RST_BUS_OHCI3>,
+ <&ccu RST_BUS_EHCI3>;
+ phys = <&usb2phy 3>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci3: usb@5311400 {
+ compatible = "allwinner,sun50i-h6-ohci", "generic-ohci";
+ reg = <0x05311400 0x100>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI3>,
+ <&ccu CLK_USB_OHCI3>;
+ resets = <&ccu RST_BUS_OHCI3>;
+ phys = <&usb2phy 3>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ hdmi: hdmi@6000000 {
+ compatible = "allwinner,sun50i-h6-dw-hdmi";
+ reg = <0x06000000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>,
+ <&ccu CLK_HDMI>, <&ccu CLK_HDMI_CEC>,
+ <&ccu CLK_HDCP>, <&ccu CLK_BUS_HDCP>;
+ clock-names = "iahb", "isfr", "tmds", "cec", "hdcp",
+ "hdcp-bus";
+ resets = <&ccu RST_BUS_HDMI_SUB>, <&ccu RST_BUS_HDCP>;
+ reset-names = "ctrl", "hdcp";
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pins>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port@0 {
+ reg = <0>;
+
+ hdmi_in_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ hdmi_phy: hdmi-phy@6010000 {
+ compatible = "allwinner,sun50i-h6-hdmi-phy";
+ reg = <0x06010000 0x10000>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_HDMI>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ };
+
+ tcon_top: tcon-top@6510000 {
+ compatible = "allwinner,sun50i-h6-tcon-top";
+ reg = <0x06510000 0x1000>;
+ clocks = <&ccu CLK_BUS_TCON_TOP>,
+ <&ccu CLK_TCON_TV0>;
+ clock-names = "bus",
+ "tcon-tv0";
+ clock-output-names = "tcon-top-tv0";
+ resets = <&ccu RST_BUS_TCON_TOP>;
+ reset-names = "rst";
+ #clock-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon_top_mixer0_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ tcon_top_mixer0_out_tcon_tv: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv_in_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_hdmi_in: port@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ tcon_top_hdmi_in_tcon_tv: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_tv_out_tcon_top>;
+ };
+ };
+
+ tcon_top_hdmi_out: port@5 {
+ reg = <5>;
+
+ tcon_top_hdmi_out_hdmi: endpoint {
+ remote-endpoint = <&hdmi_in_tcon_top>;
+ };
+ };
+ };
+ };
+
+ tcon_tv: lcd-controller@6515000 {
+ compatible = "allwinner,sun50i-h6-tcon-tv",
+ "allwinner,sun8i-r40-tcon-tv";
+ reg = <0x06515000 0x1000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV0>,
+ <&tcon_top CLK_TCON_TOP_TV0>;
+ clock-names = "ahb",
+ "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON_TV0>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv_in: port@0 {
+ reg = <0>;
+
+ tcon_tv_in_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv>;
+ };
+ };
+
+ tcon_tv_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ tcon_tv_out_tcon_top: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv>;
+ };
+ };
+ };
+ };
+
r_ccu: clock@7010000 {
compatible = "allwinner,sun50i-h6-r-ccu";
reg = <0x07010000 0x400>;
diff --git a/include/dt-bindings/clock/sun8i-tcon-top.h b/include/dt-bindings/clock/sun8i-tcon-top.h
new file mode 100644
index 0000000000..25164d7678
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-tcon-top.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/* Copyright (C) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_TCON_TOP_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_TCON_TOP_H_
+
+#define CLK_TCON_TOP_TV0 0
+#define CLK_TCON_TOP_TV1 1
+#define CLK_TCON_TOP_DSI 2
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_TCON_TOP_H_ */

View File

@ -0,0 +1,23 @@
[Unit]
Description=Debug Shell on /dev/console
DefaultDependencies=no
ConditionKernelCommandLine=console
[Service]
WorkingDirectory=/storage
Environment="ENV=/etc/profile"
ExecStartPre=/bin/sh -c 'echo -en "\033[?25h"'
ExecStart=/bin/sh
Restart=always
RestartSec=0
StandardInput=tty
TTYPath=/dev/console
TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
# bash ignores SIGTERM
KillSignal=SIGHUP
[Install]
WantedBy=sysinit.target

View File

@ -0,0 +1,34 @@
#
# Configuration for HDMI
#
<confdir:pcm/hdmi.conf>
allwinner-hdmi.pcm.hdmi.0 {
@args [ CARD AES0 AES1 AES2 AES3 ]
@args.CARD { type string }
@args.AES0 { type integer }
@args.AES1 { type integer }
@args.AES2 { type integer }
@args.AES3 { type integer }
type hooks
slave.pcm {
type hw
card $CARD
device 0
}
hooks.0 {
type ctl_elems
hook_args [
{
interface MIXER
name "IEC958 Playback Default"
lock true
preserve true
optional true
value [ $AES0 $AES1 $AES2 $AES3 ]
}
]
}
hint.device 0
}

View File

@ -0,0 +1,34 @@
#
# Configuration for SPDIF
#
<confdir:pcm/iec958.conf>
On-board_SPDIF.pcm.iec958.0 {
@args [ CARD AES0 AES1 AES2 AES3 ]
@args.CARD { type string }
@args.AES0 { type integer }
@args.AES1 { type integer }
@args.AES2 { type integer }
@args.AES3 { type integer }
type hooks
slave.pcm {
type hw
card $CARD
device 0
}
hooks.0 {
type ctl_elems
hook_args [
{
interface MIXER
name "IEC958 Playback Default"
lock true
preserve true
optional true
value [ $AES0 $AES1 $AES2 $AES3 ]
}
]
}
hint.device 0
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<settings version="1">
<section id="system">
<category id="display">
<group id="1">
<setting id="videoscreen.limitguisize">
<visible>false</visible>
<default>3</default>
</setting>
</group>
</category>
<category id="audio">
<group id="1">
<setting id="audiooutput.audiodevice">
<default>ALSA:hdmi:CARD=allwinnerhdmi,DEV=0</default>
</setting>
</group>
</category>
</section>
</settings>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
################################################################################
# setup system defaults
################################################################################
# Bootloader to use (syslinux / u-boot / bcm2835-bootloader)
BOOTLOADER="u-boot"
# u-boot version to use (default)
UBOOT_VERSION="default"
# Configuration for u-boot
UBOOT_CONFIG=""
# Target Configfile for u-boot
UBOOT_CONFIGFILE=""
# Kernel extra targets to build
KERNEL_UBOOT_EXTRA_TARGET=""
# Additional kernel make parameters (for example to specify the u-boot loadaddress)
KERNEL_MAKE_EXTRACMD="dtbs"
# Kernel to use. values can be:
# default: default mainline kernel
LINUX="default"
EXTRA_CMDLINE="console=ttyS0,115200 console=tty1"
################################################################################
# setup build defaults
################################################################################
# Project CFLAGS
PROJECT_CFLAGS=""
# SquashFS compression method (gzip / lzo / xz / zstd)
SQUASHFS_COMPRESSION="zstd"
################################################################################
# setup project defaults
################################################################################
# build and install ALSA Audio support (yes / no)
ALSA_SUPPORT="yes"
# OpenGL(X) implementation to use (no / mesa)
OPENGL="no"
# OpenGL-ES implementation to use (no / bcm2835-driver / gpu-viv-bin-mx6q)
OPENGLES="libmali"
# include uvesafb support (yes / no)
UVESAFB_SUPPORT="no"
# Displayserver to use (x11 / no)
DISPLAYSERVER="no"
# Windowmanager to use (ratpoison / fluxbox / none)
WINDOWMANAGER="none"
# Xorg Graphic drivers to use (all / i915,i965,r200,r300,r600,nvidia)
# Space separated list is supported,
# e.g. GRAPHIC_DRIVERS="i915 i965 r300 r600 radeonsi nvidia"
GRAPHIC_DRIVERS=""
# KODI Player implementation to use (default / bcm2835-driver / libfslvpuwrap)
KODIPLAYER_DRIVER="$OPENGLES"
# Modules to install in initramfs for early boot
INITRAMFS_MODULES=""
# additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware)
# Space separated list is supported,
# e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware"
FIRMWARE="misc-firmware wlan-firmware dvb-firmware"
# build and install ATV IR remote support (yes / no)
ATVCLIENT_SUPPORT="no"
# build and install CEC framework support (yes / no)
CEC_FRAMEWORK_SUPPORT="yes"
# build with installer (yes / no)
INSTALLER_SUPPORT="no"

View File

@ -0,0 +1,18 @@
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
index 3b0d0d832d..221f48f061 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
@@ -243,12 +362,6 @@ bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& optio
return false;
}
- if (m_pCodecContext->pix_fmt != AV_PIX_FMT_DRM_PRIME)
- {
- CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unexpected pix fmt %s", __FUNCTION__, av_get_pix_fmt_name(m_pCodecContext->pix_fmt));
- avcodec_free_context(&m_pCodecContext);
- return false;
- }
const char* pixFmtName = av_get_pix_fmt_name(m_pCodecContext->pix_fmt);
m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");

View File

@ -0,0 +1,153 @@
From 7a88b0ad7a90a8ac2266f87ccb08dca5df0c0867 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 14 Oct 2018 14:20:03 +0200
Subject: [PATCH] WIP: windowing/gbm: add option to limit gui size
---
.../resources/strings.po | 52 ++++++++++++++++++-
system/settings/gbm.xml | 15 ++++++
xbmc/windowing/gbm/DRMUtils.cpp | 28 ++++++++++
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 97211d3b718a..eaa5b3fed759 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -7256,7 +7256,57 @@ msgctxt "#13465"
msgid "EGL"
msgstr ""
-#empty strings from id 13466 to 13504
+#empty strings from id 13466 to 13485
+
+#. String for options 3 of setting with label #13482 "HDMI Quantization Range"
+#: system/settings/gbm.xml
+msgctxt "#13486"
+msgid "Limited"
+msgstr ""
+
+#. Option for setting Limit GUI Size
+#: system/settings/gbm.xml
+msgctxt "#13487"
+msgid "Limit GUI Size"
+msgstr ""
+
+#. Description of setting with label #13487 "Limit GUI Size"
+#: system/settings/gbm.xml
+msgctxt "#13488"
+msgid "This option limits GUI size for screen resolutions above 1080p. Requires restart."
+msgstr ""
+
+#. String for options 1 of setting with label #13487 "Limit GUI Size"
+#: system/settings/gbm.xml
+msgctxt "#13489"
+msgid "No limit"
+msgstr ""
+
+#. String for options 2 of setting with label #13487 "Limit GUI Size"
+#: system/settings/gbm.xml
+msgctxt "#13490"
+msgid "720p"
+msgstr ""
+
+#. String for options 3 of setting with label #13487 "Limit GUI Size"
+#: system/settings/gbm.xml
+msgctxt "#13491"
+msgid "1080p / 720p (>30hz)"
+msgstr ""
+
+#. String for options 4 of setting with label #13487 "Limit GUI Size"
+#: system/settings/gbm.xml
+msgctxt "#13492"
+msgid "1080p"
+msgstr ""
+
+#. String for options 5 of setting with label #13487 "Limit GUI Size"
+#: system/settings/gbm.xml
+msgctxt "#13493"
+msgid "No limit / 1080p (>30hz)"
+msgstr ""
+
+#empty strings from id 13494 to 13504
#: system/settings/settings.xml
msgctxt "#13505"
diff --git a/system/settings/gbm.xml b/system/settings/gbm.xml
index c5e4d98e0bef..830576c156a6 100644
--- a/system/settings/gbm.xml
+++ b/system/settings/gbm.xml
@@ -41,6 +41,21 @@
<setting id="videoscreen.screen">
<visible>false</visible>
</setting>
+ <setting id="videoscreen.limitguisize" type="integer" label="13487" help="13488">
+ <visible>false</visible>
+ <level>3</level>
+ <default>0</default>
+ <constraints>
+ <options>
+ <option label="13489">0</option> <!-- No limit -->
+ <option label="13490">1</option> <!-- 720p -->
+ <option label="13491">2</option> <!-- 1080p / 720p (>30hz) -->
+ <option label="13492">3</option> <!-- 1080p -->
+ <option label="13493">4</option> <!-- No limit / 1080p (>30hz) -->
+ </options>
+ </constraints>
+ <control type="list" format="string" />
+ </setting>
<setting id="videoscreen.limitedrange" type="boolean" label="36042" help="36359">
<level>3</level>
<default>false</default>
diff --git a/xbmc/windowing/gbm/DRMUtils.cpp b/xbmc/windowing/gbm/DRMUtils.cpp
index fceaf770d363..21a6f8f1b926 100644
--- a/xbmc/windowing/gbm/DRMUtils.cpp
+++ b/xbmc/windowing/gbm/DRMUtils.cpp
@@ -17,6 +17,8 @@
#include <unistd.h>
#include "platform/linux/XTimeUtils.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
#include "utils/log.h"
#include "utils/StringUtils.h"
#include "windowing/GraphicContext.h"
@@ -25,6 +27,8 @@
using namespace KODI::WINDOWING::GBM;
+const std::string SETTING_VIDEOSCREEN_LIMITGUISIZE = "videoscreen.limitguisize";
+
CDRMUtils::CDRMUtils()
: m_connector(new connector)
, m_encoder(new encoder)
@@ -731,6 +735,30 @@ RESOLUTION_INFO CDRMUtils::GetResolutionInfo(drmModeModeInfoPtr mode)
res.iWidth = res.iScreenWidth;
res.iHeight = res.iScreenHeight;
+ int limit = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(SETTING_VIDEOSCREEN_LIMITGUISIZE);
+ if (limit > 0 && res.iScreenWidth > 1920 && res.iScreenHeight > 1080)
+ {
+ switch (limit)
+ {
+ case 1:
+ res.iWidth = 1280;
+ res.iHeight = 720;
+ break;
+ case 2:
+ res.iWidth = mode->vrefresh > 30 ? 1280 : 1920;
+ res.iHeight = mode->vrefresh > 30 ? 720 : 1080;
+ break;
+ case 3:
+ res.iWidth = 1920;
+ res.iHeight = 1080;
+ break;
+ case 4:
+ res.iWidth = mode->vrefresh > 30 ? 1920 : res.iScreenWidth;
+ res.iHeight = mode->vrefresh > 30 ? 1080 : res.iScreenHeight;
+ break;
+ }
+ }
+
if (mode->clock % 5 != 0)
res.fRefreshRate = static_cast<float>(mode->vrefresh) * (1000.0f/1001.0f);
else

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,676 @@
From 2495f39ce1fa027aab0c3161c14f074295f81c71 Mon Sep 17 00:00:00 2001
From: Dafna Hirschfeld <dafna3@gmail.com>
Date: Wed, 6 Mar 2019 16:13:40 -0500
Subject: [PATCH] media: vicodec: Introducing stateless fwht defs and structs
Add structs and definitions needed to implement stateless
decoder for fwht and add I/P-frames QP controls to the
public api.
Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
drivers/media/platform/vicodec/vicodec-core.c | 41 ++++++-------------
drivers/media/v4l2-core/v4l2-ctrls.c | 12 ++++++
include/media/fwht-ctrls.h | 31 ++++++++++++++
include/media/v4l2-ctrls.h | 5 ++-
include/uapi/linux/v4l2-controls.h | 4 ++
include/uapi/linux/videodev2.h | 1 +
6 files changed, 65 insertions(+), 29 deletions(-)
create mode 100644 include/media/fwht-ctrls.h
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
index b86985babdb1..a3a9d8ac4a33 100644
--- a/drivers/media/platform/vicodec/vicodec-core.c
+++ b/drivers/media/platform/vicodec/vicodec-core.c
@@ -64,6 +64,10 @@ static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = {
V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1, 0, 1
};
+static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = {
+ V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1
+};
+
static void vicodec_dev_release(struct device *dev)
{
}
@@ -1524,10 +1528,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
return vb2_queue_init(dst_vq);
}
-#define VICODEC_CID_CUSTOM_BASE (V4L2_CID_MPEG_BASE | 0xf000)
-#define VICODEC_CID_I_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 0)
-#define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1)
-
static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct vicodec_ctx *ctx = container_of(ctrl->handler,
@@ -1537,10 +1537,10 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
ctx->state.gop_size = ctrl->val;
return 0;
- case VICODEC_CID_I_FRAME_QP:
+ case V4L2_CID_FWHT_I_FRAME_QP:
ctx->state.i_frame_qp = ctrl->val;
return 0;
- case VICODEC_CID_P_FRAME_QP:
+ case V4L2_CID_FWHT_P_FRAME_QP:
ctx->state.p_frame_qp = ctrl->val;
return 0;
}
@@ -1551,26 +1551,9 @@ static const struct v4l2_ctrl_ops vicodec_ctrl_ops = {
.s_ctrl = vicodec_s_ctrl,
};
-static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = {
- .ops = &vicodec_ctrl_ops,
- .id = VICODEC_CID_I_FRAME_QP,
- .name = "FWHT I-Frame QP Value",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 31,
- .def = 20,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = {
- .ops = &vicodec_ctrl_ops,
- .id = VICODEC_CID_P_FRAME_QP,
- .name = "FWHT P-Frame QP Value",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 31,
- .def = 20,
- .step = 1,
+static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = {
+ .id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS,
+ .elem_size = sizeof(struct v4l2_ctrl_fwht_params),
};
/*
@@ -1603,8 +1586,10 @@ static int vicodec_open(struct file *file)
v4l2_ctrl_handler_init(hdl, 4);
v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1, 16, 1, 10);
- v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_i_frame, NULL);
- v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_p_frame, NULL);
+ v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_I_FRAME_QP,
+ 1, 31, 1, 20);
+ v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP,
+ 1, 31, 1, 20);
if (hdl->error) {
rc = hdl->error;
v4l2_ctrl_handler_free(hdl);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 54d66dbc2a31..aed1c3a06500 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -849,6 +849,9 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: return "Force Key Frame";
case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: return "MPEG-2 Slice Parameters";
case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: return "MPEG-2 Quantization Matrices";
+ case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: return "FWHT Stateless Parameters";
+ case V4L2_CID_FWHT_I_FRAME_QP: return "FWHT I-Frame QP Value";
+ case V4L2_CID_FWHT_P_FRAME_QP: return "FWHT P-Frame QP Value";
/* VPX controls */
case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions";
@@ -1303,6 +1306,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION:
*type = V4L2_CTRL_TYPE_MPEG2_QUANTIZATION;
break;
+ case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
+ *type = V4L2_CTRL_TYPE_FWHT_PARAMS;
+ break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
@@ -1669,6 +1675,9 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
return 0;
+ case V4L2_CTRL_TYPE_FWHT_PARAMS:
+ return 0;
+
default:
return -EINVAL;
}
@@ -2249,6 +2258,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization);
break;
+ case V4L2_CTRL_TYPE_FWHT_PARAMS:
+ elem_size = sizeof(struct v4l2_ctrl_fwht_params);
+ break;
default:
if (type < V4L2_CTRL_COMPOUND_TYPES)
elem_size = sizeof(s32);
diff --git a/include/media/fwht-ctrls.h b/include/media/fwht-ctrls.h
new file mode 100644
index 000000000000..615027410e47
--- /dev/null
+++ b/include/media/fwht-ctrls.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * These are the FWHT state controls for use with stateless FWHT
+ * codec drivers.
+ *
+ * It turns out that these structs are not stable yet and will undergo
+ * more changes. So keep them private until they are stable and ready to
+ * become part of the official public API.
+ */
+
+#ifndef _FWHT_CTRLS_H_
+#define _FWHT_CTRLS_H_
+
+#define V4L2_CTRL_TYPE_FWHT_PARAMS 0x0105
+
+#define V4L2_CID_MPEG_VIDEO_FWHT_PARAMS (V4L2_CID_MPEG_BASE + 292)
+
+struct v4l2_ctrl_fwht_params {
+ __u64 backward_ref_ts;
+ __u32 version;
+ __u32 width;
+ __u32 height;
+ __u32 flags;
+ __u32 colorspace;
+ __u32 xfer_func;
+ __u32 ycbcr_enc;
+ __u32 quantization;
+};
+
+
+#endif
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 200f8a66ecaa..bd621cec65a5 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -23,10 +23,11 @@
#include <media/media-request.h>
/*
- * Include the mpeg2 stateless codec compound control definitions.
+ * Include the mpeg2 and fwht stateless codec compound control definitions.
* This will move to the public headers once this API is fully stable.
*/
#include <media/mpeg2-ctrls.h>
+#include <media/fwht-ctrls.h>
/* forward references */
struct file;
@@ -49,6 +50,7 @@ struct poll_table_struct;
* @p_char: Pointer to a string.
* @p_mpeg2_slice_params: Pointer to a MPEG2 slice parameters structure.
* @p_mpeg2_quantization: Pointer to a MPEG2 quantization data structure.
+ * @p_fwht_params: Pointer to a FWHT stateless parameters structure.
* @p: Pointer to a compound value.
*/
union v4l2_ctrl_ptr {
@@ -60,6 +62,7 @@ union v4l2_ctrl_ptr {
char *p_char;
struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
struct v4l2_ctrl_mpeg2_quantization *p_mpeg2_quantization;
+ struct v4l2_ctrl_fwht_params *p_fwht_params;
void *p;
};
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 06479f2fb3ae..78816ec88751 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -404,6 +404,10 @@ enum v4l2_mpeg_video_multi_slice_mode {
#define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE (V4L2_CID_MPEG_BASE+228)
#define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME (V4L2_CID_MPEG_BASE+229)
+/* CIDs for the FWHT codec as used by the vicodec driver. */
+#define V4L2_CID_FWHT_I_FRAME_QP (V4L2_CID_MPEG_BASE + 290)
+#define V4L2_CID_FWHT_P_FRAME_QP (V4L2_CID_MPEG_BASE + 291)
+
#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300)
#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301)
#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE+302)
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 1db220da3bcc..496e6453450c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -669,6 +669,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0') /* VP9 */
#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */
#define V4L2_PIX_FMT_FWHT v4l2_fourcc('F', 'W', 'H', 'T') /* Fast Walsh Hadamard Transform (vicodec) */
+#define V4L2_PIX_FMT_FWHT_STATELESS v4l2_fourcc('S', 'F', 'W', 'H') /* Stateless FWHT (vicodec) */
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
--
2.21.0
From 97ed8eab2a0067bee21aa634c938454660e76a38 Mon Sep 17 00:00:00 2001
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: Tue, 2 Apr 2019 12:31:49 +0200
Subject: [PATCH] staging: add missing SPDX lines to Makefile files
There are a few remaining drivers/staging/*/Makefile files that do not
have SPDX identifiers in them. Add the correct GPL-2.0 identifier to
them to make scanning tools happy.
Reviewed-by: Mukesh Ojha <mojha@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/media/sunxi/Makefile | 1 +
drivers/staging/media/sunxi/cedrus/Makefile | 1 +
56 files changed, 56 insertions(+)
diff --git a/drivers/staging/media/sunxi/Makefile b/drivers/staging/media/sunxi/Makefile
index cee2846c3ecf..b87140b0e15f 100644
--- a/drivers/staging/media/sunxi/Makefile
+++ b/drivers/staging/media/sunxi/Makefile
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += cedrus/
diff --git a/drivers/staging/media/sunxi/cedrus/Makefile b/drivers/staging/media/sunxi/cedrus/Makefile
index e9dc68b7bcb6..808842f0119e 100644
--- a/drivers/staging/media/sunxi/cedrus/Makefile
+++ b/drivers/staging/media/sunxi/cedrus/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o cedrus_mpeg2.o
--
2.21.0
From 6ece1909256d809df8cf975a62bddd565d03eb1a Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 28 Feb 2019 18:57:48 +0100
Subject: [PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate
DE2/DE3 mixers have to run at specific frequency in order to work
optimally. This wasn't actually possible for some SoCs because "de"
clock wasn't allowed to adjust parent rate.
Add CLK_SET_RATE_PARENT flag to all "de" clocks which didn't have it
yet.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 3 ++-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 2 +-
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | 3 ++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 932836d26e2b..be0deee70182 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -531,7 +531,8 @@ static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram",
static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
- 0x104, 0, 4, 24, 3, BIT(31), 0);
+ 0x104, 0, 4, 24, 3, BIT(31),
+ CLK_SET_RATE_PARENT);
static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
static const u8 tcon0_table[] = { 0, 2, };
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index 139e8389615c..daf78966555e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -266,7 +266,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
0, 4, /* M */
24, 1, /* mux */
BIT(31), /* gate */
- 0);
+ CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
0x60c, BIT(0), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index 621b1cd996db..ee170bf21cdf 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -325,7 +325,8 @@ static SUNXI_CCU_GATE(dram_ohci_clk, "dram-ohci", "dram",
static const char * const de_parents[] = { "pll-video", "pll-periph0" };
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
- 0x104, 0, 4, 24, 2, BIT(31), 0);
+ 0x104, 0, 4, 24, 2, BIT(31),
+ CLK_SET_RATE_PARENT);
static const char * const tcon_parents[] = { "pll-video" };
static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
--
2.20.1
From 3622c17fc40031cd2ca7b4030b83e6fad0c4e127 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 24 Dec 2018 18:11:56 +0100
Subject: [PATCH 2/3] drm/sun4i: Add VI scaler line size quirk for DE2/DE3
While all RGB scalers have maximum line size of 2048, some YUV scalers
have maximum line size of 2048 and some have line size of 4096.
Since there is no rule for that, add a quirk.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_mixer.c | 9 +++++++++
drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 ++
2 files changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 44a9ba7d8433..e46edacb7ab4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -554,6 +554,7 @@ static int sun8i_mixer_remove(struct platform_device *pdev)
static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
.ccsc = 0,
.scaler_mask = 0xf,
+ .scanline_yuv = 2048,
.ui_num = 3,
.vi_num = 1,
};
@@ -561,6 +562,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
.ccsc = 1,
.scaler_mask = 0x3,
+ .scanline_yuv = 2048,
.ui_num = 1,
.vi_num = 1,
};
@@ -569,6 +571,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
.ccsc = 0,
.mod_rate = 432000000,
.scaler_mask = 0xf,
+ .scanline_yuv = 2048,
.ui_num = 3,
.vi_num = 1,
};
@@ -577,6 +580,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
.ccsc = 0,
.mod_rate = 297000000,
.scaler_mask = 0xf,
+ .scanline_yuv = 2048,
.ui_num = 3,
.vi_num = 1,
};
@@ -585,6 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
.ccsc = 1,
.mod_rate = 297000000,
.scaler_mask = 0x3,
+ .scanline_yuv = 2048,
.ui_num = 1,
.vi_num = 1,
};
@@ -593,6 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
.vi_num = 2,
.ui_num = 1,
.scaler_mask = 0x3,
+ .scanline_yuv = 2048,
.ccsc = 0,
.mod_rate = 150000000,
};
@@ -601,6 +607,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
.ccsc = 0,
.mod_rate = 297000000,
.scaler_mask = 0xf,
+ .scanline_yuv = 4096,
.ui_num = 3,
.vi_num = 1,
};
@@ -609,6 +616,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
.ccsc = 1,
.mod_rate = 297000000,
.scaler_mask = 0x3,
+ .scanline_yuv = 2048,
.ui_num = 1,
.vi_num = 1,
};
@@ -618,6 +626,7 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
.is_de3 = true,
.mod_rate = 600000000,
.scaler_mask = 0xf,
+ .scanline_yuv = 4096,
.ui_num = 3,
.vi_num = 1,
};
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 913d14ce68b0..80e084caa084 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -159,6 +159,7 @@ struct de2_fmt_info {
* @mod_rate: module clock rate that needs to be set in order to have
* a functional block.
* @is_de3: true, if this is next gen display engine 3.0, false otherwise.
+ * @scaline_yuv: size of a scanline for VI scaler for YUV formats.
*/
struct sun8i_mixer_cfg {
int vi_num;
@@ -167,6 +168,7 @@ struct sun8i_mixer_cfg {
int ccsc;
unsigned long mod_rate;
unsigned int is_de3 : 1;
+ unsigned int scanline_yuv;
};
struct sun8i_mixer {
--
2.20.1
From 6d1be62144db6bebfdbcb8c50a11ac428dcdc741 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 24 Dec 2018 18:16:50 +0100
Subject: [PATCH 3/3] drm/sun4i: Improve VI scaling for DE2/DE3
VI planes support coarse scaling which helps to overcome VI scaler
limitations. While exact working of coarse scaling isn't known, it seems
that it just skips programmed amount of rows and columns. This is
especially useful for downscaling very big planes (4K down to 1080p).
Horizontal coarse scaling is currently used to fit one line to VI scaler
buffer.
Vertical coarse scaling is used to assure that VI scaler is actually
capable of processing framebuffer in one frame time.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 54 ++++++++++++++++++++++++--
drivers/gpu/drm/sun4i/sun8i_vi_layer.h | 11 ++++++
2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 87be898f9b7a..ce42560aa9df 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -80,6 +80,8 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
u32 bld_base, ch_base;
u32 outsize, insize;
u32 hphase, vphase;
+ u32 hn = 0, hm = 0;
+ u32 vn = 0, vm = 0;
bool subsampled;
DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
@@ -137,12 +139,41 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
subsampled = format->hsub > 1 || format->vsub > 1;
if (insize != outsize || subsampled || hphase || vphase) {
- u32 hscale, vscale;
+ unsigned int scanline, required;
+ struct drm_display_mode *mode;
+ u32 hscale, vscale, fps;
+ u64 ability;
DRM_DEBUG_DRIVER("HW scaling is enabled\n");
- hscale = state->src_w / state->crtc_w;
- vscale = state->src_h / state->crtc_h;
+ mode = &plane->state->crtc->state->mode;
+ fps = (mode->clock * 1000) / (mode->vtotal * mode->htotal);
+ ability = clk_get_rate(mixer->mod_clk);
+ /* BSP algorithm assumes 80% efficiency of VI scaler unit */
+ ability *= 80;
+ do_div(ability, mode->vdisplay * fps * max(src_w, dst_w));
+
+ required = src_h * 100 / dst_h;
+
+ if (ability < required) {
+ DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
+ vm = src_h;
+ vn = (u32)ability * dst_h / 100;
+ src_h = vn;
+ }
+
+ /* it seems that every RGB scaler has buffer for 2048 pixels */
+ scanline = subsampled ? mixer->cfg->scanline_yuv : 2048;
+
+ if (src_w > scanline) {
+ DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
+ hm = src_w;
+ hn = scanline;
+ src_w = hn;
+ }
+
+ hscale = (src_w << 16) / dst_w;
+ vscale = (src_h << 16) / dst_h;
sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
dst_h, hscale, vscale, hphase, vphase,
@@ -153,6 +184,23 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
sun8i_vi_scaler_enable(mixer, channel, false);
}
+ regmap_write(mixer->engine.regs,
+ SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
+ SUN8I_MIXER_CHAN_VI_DS_N(hn) |
+ SUN8I_MIXER_CHAN_VI_DS_M(hm));
+ regmap_write(mixer->engine.regs,
+ SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
+ SUN8I_MIXER_CHAN_VI_DS_N(hn) |
+ SUN8I_MIXER_CHAN_VI_DS_M(hm));
+ regmap_write(mixer->engine.regs,
+ SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
+ SUN8I_MIXER_CHAN_VI_DS_N(vn) |
+ SUN8I_MIXER_CHAN_VI_DS_M(vm));
+ regmap_write(mixer->engine.regs,
+ SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
+ SUN8I_MIXER_CHAN_VI_DS_N(vn) |
+ SUN8I_MIXER_CHAN_VI_DS_M(vm));
+
/* Set base coordinates */
DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
state->dst.x1, state->dst.y1);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
index 8a5e6d01c85d..a223a4839f45 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
@@ -24,6 +24,14 @@
((base) + 0x30 * (layer) + 0x18 + 4 * (plane))
#define SUN8I_MIXER_CHAN_VI_OVL_SIZE(base) \
((base) + 0xe8)
+#define SUN8I_MIXER_CHAN_VI_HDS_Y(base) \
+ ((base) + 0xf0)
+#define SUN8I_MIXER_CHAN_VI_HDS_UV(base) \
+ ((base) + 0xf4)
+#define SUN8I_MIXER_CHAN_VI_VDS_Y(base) \
+ ((base) + 0xf8)
+#define SUN8I_MIXER_CHAN_VI_VDS_UV(base) \
+ ((base) + 0xfc)
#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN BIT(0)
/* RGB mode should be set for RGB formats and cleared for YCbCr */
@@ -33,6 +41,9 @@
#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK GENMASK(31, 24)
#define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(x) ((x) << 24)
+#define SUN8I_MIXER_CHAN_VI_DS_N(x) ((x) << 16)
+#define SUN8I_MIXER_CHAN_VI_DS_M(x) ((x) << 0)
+
struct sun8i_mixer;
struct sun8i_vi_layer {
--
2.20.1
From 05f640b80bb6797ec11c328d16e9905884653f98 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sun, 7 Apr 2019 20:36:40 +0200
Subject: [PATCH] media: cedrus: Fix initialization order
Currently, MEDIA_IOC_G_TOPOLOGY ioctl on cedrus fails due to incorrect
initialization order. Fix that by moving video_register_device() before
v4l2_m2m_register_media_controller() and while at it, fix error path.
Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.c | 24 ++++++++++-----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index b98add3cdedd..d0429c0e6b6b 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -300,7 +300,7 @@ static int cedrus_probe(struct platform_device *pdev)
"Failed to initialize V4L2 M2M device\n");
ret = PTR_ERR(dev->m2m_dev);
- goto err_video;
+ goto err_v4l2;
}
dev->mdev.dev = &pdev->dev;
@@ -310,23 +310,23 @@ static int cedrus_probe(struct platform_device *pdev)
dev->mdev.ops = &cedrus_m2m_media_ops;
dev->v4l2_dev.mdev = &dev->mdev;
- ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
- MEDIA_ENT_F_PROC_VIDEO_DECODER);
- if (ret) {
- v4l2_err(&dev->v4l2_dev,
- "Failed to initialize V4L2 M2M media controller\n");
- goto err_m2m;
- }
-
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
- goto err_v4l2;
+ goto err_m2m;
}
v4l2_info(&dev->v4l2_dev,
"Device registered as /dev/video%d\n", vfd->num);
+ ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
+ MEDIA_ENT_F_PROC_VIDEO_DECODER);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev,
+ "Failed to initialize V4L2 M2M media controller\n");
+ goto err_video;
+ }
+
ret = media_device_register(&dev->mdev);
if (ret) {
v4l2_err(&dev->v4l2_dev, "Failed to register media device\n");
@@ -339,10 +339,10 @@ static int cedrus_probe(struct platform_device *pdev)
err_m2m_mc:
v4l2_m2m_unregister_media_controller(dev->m2m_dev);
-err_m2m:
- v4l2_m2m_release(dev->m2m_dev);
err_video:
video_unregister_device(&dev->vfd);
+err_m2m:
+ v4l2_m2m_release(dev->m2m_dev);
err_v4l2:
v4l2_device_unregister(&dev->v4l2_dev);
--
2.21.0

View File

@ -0,0 +1,133 @@
From e41186f41a546d1c60797f090001da969f5eda5a Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 14 Feb 2019 22:50:12 +0100
Subject: [PATCH] cedrus: Improve H264
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
.../staging/media/sunxi/cedrus/cedrus_h264.c | 69 +++++++++++--------
1 file changed, 41 insertions(+), 28 deletions(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index a5c5f13ffecb..405545947b85 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -38,7 +38,7 @@ struct cedrus_h264_sram_ref_pic {
#define CEDRUS_H264_FRAME_NUM 18
#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K)
-#define CEDRUS_PIC_INFO_BUF_SIZE (128 * SZ_1K)
+#define CEDRUS_PIC_INFO_BUF_SIZE (336 * SZ_1K)
static void cedrus_h264_write_sram(struct cedrus_dev *dev,
enum cedrus_h264_sram_off off,
@@ -101,7 +101,7 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
struct cedrus_dev *dev = ctx->dev;
unsigned long used_dpbs = 0;
unsigned int position;
- unsigned int output = 0;
+ int output = -1;
unsigned int i;
memset(pic_list, 0, sizeof(pic_list));
@@ -126,6 +126,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
position = cedrus_buf->codec.h264.position;
used_dpbs |= BIT(position);
+ if (run->dst->vb2_buf.timestamp == dpb->reference_ts) {
+ output = position;
+ continue;
+ }
+
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
continue;
@@ -133,13 +138,11 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
dpb->top_field_order_cnt,
dpb->bottom_field_order_cnt,
&pic_list[position]);
-
- output = max(position, output);
}
- position = find_next_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM,
- output);
- if (position >= CEDRUS_H264_FRAME_NUM)
+ if (output >= 0)
+ position = output;
+ else
position = find_first_zero_bit(&used_dpbs, CEDRUS_H264_FRAME_NUM);
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
@@ -165,6 +168,10 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
#define CEDRUS_MAX_REF_IDX 32
+#define REF_IDX(v) (v & GENMASK(5, 0))
+#define REF_FIELD(v) (v >> 6)
+#define REF_FIELD_BOTTOM 2
+
static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
struct cedrus_run *run,
const u8 *ref_list, u8 num_ref,
@@ -187,7 +194,7 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
int buf_idx;
u8 dpb_idx;
- dpb_idx = ref_list[i];
+ dpb_idx = REF_IDX(ref_list[i]);
dpb = &decode->dpb[dpb_idx];
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
@@ -206,7 +213,8 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
position = cedrus_buf->codec.h264.position;
sram_array[i] |= position << 1;
- if (ref_buf->field == V4L2_FIELD_BOTTOM)
+ /* set bottom field flag when reference is to bottom field */
+ if (REF_FIELD(ref_list[i]) == REF_FIELD_BOTTOM)
sram_array[i] |= BIT(0);
}
@@ -309,6 +317,8 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
dma_addr_t src_buf_addr;
u32 offset = slice->header_bit_size;
u32 len = (slice->size * 8) - offset;
+ unsigned int pic_width_in_mbs;
+ bool mbaff_picture;
u32 reg;
cedrus_write(dev, VE_H264_VLD_LEN, len);
@@ -378,12 +387,19 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
reg |= VE_H264_SPS_DIRECT_8X8_INFERENCE;
cedrus_write(dev, VE_H264_SPS, reg);
+ mbaff_picture = !(slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC) &&
+ (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
+ pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1;
+
// slice parameters
reg = 0;
+ reg |= ((slice->first_mb_in_slice % pic_width_in_mbs) & 0xff) << 24;
+ reg |= (((slice->first_mb_in_slice / pic_width_in_mbs) * (mbaff_picture ? 2 : 1)) & 0xff) << 16;
reg |= decode->nal_ref_idc ? BIT(12) : 0;
reg |= (slice->slice_type & 0xf) << 8;
reg |= slice->cabac_init_idc & 0x3;
- reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
+ if (decode->num_slices == 1)
+ reg |= VE_H264_SHS_FIRST_SLICE_IN_PIC;
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
reg |= VE_H264_SHS_FIELD_PIC;
if (slice->flags & V4L2_H264_SLICE_FLAG_BOTTOM_FIELD)
@@ -531,7 +541,7 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
* we need to work on.
*/
field_size = field_size * 2;
- ctx->codec.h264.mv_col_buf_field_size = field_size;
+ ctx->codec.h264.mv_col_buf_field_size = ALIGN(field_size, 1024);
mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM;
ctx->codec.h264.mv_col_buf_size = mv_col_size;
--
2.20.1

View File

@ -0,0 +1,703 @@
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 3bab9d4e3304..a14762dff91d 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -916,6 +916,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set";
case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set";
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters";
+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: return "HEVC Scaling Matrix";
/* CAMERA controls */
/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1332,6 +1333,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:
*type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS;
break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:
+ *type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX;
+ break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
@@ -1708,6 +1712,7 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
case V4L2_CTRL_TYPE_HEVC_SPS:
case V4L2_CTRL_TYPE_HEVC_PPS:
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
return 0;
default:
@@ -2314,6 +2319,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params);
break;
+ case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
+ elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix);
+ break;
default:
if (type < V4L2_CTRL_COMPOUND_TYPES)
elem_size = sizeof(s32);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index a713630ce7ba..3040f483e0a2 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -87,6 +87,12 @@ static const struct cedrus_control cedrus_controls[] = {
.codec = CEDRUS_CODEC_H265,
.required = true,
},
+ {
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX,
+ .elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix),
+ .codec = CEDRUS_CODEC_H265,
+ .required = true,
+ },
};
#define CEDRUS_CONTROLS_COUNT ARRAY_SIZE(cedrus_controls)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index b5d083812bea..deb9fa1de97c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -72,6 +72,7 @@ struct cedrus_h265_run {
const struct v4l2_ctrl_hevc_sps *sps;
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params *slice_params;
+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix;
};
struct cedrus_run {
@@ -88,6 +89,10 @@ struct cedrus_run {
struct cedrus_buffer {
struct v4l2_m2m_buffer m2m_buf;
+ void *mv_col_buf;
+ dma_addr_t mv_col_buf_dma;
+ ssize_t mv_col_buf_size;
+
union {
struct {
unsigned int position;
@@ -121,12 +126,10 @@ struct cedrus_ctx {
dma_addr_t neighbor_info_buf_dma;
} h264;
struct {
- void *mv_col_buf;
- dma_addr_t mv_col_buf_addr;
- ssize_t mv_col_buf_size;
- ssize_t mv_col_buf_unit_size;
void *neighbor_info_buf;
dma_addr_t neighbor_info_buf_addr;
+ void *entry_points_buf;
+ dma_addr_t entry_points_buf_addr;
} h265;
} codec;
};
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index c50397f8692f..80c6d920142d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -68,6 +68,8 @@ void cedrus_device_run(void *priv)
V4L2_CID_MPEG_VIDEO_HEVC_PPS);
run.h265.slice_params = cedrus_find_control_data(ctx,
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
+ run.h265.scaling_matrix = cedrus_find_control_data(ctx,
+ V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX);
break;
default:
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index f1c3665e95ab..2cc36d69548e 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -77,24 +77,25 @@ static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset)
cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset);
}
-static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
+static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, const void *data,
unsigned int size)
{
- u32 *word = data;
+ size_t count = DIV_ROUND_UP(size, 4);
+ const u32 *word = data;
- while (size >= sizeof(u32)) {
+ while (count--)
cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++);
- size -= sizeof(u32);
- }
}
static inline dma_addr_t
cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
- unsigned int index, unsigned int field)
+ unsigned int index)
{
- return ctx->codec.h265.mv_col_buf_addr + index *
- ctx->codec.h265.mv_col_buf_unit_size +
- field * ctx->codec.h265.mv_col_buf_unit_size / 2;
+ struct cedrus_buffer *cedrus_buf;
+
+ cedrus_buf = vb2_to_cedrus_buffer(ctx->dst_bufs[index]);
+
+ return cedrus_buf->mv_col_buf_dma;
}
static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
@@ -107,9 +108,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0);
dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1);
dma_addr_t mv_col_buf_addr[2] = {
- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0),
- cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index,
- field_pic ? 1 : 0)
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index),
+ cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index)
};
u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
@@ -157,28 +157,24 @@ static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev,
u8 num_ref_idx_active,
u32 sram_offset)
{
+ u8 sram_array[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
unsigned int i;
- u32 word = 0;
+
+ memset(sram_array, 0, sizeof(sram_array));
+ num_ref_idx_active = min(num_ref_idx_active,
+ (u8)V4L2_HEVC_DPB_ENTRIES_NUM_MAX);
cedrus_h265_sram_write_offset(dev, sram_offset);
for (i = 0; i < num_ref_idx_active; i++) {
- unsigned int shift = (i % 4) * 8;
unsigned int index = list[i];
- u8 value = list[i];
+ sram_array[i] = index;
if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
- value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
-
- /* Each SRAM word gathers up to 4 references. */
- word |= value << shift;
-
- /* Write the word to SRAM and clear it for the next batch. */
- if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) {
- cedrus_h265_sram_write_data(dev, &word, sizeof(word));
- word = 0;
- }
+ sram_array[i] |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
}
+
+ cedrus_h265_sram_write_data(dev, &sram_array, num_ref_idx_active);
}
static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
@@ -219,6 +215,105 @@ static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
}
}
+static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
+ struct cedrus_run *run)
+{
+ const struct v4l2_ctrl_hevc_scaling_matrix *scaling;
+ struct cedrus_dev *dev = ctx->dev;
+
+ scaling = run->h265.scaling_matrix;
+
+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0,
+ (scaling->scaling_list_dc_coef_32x32[1] << 24) |
+ (scaling->scaling_list_dc_coef_32x32[0] << 16) |
+ (scaling->scaling_list_dc_coef_16x16[1] << 8) |
+ (scaling->scaling_list_dc_coef_16x16[0] << 0));
+
+ cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1,
+ (scaling->scaling_list_dc_coef_16x16[5] << 24) |
+ (scaling->scaling_list_dc_coef_16x16[4] << 16) |
+ (scaling->scaling_list_dc_coef_16x16[3] << 8) |
+ (scaling->scaling_list_dc_coef_16x16[2] << 0));
+
+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_8x8);
+ cedrus_h265_sram_write_data(dev, scaling->scaling_list_8x8,
+ sizeof(scaling->scaling_list_8x8));
+
+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_32x32);
+ cedrus_h265_sram_write_data(dev, scaling->scaling_list_32x32,
+ sizeof(scaling->scaling_list_32x32));
+
+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_16x16);
+ cedrus_h265_sram_write_data(dev, scaling->scaling_list_16x16,
+ sizeof(scaling->scaling_list_16x16));
+
+ cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_4x4);
+ cedrus_h265_sram_write_data(dev, scaling->scaling_list_4x4,
+ sizeof(scaling->scaling_list_4x4));
+}
+
+static void write_entry_point_list(struct cedrus_ctx *ctx,
+ struct cedrus_run *run)
+{
+ const struct v4l2_ctrl_hevc_slice_params *slice_params;
+ unsigned int ctb_size_luma, width_in_ctb_luma;
+ unsigned int log2_max_luma_coding_block_size;
+ const struct v4l2_ctrl_hevc_pps *pps;
+ const struct v4l2_ctrl_hevc_sps *sps;
+ struct cedrus_dev *dev = ctx->dev;
+ uint32_t *entry_points;
+ int i, x, tx, y, ty;
+
+ pps = run->h265.pps;
+ sps = run->h265.sps;
+ slice_params = run->h265.slice_params;
+
+ log2_max_luma_coding_block_size =
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size;
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
+
+ for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) {
+ if (x + pps->column_width_minus1[tx] + 1 > (slice_params->slice_segment_addr % width_in_ctb_luma))
+ break;
+
+ x += pps->column_width_minus1[tx] + 1;
+ }
+
+ for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) {
+ if (y + pps->row_height_minus1[ty] + 1 > (slice_params->slice_segment_addr / width_in_ctb_luma))
+ break;
+
+ y += pps->row_height_minus1[ty] + 1;
+ }
+
+ cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0));
+ cedrus_write(dev, VE_DEC_H265_TILE_END_CTB,
+ ((y + pps->row_height_minus1[ty]) << 16) |
+ ((x + pps->column_width_minus1[tx]) << 0));
+
+ entry_points = ctx->codec.h265.entry_points_buf;
+ if (pps->entropy_coding_sync_enabled_flag) {
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++)
+ entry_points[i] = slice_params->entry_point_offset_minus1[i] + 1;
+ } else {
+ for (i = 0; i < slice_params->num_entry_point_offsets; i++) {
+ if (tx + 1 >= pps->num_tile_columns_minus1 + 1) {
+ x = tx = 0;
+ y += pps->row_height_minus1[ty++] + 1;
+ } else {
+ x += pps->column_width_minus1[tx++] + 1;
+ }
+
+ entry_points[i * 4 + 0] = slice_params->entry_point_offset_minus1[i] + 1;
+ entry_points[i * 4 + 1] = 0x0;
+ entry_points[i * 4 + 2] = (y << 16) | (x << 0);
+ entry_points[i * 4 + 3] = ((y + pps->row_height_minus1[ty]) << 16) | ((x + pps->column_width_minus1[tx]) << 0);
+ }
+ }
+}
+
static void cedrus_h265_setup(struct cedrus_ctx *ctx,
struct cedrus_run *run)
{
@@ -227,6 +322,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
const struct v4l2_ctrl_hevc_pps *pps;
const struct v4l2_ctrl_hevc_slice_params *slice_params;
const struct v4l2_hevc_pred_weight_table *pred_weight_table;
+ struct cedrus_buffer *cedrus_buf;
dma_addr_t src_buf_addr;
dma_addr_t src_buf_end_addr;
u32 chroma_log2_weight_denom;
@@ -239,43 +335,10 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
slice_params = run->h265.slice_params;
pred_weight_table = &slice_params->pred_weight_table;
- /* MV column buffer size and allocation. */
- if (!ctx->codec.h265.mv_col_buf_size) {
- unsigned int num_buffers =
- run->dst->vb2_buf.vb2_queue->num_buffers;
- unsigned int log2_max_luma_coding_block_size =
- sps->log2_min_luma_coding_block_size_minus3 + 3 +
- sps->log2_diff_max_min_luma_coding_block_size;
- unsigned int ctb_size_luma =
- 1 << log2_max_luma_coding_block_size;
-
- /*
- * Each CTB requires a MV col buffer with a specific unit size.
- * Since the address is given with missing lsb bits, 1 KiB is
- * added to each buffer to ensure proper alignment.
- */
- ctx->codec.h265.mv_col_buf_unit_size =
- DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
- DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
- CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
-
- ctx->codec.h265.mv_col_buf_size = num_buffers *
- ctx->codec.h265.mv_col_buf_unit_size;
-
- ctx->codec.h265.mv_col_buf =
- dma_alloc_coherent(dev->dev,
- ctx->codec.h265.mv_col_buf_size,
- &ctx->codec.h265.mv_col_buf_addr,
- GFP_KERNEL);
- if (!ctx->codec.h265.mv_col_buf) {
- ctx->codec.h265.mv_col_buf_size = 0;
- // TODO: Abort the process here.
- return;
- }
- }
-
/* Activate H265 engine. */
cedrus_engine_enable(dev, CEDRUS_CODEC_H265);
+ if (sps->pic_width_in_luma_samples > 2048)
+ cedrus_write(dev, VE_MODE, cedrus_read(dev, VE_MODE) | BIT(21));
/* Source offset and length in bits. */
@@ -299,18 +362,35 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
src_buf_end_addr = src_buf_addr +
DIV_ROUND_UP(slice_params->bit_size, 8);
- reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
+ reg = VE_DEC_H265_BITS_END_ADDR_BASE(ALIGN(src_buf_end_addr, 1024) - 1);
cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
- /* Coding tree block address: start at the beginning. */
- reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
- cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
-
cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
+ if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag)
+ write_entry_point_list(ctx, run);
+
+ /* Coding tree block address */
+ reg = 0;
+ if (!slice_params->first_slice_segment_in_pic_flag) {
+ unsigned int ctb_size_luma, width_in_ctb_luma;
+ unsigned int log2_max_luma_coding_block_size;
+
+ log2_max_luma_coding_block_size =
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size;
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
+
+ reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma);
+ reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma);
+ }
+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
+
/* Clear the number of correctly-decoded coding tree blocks. */
- cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
+ if (slice_params->first_slice_segment_in_pic_flag)
+ cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
/* Initialize bitstream access. */
cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
@@ -333,6 +413,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) |
VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) |
VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
+ VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
VE_DEC_H265_DEC_SPS_HDR_SEPARATE_COLOUR_PLANE_FLAG(sps->separate_colour_plane_flag) |
VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
@@ -362,7 +443,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
VE_DEC_H265_DEC_PPS_CTRL1_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG(pps->pps_loop_filter_across_slices_enabled_flag) |
VE_DEC_H265_DEC_PPS_CTRL1_LOOP_FILTER_ACROSS_TILES_ENABLED_FLAG(pps->loop_filter_across_tiles_enabled_flag) |
VE_DEC_H265_DEC_PPS_CTRL1_ENTROPY_CODING_SYNC_ENABLED_FLAG(pps->entropy_coding_sync_enabled_flag) |
- VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(0) |
+ VE_DEC_H265_DEC_PPS_CTRL1_TILES_ENABLED_FLAG(pps->tiles_enabled_flag) |
VE_DEC_H265_DEC_PPS_CTRL1_TRANSQUANT_BYPASS_ENABLE_FLAG(pps->transquant_bypass_enabled_flag) |
VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_BIPRED_FLAG(pps->weighted_bipred_flag) |
VE_DEC_H265_DEC_PPS_CTRL1_WEIGHTED_PRED_FLAG(pps->weighted_pred_flag);
@@ -383,7 +464,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) |
VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type) |
VE_DEC_H265_DEC_SLICE_HDR_INFO0_DEPENDENT_SLICE_SEGMENT_FLAG(pps->dependent_slice_segment_flag) |
- VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(1);
+ VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIRST_SLICE_SEGMENT_IN_PIC_FLAG(slice_params->first_slice_segment_in_pic_flag);
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
@@ -400,34 +481,68 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
pred_weight_table->delta_chroma_log2_weight_denom;
- reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) |
+ reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(slice_params->num_entry_point_offsets) |
VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
+ cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR, ctx->codec.h265.entry_points_buf_addr >> 8);
+
/* Decoded picture size. */
- reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
- VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height);
+ reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(sps->pic_width_in_luma_samples) |
+ VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(sps->pic_height_in_luma_samples);
cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg);
- /* Scaling list. */
+ /* Scaling list */
- reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
+ if (sps->scaling_list_enabled_flag) {
+ cedrus_h265_write_scaling_list(ctx, run);
+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_ENABLED_FLAG(1);
+ } else {
+ reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
+ }
cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
/* Neightbor information address. */
reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr);
cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
+ cedrus_write(dev, VE_DEC_H265_LOW_ADDR, 0);
+
/* Write decoded picture buffer in pic list. */
cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
slice_params->num_active_dpb_entries);
/* Output frame. */
+ cedrus_buf = vb2_to_cedrus_buffer(ctx->dst_bufs[run->dst->vb2_buf.index]);
+ if (!cedrus_buf->mv_col_buf_size) {
+ unsigned int ctb_size_luma, width_in_ctb_luma;
+ unsigned int log2_max_luma_coding_block_size;
+
+ log2_max_luma_coding_block_size =
+ sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size;
+ ctb_size_luma = 1 << log2_max_luma_coding_block_size;
+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
+
+ cedrus_buf->mv_col_buf_size = ALIGN(width_in_ctb_luma *
+ DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) *
+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024);
+
+ cedrus_buf->mv_col_buf =
+ dma_alloc_coherent(dev->dev,
+ cedrus_buf->mv_col_buf_size,
+ &cedrus_buf->mv_col_buf_dma,
+ GFP_KERNEL);
+
+ if (!cedrus_buf->mv_col_buf)
+ cedrus_buf->mv_col_buf_size = 0;
+ }
+
output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX;
pic_order_cnt[0] = slice_params->slice_pic_order_cnt;
pic_order_cnt[1] = slice_params->slice_pic_order_cnt;
@@ -443,36 +558,36 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
slice_params->ref_idx_l0,
- slice_params->num_ref_idx_l0_active_minus1 + 1,
- VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
+ slice_params->num_ref_idx_l0_active_minus1 + 1,
+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
if (pps->weighted_pred_flag || pps->weighted_bipred_flag)
cedrus_h265_pred_weight_write(dev,
- pred_weight_table->delta_luma_weight_l0,
- pred_weight_table->luma_offset_l0,
- pred_weight_table->delta_chroma_weight_l0,
- pred_weight_table->chroma_offset_l0,
- slice_params->num_ref_idx_l0_active_minus1 + 1,
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
+ pred_weight_table->delta_luma_weight_l0,
+ pred_weight_table->luma_offset_l0,
+ pred_weight_table->delta_chroma_weight_l0,
+ pred_weight_table->chroma_offset_l0,
+ slice_params->num_ref_idx_l0_active_minus1 + 1,
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
}
/* Reference picture list 1 (for B frames). */
if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
slice_params->ref_idx_l1,
- slice_params->num_ref_idx_l1_active_minus1 + 1,
- VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
+ slice_params->num_ref_idx_l1_active_minus1 + 1,
+ VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
if (pps->weighted_bipred_flag)
cedrus_h265_pred_weight_write(dev,
- pred_weight_table->delta_luma_weight_l1,
- pred_weight_table->luma_offset_l1,
- pred_weight_table->delta_chroma_weight_l1,
- pred_weight_table->chroma_offset_l1,
- slice_params->num_ref_idx_l1_active_minus1 + 1,
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
- VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
+ pred_weight_table->delta_luma_weight_l1,
+ pred_weight_table->luma_offset_l1,
+ pred_weight_table->delta_chroma_weight_l1,
+ pred_weight_table->chroma_offset_l1,
+ slice_params->num_ref_idx_l1_active_minus1 + 1,
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
+ VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
}
/* Enable appropriate interruptions. */
@@ -483,9 +598,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
- /* The buffer size is calculated at setup time. */
- ctx->codec.h265.mv_col_buf_size = 0;
-
ctx->codec.h265.neighbor_info_buf =
dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
&ctx->codec.h265.neighbor_info_buf_addr,
@@ -493,6 +605,17 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx)
if (!ctx->codec.h265.neighbor_info_buf)
return -ENOMEM;
+ ctx->codec.h265.entry_points_buf =
+ dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
+ &ctx->codec.h265.entry_points_buf_addr,
+ GFP_KERNEL);
+ if (!ctx->codec.h265.entry_points_buf) {
+ dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
+ ctx->codec.h265.neighbor_info_buf,
+ ctx->codec.h265.neighbor_info_buf_addr);
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -500,17 +623,12 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
- if (ctx->codec.h265.mv_col_buf_size > 0) {
- dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size,
- ctx->codec.h265.mv_col_buf,
- ctx->codec.h265.mv_col_buf_addr);
-
- ctx->codec.h265.mv_col_buf_size = 0;
- }
-
dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
ctx->codec.h265.neighbor_info_buf,
ctx->codec.h265.neighbor_info_buf_addr);
+ dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
+ ctx->codec.h265.entry_points_buf,
+ ctx->codec.h265.entry_points_buf_addr);
}
static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index 87651d6b6227..a2931f322c7a 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -496,6 +496,9 @@
#define VE_DEC_H265_TILE_START_CTB (VE_ENGINE_DEC_H265 + 0x68)
#define VE_DEC_H265_TILE_END_CTB (VE_ENGINE_DEC_H265 + 0x6c)
+#define VE_DEC_H265_SCALING_LIST_DC_COEF0 (VE_ENGINE_DEC_H265 + 0x78)
+#define VE_DEC_H265_SCALING_LIST_DC_COEF1 (VE_ENGINE_DEC_H265 + 0x7c)
+
#define VE_DEC_H265_LOW_ADDR (VE_ENGINE_DEC_H265 + 0x80)
#define VE_DEC_H265_LOW_ADDR_PRIMARY_CHROMA(a) \
@@ -513,7 +516,10 @@
#define VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1 0x80
#define VE_DEC_H265_SRAM_OFFSET_FRAME_INFO 0x400
#define VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT 0x20
-#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS 0x800
+#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_8x8 0x800
+#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_32x32 0x980
+#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_16x16 0xa00
+#define VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS_4x4 0xb80
#define VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0 0xc00
#define VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1 0xc10
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index b9acdc03c839..adf00513c15f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -423,8 +423,18 @@ static void cedrus_buf_cleanup(struct vb2_buffer *vb)
struct vb2_queue *vq = vb->vb2_queue;
struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
- if (!V4L2_TYPE_IS_OUTPUT(vq->type))
+ if (!V4L2_TYPE_IS_OUTPUT(vq->type)) {
+ struct cedrus_buffer *cedrus_buf;
+
+ cedrus_buf = vb2_to_cedrus_buffer(ctx->dst_bufs[vb->index]);
+
+ if (cedrus_buf->mv_col_buf_size)
+ dma_free_coherent(ctx->dev->dev,
+ cedrus_buf->mv_col_buf_size,
+ cedrus_buf->mv_col_buf,
+ cedrus_buf->mv_col_buf_dma);
ctx->dst_bufs[vb->index] = NULL;
+ }
}
static int cedrus_buf_out_validate(struct vb2_buffer *vb)
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
index 005c71c67163..4bf3d79047f4 100644
--- a/include/media/hevc-ctrls.h
+++ b/include/media/hevc-ctrls.h
@@ -14,11 +14,13 @@
#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 645)
#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 646)
#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 647)
+#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (V4L2_CID_MPEG_BASE + 648)
/* enum v4l2_ctrl_type type values */
#define V4L2_CTRL_TYPE_HEVC_SPS 0x0115
#define V4L2_CTRL_TYPE_HEVC_PPS 0x0116
#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0117
+#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0118
#define V4L2_HEVC_SLICE_TYPE_B 0
#define V4L2_HEVC_SLICE_TYPE_P 1
@@ -91,7 +93,7 @@ struct v4l2_ctrl_hevc_pps {
__u8 lists_modification_present_flag;
__u8 log2_parallel_merge_level_minus2;
__u8 slice_segment_header_extension_present_flag;
- __u8 padding;
+ __u8 scaling_list_enable_flag;
};
#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01
@@ -175,7 +177,21 @@ struct v4l2_ctrl_hevc_slice_params {
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
struct v4l2_hevc_pred_weight_table pred_weight_table;
- __u8 padding[2];
+ __u32 slice_segment_addr;
+ __u32 num_entry_point_offsets;
+ __u32 entry_point_offset_minus1[256];
+ __u8 first_slice_segment_in_pic_flag;
+
+ __u8 padding;
+};
+
+struct v4l2_ctrl_hevc_scaling_matrix {
+ __u8 scaling_list_4x4[6][16];
+ __u8 scaling_list_8x8[6][64];
+ __u8 scaling_list_16x16[6][64];
+ __u8 scaling_list_32x32[2][64];
+ __u8 scaling_list_dc_coef_16x16[6];
+ __u8 scaling_list_dc_coef_32x32[2];
};
#endif

View File

@ -0,0 +1,358 @@
From bd5fed9f390fea4ef8df1abb5f4ac6b64fab5974 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon, 18 Feb 2019 21:51:31 +0100
Subject: [PATCH] cedrus h264 4k
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/staging/media/sunxi/cedrus/cedrus.h | 12 +-
.../staging/media/sunxi/cedrus/cedrus_h264.c | 117 +++++++++++-------
.../staging/media/sunxi/cedrus/cedrus_h265.c | 4 +-
.../staging/media/sunxi/cedrus/cedrus_hw.c | 11 +-
.../staging/media/sunxi/cedrus/cedrus_hw.h | 3 +-
.../staging/media/sunxi/cedrus/cedrus_mpeg2.c | 2 +-
.../staging/media/sunxi/cedrus/cedrus_regs.h | 4 +
.../staging/media/sunxi/cedrus/cedrus_video.c | 4 +-
8 files changed, 98 insertions(+), 59 deletions(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index deb9fa1de97c..8815332fe1c1 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -116,14 +116,18 @@ struct cedrus_ctx {
union {
struct {
- void *mv_col_buf;
- dma_addr_t mv_col_buf_dma;
- ssize_t mv_col_buf_field_size;
- ssize_t mv_col_buf_size;
void *pic_info_buf;
dma_addr_t pic_info_buf_dma;
void *neighbor_info_buf;
dma_addr_t neighbor_info_buf_dma;
+
+ void *deblk_buf;
+ dma_addr_t deblk_buf_dma;
+ ssize_t deblk_buf_size;
+
+ void *intra_pred_buf;
+ dma_addr_t intra_pred_buf_dma;
+ ssize_t intra_pred_buf_size;
} h264;
struct {
void *neighbor_info_buf;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index 405545947b85..737a317fd1ee 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -55,16 +55,14 @@ static void cedrus_h264_write_sram(struct cedrus_dev *dev,
}
static dma_addr_t cedrus_h264_mv_col_buf_addr(struct cedrus_ctx *ctx,
- unsigned int position,
+ struct cedrus_buffer *buf,
unsigned int field)
{
- dma_addr_t addr = ctx->codec.h264.mv_col_buf_dma;
-
- /* Adjust for the position */
- addr += position * ctx->codec.h264.mv_col_buf_field_size * 2;
+ dma_addr_t addr = buf->mv_col_buf_dma;
/* Adjust for the field */
- addr += field * ctx->codec.h264.mv_col_buf_field_size;
+ if (field)
+ addr += buf->mv_col_buf_size / 2;
return addr;
}
@@ -76,7 +74,6 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
struct cedrus_h264_sram_ref_pic *pic)
{
struct vb2_buffer *vbuf = &buf->m2m_buf.vb.vb2_buf;
- unsigned int position = buf->codec.h264.position;
pic->top_field_order_cnt = top_field_order_cnt;
pic->bottom_field_order_cnt = bottom_field_order_cnt;
@@ -84,8 +81,8 @@ static void cedrus_fill_ref_pic(struct cedrus_ctx *ctx,
pic->luma_ptr = cedrus_buf_addr(vbuf, &ctx->dst_fmt, 0);
pic->chroma_ptr = cedrus_buf_addr(vbuf, &ctx->dst_fmt, 1);
- pic->mv_col_top_ptr = cedrus_h264_mv_col_buf_addr(ctx, position, 0);
- pic->mv_col_bot_ptr = cedrus_h264_mv_col_buf_addr(ctx, position, 1);
+ pic->mv_col_top_ptr = cedrus_h264_mv_col_buf_addr(ctx, buf, 0);
+ pic->mv_col_bot_ptr = cedrus_h264_mv_col_buf_addr(ctx, buf, 1);
}
static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
@@ -148,6 +145,28 @@ static void cedrus_write_frame_list(struct cedrus_ctx *ctx,
output_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
output_buf->codec.h264.position = position;
+ if (!output_buf->mv_col_buf_size) {
+ const struct v4l2_ctrl_h264_sps *sps = run->h264.sps;
+ unsigned int field_size;
+
+ field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
+ DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
+ field_size = field_size * 2;
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
+ field_size = field_size * 2;
+
+ output_buf->mv_col_buf_size = ALIGN(field_size, 1024) * 2;
+ output_buf->mv_col_buf =
+ dma_alloc_coherent(dev->dev,
+ output_buf->mv_col_buf_size,
+ &output_buf->mv_col_buf_dma,
+ GFP_KERNEL);
+
+ if (!output_buf->mv_col_buf)
+ output_buf->mv_col_buf_size = 0;
+ }
+
if (slice->flags & V4L2_H264_SLICE_FLAG_FIELD_PIC)
output_buf->codec.h264.pic_type = CEDRUS_H264_PIC_TYPE_FIELD;
else if (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)
@@ -331,6 +350,14 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
VE_H264_VLD_ADDR_FIRST | VE_H264_VLD_ADDR_VALID |
VE_H264_VLD_ADDR_LAST);
+ if (((sps->pic_width_in_mbs_minus1 + 1) * 16) > 2048) {
+ cedrus_write(dev, VE_DBLK_INTRAPRED_BUF_CTRL, 0x5);
+ cedrus_write(dev, VE_DBLK_DRAM_BUF_ADDR,
+ ctx->codec.h264.deblk_buf_dma);
+ cedrus_write(dev, VE_INTRAPRED_DRAM_BUF_ADDR,
+ ctx->codec.h264.intra_pred_buf_dma);
+ }
+
/*
* FIXME: Since the bitstream parsing is done in software, and
* in userspace, this shouldn't be needed anymore. But it
@@ -471,7 +498,8 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
{
struct cedrus_dev *dev = ctx->dev;
- cedrus_engine_enable(dev, CEDRUS_CODEC_H264);
+ cedrus_engine_enable(dev, CEDRUS_CODEC_H264,
+ ctx->src_fmt.width);
cedrus_write(dev, VE_H264_SDROT_CTRL, 0);
cedrus_write(dev, VE_H264_EXTRA_BUFFER1,
@@ -490,8 +518,6 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
static int cedrus_h264_start(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
- unsigned int field_size;
- unsigned int mv_col_size;
int ret;
/*
@@ -523,44 +549,42 @@ static int cedrus_h264_start(struct cedrus_ctx *ctx)
goto err_pic_buf;
}
- field_size = DIV_ROUND_UP(ctx->src_fmt.width, 16) *
- DIV_ROUND_UP(ctx->src_fmt.height, 16) * 16;
-
- /*
- * FIXME: This is actually conditional to
- * V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE not being set, we
- * might have to rework this if memory efficiency ever is
- * something we need to work on.
- */
- field_size = field_size * 2;
+ if (ctx->src_fmt.width > 2048) {
+ ctx->codec.h264.deblk_buf_size =
+ ALIGN(ctx->src_fmt.width, 32) * 12;
+ ctx->codec.h264.deblk_buf =
+ dma_alloc_coherent(dev->dev,
+ ctx->codec.h264.deblk_buf_size,
+ &ctx->codec.h264.deblk_buf_dma,
+ GFP_KERNEL);
+ if (!ctx->codec.h264.deblk_buf) {
+ ret = -ENOMEM;
+ goto err_neighbor_buf;
+ }
- /*
- * FIXME: This is actually conditional to
- * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY not being set, we might
- * have to rework this if memory efficiency ever is something
- * we need to work on.
- */
- field_size = field_size * 2;
- ctx->codec.h264.mv_col_buf_field_size = ALIGN(field_size, 1024);
-
- mv_col_size = field_size * 2 * CEDRUS_H264_FRAME_NUM;
- ctx->codec.h264.mv_col_buf_size = mv_col_size;
- ctx->codec.h264.mv_col_buf = dma_alloc_coherent(dev->dev,
- ctx->codec.h264.mv_col_buf_size,
- &ctx->codec.h264.mv_col_buf_dma,
- GFP_KERNEL);
- if (!ctx->codec.h264.mv_col_buf) {
- ret = -ENOMEM;
- goto err_neighbor_buf;
+ ctx->codec.h264.intra_pred_buf_size =
+ ALIGN(ctx->src_fmt.width, 64) * 5;
+ ctx->codec.h264.intra_pred_buf =
+ dma_alloc_coherent(dev->dev,
+ ctx->codec.h264.intra_pred_buf_size,
+ &ctx->codec.h264.intra_pred_buf_dma,
+ GFP_KERNEL);
+ if (!ctx->codec.h264.intra_pred_buf) {
+ ret = -ENOMEM;
+ goto err_deblk_buf;
+ }
}
return 0;
+err_deblk_buf:
+ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size,
+ ctx->codec.h264.deblk_buf,
+ ctx->codec.h264.deblk_buf_dma);
err_neighbor_buf:
dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
ctx->codec.h264.neighbor_info_buf,
ctx->codec.h264.neighbor_info_buf_dma);
-
err_pic_buf:
dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
ctx->codec.h264.pic_info_buf,
@@ -572,15 +596,20 @@ static void cedrus_h264_stop(struct cedrus_ctx *ctx)
{
struct cedrus_dev *dev = ctx->dev;
- dma_free_coherent(dev->dev, ctx->codec.h264.mv_col_buf_size,
- ctx->codec.h264.mv_col_buf,
- ctx->codec.h264.mv_col_buf_dma);
dma_free_coherent(dev->dev, CEDRUS_NEIGHBOR_INFO_BUF_SIZE,
ctx->codec.h264.neighbor_info_buf,
ctx->codec.h264.neighbor_info_buf_dma);
dma_free_coherent(dev->dev, CEDRUS_PIC_INFO_BUF_SIZE,
ctx->codec.h264.pic_info_buf,
ctx->codec.h264.pic_info_buf_dma);
+ if (ctx->codec.h264.deblk_buf_size)
+ dma_free_coherent(dev->dev, ctx->codec.h264.deblk_buf_size,
+ ctx->codec.h264.deblk_buf,
+ ctx->codec.h264.deblk_buf_dma);
+ if (ctx->codec.h264.intra_pred_buf_size)
+ dma_free_coherent(dev->dev, ctx->codec.h264.intra_pred_buf_size,
+ ctx->codec.h264.intra_pred_buf,
+ ctx->codec.h264.intra_pred_buf_dma);
}
static void cedrus_h264_trigger(struct cedrus_ctx *ctx)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 2cc36d69548e..246d747d3fa9 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -336,9 +336,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
pred_weight_table = &slice_params->pred_weight_table;
/* Activate H265 engine. */
- cedrus_engine_enable(dev, CEDRUS_CODEC_H265);
- if (sps->pic_width_in_luma_samples > 2048)
- cedrus_write(dev, VE_MODE, cedrus_read(dev, VE_MODE) | BIT(21));
+ cedrus_engine_enable(dev, CEDRUS_CODEC_H265, ctx->src_fmt.width);
/* Source offset and length in bits. */
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 6be604c52d5c..4b6c69010e39 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -30,7 +30,8 @@
#include "cedrus_hw.h"
#include "cedrus_regs.h"
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
+int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec,
+ unsigned int width)
{
u32 reg = 0;
@@ -58,6 +59,11 @@ int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec)
return -EINVAL;
}
+ if (width >= 4096)
+ reg |= BIT(22);
+ if (width > 2048)
+ reg |= BIT(21);
+
cedrus_write(dev, VE_MODE, reg);
return 0;
@@ -83,9 +89,6 @@ void cedrus_dst_format_set(struct cedrus_dev *dev,
reg = VE_PRIMARY_OUT_FMT_NV12;
cedrus_write(dev, VE_PRIMARY_OUT_FMT, reg);
- reg = VE_CHROMA_BUF_LEN_SDRT(chroma_size / 2);
- cedrus_write(dev, VE_CHROMA_BUF_LEN, reg);
-
reg = chroma_size / 2;
cedrus_write(dev, VE_PRIMARY_CHROMA_BUF_LEN, reg);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index b43c77d54b95..40b44722b7c0 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -18,7 +18,8 @@
#define CEDRUS_CLOCK_RATE_DEFAULT 320000000
-int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
+int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec,
+ unsigned int width);
void cedrus_engine_disable(struct cedrus_dev *dev);
void cedrus_dst_format_set(struct cedrus_dev *dev,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
index cb45fda9aaeb..2f6384ca385d 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c
@@ -96,7 +96,7 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
quantization = run->mpeg2.quantization;
/* Activate MPEG engine. */
- cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2);
+ cedrus_engine_enable(dev, CEDRUS_CODEC_MPEG2, ctx->src_fmt.width);
/* Set intra quantization matrix. */
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
index a2931f322c7a..df000b7c99be 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h
@@ -41,6 +41,10 @@
#define VE_MODE_DEC_H264 (0x01 << 0)
#define VE_MODE_DEC_MPEG (0x00 << 0)
+#define VE_DBLK_INTRAPRED_BUF_CTRL 0x50
+#define VE_DBLK_DRAM_BUF_ADDR 0x54
+#define VE_INTRAPRED_DRAM_BUF_ADDR 0x58
+
#define VE_PRIMARY_CHROMA_BUF_LEN 0xc4
#define VE_PRIMARY_FB_LINE_STRIDE 0xc8
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index adf00513c15f..b24317b26fd2 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -29,8 +29,8 @@
#define CEDRUS_MIN_WIDTH 16U
#define CEDRUS_MIN_HEIGHT 16U
-#define CEDRUS_MAX_WIDTH 3840U
-#define CEDRUS_MAX_HEIGHT 2160U
+#define CEDRUS_MAX_WIDTH 4096U
+#define CEDRUS_MAX_HEIGHT 2768U
static struct cedrus_format cedrus_formats[] = {
{
--
2.20.1

View File

@ -0,0 +1,62 @@
From 9ce5c66f0f98cc968598307f7f7feb39a83d7342 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Tue, 26 Feb 2019 20:45:14 +0000
Subject: [PATCH] WIP: dw-hdmi-cec: sleep 100ms on error
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index 6c323510f128..b5a1a85c8700 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -132,8 +133,15 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data)
dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0);
- if (stat & CEC_STAT_ERROR_INIT) {
- cec->tx_status = CEC_TX_STATUS_ERROR;
+ /* Status with both done and error_initiator bits have been seen
+ * on Rockchip RK3328 devices, transmit attempt seems to have failed
+ * when this happens, report as low drive and block cec-framework
+ * 100ms before core retransmits the failed message, this seems to
+ * mitigate the issue with failed transmit attempts.
+ */
+ if ((stat & (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) == (CEC_STAT_DONE|CEC_STAT_ERROR_INIT)) {
+ pr_info("dw_hdmi_cec_hardirq: stat=%02x LOW_DRIVE\n", stat);
+ cec->tx_status = CEC_TX_STATUS_LOW_DRIVE;
cec->tx_done = true;
ret = IRQ_WAKE_THREAD;
} else if (stat & CEC_STAT_DONE) {
@@ -144,6 +152,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data)
cec->tx_status = CEC_TX_STATUS_NACK;
cec->tx_done = true;
ret = IRQ_WAKE_THREAD;
+ } else if (stat & CEC_STAT_ERROR_INIT) {
+ cec->tx_status = CEC_TX_STATUS_ERROR;
+ cec->tx_done = true;
+ ret = IRQ_WAKE_THREAD;
}
if (stat & CEC_STAT_EOM) {
@@ -176,6 +188,8 @@ static irqreturn_t dw_hdmi_cec_thread(int irq, void *data)
if (cec->tx_done) {
cec->tx_done = false;
+ if (cec->tx_status == CEC_TX_STATUS_LOW_DRIVE)
+ msleep(100);
cec_transmit_attempt_done(adap, cec->tx_status);
}
if (cec->rx_done) {
--
2.20.1

View File

@ -0,0 +1,232 @@
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a63e5f0dae56..fdda26f8b056 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2634,7 +2634,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->audio = platform_device_register_full(&pdevinfo);
}
- if (config0 & HDMI_CONFIG0_CEC) {
+ if (!plat_data->is_cec_unusable && (config0 & HDMI_CONFIG0_CEC)) {
cec.hdmi = hdmi;
cec.ops = &dw_hdmi_cec_ops;
cec.irq = irq;
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 1dbbc3a1b763..7149c72e44c8 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -60,6 +60,16 @@ config DRM_SUN8I_DW_HDMI
DesignWare HDMI controller with custom HDMI PHY. If M is
selected the module will be called sun8i_dw_hdmi.
+config DRM_SUN8I_DW_HDMI_CEC
+ bool "Allwinner DesignWare HDMI CEC Support for 40nm SoCs"
+ depends on DRM_SUN8I_DW_HDMI
+ select CEC_CORE
+ select CEC_PIN
+ help
+ Choose this option if you have an 40nm Allwinner SoC with
+ the DesignWare HDMI controller with custom HDMI PHY and
+ you want to use CEC.
+
config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
default MACH_SUN8I
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 720c5aa8adc1..82dd84094638 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -12,6 +12,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
+#include <media/cec-pin.h>
#define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000
#define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0)
@@ -144,6 +145,13 @@
#define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK GENMASK(5, 0)
#define SUN8I_HDMI_PHY_CEC_REG 0x003c
+#define SUN8I_HDMI_PHY_CEC_PIN_CTRL BIT(7)
+/*
+ * Documentation says that this bit is output enable. However,
+ * it seems that this bit is actually output disable.
+ */
+#define SUN8I_HDMI_PHY_CEC_OUT_DIS BIT(2)
+#define SUN8I_HDMI_PHY_CEC_IN_DATA BIT(1)
struct sun8i_hdmi_phy;
@@ -151,6 +159,7 @@ struct sun8i_hdmi_phy_variant {
bool has_phy_clk;
bool has_second_pll;
unsigned int is_custom_phy : 1;
+ unsigned int bit_bang_cec : 1;
const struct dw_hdmi_curr_ctrl *cur_ctr;
const struct dw_hdmi_mpll_config *mpll_cfg;
const struct dw_hdmi_phy_config *phy_cfg;
@@ -163,6 +172,8 @@ struct sun8i_hdmi_phy_variant {
};
struct sun8i_hdmi_phy {
+ struct cec_adapter *cec_adapter;
+ struct cec_notifier *cec_notifier;
struct clk *clk_bus;
struct clk *clk_mod;
struct clk *clk_phy;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 66ea3a902e36..70e291353569 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -503,8 +503,9 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0);
- /* set HW control of CEC pins */
- regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0);
+ /* manual control of CEC pins */
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+ SUN8I_HDMI_PHY_CEC_PIN_CTRL);
/* read calibration data */
regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val);
@@ -530,8 +531,49 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
plat_data->cur_ctr = variant->cur_ctr;
plat_data->phy_config = variant->phy_cfg;
}
+ plat_data->is_cec_unusable = phy->variant->bit_bang_cec;
}
+#ifdef CONFIG_DRM_SUN8I_DW_HDMI_CEC
+static bool sun8i_hdmi_phy_cec_pin_read(struct cec_adapter *adap)
+{
+ struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+ unsigned int val;
+
+ regmap_read(phy->regs, SUN8I_HDMI_PHY_CEC_REG, &val);
+
+ return val & SUN8I_HDMI_PHY_CEC_IN_DATA;
+}
+
+static void sun8i_hdmi_phy_cec_pin_low(struct cec_adapter *adap)
+{
+ struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+
+ /* Start driving the CEC pin low */
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+ SUN8I_HDMI_PHY_CEC_PIN_CTRL);
+}
+
+static void sun8i_hdmi_phy_cec_pin_high(struct cec_adapter *adap)
+{
+ struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+
+ /*
+ * Stop driving the CEC pin, the pull up will take over
+ * unless another CEC device is driving the pin low.
+ */
+ regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+ SUN8I_HDMI_PHY_CEC_PIN_CTRL |
+ SUN8I_HDMI_PHY_CEC_OUT_DIS);
+}
+
+static const struct cec_pin_ops sun8i_hdmi_phy_cec_pin_ops = {
+ .read = sun8i_hdmi_phy_cec_pin_read,
+ .low = sun8i_hdmi_phy_cec_pin_low,
+ .high = sun8i_hdmi_phy_cec_pin_high,
+};
+#endif
+
static struct regmap_config sun8i_hdmi_phy_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
@@ -548,6 +590,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
};
static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
+ .bit_bang_cec = true,
.has_phy_clk = true,
.is_custom_phy = true,
.phy_init = &sun8i_hdmi_phy_init_h3,
@@ -556,6 +599,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
};
static const struct sun8i_hdmi_phy_variant sun8i_r40_hdmi_phy = {
+ .bit_bang_cec = true,
.has_phy_clk = true,
.has_second_pll = true,
.is_custom_phy = true,
@@ -565,6 +609,7 @@ static const struct sun8i_hdmi_phy_variant sun8i_r40_hdmi_phy = {
};
static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
+ .bit_bang_cec = true,
.has_phy_clk = true,
.is_custom_phy = true,
.phy_init = &sun8i_hdmi_phy_init_h3,
@@ -708,10 +753,40 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
goto err_disable_clk_bus;
}
+#ifdef CONFIG_DRM_SUN8I_DW_HDMI_CEC
+ if (phy->variant->bit_bang_cec) {
+ phy->cec_notifier = cec_notifier_get(dev);
+ if (!phy->cec_notifier) {
+ ret = -ENOMEM;
+ goto err_disable_clk_mod;
+ }
+
+ phy->cec_adapter =
+ cec_pin_allocate_adapter(&sun8i_hdmi_phy_cec_pin_ops,
+ phy, "sun8i-cec",
+ CEC_CAP_DEFAULTS);
+ ret = PTR_ERR_OR_ZERO(phy->cec_adapter);
+ if (ret < 0)
+ goto err_put_cec_notifier;
+
+ ret = cec_register_adapter(phy->cec_adapter, dev);
+ if (ret < 0)
+ goto err_delete_cec_adapter;
+
+ cec_register_cec_notifier(phy->cec_adapter, phy->cec_notifier);
+ }
+#endif
+
hdmi->phy = phy;
return 0;
+err_delete_cec_adapter:
+ cec_delete_adapter(phy->cec_adapter);
+err_put_cec_notifier:
+ cec_notifier_put(phy->cec_notifier);
+err_disable_clk_mod:
+ clk_disable_unprepare(phy->clk_mod);
err_disable_clk_bus:
clk_disable_unprepare(phy->clk_bus);
err_deassert_rst_phy:
@@ -736,6 +811,10 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
{
struct sun8i_hdmi_phy *phy = hdmi->phy;
+ cec_unregister_adapter(phy->cec_adapter);
+ if (phy->cec_notifier)
+ cec_notifier_put(phy->cec_notifier);
+
clk_disable_unprepare(phy->clk_mod);
clk_disable_unprepare(phy->clk_bus);
clk_disable_unprepare(phy->clk_phy);
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 66e70770cce5..764b8bcfa62c 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -144,6 +144,8 @@ struct dw_hdmi_plat_data {
int (*configure_phy)(struct dw_hdmi *hdmi,
const struct dw_hdmi_plat_data *pdata,
unsigned long mpixelclock);
+
+ unsigned int is_cec_unusable : 1;
};
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,

View File

@ -0,0 +1,25 @@
From 18c9a269e2b744ee84f32de9d5c6c66857725ef8 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 15 Dec 2018 12:56:53 +0100
Subject: [PATCH 20/20] cedrus increase frequency
---
drivers/staging/media/sunxi/cedrus/cedrus_hw.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index b43c77d54b95..70677571f3d3 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -16,7 +16,7 @@
#ifndef _CEDRUS_HW_H_
#define _CEDRUS_HW_H_
-#define CEDRUS_CLOCK_RATE_DEFAULT 320000000
+#define CEDRUS_CLOCK_RATE_DEFAULT 402000000
int cedrus_engine_enable(struct cedrus_dev *dev, enum cedrus_codec codec);
void cedrus_engine_disable(struct cedrus_dev *dev);
--
2.20.0

View File

@ -0,0 +1,280 @@
From patchwork Thu Nov 15 10:39:03 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [U-Boot,v3] sun8i: h3: Add support for the Beelink-x2 STB
X-Patchwork-Submitter: Code Kipper <codekipper@gmail.com>
X-Patchwork-Id: 998268
Message-Id: <20181115103903.7348-1-codekipper@gmail.com>
To: maxime.ripard@free-electrons.com
Cc: u-boot@lists.denx.de, linux-sunxi@googlegroups.com, jagan@openedev.com,
Marcus Cooper <codekipper@gmail.com>
Date: Thu, 15 Nov 2018 11:39:03 +0100
From: codekipper@gmail.com
List-Id: U-Boot discussion <u-boot.lists.denx.de>
From: Marcus Cooper <codekipper@gmail.com>
The Beelink X2 is an STB based on the Allwinner H3 SoC with a uSD slot,
2 USB ports( 1 * USB-2 Host, 1 USB OTG), a 10/100M ethernet port using the
SoC's integrated PHY, Wifi via an sdio wifi chip, HDMI, an IR receiver, a
dual colour LED and an optical S/PDIF connector.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
Changes in v3:
- Removed incorrect commit author
- Included v1-v2 change info
Changes in v2:
- updated dts to reflex current linux kernel status
---
arch/arm/dts/Makefile | 1 +
arch/arm/dts/sun8i-h3-beelink-x2.dts | 179 +++++++++++++++++++++++++++
board/sunxi/MAINTAINERS | 5 +
configs/beelink_x2_defconfig | 19 +++
4 files changed, 204 insertions(+)
create mode 100644 arch/arm/dts/sun8i-h3-beelink-x2.dts
create mode 100644 configs/beelink_x2_defconfig
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 1cbb45d679..cc217d4f98 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -370,6 +370,7 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
sun8i-h2-plus-orangepi-r1.dtb \
sun8i-h2-plus-orangepi-zero.dtb \
sun8i-h3-bananapi-m2-plus.dtb \
+ sun8i-h3-beelink-x2.dtb \
sun8i-h3-libretech-all-h3-cc.dtb \
sun8i-h3-nanopi-m1.dtb \
sun8i-h3-nanopi-m1-plus.dtb \
diff --git a/arch/arm/dts/sun8i-h3-beelink-x2.dts b/arch/arm/dts/sun8i-h3-beelink-x2.dts
new file mode 100644
index 0000000000..683c5c31a9
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-beelink-x2.dts
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Device Tree Source for Beelink X2
+//
+// Copyright (C) 2018 Marcus Cooper <codekipper@gmail.com>
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Beelink X2";
+ compatible = "roofull,beelink-x2", "allwinner,sun8i-h3";
+
+ aliases {
+ serial0 = &uart0;
+ /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+ ethernet0 = &emac;
+ ethernet1 = &sdiowifi;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ blue {
+ label = "beelink-x2:blue:pwr";
+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+ default-state = "on";
+ };
+
+ red {
+ label = "beelink-x2:red:standby";
+ gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
+ };
+ };
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
+ };
+
+ sound_spdif {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "On-board SPDIF";
+
+ simple-audio-card,cpu {
+ sound-dai = <&spdif>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&spdif_out>;
+ };
+ };
+
+ spdif_out: spdif-out {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ };
+};
+
+&de {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&ir {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_pins_a>;
+ status = "okay";
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ status = "okay";
+};
+
+&mmc1 {
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ /*
+ * Explicitly define the sdio device, so that we can add an ethernet
+ * alias for it (which e.g. makes u-boot set a mac-address).
+ */
+ sdiowifi: sdio_wifi@1 {
+ reg = <1>;
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&reg_usb0_vbus {
+ gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
+ status = "okay";
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spdif_tx_pins_a>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ /* USB VBUS is always on except for the OTG port */
+ status = "okay";
+ usb0_id_det-gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA07 */
+ usb0_vbus-supply = <&reg_usb0_vbus>;
+};
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 478e37285f..6417158fd1 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -159,6 +159,11 @@ M: Jagan Teki <jagan@amarulasolutions.com>
S: Maintained
F: configs/bananapi_m64_defconfig
+BEELINK X2 BOARD
+M: Marcus Cooper <codekipper@gmail.com>
+S: Maintained
+F: configs/beelink_x2_defconfig
+
COLOMBUS BOARD
M: Maxime Ripard <maxime.ripard@bootlin.com>
S: Maintained
diff --git a/configs/beelink_x2_defconfig b/configs/beelink_x2_defconfig
new file mode 100644
index 0000000000..6508e470a0
--- /dev/null
+++ b/configs/beelink_x2_defconfig
@@ -0,0 +1,19 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=624
+CONFIG_DRAM_ZQ=3881979
+CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-beelink-x2"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_CONSOLE_MUX=y
+CONFIG_SPL_I2C_SUPPORT=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_SUN8I_EMAC=y
+CONFIG_SY8106A_POWER=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y

View File

@ -0,0 +1,13 @@
diff -Nur a/arch/arm/Kconfig usb/arch/arm/Kconfig
--- a/arch/arm/Kconfig 2016-09-12 16:05:51.000000000 +0200
+++ usb/arch/arm/Kconfig 2016-09-21 19:19:44.533396743 +0200
@@ -590,9 +590,8 @@
select SPL_SYS_THUMB_BUILD if !ARM64
select SYS_NS16550
select SYS_THUMB_BUILD if !ARM64
select USB if DISTRO_DEFAULTS
- select USB_KEYBOARD if DISTRO_DEFAULTS
select USB_STORAGE if DISTRO_DEFAULTS
select USE_TINY_PRINTF
imply CMD_DM
imply CMD_GPT

View File

@ -0,0 +1,135 @@
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 9dbea649a0..a2aced2cab 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -132,7 +132,7 @@ static int sunxi_dw_hdmi_wait_for_hpd(void)
return -1;
}
-static void sunxi_dw_hdmi_phy_set(uint clock)
+static void sunxi_dw_hdmi_phy_set(uint clock, int phy_div)
{
struct sunxi_hdmi_phy * const phy =
(struct sunxi_hdmi_phy *)(SUNXI_HDMI_BASE + HDMI_PHY_OFFS);
@@ -146,7 +146,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
switch (div) {
case 1:
writel(0x30dc5fc0, &phy->pll);
- writel(0x800863C0, &phy->clk);
+ writel(0x800863C0 | (phy_div - 1), &phy->clk);
mdelay(10);
writel(0x00000001, &phy->unk3);
setbits_le32(&phy->pll, BIT(25));
@@ -164,7 +164,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
break;
case 2:
writel(0x39dc5040, &phy->pll);
- writel(0x80084381, &phy->clk);
+ writel(0x80084380 | (phy_div - 1), &phy->clk);
mdelay(10);
writel(0x00000001, &phy->unk3);
setbits_le32(&phy->pll, BIT(25));
@@ -178,7 +178,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
break;
case 4:
writel(0x39dc5040, &phy->pll);
- writel(0x80084343, &phy->clk);
+ writel(0x80084340 | (phy_div - 1), &phy->clk);
mdelay(10);
writel(0x00000001, &phy->unk3);
setbits_le32(&phy->pll, BIT(25));
@@ -192,7 +192,7 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
break;
case 11:
writel(0x39dc5040, &phy->pll);
- writel(0x8008430a, &phy->clk);
+ writel(0x80084300 | (phy_div - 1), &phy->clk);
mdelay(10);
writel(0x00000001, &phy->unk3);
setbits_le32(&phy->pll, BIT(25));
@@ -207,36 +207,46 @@ static void sunxi_dw_hdmi_phy_set(uint clock)
}
}
-static void sunxi_dw_hdmi_pll_set(uint clk_khz)
+static void sunxi_dw_hdmi_pll_set(uint clk_khz, int *phy_div)
{
- int value, n, m, div = 0, diff;
- int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
-
- div = sunxi_dw_hdmi_get_divider(clk_khz * 1000);
+ int value, n, m, div, diff;
+ int best_n = 0, best_m = 0, best_div = 0, best_diff = 0x0FFFFFFF;
/*
* Find the lowest divider resulting in a matching clock. If there
* is no match, pick the closest lower clock, as monitors tend to
* not sync to higher frequencies.
*/
- for (m = 1; m <= 16; m++) {
- n = (m * div * clk_khz) / 24000;
-
- if ((n >= 1) && (n <= 128)) {
- value = (24000 * n) / m / div;
- diff = clk_khz - value;
- if (diff < best_diff) {
- best_diff = diff;
- best_m = m;
- best_n = n;
+ for (div = 1; div <= 16; div++) {
+ int target = clk_khz * div;
+
+ if (target < 192000)
+ continue;
+ if (target > 912000)
+ continue;
+
+ for (m = 1; m <= 16; m++) {
+ n = (m * target) / 24000;
+
+ if ((n >= 1) && (n <= 128)) {
+ value = (24000 * n) / m / div;
+ diff = clk_khz - value;
+ if (diff < best_diff) {
+ best_diff = diff;
+ best_m = m;
+ best_n = n;
+ best_div = div;
+ }
}
}
}
+ *phy_div = best_div;
+
clock_set_pll3_factors(best_m, best_n);
debug("dotclock: %dkHz = %dkHz: (24MHz * %d) / %d / %d\n",
- clk_khz, (clock_get_pll3() / 1000) / div,
- best_n, best_m, div);
+ clk_khz, (clock_get_pll3() / 1000) / best_div,
+ best_n, best_m, best_div);
}
static void sunxi_dw_hdmi_lcdc_init(int mux, const struct display_timing *edid,
@@ -244,7 +254,7 @@ static void sunxi_dw_hdmi_lcdc_init(int mux, const struct display_timing *edid,
{
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- int div = sunxi_dw_hdmi_get_divider(edid->pixelclock.typ);
+ int div = clock_get_pll3() / edid->pixelclock.typ;
struct sunxi_lcdc_reg *lcdc;
if (mux == 0) {
@@ -276,8 +286,10 @@ static void sunxi_dw_hdmi_lcdc_init(int mux, const struct display_timing *edid,
static int sunxi_dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
{
- sunxi_dw_hdmi_pll_set(mpixelclock/1000);
- sunxi_dw_hdmi_phy_set(mpixelclock);
+ int phy_div;
+
+ sunxi_dw_hdmi_pll_set(mpixelclock/1000, &phy_div);
+ sunxi_dw_hdmi_phy_set(mpixelclock, phy_div);
return 0;
}

View File

@ -9,6 +9,28 @@ devices = {
},
},
'Allwinner' : {
'A64' : {
'pine64' : { 'dtb' : 'sun50i-a64-pine64.dtb', 'config' : 'pine64_plus_defconfig' },
'pine64_plus' : { 'dtb' : 'sun50i-a64-pine64-plus.dtb', 'config' : 'pine64_plus_defconfig' },
'pine64_lts' : { 'dtb' : 'sun50i-a64-sopine-baseboard.dtb', 'config' : 'sopine_baseboard_defconfig' },
'orangepi_win' : { 'dtb' : 'sun50i-a64-orangepi-win.dtb', 'config' : 'orangepi_win_defconfig' },
},
'H3' : {
'bananapi_m2p' : { 'dtb' : 'sun8i-h3-bananapi-m2-plus.dtb', 'config' : 'Sinovoip_BPI_M2_Plus_defconfig' },
'beelink_x2' : { 'dtb' : 'sun8i-h3-beelink-x2.dtb', 'config' : 'beelink_x2_defconfig' },
'libretech_h3' : { 'dtb' : 'sun8i-h3-libretech-all-h3-cc.dtb', 'config' : 'libretech_all_h3_cc_h3_defconfig' },
'orangepi_2' : { 'dtb' : 'sun8i-h3-orangepi-2.dtb', 'config' : 'orangepi_2_defconfig' },
'orangepi_pc': { 'dtb': 'sun8i-h3-orangepi-pc.dtb', 'config': 'orangepi_pc_defconfig' },
'orangepi_pc_plus': { 'dtb': 'sun8i-h3-orangepi-pc-plus.dtb', 'config': 'orangepi_pc_plus_defconfig' },
'orangepi_plus2e': { 'dtb': 'sun8i-h3-orangepi-plus2e.dtb', 'config': 'orangepi_plus2e_defconfig' },
'orangepi_plus': { 'dtb': 'sun8i-h3-orangepi-plus.dtb', 'config': 'orangepi_plus_defconfig' },
},
'H6' : {
'pine_h64' : { 'dtb' : 'sun50i-h6-pine-h64.dtb', 'config' : 'pine_h64_defconfig' },
},
},
'Rockchip' : {
'MiQi' : { 'rk3288' : { 'dtb' : 'rk3288-miqi.dtb', 'config' : 'miqi-rk3288_config' }, },
'RK3328' : {