Allwinner: initial project

This commit is contained in:
Lukas Rusak 2016-04-12 22:01:47 -07:00 committed by Jernej Skrabec
parent 421cc1272c
commit 5d568f9796
47 changed files with 23048 additions and 0 deletions

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;
}