rockchip-rk322x: new device

Adds a generic device target for the Rockchip RK3228 and RK3229 SoCs
with mainline U-Boot and kernel. I tested this on my MXQ Pro 4K STB,
which originally had Android 7.1 installed. I've been testing it on a
32 GB SD card, as I currently have [ilmich's
LibreELEC port](https://github.com/rk-unofficial-cfw/LibreELEC.tv/tree/le12-rk322x-wip]
installed to the eMMC, though it should boot from eMMC just fine. The
bulk of the patches comes from the aforementioned LibreELEC port and
Armbian.

Part-of: <https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/6982>
This commit is contained in:
leap123 2025-08-26 21:04:24 +07:00 committed by The Friendly Merge Bot
parent a68e7fb105
commit 6a9168cd47
No known key found for this signature in database
37 changed files with 23912 additions and 0 deletions

View file

@ -0,0 +1,48 @@
# Maintainer: leap123 <leap123@canaglie.org>
pkgname=device-rockchip-rk322x
pkgdesc="Generic device package for various Rockchip RK3228/RK3229-based devices"
pkgver=1
pkgrel=0
url="https://postmarketos.org"
license="MIT"
arch="armv7"
options="!check !archcheck"
depends="
firmware-rockchip-rk322x
linux-postmarketos-rockchip-rk322x
linux-firmware-rockchip
mkbootimg
postmarketos-base
u-boot-rockchip-rk322x
"
subpackages="$pkgname-xorg:x11"
makedepends="devicepkg-dev"
source="
deviceinfo
modules-initfs
xorg.conf
"
build() {
devicepkg_build $startdir $pkgname
}
x11() {
pkgdesc="X11 configuration for Rockchip RK3228/RK3229-based devices"
# Shamelessly taken from the Amlogic Aarch64 SOC package which in turn is shamelessly taken from Armbian.
# (modified to fit rockchip instead of amlogic ofc)
# https://github.com/armbian/build/blob/master/config/sources/families/include/meson64_common.inc
install_if="$pkgname xorg-server"
install -D -m644 "$srcdir"/xorg.conf \
"$subpkgdir"/etc/X11/xorg.conf.d/11-rockchip.conf
}
package() {
devicepkg_package $startdir $pkgname
}
sha512sums="
7712afecf08fff8fef3cd0667b8bacc24303adafb2c980024b5420c0c677ef873e825c3624b093948f09438064180d176766044a982f15bfc1c10c510535fdd7 deviceinfo
967c1208357b67bd947853b82fc04db3603c86b159972d67a741eb5970498206b89657337e2d8b6c282f1083f38a93d7a0d5cf7b102a19a81e98bbe46b5741ad modules-initfs
dc483ce1abaae00124cff1251ed10f9cc4dd2c1ac03d162fe095371e76fd9b90ee868d760cdda0b19a3faaaba2687133e492c045da9c4726a33abd0480aef893 xorg.conf
"

View file

@ -0,0 +1,35 @@
# Reference: <https://postmarketos.org/deviceinfo>
# Please use double quotes only. You can source this file in shell
# scripts.
deviceinfo_format_version="0"
deviceinfo_name="Rockchip rk3228/rk3229-based device"
deviceinfo_manufacturer="Rockchip"
deviceinfo_codename="rockchip-rk322x"
deviceinfo_year="2016"
deviceinfo_dtb="rk322*"
deviceinfo_arch="armv7"
deviceinfo_uboot_boardname="rockchip-rk322x"
# Device related
deviceinfo_chassis="embedded"
deviceinfo_keyboard="false"
deviceinfo_external_storage="true"
deviceinfo_drm="true"
deviceinfo_getty="ttyS2;115200"
deviceinfo_disable_dhcpd="true"
deviceinfo_swap_size_recommended="512"
# Installer related
deviceinfo_dev_internal_storage="/dev/mmcblk1"
deviceinfo_dev_internal_storage_repartition="true"
# Bootloader related
deviceinfo_flash_method="none"
deviceinfo_kernel_cmdline="quiet loglevel=2 earlycon=uart8250,mmio32,0x11030000 PMOS_FORCE_PARTITION_RESIZE"
deviceinfo_partition_type="gpt"
deviceinfo_boot_filesystem="fat32"
deviceinfo_generate_extlinux_config="true"
deviceinfo_boot_part_start="32768"
deviceinfo_sd_embed_firmware_step_size="512"
deviceinfo_sd_embed_firmware="u-boot/rockchip-rk322x/idbloader.img:64,u-boot/rockchip-rk322x/u-boot.itb:16384"

View file

@ -0,0 +1,5 @@
clk_scmi
drm_kms_helper
drm_shmem_helper
pvi_waveform
rockchip_ebc

View file

@ -0,0 +1,6 @@
Section "OutputClass"
Identifier "Rockchip"
MatchDriver "rockchip"
Driver "modesetting"
Option "PrimaryGPU" "true"
EndSection

View file

@ -0,0 +1,34 @@
# Maintainer: leap123 <leap123@canaglie.org>
pkgname=firmware-rockchip-rk322x
pkgver=1
pkgrel=0
pkgdesc="Firmware files for Rockchip RK3228/RK3229 devices from ilmich's LibreELEC port"
url="https://github.com/ilmich/rkbin"
arch="armv7"
license="proprietary"
makedepends="coreutils"
options="!check !strip !archcheck !tracedeps pmb:cross-native"
# source
_commit="84f2356cf510319665874daf29df9ad8a94ac7e4"
source="rkbin-$_commit.tar.gz::$url/archive/$_commit.tar.gz"
_fwdir="/lib/firmware/postmarketos"
builddir="$srcdir/rkbin-$_commit"
package() {
mkdir -p "$pkgdir"
install -Dm644 firmware/wifi/ssv6051-sw.bin -t "$pkgdir/$_fwdir"
install -Dm644 firmware/wifi/ssv6051-wifi.cfg -t "$pkgdir/$_fwdir"
install -Dm644 firmware/wifi/brcmfmac43342-sdio.bin -t "$pkgdir/$_fwdir"/brcm
install -Dm644 firmware/wifi/brcmfmac43342-sdio.txt -t "$pkgdir/$_fwdir"/brcm
install -Dm644 firmware/wifi/eagle_fw_ate_config_v19.bin -t "$pkgdir/$_fwdir"
install -Dm644 firmware/wifi/eagle_fw_first_init_v19.bin -t "$pkgdir/$_fwdir"
install -Dm644 firmware/wifi/eagle_fw_second_init_v19.bin -t "$pkgdir/$_fwdir"
install -Dm644 firmware/bluetooth/rtl8723cs_xx_config.bin -t "$pkgdir/$_fwdir"/rtl_bt
install -Dm644 firmware/bluetooth/rtl8723cs_xx_fw.bin -t "$pkgdir/$_fwdir"/rtl_bt
}
sha512sums="
c4d3e07b435b0e706ba83149ab2973ce1beb6c1064ccf5db6189f6ca100a5285a5dc5260c5ec26d1e22fba0aa7d46ccc9a594f0b66f356560bd8ab2486e4ac24 rkbin-84f2356cf510319665874daf29df9ad8a94ac7e4.tar.gz
"

View file

@ -0,0 +1,131 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 17 Feb 2019 22:14:38 +0000
Subject: [PATCH] mmc: core: set initial signal voltage on power off
Some boards have SD card connectors where the power rail cannot be switched
off by the driver. If the card has not been power cycled, it may still be
using 1.8V signaling after a warm re-boot. Bootroms expecting 3.3V signaling
will fail to boot from a UHS card that continue to use 1.8V signaling.
Set initial signal voltage in mmc_power_off() to allow re-boot to function.
This fixes re-boot with UHS cards on Asus Tinker Board (Rockchip RK3288),
same issue have been seen on some Rockchip RK3399 boards.
I am sending this as a RFC because I have no insights into SD/MMC subsystem,
this change fix a re-boot issue on my boards and does not break emmc/sdio.
Is this an acceptable workaround? Any advice is appreciated.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/mmc/core/core.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index ef53a2578824..d4c53074154a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1358,6 +1358,14 @@ void mmc_power_off(struct mmc_host *host)
if (host->ios.power_mode == MMC_POWER_OFF)
return;
+ mmc_set_initial_signal_voltage(host);
+
+ /*
+ * This delay should be sufficient to allow the power supply
+ * to reach the minimum voltage.
+ */
+ mmc_delay(host->ios.power_delay_ms);
+
mmc_pwrseq_power_off(host);
host->ios.clock = 0;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 23 Jun 2021 16:59:18 +0200
Subject: [PATCH] arm64: dts: rockchip: Add sdmmc_ext for RK3328
RK3328 SoC has a fourth mmc controller called SDMMC_EXT. Some
boards have sdio wifi connected to it. In order to use it
one would have to add the pinctrls from sdmmc0ext group which
is done on board level.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 49ae15708a0b..60348d517efb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -993,6 +993,20 @@ usb_host0_ohci: usb@ff5d0000 {
status = "disabled";
};
+ sdmmc_ext: mmc@ff5f0000 {
+ compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0x0 0xff5f0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_SDMMC_EXT>, <&cru SCLK_SDMMC_EXT>,
+ <&cru SCLK_SDMMC_EXT_DRV>, <&cru SCLK_SDMMC_EXT_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <150000000>;
+ resets = <&cru SRST_SDMMCEXT>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
usbdrd3: usb@ff600000 {
compatible = "rockchip,rk3328-dwc3", "snps,dwc3";
reg = <0x0 0xff600000 0x0 0x100000>;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 23 Jun 2021 17:02:08 +0200
Subject: [PATCH] arm64: dts: rockchip: Add sdmmc/sdio/emmc reset controls for
RK3328
The DW MCI controller driver will use them to reset the IP block before
initialisation.
Fixes: d717f7352ec6 ("arm64: dts: rockchip: add sdmmc/sdio/emmc nodes for RK3328 SoCs")
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 60348d517efb..d7e44d174d7b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -871,6 +871,8 @@ sdmmc: mmc@ff500000 {
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
max-frequency = <150000000>;
+ resets = <&cru SRST_MMC0>;
+ reset-names = "reset";
status = "disabled";
};
@@ -883,6 +885,8 @@ sdio: mmc@ff510000 {
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
max-frequency = <150000000>;
+ resets = <&cru SRST_SDIO>;
+ reset-names = "reset";
status = "disabled";
};
@@ -895,6 +899,8 @@ emmc: mmc@ff520000 {
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
max-frequency = <150000000>;
+ resets = <&cru SRST_EMMC>;
+ reset-names = "reset";
status = "disabled";
};

View file

@ -0,0 +1,659 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 21:54:35 +0000
Subject: [PATCH] media: v4l2-common: Add helpers to calculate bytesperline and
sizeimage
Add helper functions to calculate plane bytesperline and sizeimage, these
new helpers consider block width and height when calculating plane
bytesperline and sizeimage.
This prepare support for new pixel formats added in next patch that make
use of block width and height.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/media/v4l2-core/v4l2-common.c | 77 +++++++++++++--------------
1 file changed, 38 insertions(+), 39 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index e0fbe6ba4b6c..cb2f1acab7cf 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -338,6 +338,33 @@ static inline unsigned int v4l2_format_block_height(const struct v4l2_format_inf
return info->block_h[plane];
}
+static inline unsigned int v4l2_format_plane_width(const struct v4l2_format_info *info, int plane,
+ unsigned int width)
+{
+ unsigned int hdiv = plane ? info->hdiv : 1;
+ unsigned int bytes = DIV_ROUND_UP(width * info->bpp[plane],
+ v4l2_format_block_width(info, plane) *
+ v4l2_format_block_height(info, plane));
+
+ return DIV_ROUND_UP(bytes, hdiv);
+}
+
+static inline unsigned int v4l2_format_plane_height(const struct v4l2_format_info *info, int plane,
+ unsigned int height)
+{
+ unsigned int vdiv = plane ? info->vdiv : 1;
+ unsigned int lines = ALIGN(height, v4l2_format_block_height(info, plane));
+
+ return DIV_ROUND_UP(lines, vdiv);
+}
+
+static inline unsigned int v4l2_format_plane_size(const struct v4l2_format_info *info, int plane,
+ unsigned int width, unsigned int height)
+{
+ return v4l2_format_plane_width(info, plane, width) *
+ v4l2_format_plane_height(info, plane, height);
+}
+
void v4l2_apply_frmsize_constraints(u32 *width, u32 *height,
const struct v4l2_frmsize_stepwise *frmsize)
{
@@ -373,37 +400,19 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt,
if (info->mem_planes == 1) {
plane = &pixfmt->plane_fmt[0];
- plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0];
+ plane->bytesperline = v4l2_format_plane_width(info, 0, width);
plane->sizeimage = 0;
- for (i = 0; i < info->comp_planes; i++) {
- unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
- unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
- unsigned int aligned_width;
- unsigned int aligned_height;
-
- aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
- aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
-
- plane->sizeimage += info->bpp[i] *
- DIV_ROUND_UP(aligned_width, hdiv) *
- DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i];
- }
+ for (i = 0; i < info->comp_planes; i++)
+ plane->sizeimage +=
+ v4l2_format_plane_size(info, i, width, height);
} else {
for (i = 0; i < info->comp_planes; i++) {
- unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
- unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
- unsigned int aligned_width;
- unsigned int aligned_height;
-
- aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
- aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
-
plane = &pixfmt->plane_fmt[i];
plane->bytesperline =
- info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) / info->bpp_div[i];
- plane->sizeimage =
- plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv);
+ v4l2_format_plane_width(info, i, width);
+ plane->sizeimage = plane->bytesperline *
+ v4l2_format_plane_height(info, i, height);
}
}
return 0;
@@ -427,22 +436,12 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat,
pixfmt->width = width;
pixfmt->height = height;
pixfmt->pixelformat = pixelformat;
- pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0];
+ pixfmt->bytesperline = v4l2_format_plane_width(info, 0, width);
pixfmt->sizeimage = 0;
- for (i = 0; i < info->comp_planes; i++) {
- unsigned int hdiv = (i == 0) ? 1 : info->hdiv;
- unsigned int vdiv = (i == 0) ? 1 : info->vdiv;
- unsigned int aligned_width;
- unsigned int aligned_height;
-
- aligned_width = ALIGN(width, v4l2_format_block_width(info, i));
- aligned_height = ALIGN(height, v4l2_format_block_height(info, i));
-
- pixfmt->sizeimage += info->bpp[i] *
- DIV_ROUND_UP(aligned_width, hdiv) *
- DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i];
- }
+ for (i = 0; i < info->comp_planes; i++)
+ pixfmt->sizeimage +=
+ v4l2_format_plane_size(info, i, width, height);
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt);
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 21:54:36 +0000
Subject: [PATCH] media: v4l2: Add NV15 and NV20 pixel formats
Add NV15 and NV20 pixel formats used by the Rockchip Video Decoder for
10-bit buffers.
NV15 and NV20 is a packed 10-bit 4:2:0/4:2:2 semi-planar Y/UV format
similar to P010 and P210 but has no padding between components. Instead,
luminance and chrominance samples are grouped into 4s so that each group is
packed into an integer number of bytes:
YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes
The '15' and '20' suffix refers to the optimum effective bits per pixel
which is achieved when the total number of luminance samples is a multiple
of 8 for NV15 and 4 for NV20.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/media/v4l2-core/v4l2-common.c | 3 +++
drivers/media/v4l2-core/v4l2-ioctl.c | 2 ++
include/uapi/linux/videodev2.h | 3 +++
3 files changed, 8 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index cb2f1acab7cf..8446a1deffd8 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -268,6 +268,9 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
{ .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
{ .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 },
+ { .format = V4L2_PIX_FMT_NV15, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } },
+ { .format = V4L2_PIX_FMT_NV20, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 5, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1, .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 } },
+
{ .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 },
{ .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 },
{ .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 1 },
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index e6fd355a2e92..24771edaa4f2 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1354,6 +1354,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_NV42: descr = "Y/VU 4:4:4"; break;
case V4L2_PIX_FMT_P010: descr = "10-bit Y/UV 4:2:0"; break;
case V4L2_PIX_FMT_P012: descr = "12-bit Y/UV 4:2:0"; break;
+ case V4L2_PIX_FMT_NV15: descr = "10-bit Y/UV 4:2:0 (Packed)"; break;
+ case V4L2_PIX_FMT_NV20: descr = "10-bit Y/UV 4:2:2 (Packed)"; break;
case V4L2_PIX_FMT_NV12_4L4: descr = "Y/UV 4:2:0 (4x4 Linear)"; break;
case V4L2_PIX_FMT_NV12_16L16: descr = "Y/UV 4:2:0 (16x16 Linear)"; break;
case V4L2_PIX_FMT_NV12_32L32: descr = "Y/UV 4:2:0 (32x32 Linear)"; break;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 01e630f2ec78..cea44992aea3 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -628,6 +628,9 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/VU 4:4:4 */
#define V4L2_PIX_FMT_P010 v4l2_fourcc('P', '0', '1', '0') /* 24 Y/UV 4:2:0 10-bit per component */
+#define V4L2_PIX_FMT_NV15 v4l2_fourcc('N', 'V', '1', '5') /* 15 Y/UV 4:2:0 10-bit packed */
+#define V4L2_PIX_FMT_NV20 v4l2_fourcc('N', 'V', '2', '0') /* 20 Y/UV 4:2:2 10-bit packed */
+
/* two non contiguous planes - one Y, one Cr + Cb interleaved */
#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/UV 4:2:0 */
#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/VU 4:2:0 */
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 21:54:36 +0000
Subject: [PATCH] media: rkvdec: h264: Use bytesperline and buffer height to
calculate stride
Use bytesperline and buffer height to calculate the strides configured.
This does not really change anything other than ensuring the bytesperline
that is signaled to userspace matches what is configured in HW.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/staging/media/rkvdec/rkvdec-h264.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
index 4fc167b42cf0..a8635105e387 100644
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
@@ -896,9 +896,9 @@ static void config_registers(struct rkvdec_ctx *ctx,
dma_addr_t rlc_addr;
dma_addr_t refer_addr;
u32 rlc_len;
- u32 hor_virstride = 0;
- u32 ver_virstride = 0;
- u32 y_virstride = 0;
+ u32 hor_virstride;
+ u32 ver_virstride;
+ u32 y_virstride;
u32 yuv_virstride = 0;
u32 offset;
dma_addr_t dst_addr;
@@ -909,8 +909,8 @@ static void config_registers(struct rkvdec_ctx *ctx,
f = &ctx->decoded_fmt;
dst_fmt = &f->fmt.pix_mp;
- hor_virstride = (sps->bit_depth_luma_minus8 + 8) * dst_fmt->width / 8;
- ver_virstride = round_up(dst_fmt->height, 16);
+ hor_virstride = dst_fmt->plane_fmt[0].bytesperline;
+ ver_virstride = dst_fmt->height;
y_virstride = hor_virstride * ver_virstride;
if (sps->chroma_format_idc == 0)
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 21:54:37 +0000
Subject: [PATCH] media: rkvdec: Extract rkvdec_fill_decoded_pixfmt helper
method
This extract setting decoded pixfmt into a helper method, current code is
replaced with a call to the new helper method.
The helper method is also called from a new function in next patch.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/staging/media/rkvdec/rkvdec.c | 29 ++++++++++++++-------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index 7bab7586918c..40cc791aef26 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -27,6 +27,17 @@
#include "rkvdec.h"
#include "rkvdec-regs.h"
+static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
+ struct v4l2_pix_format_mplane *pix_mp)
+{
+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
+ pix_mp->width, pix_mp->height);
+ pix_mp->plane_fmt[0].sizeimage += 128 *
+ DIV_ROUND_UP(pix_mp->width, 16) *
+ DIV_ROUND_UP(pix_mp->height, 16);
+ pix_mp->field = V4L2_FIELD_NONE;
+}
+
static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
{
struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
@@ -192,13 +203,9 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx)
rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]);
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- v4l2_fill_pixfmt_mp(&f->fmt.pix_mp,
- ctx->coded_fmt_desc->decoded_fmts[0],
- ctx->coded_fmt.fmt.pix_mp.width,
- ctx->coded_fmt.fmt.pix_mp.height);
- f->fmt.pix_mp.plane_fmt[0].sizeimage += 128 *
- DIV_ROUND_UP(f->fmt.pix_mp.width, 16) *
- DIV_ROUND_UP(f->fmt.pix_mp.height, 16);
+ f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width;
+ f->fmt.pix_mp.height = ctx->coded_fmt.fmt.pix_mp.height;
+ rkvdec_fill_decoded_pixfmt(ctx, &f->fmt.pix_mp);
}
static int rkvdec_enum_framesizes(struct file *file, void *priv,
@@ -264,13 +271,7 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv,
&pix_mp->height,
&coded_desc->frmsize);
- v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
- pix_mp->width, pix_mp->height);
- pix_mp->plane_fmt[0].sizeimage +=
- 128 *
- DIV_ROUND_UP(pix_mp->width, 16) *
- DIV_ROUND_UP(pix_mp->height, 16);
- pix_mp->field = V4L2_FIELD_NONE;
+ rkvdec_fill_decoded_pixfmt(ctx, pix_mp);
return 0;
}
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 21:54:37 +0000
Subject: [PATCH] media: rkvdec: Lock capture pixel format in s_ctrl and s_fmt
Add an optional valid_fmt operation that should return the valid
pixelformat of CAPTURE buffers.
This is used in next patch to ensure correct pixelformat is used for 10-bit
and 4:2:2 content.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/staging/media/rkvdec/rkvdec.c | 67 +++++++++++++++++++++++----
drivers/staging/media/rkvdec/rkvdec.h | 2 +
2 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index 40cc791aef26..e93e1cb0f829 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -38,19 +38,56 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
pix_mp->field = V4L2_FIELD_NONE;
}
+static u32 rkvdec_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
+{
+ const struct rkvdec_coded_fmt_desc *coded_desc = ctx->coded_fmt_desc;
+
+ if (coded_desc->ops->valid_fmt)
+ return coded_desc->ops->valid_fmt(ctx, ctrl);
+
+ return ctx->valid_fmt;
+}
+
static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
{
struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc;
- if (desc->ops->try_ctrl)
- return desc->ops->try_ctrl(ctx, ctrl);
+ if (desc->ops->try_ctrl) {
+ int ret;
+ ret = desc->ops->try_ctrl(ctx, ctrl);
+ if (ret)
+ return ret;
+ }
+
+ if (ctx->valid_fmt && ctx->valid_fmt != rkvdec_valid_fmt(ctx, ctrl))
+ /* Only current valid format */
+ return -EINVAL;
+
+ return 0;
+}
+
+static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
+
+ if (ctrl->id == V4L2_CID_STATELESS_H264_SPS && !ctx->valid_fmt) {
+ ctx->valid_fmt = rkvdec_valid_fmt(ctx, ctrl);
+ if (ctx->valid_fmt) {
+ struct v4l2_pix_format_mplane *pix_mp;
+
+ pix_mp = &ctx->decoded_fmt.fmt.pix_mp;
+ pix_mp->pixelformat = ctx->valid_fmt;
+ rkvdec_fill_decoded_pixfmt(ctx, pix_mp);
+ }
+ }
return 0;
}
static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = {
.try_ctrl = rkvdec_try_ctrl,
+ .s_ctrl = rkvdec_s_ctrl,
};
static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
@@ -201,6 +238,7 @@ static void rkvdec_reset_decoded_fmt(struct rkvdec_ctx *ctx)
{
struct v4l2_format *f = &ctx->decoded_fmt;
+ ctx->valid_fmt = 0;
rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]);
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
f->fmt.pix_mp.width = ctx->coded_fmt.fmt.pix_mp.width;
@@ -256,13 +294,17 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv,
if (WARN_ON(!coded_desc))
return -EINVAL;
- for (i = 0; i < coded_desc->num_decoded_fmts; i++) {
- if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat)
- break;
- }
+ if (ctx->valid_fmt) {
+ pix_mp->pixelformat = ctx->valid_fmt;
+ } else {
+ for (i = 0; i < coded_desc->num_decoded_fmts; i++) {
+ if (coded_desc->decoded_fmts[i] == pix_mp->pixelformat)
+ break;
+ }
- if (i == coded_desc->num_decoded_fmts)
- pix_mp->pixelformat = coded_desc->decoded_fmts[0];
+ if (i == coded_desc->num_decoded_fmts)
+ pix_mp->pixelformat = coded_desc->decoded_fmts[0];
+ }
/* Always apply the frmsize constraint of the coded end. */
pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width);
@@ -326,6 +368,7 @@ static int rkvdec_s_capture_fmt(struct file *file, void *priv,
return ret;
ctx->decoded_fmt = *f;
+ ctx->valid_fmt = f->fmt.pix_mp.pixelformat;
return 0;
}
@@ -429,6 +472,14 @@ static int rkvdec_enum_capture_fmt(struct file *file, void *priv,
if (WARN_ON(!ctx->coded_fmt_desc))
return -EINVAL;
+ if (ctx->valid_fmt) {
+ if (f->index)
+ return -EINVAL;
+
+ f->pixelformat = ctx->valid_fmt;
+ return 0;
+ }
+
if (f->index >= ctx->coded_fmt_desc->num_decoded_fmts)
return -EINVAL;
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
index 633335ebb9c4..b9e219438bc9 100644
--- a/drivers/staging/media/rkvdec/rkvdec.h
+++ b/drivers/staging/media/rkvdec/rkvdec.h
@@ -66,6 +66,7 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf)
struct rkvdec_coded_fmt_ops {
int (*adjust_fmt)(struct rkvdec_ctx *ctx,
struct v4l2_format *f);
+ u32 (*valid_fmt)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
int (*start)(struct rkvdec_ctx *ctx);
void (*stop)(struct rkvdec_ctx *ctx);
int (*run)(struct rkvdec_ctx *ctx);
@@ -101,6 +102,7 @@ struct rkvdec_ctx {
struct v4l2_fh fh;
struct v4l2_format coded_fmt;
struct v4l2_format decoded_fmt;
+ u32 valid_fmt;
const struct rkvdec_coded_fmt_desc *coded_fmt_desc;
struct v4l2_ctrl_handler ctrl_hdl;
struct rkvdec_dev *dev;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 21:54:37 +0000
Subject: [PATCH] media: rkvdec: h264: Support High 10 and 4:2:2 profiles
Add support and enable decoding of H264 High 10 and 4:2:2 profiles.
Decoded CAPTURE buffer width is aligned to 64 pixels to accommodate HW
requirement on 10-bit format buffers.
The new valid_fmt operation is implemented and return a valid pixelformat
for the provided SPS control.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/staging/media/rkvdec/rkvdec-h264.c | 33 ++++++++++++++++------
drivers/staging/media/rkvdec/rkvdec.c | 19 +++++++++----
2 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
index a8635105e387..0069d3d198db 100644
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
@@ -1031,19 +1031,14 @@ static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
{
unsigned int width, height;
- /*
- * TODO: The hardware supports 10-bit and 4:2:2 profiles,
- * but it's currently broken in the driver.
- * Reject them for now, until it's fixed.
- */
- if (sps->chroma_format_idc > 1)
- /* Only 4:0:0 and 4:2:0 are supported */
+ if (sps->chroma_format_idc > 2)
+ /* Only 4:0:0, 4:2:0 and 4:2:2 are supported */
return -EINVAL;
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
/* Luma and chroma bit depth mismatch */
return -EINVAL;
- if (sps->bit_depth_luma_minus8 != 0)
- /* Only 8-bit is supported */
+ if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
+ /* Only 8-bit and 10-bit is supported */
return -EINVAL;
width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
@@ -1064,6 +1059,25 @@ static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
return 0;
}
+static u32 rkvdec_h264_valid_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
+{
+ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
+
+ if (sps->bit_depth_luma_minus8 == 0) {
+ if (sps->chroma_format_idc == 2)
+ return V4L2_PIX_FMT_NV16;
+ else
+ return V4L2_PIX_FMT_NV12;
+ } else if (sps->bit_depth_luma_minus8 == 2) {
+ if (sps->chroma_format_idc == 2)
+ return V4L2_PIX_FMT_NV20;
+ else
+ return V4L2_PIX_FMT_NV15;
+ }
+
+ return 0;
+}
+
static int rkvdec_h264_start(struct rkvdec_ctx *ctx)
{
struct rkvdec_dev *rkvdec = ctx->dev;
@@ -1185,6 +1199,7 @@ static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = {
.adjust_fmt = rkvdec_h264_adjust_fmt,
+ .valid_fmt = rkvdec_h264_valid_fmt,
.start = rkvdec_h264_start,
.stop = rkvdec_h264_stop,
.run = rkvdec_h264_run,
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index e93e1cb0f829..4f5436c89e08 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -31,7 +31,7 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
struct v4l2_pix_format_mplane *pix_mp)
{
v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
- pix_mp->width, pix_mp->height);
+ ALIGN(pix_mp->width, 64), pix_mp->height);
pix_mp->plane_fmt[0].sizeimage += 128 *
DIV_ROUND_UP(pix_mp->width, 16) *
DIV_ROUND_UP(pix_mp->height, 16);
@@ -136,8 +136,11 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = {
.num_ctrls = ARRAY_SIZE(rkvdec_h264_ctrl_descs),
};
-static const u32 rkvdec_h264_vp9_decoded_fmts[] = {
+static const u32 rkvdec_h264_decoded_fmts[] = {
V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_NV15,
+ V4L2_PIX_FMT_NV16,
+ V4L2_PIX_FMT_NV20,
};
static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = {
@@ -160,6 +163,10 @@ static const struct rkvdec_ctrls rkvdec_vp9_ctrls = {
.num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs),
};
+static const u32 rkvdec_vp9_decoded_fmts[] = {
+ V4L2_PIX_FMT_NV12,
+};
+
static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
@@ -173,8 +180,8 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
},
.ctrls = &rkvdec_h264_ctrls,
.ops = &rkvdec_h264_fmt_ops,
- .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts),
- .decoded_fmts = rkvdec_h264_vp9_decoded_fmts,
+ .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts),
+ .decoded_fmts = rkvdec_h264_decoded_fmts,
.subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF,
},
{
@@ -189,8 +196,8 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
},
.ctrls = &rkvdec_vp9_ctrls,
.ops = &rkvdec_vp9_fmt_ops,
- .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts),
- .decoded_fmts = rkvdec_h264_vp9_decoded_fmts,
+ .num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts),
+ .decoded_fmts = rkvdec_vp9_decoded_fmts,
}
};
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 27 Mar 2022 14:18:07 +0200
Subject: [PATCH] media: rkvdec-h264: Don't hardcode SPS/PPS parameters
Some SPS/PPS parameters are currently hardcoded in the driver
even though so do exist in the uapi which is stable by now.
Use them instead of hardcoding them.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/staging/media/rkvdec/rkvdec-h264.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
index 0069d3d198db..2c27acaba85e 100644
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
@@ -655,13 +655,14 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
#define WRITE_PPS(value, field) set_ps_field(hw_ps->info, field, value)
/* write sps */
- WRITE_PPS(0xf, SEQ_PARAMETER_SET_ID);
- WRITE_PPS(0xff, PROFILE_IDC);
- WRITE_PPS(1, CONSTRAINT_SET3_FLAG);
+ WRITE_PPS(sps->seq_parameter_set_id, SEQ_PARAMETER_SET_ID);
+ WRITE_PPS(sps->profile_idc, PROFILE_IDC);
+ WRITE_PPS((sps->constraint_set_flags & 1 << 3) ? 1 : 0, CONSTRAINT_SET3_FLAG);
WRITE_PPS(sps->chroma_format_idc, CHROMA_FORMAT_IDC);
WRITE_PPS(sps->bit_depth_luma_minus8, BIT_DEPTH_LUMA);
WRITE_PPS(sps->bit_depth_chroma_minus8, BIT_DEPTH_CHROMA);
- WRITE_PPS(0, QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG);
+ WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS),
+ QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG);
WRITE_PPS(sps->log2_max_frame_num_minus4, LOG2_MAX_FRAME_NUM_MINUS4);
WRITE_PPS(sps->max_num_ref_frames, MAX_NUM_REF_FRAMES);
WRITE_PPS(sps->pic_order_cnt_type, PIC_ORDER_CNT_TYPE);
@@ -688,8 +689,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
DIRECT_8X8_INFERENCE_FLAG);
/* write pps */
- WRITE_PPS(0xff, PIC_PARAMETER_SET_ID);
- WRITE_PPS(0x1f, PPS_SEQ_PARAMETER_SET_ID);
+ WRITE_PPS(pps->pic_parameter_set_id, PIC_PARAMETER_SET_ID);
+ WRITE_PPS(pps->seq_parameter_set_id, PPS_SEQ_PARAMETER_SET_ID);
WRITE_PPS(!!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE),
ENTROPY_CODING_MODE_FLAG);
WRITE_PPS(!!(pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT),

View file

@ -0,0 +1,837 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 22:30:13 +0000
Subject: [PATCH] drm: drm_fourcc: add NV20 and NV30 YUV formats
DRM_FORMAT_NV20 and DRM_FORMAT_NV30 formats is the 2x1 and non-subsampled
variant of NV15, a 10-bit 2-plane YUV format that has no padding between
components. Instead, luminance and chrominance samples are grouped into 4s
so that each group is packed into an integer number of bytes:
YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes
The '20' and '30' suffix refers to the optimum effective bits per pixel
which is achieved when the total number of luminance samples is a multiple
of 4.
V2: Added NV30 format
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Sandy Huang <hjc@rock-chips.com>
---
drivers/gpu/drm/drm_fourcc.c | 8 ++++++++
include/uapi/drm/drm_fourcc.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 07741b678798..5ec38456dc5d 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -261,6 +261,14 @@ const struct drm_format_info *__drm_format_info(u32 format)
.num_planes = 2, .char_per_block = { 5, 5, 0 },
.block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
.vsub = 2, .is_yuv = true },
+ { .format = DRM_FORMAT_NV20, .depth = 0,
+ .num_planes = 2, .char_per_block = { 5, 5, 0 },
+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
+ .vsub = 1, .is_yuv = true },
+ { .format = DRM_FORMAT_NV30, .depth = 0,
+ .num_planes = 2, .char_per_block = { 5, 5, 0 },
+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1,
+ .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_Q410, .depth = 0,
.num_planes = 3, .char_per_block = { 2, 2, 2 },
.block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0,
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 0206f812c569..fa49ee98f275 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -285,6 +285,8 @@ extern "C" {
* index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian
*/
#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */
/*
* 2 plane YCbCr MSB aligned
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Mon, 6 Jul 2020 22:30:13 +0000
Subject: [PATCH] drm: rockchip: add NV15, NV20 and NV30 support
Add support for displaying 10-bit 4:2:0 and 4:2:2 formats produced by the
Rockchip Video Decoder on RK322X, RK3288, RK3328, RK3368 and RK3399.
Also add support for 10-bit 4:4:4 format while at it.
V2: Added NV30 support
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Sandy Huang <hjc@rock-chips.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++--
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 +
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 32 +++++++++++++++++----
3 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index d32117633efe..9e71263ac770 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -280,6 +280,18 @@ static bool has_uv_swapped(uint32_t format)
}
}
+static bool is_fmt_10(uint32_t format)
+{
+ switch (format) {
+ case DRM_FORMAT_NV15:
+ case DRM_FORMAT_NV20:
+ case DRM_FORMAT_NV30:
+ return true;
+ default:
+ return false;
+ }
+}
+
static enum vop_data_format vop_convert_format(uint32_t format)
{
switch (format) {
@@ -295,12 +307,15 @@ static enum vop_data_format vop_convert_format(uint32_t format)
case DRM_FORMAT_BGR565:
return VOP_FMT_RGB565;
case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV15:
case DRM_FORMAT_NV21:
return VOP_FMT_YUV420SP;
case DRM_FORMAT_NV16:
+ case DRM_FORMAT_NV20:
case DRM_FORMAT_NV61:
return VOP_FMT_YUV422SP;
case DRM_FORMAT_NV24:
+ case DRM_FORMAT_NV30:
case DRM_FORMAT_NV42:
return VOP_FMT_YUV444SP;
default:
@@ -954,7 +969,12 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
- offset = (src->x1 >> 16) * fb->format->cpp[0];
+ if (fb->format->block_w[0])
+ offset = (src->x1 >> 16) * fb->format->char_per_block[0] /
+ fb->format->block_w[0];
+ else
+ offset = (src->x1 >> 16) * fb->format->cpp[0];
+
offset += (src->y1 >> 16) * fb->pitches[0];
dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
@@ -980,6 +1000,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
}
VOP_WIN_SET(vop, win, format, format);
+ VOP_WIN_SET(vop, win, fmt_10, is_fmt_10(fb->format->format));
VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv);
@@ -996,7 +1017,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
uv_obj = fb->obj[1];
rk_uv_obj = to_rockchip_obj(uv_obj);
- offset = (src->x1 >> 16) * bpp / hsub;
+ if (fb->format->block_w[1])
+ offset = (src->x1 >> 16) * bpp /
+ fb->format->block_w[1] / hsub;
+ else
+ offset = (src->x1 >> 16) * bpp / hsub;
offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 8502849833d9..b6eea31109d5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -181,6 +181,7 @@ struct vop_win_phy {
struct vop_reg enable;
struct vop_reg gate;
struct vop_reg format;
+ struct vop_reg fmt_10;
struct vop_reg rb_swap;
struct vop_reg uv_swap;
struct vop_reg act_info;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 014f99e8928e..16e6aa01e400 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -53,6 +53,23 @@ static const uint32_t formats_win_full[] = {
DRM_FORMAT_NV42,
};
+static const uint32_t formats_win_full_10[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_BGR565,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV24,
+ DRM_FORMAT_NV15,
+ DRM_FORMAT_NV20,
+ DRM_FORMAT_NV30,
+};
+
static const uint64_t format_modifiers_win_full[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID,
@@ -621,11 +638,12 @@ static const struct vop_scl_regs rk3288_win_full_scl = {
static const struct vop_win_phy rk3288_win01_data = {
.scl = &rk3288_win_full_scl,
- .data_formats = formats_win_full,
- .nformats = ARRAY_SIZE(formats_win_full),
+ .data_formats = formats_win_full_10,
+ .nformats = ARRAY_SIZE(formats_win_full_10),
.format_modifiers = format_modifiers_win_full,
.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4),
.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
@@ -756,11 +774,12 @@ static const struct vop_intr rk3368_vop_intr = {
static const struct vop_win_phy rk3368_win01_data = {
.scl = &rk3288_win_full_scl,
- .data_formats = formats_win_full,
- .nformats = ARRAY_SIZE(formats_win_full),
+ .data_formats = formats_win_full_10,
+ .nformats = ARRAY_SIZE(formats_win_full_10),
.format_modifiers = format_modifiers_win_full,
.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
+ .fmt_10 = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 4),
.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
.uv_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 15),
.x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
@@ -924,11 +943,12 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
static const struct vop_win_phy rk3399_win01_data = {
.scl = &rk3288_win_full_scl,
- .data_formats = formats_win_full,
- .nformats = ARRAY_SIZE(formats_win_full),
+ .data_formats = formats_win_full_10,
+ .nformats = ARRAY_SIZE(formats_win_full_10),
.format_modifiers = format_modifiers_win_full_afbc,
.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4),
.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
.x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21),
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 05/13] drm/rockchip: dw_hdmi: Allow High TMDS Bit Rates
Date: Sat, 15 Jun 2024 17:03:56 +0000
Call dw_hdmi_set_high_tmds_clock_ratio in phy init ops to allow support
of High TMDS Bit Rates used by HDMI2.0 display modes.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index aae48e906af1..5df9c9a0d369 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -362,6 +362,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data,
{
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display);
+
return phy_power_on(hdmi->phy);
}
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 06/13] drm/rockchip: dw_hdmi: Add max_tmds_clock validation
Date: Sat, 15 Jun 2024 17:03:57 +0000
Add max_tmds_clock validation to prepare for additions and changes to
the MPLL config table. Use the same rate restrictions that is currently
applied.
The rate limit for RK3288, RK3399 and RK3568 is based on current mpll
table. The rate limit for RK3228 and RK3228 is based on the
inno-hdmi-phy pre-pll table.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 5df9c9a0d369..75b5d63ec570 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -61,11 +61,13 @@
* @lcdsel_grf_reg: grf register offset of lcdc select
* @lcdsel_big: reg value of selecting vop big for HDMI
* @lcdsel_lit: reg value of selecting vop little for HDMI
+ * @max_tmds_clock: maximum TMDS clock rate supported
*/
struct rockchip_hdmi_chip_data {
int lcdsel_grf_reg;
u32 lcdsel_big;
u32 lcdsel_lit;
+ int max_tmds_clock;
};
struct rockchip_hdmi {
@@ -259,6 +261,10 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
bool exact_match = hdmi->plat_data->phy_force_vendor;
int i;
+ if (hdmi->chip_data->max_tmds_clock &&
+ mode->clock > hdmi->chip_data->max_tmds_clock)
+ return MODE_CLOCK_HIGH;
+
if (hdmi->ref_clk) {
int rpclk = clk_round_rate(hdmi->ref_clk, pclk);
@@ -450,6 +456,7 @@ static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = {
static struct rockchip_hdmi_chip_data rk3228_chip_data = {
.lcdsel_grf_reg = -1,
+ .max_tmds_clock = 594000,
};
static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
@@ -467,6 +474,7 @@ static struct rockchip_hdmi_chip_data rk3288_chip_data = {
.lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
.lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL),
.lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL),
+ .max_tmds_clock = 340000,
};
static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
@@ -487,6 +495,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = {
static struct rockchip_hdmi_chip_data rk3328_chip_data = {
.lcdsel_grf_reg = -1,
+ .max_tmds_clock = 594000,
};
static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
@@ -505,6 +514,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = {
.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
.lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL),
.lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL),
+ .max_tmds_clock = 340000,
};
static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
@@ -518,6 +528,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
static struct rockchip_hdmi_chip_data rk3568_chip_data = {
.lcdsel_grf_reg = -1,
+ .max_tmds_clock = 340000,
};
static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 07/13] drm/rockchip: dw_hdmi: Filter modes based on hdmiphy_clk
Date: Sat, 15 Jun 2024 17:03:58 +0000
RK3228 and RK3328 clock rate is being validated against a mpll config
table intended for Synopsys phy, and not the inno-hdmi-phy used.
Instead get a reference to the hdmiphy clk and validate rates against
it to enable use of HDMI2.0 modes, e.g. 4K@60Hz, on RK3228 and RK3328.
For Synopsis phy the max_tmds_clock validation is sufficient.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 35 ++++++++++-----------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 75b5d63ec570..4acf73b5692a 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -76,6 +76,7 @@ struct rockchip_hdmi {
struct rockchip_encoder encoder;
const struct rockchip_hdmi_chip_data *chip_data;
const struct dw_hdmi_plat_data *plat_data;
+ struct clk *hdmiphy_clk;
struct clk *ref_clk;
struct clk *grf_clk;
struct dw_hdmi *hdmi;
@@ -256,10 +257,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
const struct drm_display_mode *mode)
{
struct rockchip_hdmi *hdmi = data;
- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
int pclk = mode->clock * 1000;
- bool exact_match = hdmi->plat_data->phy_force_vendor;
- int i;
if (hdmi->chip_data->max_tmds_clock &&
mode->clock > hdmi->chip_data->max_tmds_clock)
@@ -268,26 +266,18 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data,
if (hdmi->ref_clk) {
int rpclk = clk_round_rate(hdmi->ref_clk, pclk);
- if (abs(rpclk - pclk) > pclk / 1000)
+ if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000)
return MODE_NOCLOCK;
}
- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
- /*
- * For vendor specific phys force an exact match of the pixelclock
- * to preserve the original behaviour of the driver.
- */
- if (exact_match && pclk == mpll_cfg[i].mpixelclock)
- return MODE_OK;
- /*
- * The Synopsys phy can work with pixelclocks up to the value given
- * in the corresponding mpll_cfg entry.
- */
- if (!exact_match && pclk <= mpll_cfg[i].mpixelclock)
- return MODE_OK;
+ if (hdmi->hdmiphy_clk) {
+ int rpclk = clk_round_rate(hdmi->hdmiphy_clk, pclk);
+
+ if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000)
+ return MODE_NOCLOCK;
}
- return MODE_BAD;
+ return MODE_OK;
}
static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
@@ -638,6 +628,15 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
goto err_clk;
}
+ if (hdmi->phy) {
+ struct of_phandle_args clkspec;
+
+ clkspec.np = hdmi->phy->dev.of_node;
+ hdmi->hdmiphy_clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(hdmi->hdmiphy_clk))
+ hdmi->hdmiphy_clk = NULL;
+ }
+
if (hdmi->chip_data == &rk3568_chip_data) {
regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 08/13] drm/rockchip: dw_hdmi: Adjust cklvl & txlvl for RF/EMI
Date: Sat, 15 Jun 2024 17:03:59 +0000
From: Yakir Yang <ykk@rock-chips.com>
Dut to the high HDMI signal voltage driver, Mickey have meet
a serious RF/EMI problem, so we decided to reduce HDMI signal
voltage to a proper value.
The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed)
ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43
tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35
1. We decided to reduce voltage value to lower, but VSwing still
keep high, RF/EMI have been improved but still failed.
ck: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50
tx: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50
2. We try to keep voltage value and vswing both lower, then RF/EMI
test all passed ;)
ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40
tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40
When we back to run HDMI different test and single-end test, we see
different test passed, but signle-end test failed. The oscilloscope
show that simgle-end clock's VL value is 1.78v (which remind LowLimit
should not lower then 2.6v).
3. That's to say there are some different between PHY document and
measure value. And according to experiment 2 results, we need to
higher clock voltage and lower data voltage, then we can keep RF/EMI
satisfied and single-end & differen test passed.
ck: lvl = 9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47
tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 4acf73b5692a..205cfe02079f 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -204,7 +204,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
/*pixelclk symbol term vlev*/
{ 74250000, 0x8009, 0x0004, 0x0272},
- { 148500000, 0x802b, 0x0004, 0x028d},
+ { 165000000, 0x802b, 0x0004, 0x0209},
{ 297000000, 0x8039, 0x0005, 0x028d},
{ ~0UL, 0x0000, 0x0000, 0x0000}
};
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 09/13] drm/rockchip: dw_hdmi: Add phy_config for 594Mhz pixel clock
Date: Sat, 15 Jun 2024 17:04:00 +0000
From: Nickey Yang <nickey.yang@rock-chips.com>
Add phy_config for 594Mhz pixel clock used for HDMI2.0 display modes.
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 205cfe02079f..9d5bd7455180 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -206,6 +206,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
{ 74250000, 0x8009, 0x0004, 0x0272},
{ 165000000, 0x802b, 0x0004, 0x0209},
{ 297000000, 0x8039, 0x0005, 0x028d},
+ { 594000000, 0x8039, 0x0000, 0x019d},
{ ~0UL, 0x0000, 0x0000, 0x0000}
};
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 10/13] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always
Date: Sat, 15 Jun 2024 17:04:01 +0000
From: Douglas Anderson <dianders@chromium.org>
Jitter was improved by lowering the MPLL bandwidth to account for high
frequency noise in the rk3288 PLL. In each case MPLL bandwidth was
lowered only enough to get us a comfortable margin. We believe that
lowering the bandwidth like this is safe given sufficient testing.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 9d5bd7455180..e532c6d294dc 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -181,23 +181,9 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
/* pixelclk bpp8 bpp10 bpp12 */
{
- 40000000, { 0x0018, 0x0018, 0x0018 },
- }, {
- 65000000, { 0x0028, 0x0028, 0x0028 },
- }, {
- 66000000, { 0x0038, 0x0038, 0x0038 },
- }, {
- 74250000, { 0x0028, 0x0038, 0x0038 },
- }, {
- 83500000, { 0x0028, 0x0038, 0x0038 },
- }, {
- 146250000, { 0x0038, 0x0038, 0x0038 },
- }, {
- 148500000, { 0x0000, 0x0038, 0x0038 },
- }, {
600000000, { 0x0000, 0x0000, 0x0000 },
}, {
- ~0UL, { 0x0000, 0x0000, 0x0000},
+ ~0UL, { 0x0000, 0x0000, 0x0000 },
}
};
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 11/13] drm/rockchip: dw_hdmi: Use auto-generated tables
Date: Sat, 15 Jun 2024 17:04:02 +0000
From: Douglas Anderson <dianders@chromium.org>
The previous tables for mpll_cfg and curr_ctrl were created using the
20-pages of example settings provided by the PHY vendor. Those
example settings weren't particularly dense, so there were places
where we were guessing what the settings would be for 10-bit and
12-bit (not that we use those anyway). It was also always a lot of
extra work every time we wanted to add a new clock rate since we had
to cross-reference several tables.
In <https://crrev.com/c/285855> I've gone through the work to figure
out how to generate this table automatically. Let's now use the
automatically generated table and then we'll never need to look at it
again.
We only support 8-bit mode right now and only support a small number
of clock rates and I've verified that the only 8-bit rate that was
affected was 148.5. That mode appears to have been wrong in the old
table.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 104 ++++++++++----------
1 file changed, 53 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index e532c6d294dc..d9886b1c299c 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -94,74 +94,70 @@ static struct rockchip_hdmi *to_rockchip_hdmi(struct drm_encoder *encoder)
static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
{
- 27000000, {
- { 0x00b3, 0x0000},
- { 0x2153, 0x0000},
- { 0x40f3, 0x0000}
+ 30666000, {
+ { 0x00b3, 0x0000 },
+ { 0x2153, 0x0000 },
+ { 0x40f3, 0x0000 },
},
}, {
- 36000000, {
- { 0x00b3, 0x0000},
- { 0x2153, 0x0000},
- { 0x40f3, 0x0000}
+ 36800000, {
+ { 0x00b3, 0x0000 },
+ { 0x2153, 0x0000 },
+ { 0x40a2, 0x0001 },
},
}, {
- 40000000, {
- { 0x00b3, 0x0000},
- { 0x2153, 0x0000},
- { 0x40f3, 0x0000}
+ 46000000, {
+ { 0x00b3, 0x0000 },
+ { 0x2142, 0x0001 },
+ { 0x40a2, 0x0001 },
},
}, {
- 54000000, {
- { 0x0072, 0x0001},
- { 0x2142, 0x0001},
- { 0x40a2, 0x0001},
+ 61333000, {
+ { 0x0072, 0x0001 },
+ { 0x2142, 0x0001 },
+ { 0x40a2, 0x0001 },
},
}, {
- 65000000, {
- { 0x0072, 0x0001},
- { 0x2142, 0x0001},
- { 0x40a2, 0x0001},
+ 73600000, {
+ { 0x0072, 0x0001 },
+ { 0x2142, 0x0001 },
+ { 0x4061, 0x0002 },
},
}, {
- 66000000, {
- { 0x013e, 0x0003},
- { 0x217e, 0x0002},
- { 0x4061, 0x0002}
+ 92000000, {
+ { 0x0072, 0x0001 },
+ { 0x2145, 0x0002 },
+ { 0x4061, 0x0002 },
},
}, {
- 74250000, {
- { 0x0072, 0x0001},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
+ 122666000, {
+ { 0x0051, 0x0002 },
+ { 0x2145, 0x0002 },
+ { 0x4061, 0x0002 },
},
}, {
- 83500000, {
- { 0x0072, 0x0001},
+ 147200000, {
+ { 0x0051, 0x0002 },
+ { 0x2145, 0x0002 },
+ { 0x4064, 0x0003 },
},
}, {
- 108000000, {
- { 0x0051, 0x0002},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
+ 184000000, {
+ { 0x0051, 0x0002 },
+ { 0x214c, 0x0003 },
+ { 0x4064, 0x0003 },
},
}, {
- 106500000, {
- { 0x0051, 0x0002},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
- },
- }, {
- 146250000, {
- { 0x0051, 0x0002},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
+ 226666000, {
+ { 0x0040, 0x0003 },
+ { 0x214c, 0x0003 },
+ { 0x4064, 0x0003 },
},
}, {
- 148500000, {
- { 0x0051, 0x0003},
- { 0x214c, 0x0003},
- { 0x4064, 0x0003}
+ 272000000, {
+ { 0x0040, 0x0003 },
+ { 0x214c, 0x0003 },
+ { 0x5a64, 0x0003 },
},
}, {
340000000, {
@@ -169,11 +165,17 @@ static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
{ 0x3b4c, 0x0003 },
{ 0x5a64, 0x0003 },
},
+ }, {
+ 600000000, {
+ { 0x1a40, 0x0003 },
+ { 0x3b4c, 0x0003 },
+ { 0x5a64, 0x0003 },
+ },
}, {
~0UL, {
- { 0x00a0, 0x000a },
- { 0x2001, 0x000f },
- { 0x4002, 0x000f },
+ { 0x0000, 0x0000 },
+ { 0x0000, 0x0000 },
+ { 0x0000, 0x0000 },
},
}
};
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 12/13] drm/rockchip: dw_hdmi: Enable 4K@60Hz mode on RK3399 and RK356x
Date: Sat, 15 Jun 2024 17:04:03 +0000
Use a maximum TMDS clock rate limit of 594MHz to enable use of HDMI2.0
modes, e.g. 4K@60Hz, on RK3399 and RK3568.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index d9886b1c299c..b255b8ceedb7 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -493,7 +493,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = {
.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
.lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL),
.lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL),
- .max_tmds_clock = 340000,
+ .max_tmds_clock = 594000,
};
static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
@@ -507,7 +507,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
static struct rockchip_hdmi_chip_data rk3568_chip_data = {
.lcdsel_grf_reg = -1,
- .max_tmds_clock = 340000,
+ .max_tmds_clock = 594000,
};
static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
From: Jonas Karlman <jonas@kwiboo.se>
Subject: [PATCH 13/13] drm/rockchip: Load crtc devices in preferred order
Date: Sat, 15 Jun 2024 17:04:04 +0000
On RK3399 the VOPL loaded before VOPB and gets registered as crtc-0.
However, on RK3288 and PX30 VOPB is gets registered as crtc-0 instead of
VOPL.
With VOPL registered as crtc-0 the kernel kms client is not able to
enable 4K display modes for console use on RK3399.
Load VOPB before VOPL to help kernel kms client make use of 4K display
modes for console use on RK3399.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 23 +++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index ab55d7132550..6492f3caf017 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -354,11 +354,34 @@ static void rockchip_drm_match_remove(struct device *dev)
device_link_del(link);
}
+/* list of preferred vop devices */
+static const char *const rockchip_drm_match_preferred[] = {
+ "rockchip,rk3399-vop-big",
+ NULL,
+};
+
static struct component_match *rockchip_drm_match_add(struct device *dev)
{
struct component_match *match = NULL;
+ struct device_node *port;
int i;
+ /* add preferred vop device match before adding driver device matches */
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(dev->of_node, "ports", i);
+ if (!port)
+ break;
+
+ if (of_device_is_available(port->parent) &&
+ of_device_compatible_match(port->parent,
+ rockchip_drm_match_preferred))
+ drm_of_component_match_add(dev, &match,
+ component_compare_of,
+ port->parent);
+
+ of_node_put(port);
+ }
+
for (i = 0; i < num_rockchip_sub_drivers; i++) {
struct platform_driver *drv = rockchip_sub_drivers[i];
struct device *p = NULL, *d;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,803 @@
From 4707a7fe2103b7600b2ca6097ce9d12bda37d4cf Mon Sep 17 00:00:00 2001
From: Finley Xiao <finley.xiao@rock-chips.com>
Date: Thu, 22 Jun 2017 20:22:25 +0800
Subject: [PATCH] clk: rockchip: rk3228: fix some PLL_NUX_CLKs' gates
Some PLL_NUX_CLKs' gates is actually behind muxs according to latest TRM,
so move the gates to composite clocks and amend their parent clocks.
Change-Id: Ib6043caa61e9df0473f2d0bdc756850968bb2a55
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
---
drivers/clk/rockchip/clk-rk3228.c | 49 ++++++++++---------------------
1 file changed, 15 insertions(+), 34 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index c1ef00247e26..6da33172c6ba 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -134,24 +134,22 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = {
PNAME(mux_pll_p) = { "clk_24m", "xin24m" };
-PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_ddrphy_p) = { "dpll", "gpll", "apll" };
PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" };
PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" };
PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" };
PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" };
-PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" };
PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "hdmiphy", "usb480m" };
PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "hdmiphy" };
PNAME(mux_pll_src_2plls_p) = { "cpll", "gpll" };
PNAME(mux_sclk_hdmi_cec_p) = { "cpll", "gpll", "xin24m" };
-PNAME(mux_aclk_peri_src_p) = { "cpll_peri", "gpll_peri", "hdmiphy_peri" };
PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "usb480m" };
PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" };
PNAME(mux_sclk_rga_p) = { "gpll", "cpll", "sclk_rga_src" };
-PNAME(mux_sclk_vop_src_p) = { "gpll_vop", "cpll_vop" };
+PNAME(mux_sclk_vop_src_p) = { "gpll", "cpll" };
PNAME(mux_dclk_vop_p) = { "hdmiphy", "sclk_vop_pre" };
PNAME(mux_i2s0_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
@@ -220,27 +218,23 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),
/* PD_DDR */
- GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+ COMPOSITE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+ RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(0), 2, GFLAGS),
- GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(0), 2, GFLAGS),
- GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(0), 2, GFLAGS),
- COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
- RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ GATE(0, "ddrphy4x", "clk_ddrphy_src", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(7), 1, GFLAGS),
- GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED,
+ FACTOR_GATE(0, "ddrc", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4,
RK2928_CLKGATE_CON(8), 5, GFLAGS),
- FACTOR_GATE(0, "ddrphy", "ddrphy4x", CLK_IGNORE_UNUSED, 1, 4,
+ FACTOR_GATE(0, "ddrphy", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4,
RK2928_CLKGATE_CON(7), 0, GFLAGS),
/* PD_CORE */
- GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(0), 6, GFLAGS),
GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(0), 6, GFLAGS),
GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+ RK2928_CLKGATE_CON(0), 6, GFLAGS),
COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
RK2928_CLKGATE_CON(4), 1, GFLAGS),
@@ -257,14 +251,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_MISC_CON, 15, 1, MFLAGS),
/* PD_BUS */
- GATE(0, "hdmiphy_aclk_cpu", "hdmiphy", CLK_IGNORE_UNUSED,
+ COMPOSITE(0, "aclk_cpu_src", mux_pll_src_3plls_p, 0,
+ RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS,
RK2928_CLKGATE_CON(0), 1, GFLAGS),
- GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(0), 1, GFLAGS),
- GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(0), 1, GFLAGS),
- COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
- RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS),
GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", 0,
RK2928_CLKGATE_CON(6), 0, GFLAGS),
COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", 0,
@@ -337,14 +326,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_CLKGATE_CON(3), 8, GFLAGS),
/* PD_PERI */
- GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(2), 0, GFLAGS),
- GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
+ COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0,
+ RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS,
RK2928_CLKGATE_CON(2), 0, GFLAGS),
- GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED,
- RK2928_CLKGATE_CON(2), 0, GFLAGS),
- COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0,
- RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS),
COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
RK2928_CLKSEL_CON(10), 12, 3, DFLAGS,
RK2928_CLKGATE_CON(5), 2, GFLAGS),
@@ -402,12 +386,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
* Clock-Architecture Diagram 2
*/
- GATE(0, "gpll_vop", "gpll", 0,
- RK2928_CLKGATE_CON(3), 1, GFLAGS),
- GATE(0, "cpll_vop", "cpll", 0,
+ COMPOSITE_NODIV(0, "sclk_vop_src", mux_sclk_vop_src_p, 0,
+ RK2928_CLKSEL_CON(27), 0, 1, MFLAGS,
RK2928_CLKGATE_CON(3), 1, GFLAGS),
- MUX(0, "sclk_vop_src", mux_sclk_vop_src_p, 0,
- RK2928_CLKSEL_CON(27), 0, 1, MFLAGS),
DIV(DCLK_HDMI_PHY, "dclk_hdmiphy", "sclk_vop_src", 0,
RK2928_CLKSEL_CON(29), 0, 3, DFLAGS),
DIV(0, "sclk_vop_pre", "sclk_vop_src", 0,
From d575c876e7f19e1699471d88edfe8d1874f6dd21 Mon Sep 17 00:00:00 2001
From: Finley Xiao <finley.xiao@rock-chips.com>
Date: Sun, 18 Mar 2018 21:41:43 +0800
Subject: [PATCH] clk: rockchip: rk3228: Fix sclk_wifi div_width
Change-Id: I8e216249fbd588ce55660eba9911fc59aedc920d
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
---
drivers/clk/rockchip/clk-rk3228.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index 6da33172c6ba..d59e619425b6 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -363,7 +363,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_CLKGATE_CON(10), 12, GFLAGS),
COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0,
- RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
+ RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 5, DFLAGS,
RK2928_CLKGATE_CON(2), 15, GFLAGS),
COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
From 13db1588f0807f2d0569a45b93d6597280e105f6 Mon Sep 17 00:00:00 2001
From: Chen Lei <lei.chen@rock-chips.com>
Date: Tue, 25 Dec 2018 18:29:04 +0800
Subject: [PATCH] clk: rockchip: rk322x: fix wrong mmc phase shift for rk3228
mmc sample shift should be 1 for rk3228, or it will fail
if we enable mmc tuning for rk3228.
Change-Id: I301c2a7d33de8d519d7c288aef03a82531016373
Signed-off-by: Chen Lei <lei.chen@rock-chips.com>
---
drivers/clk/rockchip/clk-rk3228.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index d59e619425b6..9c5ad7c71143 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -620,13 +620,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
/* PD_MMC */
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1),
- MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1),
MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1),
- MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 0),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1),
MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1),
- MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0),
+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1),
};
static const char *const rk3228_critical_clocks[] __initconst = {
From 8b9b8802556c4f7ce09699a4a85e19143de43c44 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Mon, 14 Dec 2020 21:05:15 +0100
Subject: [PATCH] clk: rockchip: add *_vio_h2p to RK3228's critical clocks
These are required in order to read the HDMI edid and must not
get disabled in order to successfully do so.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/clk/rockchip/clk-rk3228.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index 9c5ad7c71143..4b2aca6b1f11 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -641,6 +641,7 @@ static const char *const rk3228_critical_clocks[] __initconst = {
"aclk_vop_noc",
"aclk_hdcp_noc",
"hclk_vio_ahb_arbi",
+ "hclk_vio_h2p",
"hclk_vio_noc",
"hclk_vop_noc",
"hclk_host0_arb",
@@ -658,6 +659,7 @@ static const char *const rk3228_critical_clocks[] __initconst = {
"pclk_ddrphy",
"pclk_acodecphy",
"pclk_phy_noc",
+ "pclk_vio_h2p",
"aclk_vpu_noc",
"aclk_rkvdec_noc",
"hclk_vpu_noc",
From 3fc147d54b06e6451775465e35de17a6126377c2 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 17:07:35 +0200
Subject: [PATCH] clk: rockchip add aclk_rkvdec and hclk_rkvdec to RK3228
critical clocks
To be prevented from being disabled at any time add aclk_rkvdec and hclk_rkvdec
to RK3228 critical clocks
---
drivers/clk/rockchip/clk-rk3228.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index 4b2aca6b1f11..2ac006e99c03 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -662,8 +662,10 @@ static const char *const rk3228_critical_clocks[] __initconst = {
"pclk_vio_h2p",
"aclk_vpu_noc",
"aclk_rkvdec_noc",
+ "aclk_rkvdec",
"hclk_vpu_noc",
"hclk_rkvdec_noc",
+ "hclk_rkvdec",
};
static void __init rk3228_clk_init(struct device_node *np)
From 8384abedb84b4f9c8648a92108de94b4b8d188a6 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Fri, 24 Apr 2020 11:42:58 +0200
Subject: [PATCH] soc: rockchip: Support powerdomains which don't need /
support to be switched on / off
Taken from https://github.com/rockchip-linux/kernel/commit/5be2cb19cf8e678655b59ec70c6a5f66f08d9418
---
drivers/genpd/rockchip/pm-domains.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/genpd/rockchip/pm-domains.c b/drivers/genpd/rockchip/pm-domains.c
index 54eb6cfc5d5b..c6b33f7c43df 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -71,6 +71,7 @@ struct rockchip_pm_domain {
struct regmap **qos_regmap;
u32 *qos_save_regs[MAX_QOS_REGS_NUM];
int num_clks;
+ bool is_ignore_pwr;
struct clk_bulk_data *clks;
};
@@ -330,6 +331,9 @@ static int rockchip_pd_power_on(struct generic_pm_domain *domain)
{
struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+ if (pd->is_ignore_pwr)
+ return 0;
+
return rockchip_pd_power(pd, true);
}
@@ -337,6 +341,9 @@ static int rockchip_pd_power_off(struct generic_pm_domain *domain)
{
struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+ if (pd->is_ignore_pwr)
+ return 0;
+
return rockchip_pd_power(pd, false);
}
@@ -416,6 +423,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
pd->info = pd_info;
pd->pmu = pmu;
+ if (!pd_info->pwr_mask)
+ pd->is_ignore_pwr = true;
+
pd->num_clks = of_clk_get_parent_count(node);
if (pd->num_clks > 0) {
pd->clks = devm_kcalloc(pmu->dev, pd->num_clks,
@@ -566,6 +576,7 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
{
struct device_node *np;
struct generic_pm_domain *child_domain, *parent_domain;
+ struct rockchip_pm_domain *child_pd, *parent_pd;
int error;
for_each_child_of_node(parent, np) {
@@ -606,6 +617,18 @@ static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
parent_domain->name, child_domain->name);
}
+ /*
+ * If child_pd doesn't do idle request or power on/off,
+ * parent_pd may fail to do power on/off, so if parent_pd
+ * need to power on/off, child_pd can't ignore to do idle
+ * request and power on/off.
+ */
+ child_pd = to_rockchip_pd(child_domain);
+ parent_pd = to_rockchip_pd(parent_domain);
+ if (!parent_pd->is_ignore_pwr)
+ child_pd->is_ignore_pwr = false;
+
+
rockchip_pm_add_subdomain(pmu, np);
}
From 14c607b588c49705ac0486d63590876089b41a20 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Fri, 24 Apr 2020 09:08:44 +0200
Subject: [PATCH] phy: rockchip: hdmi: readout hdmi phy flag for RK3228 HDMI
phys
Some RK3228 HDMI phys only get a stable pll on frequencies higher 33,75 MHz.
This is defined in a flag in efuse of those devices.
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 6 +++
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 38 ++++++++++++++++++-
2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index 48e6e8d44a1a..a5f1d1a004d4 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -317,6 +317,10 @@ efuse_id: id@7 {
cpu_leakage: cpu_leakage@17 {
reg = <0x17 0x1>;
};
+ hdmi_phy_flag: hdmi-phy-flag@1d {
+ reg = <0x1d 0x1>;
+ bits = <1 1>;
+ };
};
i2c0: i2c@11050000 {
@@ -536,6 +540,8 @@ hdmi_phy: hdmi-phy@12030000 {
clock-names = "sysclk", "refoclk", "refpclk";
#clock-cells = <0>;
clock-output-names = "hdmiphy_phy";
+ nvmem-cells = <&hdmi_phy_flag>;
+ nvmem-cell-names = "hdmi-phy-flag";
#phy-cells = <0>;
status = "disabled";
};
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index bb8bdf5e3301..0c7a97352714 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -237,6 +237,9 @@ struct inno_hdmi_phy {
struct clk *refoclk;
struct clk *refpclk;
+ /* phy_flag flag */
+ bool phy_flag;
+
/* platform data */
const struct inno_hdmi_phy_drv_data *plat_data;
int chip_version;
@@ -347,6 +350,7 @@ static const struct pre_pll_config pre_pll_cfg_table[] = {
static const struct post_pll_config post_pll_cfg_table[] = {
{33750000, 1, 40, 8, 1},
{33750000, 1, 80, 8, 2},
+ {33750000, 1, 10, 2, 4},
{74250000, 1, 40, 8, 1},
{74250000, 18, 80, 8, 2},
{148500000, 2, 40, 4, 3},
@@ -497,8 +501,11 @@ static int inno_hdmi_phy_power_on(struct phy *phy)
return -EINVAL;
for (; cfg->tmdsclock != 0; cfg++)
- if (tmdsclock <= cfg->tmdsclock &&
- cfg->version & inno->chip_version)
+ if (((!inno->phy_flag || tmdsclock > 33750000)
+ && tmdsclock <= cfg->tmdsclock
+ && cfg->version & inno->chip_version) ||
+ (inno->phy_flag && tmdsclock <= 33750000
+ && cfg->version & 4))
break;
for (; phy_cfg->tmdsclock != 0; phy_cfg++)
@@ -909,6 +916,10 @@ static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno)
static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno)
{
+ struct nvmem_cell *cell;
+ unsigned char *efuse_buf;
+ size_t len;
+
/*
* Use phy internal register control
* rxsense/poweron/pllpd/pdataen signal.
@@ -923,7 +934,28 @@ static int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno)
inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL,
RK3228_POST_PLL_CTRL_MANUAL);
+
inno->chip_version = 1;
+ inno->phy_flag = false;
+
+ cell = nvmem_cell_get(inno->dev, "hdmi-phy-flag");
+ if (IS_ERR(cell)) {
+ if (PTR_ERR(cell) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ return 0;
+ }
+
+ efuse_buf = nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
+
+ if (IS_ERR(efuse_buf))
+ return 0;
+ if (len == 1)
+ inno->phy_flag = (efuse_buf[0] & BIT(1)) ? true : false;
+ kfree(efuse_buf);
+
+ dev_info(inno->dev, "phy_flag is: %d\n", inno->phy_flag);
return 0;
}
@@ -1023,6 +1055,8 @@ static int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno)
/* try to read the chip-version */
inno->chip_version = 1;
+ inno->phy_flag = false;
+
cell = nvmem_cell_get(inno->dev, "cpu-version");
if (IS_ERR(cell)) {
if (PTR_ERR(cell) == -EPROBE_DEFER)
From 01d16d33ee32f2e2de85cbc8a0a399527c2121ad Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Tue, 26 May 2020 14:41:39 +0200
Subject: [PATCH] usb: dwc2: QUIRKS: rockchip host only controller needs longer
msleep to initialize
---
drivers/usb/dwc2/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fec17a2d2447..eb55c64f63be 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -663,7 +663,7 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
* platforms on their host-only dwc2.
*/
if (!dwc2_hw_is_otg(hsotg))
- msleep(50);
+ msleep(200);
break;
case USB_DR_MODE_PERIPHERAL:
From 713a88dec72631a71bf736e120236f60d06f3989 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 18:51:38 +0200
Subject: [PATCH] ARM: dts: rockchip add operating-points, power-domain for
RK322Xs GPU
This adds the operating-points table and the power-domain and the respective
qos registers for RK322xs GPU.
While at this it also adds the GPU to be a cooling cell.
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index a5f1d1a004d4..dedf84af9e51 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -510,6 +510,11 @@ map1 {
<&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
<&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
+ map2 {
+ trip = <&cpu_alert1>;
+ cooling-device =
+ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
};
};
};
@@ -564,7 +569,28 @@ gpu: gpu@20000000 {
clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>;
clock-names = "bus", "core";
resets = <&cru SRST_GPU_A>;
- status = "disabled";
+ operating-points-v2 = <&gpu_opp_table>;
+ #cooling-cells = <2>; /* min followed by max */
+ };
+
+ gpu_opp_table: opp-table2 {
+ compatible = "operating-points-v2";
+
+ opp-216000000 {
+ opp-hz = /bits/ 64 <216000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ };
+
+ opp-408000000 {
+ opp-hz = /bits/ 64 <408000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ };
+
+ opp-504000000 {
+ opp-hz = /bits/ 64 <504000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ status="disabled";
+ };
};
vpu_mmu: iommu@20020800 {
From 4526da0caf4ecc56cc6e6b8602715dbe839c3eac Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 19:44:42 +0200
Subject: [PATCH] ARM: dts: rockchip: add ethernet0 alias
Add ethernet0 alias for gmac. This will, for example, be used
by u-boot to inject a "local-mac-address" in the devicetree.
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index dedf84af9e51..3c20ee3a7837 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -14,6 +14,7 @@ / {
interrupt-parent = <&gic>;
aliases {
+ ethernet0 = &gmac;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
From 3d6864134434144078395786338b194704a5a41a Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 20:00:01 +0200
Subject: [PATCH] ARM: dts: rockchip: add hdmi simple-audio-card for RK322x
Add "simple-audio-card" definition for hdmi-sound. While at
that also add the missing #sound-dai-cells for i2s, spdif and hdmi
nodes.
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index 3c20ee3a7837..d10ca04c20d6 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -123,6 +123,22 @@ arm-pmu {
interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
};
+ hdmi_sound: hdmi-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "HDMI";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+ status = "disabled";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+ };
+
psci {
compatible = "arm,psci-1.0", "arm,psci-0.2";
method = "smc";
@@ -160,6 +176,7 @@ i2s1: i2s1@100b0000 {
dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&i2s1_bus>;
+ #sound-dai-cells = <0>;
status = "disabled";
};
@@ -171,6 +188,7 @@ i2s0: i2s0@100c0000 {
clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0_8CH>;
dmas = <&pdma 11>, <&pdma 12>;
dma-names = "tx", "rx";
+ #sound-dai-cells = <0>;
status = "disabled";
};
@@ -184,6 +202,7 @@ spdif: spdif@100d0000 {
dma-names = "tx";
pinctrl-names = "default";
pinctrl-0 = <&spdif_tx>;
+ #sound-dai-cells = <0>;
status = "disabled";
};
@@ -685,6 +704,7 @@ hdmi: hdmi@200a0000 {
phys = <&hdmi_phy>;
phy-names = "hdmi";
rockchip,grf = <&grf>;
+ #sound-dai-cells = <0>;
status = "disabled";
ports {
From f917eada6b9f431a797e3bfab7cd06dbd9dfe981 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 21:16:11 +0200
Subject: [PATCH] ARM: dts: rockchip: add uart1-1 pins for RK322x
Add uart uart1-1 pins.
While at this also correct the uart2 default pinctrl, which is uart21_xfer.
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index d10ca04c20d6..f675551391c3 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -316,7 +316,7 @@ uart2: serial@11030000 {
clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
clock-names = "baudclk", "apb_pclk";
pinctrl-names = "default";
- pinctrl-0 = <&uart2_xfer>;
+ pinctrl-0 = <&uart21_xfer>;
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
@@ -1194,13 +1194,30 @@ uart1_xfer: uart1-xfer {
<1 RK_PB2 1 &pcfg_pull_none>;
};
+ uart11_xfer: uart11-xfer {
+ rockchip,pins = <3 RK_PB6 1 &pcfg_pull_up>,
+ <3 RK_PB5 1 &pcfg_pull_none>;
+ };
+
uart1_cts: uart1-cts {
rockchip,pins = <1 RK_PB0 1 &pcfg_pull_none>;
};
+ uart11_cts: uart11-cts {
+ rockchip,pins = <3 RK_PA7 1 &pcfg_pull_none>;
+ };
+
uart1_rts: uart1-rts {
rockchip,pins = <1 RK_PB3 1 &pcfg_pull_none>;
};
+
+ uart11_rts: uart11-rts {
+ rockchip,pins = <3 RK_PA6 1 &pcfg_pull_none>;
+ };
+
+ uart11_rts_gpio: uart11-rts-gpio {
+ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
};
uart2 {
From cbbb85e00a2b19c1e3e9e4d6591c481718e5fb42 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 21:58:56 +0200
Subject: [PATCH] ARM: dts: rockchip: align mmc* node properties with driver
Add resets, max-frequency and bus-width properties where required to emmc
,sdmmc and sdio nodes. While at that also add the sdmmc_pwr pinctrl which
is required to get the sd-card controller to work, if it was not/wrong
initialized by the bootloader (i.e. u-boot)
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index f675551391c3..8e7a866e39e5 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -726,9 +726,13 @@ sdmmc: mmc@30000000 {
clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ bus-width = <4>;
fifo-depth = <0x100>;
+ max-frequency = <150000000>;
pinctrl-names = "default";
- pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
+ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_pwr>;
+ resets = <&cru SRST_SDMMC>;
+ reset-names = "reset";
status = "disabled";
};
@@ -738,10 +742,14 @@ sdio: mmc@30010000 {
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
<&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+ bus-width = <4>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
+ max-frequency = <150000000>;
pinctrl-names = "default";
pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>;
+ resets = <&cru SRST_SDIO>;
+ reset-names = "reset";
status = "disabled";
};
@@ -749,14 +757,13 @@ emmc: mmc@30020000 {
compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc";
reg = <0x30020000 0x4000>;
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
- clock-frequency = <37500000>;
- max-frequency = <37500000>;
clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
<&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
bus-width = <8>;
rockchip,default-sample-phase = <158>;
fifo-depth = <0x100>;
+ max-frequency = <150000000>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
resets = <&cru SRST_EMMC>;
@@ -962,6 +969,10 @@ sdmmc_bus4: sdmmc-bus4 {
<1 RK_PC4 1 &pcfg_pull_none_drv_12ma>,
<1 RK_PC5 1 &pcfg_pull_none_drv_12ma>;
};
+
+ sdmmc_pwr: sdmmc-pwr {
+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
};
sdio {
From 86ae340dabdfbc27ebdb1b43b96d59999dfa4f5a Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 23:12:25 +0200
Subject: [PATCH] ARM: dts: rk322x: add crypto node
In order to add support for RK322x's crypto HW, the node
has been added t its dts.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index 8e7a866e39e5..217ee6568f9e 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -166,6 +166,17 @@ display_subsystem: display-subsystem {
ports = <&vop_out>;
};
+ crypto: cypto-controller@100a0000 {
+ compatible = "rockchip,rk3288-crypto";
+ reg = <0x100a0000 0x4000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_M_CRYPTO>, <&cru HCLK_S_CRYPTO>,
+ <&cru SCLK_CRYPTO>, <&cru ACLK_DMAC>;
+ clock-names = "aclk", "hclk", "sclk", "apb_pclk";
+ resets = <&cru SRST_CRYPTO>;
+ reset-names = "crypto-rst";
+ };
+
i2s1: i2s1@100b0000 {
compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s";
reg = <0x100b0000 0x4000>;

View file

@ -0,0 +1,69 @@
From 9be348c6cade7e709be7347d336c7638bf603b46 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 15 Aug 2020 23:38:05 +0200
Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3188
---
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 27a04c5bc2fd..b47f036d4a2c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -555,6 +555,7 @@ static const struct vop_common rk3188_common = {
.dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9),
.dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28),
.data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25),
+ .dsp_data_swap = VOP_REG(RK3188_DSP_CTRL1, 0x1f, 26),
};
static const struct vop_win_data rk3188_vop_win_data[] = {
From 195b202dbc5abe9c65e029826a7f3e2a2d71067a Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 22 Jul 2020 20:22:02 +0200
Subject: [PATCH] rockchip/drm: add dsp_data_swap register for RK3066
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index b47f036d4a2c..ae4a27704ad6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -448,6 +448,7 @@ static const struct vop_common rk3066_common = {
.dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9),
.dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31),
.data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25),
+ .dsp_data_swap = VOP_REG(RK3066_DSP_CTRL1, 0x1f, 26),
};
static const struct vop_win_data rk3066_vop_win_data[] = {
From a8d962000848a237f8e8f0de8395d4e7df2a7197 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 16 Aug 2020 23:40:24 +0200
Subject: [PATCH] WIP: ARM: dts: rockchip add vpll clock to RK322Xs hdmi node
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index 4bc631881c05..f98a945c68d3 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -766,8 +766,8 @@ hdmi: hdmi@200a0000 {
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
assigned-clocks = <&cru SCLK_HDMI_PHY>;
assigned-clock-parents = <&hdmi_phy>;
- clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;
- clock-names = "iahb", "isfr", "cec";
+ clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&hdmi_phy>, <&cru SCLK_HDMI_CEC>;
+ clock-names = "iahb", "isfr", "vpll", "cec";
pinctrl-names = "default";
pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>;
resets = <&cru SRST_HDMI_P>;

View file

@ -0,0 +1,506 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sat, 23 May 2020 10:16:01 +0000
Subject: [PATCH] WIP: media: rkvdec: pm runtime dont use autosuspend before
disable and cleanup
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
drivers/staging/media/rkvdec/rkvdec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index 4f5436c89e08..eaf2f133a264 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -1125,9 +1125,9 @@ static int rkvdec_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&rkvdec->watchdog_work);
- rkvdec_v4l2_cleanup(rkvdec);
- pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ rkvdec_v4l2_cleanup(rkvdec);
}
#ifdef CONFIG_PM
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Randy Li <ayaka@soulik.info>
Date: Sun, 6 Jan 2019 01:48:37 +0800
Subject: [PATCH] soc: rockchip: power-domain: export idle request
We need to put the power status of HEVC IP into IDLE unless
we can't reset that IP or the SoC would crash down.
rockchip_pmu_idle_request(dev, true)---> enter idle
rockchip_pmu_idle_request(dev, false)---> exit idle
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: Randy Li <ayaka@soulik.info>
---
drivers/pmdomain/rockchip/pm-domains.c | 23 +++++++++++++++++++++++
include/linux/rockchip_pmu.h | 15 +++++++++++++++
include/soc/rockchip/pm_domains.h | 6 ++++++
3 files changed, 44 insertions(+)
create mode 100644 include/linux/rockchip_pmu.h
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
index 89795abac951..ffb5d62c9d52 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -309,6 +309,29 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
return 0;
}
+int rockchip_pmu_idle_request(struct device *dev, bool idle)
+{
+ struct generic_pm_domain *genpd;
+ struct rockchip_pm_domain *pd;
+ int ret;
+
+ if (IS_ERR_OR_NULL(dev))
+ return -EINVAL;
+
+ if (IS_ERR_OR_NULL(dev->pm_domain))
+ return -EINVAL;
+
+ genpd = pd_to_genpd(dev->pm_domain);
+ pd = to_rockchip_pd(genpd);
+
+ mutex_lock(&pd->pmu->mutex);
+ ret = rockchip_pmu_set_idle_request(pd, idle);
+ mutex_unlock(&pd->pmu->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(rockchip_pmu_idle_request);
+
static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
{
int i;
diff --git a/include/linux/rockchip_pmu.h b/include/linux/rockchip_pmu.h
new file mode 100644
index 000000000000..720b3314e71a
--- /dev/null
+++ b/include/linux/rockchip_pmu.h
@@ -0,0 +1,15 @@
+/*
+ * pm_domain.h - Definitions and headers related to device power domains.
+ *
+ * Copyright (C) 2017 Randy Li <ayaka@soulik.info>.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#ifndef _LINUX_ROCKCHIP_PM_H
+#define _LINUX_ROCKCHIP_PM_H
+#include <linux/device.h>
+
+int rockchip_pmu_idle_request(struct device *dev, bool idle);
+
+#endif /* _LINUX_ROCKCHIP_PM_H */
diff --git a/include/soc/rockchip/pm_domains.h b/include/soc/rockchip/pm_domains.h
index 7dbd941fc937..c5a59dd71754 100644
--- a/include/soc/rockchip/pm_domains.h
+++ b/include/soc/rockchip/pm_domains.h
@@ -10,6 +10,7 @@
int rockchip_pmu_block(void);
void rockchip_pmu_unblock(void);
+int rockchip_pmu_idle_request(struct device *dev, bool idle);
#else /* CONFIG_ROCKCHIP_PM_DOMAINS */
@@ -20,6 +21,11 @@ static inline int rockchip_pmu_block(void)
static inline void rockchip_pmu_unblock(void) { }
+static inline int rockchip_pmu_idle_request(struct device *dev, bool idle)
+{
+ return -ENOTSUPP;
+}
+
#endif /* CONFIG_ROCKCHIP_PM_DOMAINS */
#endif /* __SOC_ROCKCHIP_PM_DOMAINS_H__ */
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 20 May 2020 17:04:47 +0200
Subject: [PATCH] WIP: media: rkvdec: implement reset controls
---
.../bindings/media/rockchip,vdec.yaml | 19 +++++++
drivers/staging/media/rkvdec/rkvdec-regs.h | 5 ++
drivers/staging/media/rkvdec/rkvdec.c | 53 +++++++++++++++++++
drivers/staging/media/rkvdec/rkvdec.h | 11 +++-
4 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml
index 3bcfb8e12333..dd6958df1de8 100644
--- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml
@@ -53,6 +53,18 @@ properties:
iommus:
maxItems: 1
+ resets:
+ maxItems: 6
+
+ reset-names:
+ items:
+ - const: video_h
+ - const: video_a
+ - const: video_core
+ - const: video_cabac
+ - const: niu_a
+ - const: niu_h
+
required:
- compatible
- reg
@@ -60,6 +72,8 @@ required:
- clocks
- clock-names
- power-domains
+ - resets
+ - reset-names
additionalProperties: false
@@ -78,6 +92,11 @@ examples:
clock-names = "axi", "ahb", "cabac", "core";
power-domains = <&power RK3399_PD_VDU>;
iommus = <&vdec_mmu>;
+ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>,
+ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>,
+ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>;
+ reset-names = "video_h", "video_a", "video_core", "video_cabac",
+ "niu_a", "niu_h";
};
...
diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h
index 15b9bee92016..3acc914888f6 100644
--- a/drivers/staging/media/rkvdec/rkvdec-regs.h
+++ b/drivers/staging/media/rkvdec/rkvdec-regs.h
@@ -28,6 +28,11 @@
#define RKVDEC_SOFTRST_EN_P BIT(20)
#define RKVDEC_FORCE_SOFTRESET_VALID BIT(21)
#define RKVDEC_SOFTRESET_RDY BIT(22)
+#define RKVDEC_ERR_MASK (RKVDEC_BUS_STA \
+ | RKVDEC_ERR_STA \
+ | RKVDEC_TIMEOUT_STA \
+ | RKVDEC_BUF_EMPTY_STA \
+ | RKVDEC_COLMV_REF_ERR_STA )
#define RKVDEC_REG_SYSCTRL 0x008
#define RKVDEC_IN_ENDIAN BIT(0)
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index eaf2f133a264..f55abb7c377f 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -10,12 +10,15 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/rockchip_pmu.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
@@ -717,6 +720,11 @@ static void rkvdec_job_finish(struct rkvdec_ctx *ctx,
pm_runtime_mark_last_busy(rkvdec->dev);
pm_runtime_put_autosuspend(rkvdec->dev);
+
+ if (result == VB2_BUF_STATE_ERROR &&
+ rkvdec->reset_mask == RESET_NONE)
+ rkvdec->reset_mask |= RESET_SOFT;
+
rkvdec_job_finish_no_pm(ctx, result);
}
@@ -754,6 +762,33 @@ static void rkvdec_device_run(void *priv)
if (WARN_ON(!desc))
return;
+ if (rkvdec->reset_mask != RESET_NONE) {
+
+ if (rkvdec->reset_mask & RESET_SOFT) {
+ writel(RKVDEC_SOFTRST_EN_P,
+ rkvdec->regs + RKVDEC_REG_INTERRUPT);
+ udelay(RKVDEC_RESET_DELAY);
+ if (readl(rkvdec->regs + RKVDEC_REG_INTERRUPT)
+ & RKVDEC_SOFTRESET_RDY)
+ dev_info_ratelimited(rkvdec->dev,
+ "softreset failed\n");
+ }
+
+ if (rkvdec->reset_mask & RESET_HARD) {
+ rockchip_pmu_idle_request(rkvdec->dev, true);
+ ret = reset_control_assert(rkvdec->rstc);
+ if (!ret) {
+ udelay(RKVDEC_RESET_DELAY);
+ ret = reset_control_deassert(rkvdec->rstc);
+ }
+ rockchip_pmu_idle_request(rkvdec->dev, false);
+ if (ret)
+ dev_notice_ratelimited(rkvdec->dev,
+ "hardreset failed\n");
+ }
+ rkvdec->reset_mask = RESET_NONE;
+ pm_runtime_suspend(rkvdec->dev);
+ }
ret = pm_runtime_resume_and_get(rkvdec->dev);
if (ret < 0) {
@@ -1020,6 +1055,11 @@ static irqreturn_t rkvdec_irq_handler(int irq, void *priv)
if (cancel_delayed_work(&rkvdec->watchdog_work)) {
struct rkvdec_ctx *ctx;
+ if (state == VB2_BUF_STATE_ERROR) {
+ rkvdec->reset_mask |= (status & RKVDEC_ERR_MASK) ?
+ RESET_HARD : RESET_SOFT;
+ }
+
ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev);
rkvdec_job_finish(ctx, state);
}
@@ -1037,6 +1077,7 @@ static void rkvdec_watchdog_func(struct work_struct *work)
ctx = v4l2_m2m_get_curr_priv(rkvdec->m2m_dev);
if (ctx) {
dev_err(rkvdec->dev, "Frame processing timed out!\n");
+ rkvdec->reset_mask |= RESET_HARD;
writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT);
writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL);
rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR);
@@ -1105,6 +1146,18 @@ static int rkvdec_probe(struct platform_device *pdev)
return ret;
}
+
+ rkvdec->rstc = devm_reset_control_array_get(&pdev->dev, false, true);
+ if (IS_ERR(rkvdec->rstc)) {
+ dev_err(&pdev->dev,
+ "get resets failed %ld\n", PTR_ERR(rkvdec->rstc));
+ return PTR_ERR(rkvdec->rstc);
+ } else {
+ dev_dbg(&pdev->dev,
+ "requested %d resets\n",
+ reset_control_get_count(&pdev->dev));
+ }
+
pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
index b9e219438bc9..f02f79c405f0 100644
--- a/drivers/staging/media/rkvdec/rkvdec.h
+++ b/drivers/staging/media/rkvdec/rkvdec.h
@@ -11,10 +11,11 @@
#ifndef RKVDEC_H_
#define RKVDEC_H_
+#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include <linux/videodev2.h>
#include <linux/wait.h>
-#include <linux/clk.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@@ -22,6 +23,12 @@
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
+#define RESET_NONE 0
+#define RESET_SOFT BIT(0)
+#define RESET_HARD BIT(1)
+
+#define RKVDEC_RESET_DELAY 5
+
struct rkvdec_ctx;
struct rkvdec_ctrl_desc {
@@ -96,6 +103,8 @@ struct rkvdec_dev {
void __iomem *regs;
struct mutex vdev_lock; /* serializes ioctls */
struct delayed_work watchdog_work;
+ struct reset_control *rstc;
+ u8 reset_mask;
};
struct rkvdec_ctx {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Tue, 18 Aug 2020 11:38:04 +0200
Subject: [PATCH] WIP: arm64: dts: add resets to vdec for RK3399
---
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 980b12cb0a49..6e3149e587c5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1345,6 +1348,11 @@ vdec: video-codec@ff660000 {
clock-names = "axi", "ahb", "cabac", "core";
iommus = <&vdec_mmu>;
power-domains = <&power RK3399_PD_VDU>;
+ resets = <&cru SRST_H_VDU>, <&cru SRST_A_VDU>,
+ <&cru SRST_VDU_CORE>, <&cru SRST_VDU_CA>,
+ <&cru SRST_A_VDU_NOC>, <&cru SRST_H_VDU_NOC>;
+ reset-names = "video_h", "video_a", "video_core", "video_cabac",
+ "niu_a", "niu_h";
};
vdec_mmu: iommu@ff660480 {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 21 Aug 2021 16:12:36 +0200
Subject: [PATCH] media: hantro: rockchip: Increase RK3288's max ACLK
Required to proper decode H.264@4K
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/media/platform/verisilicon/rockchip_vpu_hw.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
index 8de6fd2e8eef..002b1a600f93 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c
@@ -15,7 +15,8 @@
#include "rockchip_vpu2_regs.h"
#define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000)
-#define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000)
+#define RK3288_ACLK_MAX_FREQ (600 * 1000 * 1000)
+#define RK3399_ACLK_MAX_FREQ (400 * 1000 * 1000)
#define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000)
#define ROCKCHIP_VPU981_MIN_SIZE 64
@@ -346,13 +347,20 @@ static int rk3066_vpu_hw_init(struct hantro_dev *vpu)
return 0;
}
-static int rockchip_vpu_hw_init(struct hantro_dev *vpu)
+static int rk3288_vpu_hw_init(struct hantro_dev *vpu)
{
/* Bump ACLK to max. possible freq. to improve performance. */
clk_set_rate(vpu->clocks[0].clk, RK3288_ACLK_MAX_FREQ);
return 0;
}
+static int rockchip_vpu_hw_init(struct hantro_dev *vpu)
+{
+ /* Bump ACLK to max. possible freq. to improve performance. */
+ clk_set_rate(vpu->clocks[0].clk, RK3399_ACLK_MAX_FREQ);
+ return 0;
+}
+
static void rk3066_vpu_dec_reset(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
@@ -592,7 +600,7 @@ const struct hantro_variant rk3288_vpu_variant = {
.codec_ops = rk3288_vpu_codec_ops,
.irqs = rockchip_vpu1_irqs,
.num_irqs = ARRAY_SIZE(rockchip_vpu1_irqs),
- .init = rockchip_vpu_hw_init,
+ .init = rk3288_vpu_hw_init,
.clk_names = rockchip_vpu_clk_names,
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 4 Jul 2021 15:19:44 +0200
Subject: [PATCH] media: rkvdec: disable QoS for VP9 (corruptions on RK3328
otherwise)
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/staging/media/rkvdec/rkvdec-regs.h | 2 ++
drivers/staging/media/rkvdec/rkvdec-vp9.c | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/drivers/staging/media/rkvdec/rkvdec-regs.h b/drivers/staging/media/rkvdec/rkvdec-regs.h
index 3acc914888f6..265f5234f4eb 100644
--- a/drivers/staging/media/rkvdec/rkvdec-regs.h
+++ b/drivers/staging/media/rkvdec/rkvdec-regs.h
@@ -222,6 +222,8 @@
#define RKVDEC_REG_H264_ERR_E 0x134
#define RKVDEC_H264_ERR_EN_HIGHBITS(x) ((x) & 0x3fffffff)
+#define RKVDEC_QOS_CTRL 0x18C
+
#define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND 0x410
#define RKVDEC_REG_PREF_CHR_CACHE_COMMAND 0x450
diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c
index d8c1c0db15c7..a289bc968e91 100644
--- a/drivers/staging/media/rkvdec/rkvdec-vp9.c
+++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c
@@ -802,6 +802,7 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
struct rkvdec_dev *rkvdec = ctx->dev;
struct rkvdec_vp9_run run = { };
int ret;
+ u32 reg;
ret = rkvdec_vp9_run_preamble(ctx, &run);
if (ret) {
@@ -823,6 +824,13 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
+
+ /* disable QOS for RK3328 - no effect on other SoCs */
+ reg = readl(rkvdec->regs + RKVDEC_QOS_CTRL);
+ reg |= 0xFFFF;
+ reg &= (~BIT(12));
+ writel(reg, rkvdec->regs + RKVDEC_QOS_CTRL);
+
/* Start decoding! */
writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E |
RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Thu, 16 Jun 2022 13:18:22 +0200
Subject: [PATCH] WIP: arm64: dts: add resets to vdec for RK3328
---
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 5519347232f6..431c4ec198be 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -674,6 +674,11 @@ vdec: video-codec@ff360000 {
assigned-clocks = <&cru ACLK_RKVDEC>, <&cru SCLK_VDEC_CABAC>,
<&cru SCLK_VDEC_CORE>;
assigned-clock-rates = <400000000>, <400000000>, <300000000>;
+ resets = <&cru SRST_VDEC_H>, <&cru SRST_VDEC_A>,
+ <&cru SRST_VDEC_CORE>, <&cru SRST_VDEC_CABAC>,
+ <&cru SRST_VDEC_NIU_A>, <&cru SRST_VDEC_NIU_H>;
+ reset-names = "video_h", "video_a", "video_core", "video_cabac",
+ "niu_a", "niu_h";
iommus = <&vdec_mmu>;
power-domains = <&power RK3328_PD_VIDEO>;
};

View file

@ -0,0 +1,543 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 2 Sep 2020 19:52:02 +0200
Subject: [PATCH] arm64: dts: rockchip: add gpu powerdomain, gpu opp-table and
cooling cell for RK3328
Note: since the regulator that supplies the GPU usually also supplies
other SoC components, we have to make sure voltage is never lower then
1075 mV - also disable 500 MHz for now, since it will crash if rkvdec
is running at the same time (voltage to high)
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
.../arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 4 +++
.../arm64/boot/dts/rockchip/rk3328-rock64.dts | 4 +++
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 35 +++++++++++++++++++
3 files changed, 43 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
index aa22a0c22265..51c7723d6762 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
@@ -166,6 +166,10 @@ &gmac2io {
status = "okay";
};
+&gpu {
+ mali-supply = <&vdd_logic>;
+};
+
&hdmi {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
index f69a38f42d2d..c198a8a7f95a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -162,6 +162,10 @@ &gmac2io {
status = "okay";
};
+&gpu {
+ mali-supply = <&vdd_logic>;
+};
+
&hdmi {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 431c4ec198be..eec03adf0902 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -300,6 +300,11 @@ power: power-controller {
#address-cells = <1>;
#size-cells = <0>;
+ power-domain@RK3328_PD_GPU {
+ reg = <RK3328_PD_GPU>;
+ clocks = <&cru ACLK_GPU>;
+ #power-domain-cells = <0>;
+ };
power-domain@RK3328_PD_HEVC {
reg = <RK3328_PD_HEVC>;
#power-domain-cells = <0>;
@@ -539,6 +544,11 @@ map0 {
<&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <4096>;
};
+ map1 {
+ trip = <&target>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ contribution = <4096>;
+ };
};
};
@@ -620,7 +630,32 @@ gpu: gpu@ff300000 {
"ppmmu1";
clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>;
clock-names = "bus", "core";
+ operating-points-v2 = <&gpu_opp_table>;
+ power-domains = <&power RK3328_PD_GPU>;
resets = <&cru SRST_GPU_A>;
+ #cooling-cells = <2>;
+ };
+
+ gpu_opp_table: gpu-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <1075000>;
+ };
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <1075000>;
+ };
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <1075000>;
+ };
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <1150000>;
+ status = "disabled";
+ };
};
h265e_mmu: iommu@ff330200 {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Tue, 2 Feb 2021 17:22:21 +0200
Subject: [PATCH] ARM: dts: RK3288 miqi add hdmi sound nodes
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm/boot/dts/rockchip/rk3288-miqi.dts | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm/boot/dts/rockchip/rk3288-miqi.dts b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
index 713f55e143c6..8d30c49f406e 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
@@ -78,6 +78,21 @@ vcc_sys: vsys-regulator {
regulator-always-on;
regulator-boot-on;
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "HDMI";
+ simple-audio-card,mclk-fs = <512>;
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s>;
+ };
+ };
};
&cpu0 {
@@ -284,6 +299,11 @@ &i2c5 {
status = "okay";
};
+&i2s {
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
&io_domains {
status = "okay";
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Fri, 2 Apr 2021 17:54:22 +0200
Subject: [PATCH] ARM/arm64: dts: rockchip: align sound card names
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi | 2 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi b/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi
index 09618bb7d872..db9106a3dd22 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi
@@ -73,7 +73,7 @@ sdio_pwrseq: sdio-pwrseq {
sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
- simple-audio-card,name = "rockchip,tinker-codec";
+ simple-audio-card,name = "HDMI";
simple-audio-card,mclk-fs = <512>;
simple-audio-card,codec {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 093ebe070775..a10fe60b7680 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1893,7 +1893,7 @@ hdmi_sound: hdmi-sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
- simple-audio-card,name = "hdmi-sound";
+ simple-audio-card,name = "HDMI";
status = "disabled";
simple-audio-card,cpu {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 27 Feb 2021 17:52:02 +0100
Subject: [PATCH] arm64: dts: rockchip: add SPDIF nodes for RK3328 A1 board
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328-a1.dts | 23 ++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
index 40bf808642b9..27a1799027c2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
@@ -57,6 +57,24 @@ ir-receiver {
gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
linux,rc-map-name = "rc-beelink-gs1";
};
+
+ spdif_sound: spdif-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "SPDIF";
+
+ simple-audio-card,cpu {
+ sound-dai = <&spdif>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&spdif_dit>;
+ };
+ };
+
+ spdif_dit: spdif-dit {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
};
&analog_sound {
@@ -325,6 +343,11 @@ &sdmmc {
status = "okay";
};
+&spdif {
+ pinctrl-0 = <&spdifm0_tx>;
+ status = "okay";
+};
+
&tsadc {
rockchip,hw-tshut-mode = <0>;
rockchip,hw-tshut-polarity = <0>;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 27 Feb 2021 18:01:13 +0100
Subject: [PATCH] arm64: dts: rockchip: Add ir-receiver node for RK3328 ROC CC
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
index 51c7723d6762..cf321302daec 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
@@ -88,6 +88,13 @@ vcc_phy: vcc-phy-regulator {
regulator-boot-on;
};
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&ir_int>;
+ pinctrl-names = "default";
+ };
+
leds {
compatible = "gpio-leds";
@@ -312,6 +319,13 @@ &io_domains {
};
&pinctrl {
+
+ ir {
+ ir_int: ir-int {
+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
pmic {
pmic_int_l: pmic-int-l {
rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Mon, 1 Mar 2021 21:24:15 +0100
Subject: [PATCH] ARM: dts: add cec pinctrl for RK3288 miqi board
---
arch/arm/boot/dts/rockchip/rk3288-miqi.dts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/rockchip/rk3288-miqi.dts b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
index 8d30c49f406e..6d90db5a3b75 100644
--- a/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
+++ b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts
@@ -145,6 +145,8 @@ &gpu {
&hdmi {
ddc-i2c-bus = <&i2c5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_cec_c0>;
status = "okay";
};
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Mon, 1 Mar 2021 19:22:15 +0100
Subject: [PATCH] HACK: arm64: dts: enable FE phy for Beelink A1 also
---
arch/arm64/boot/dts/rockchip/rk3328-a1.dts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
index 27a1799027c2..7de9dfa71d89 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
@@ -147,6 +147,14 @@ rtl8211f: ethernet-phy@0 {
};
};
+&gmac2phy {
+ clock_in_out = "output";
+ assigned-clock-rate = <50000000>;
+ assigned-clocks = <&cru SCLK_MAC2PHY>;
+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>;
+ status = "okay";
+};
+
&gpu {
mali-supply = <&vdd_logic>;
};
From 0000000000000000000000000000000000000000 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 c8f44bcb298a..d4280ce4542c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2015-2017 Russell King.
*/
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -129,8 +130,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_debug("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) {
@@ -141,6 +149,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) {
@@ -173,6 +185,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) {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 5 May 2021 19:11:12 +0200
Subject: [PATCH] arm64: boot: dts: Increase ACLK_PERILP0 clock rate for RK3399
As per vendor kernel. Leaving this clock at the lower rate will
result in poor DMA controller performance
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index a10fe60b7680..dbe6a9cb98a5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1477,7 +1477,7 @@ cru: clock-controller@ff760000 {
<1000000000>,
<150000000>, <75000000>,
<37500000>,
- <100000000>, <100000000>,
+ <300000000>, <100000000>,
<50000000>, <600000000>,
<100000000>, <50000000>,
<400000000>, <400000000>,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 21 Aug 2021 17:04:46 +0200
Subject: [PATCH] arm64: dts: rockchip: Enable USB3 for rk3328 Beelink A1
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328-a1.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
index 7de9dfa71d89..e857e5a727f4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
@@ -389,6 +389,11 @@ &usb_host0_ehci {
status = "okay";
};
+&usbdrd3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
&vop {
status = "okay";
};
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 30 Oct 2021 12:19:19 +0200
Subject: [PATCH] WIP: drm: bridge: dw-hdmi: switch from .hw_parmas to .prepare
for i2s
Seems to be the only way to get AES bits correctly as set by
userspace.
TODO: check other consequences.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index a2f0860b20bb..8961f9c7885d 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -34,9 +34,9 @@ static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
return audio->read(hdmi, offset);
}
-static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
- struct hdmi_codec_daifmt *fmt,
- struct hdmi_codec_params *hparms)
+static int dw_hdmi_i2s_prepare(struct device *dev, void *data,
+ struct hdmi_codec_daifmt *fmt,
+ struct hdmi_codec_params *hparms)
{
struct dw_hdmi_i2s_audio_data *audio = data;
struct dw_hdmi *hdmi = audio->hdmi;
@@ -178,7 +178,7 @@ static int dw_hdmi_i2s_hook_plugged_cb(struct device *dev, void *data,
}
static const struct hdmi_codec_ops dw_hdmi_i2s_ops = {
- .hw_params = dw_hdmi_i2s_hw_params,
+ .prepare = dw_hdmi_i2s_prepare,
.audio_startup = dw_hdmi_i2s_audio_startup,
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
.get_eld = dw_hdmi_i2s_get_eld,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 18 Sep 2022 10:35:52 +0200
Subject: [PATCH] arm64: dts: rockchip: Disbake fusb for rk3399-roc-pc
As it will lead to an unbootable device in case one if those ports
is used to power up the device.
See https://lkml.org/lkml/2022/6/20/413
---
arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
index 2f4b1b2e3ac7..7217ead94d39 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi
@@ -215,7 +215,7 @@ vdd_log: vdd-log {
regulator-name = "vdd_log";
regulator-always-on;
regulator-boot-on;
- regulator-min-microvolt = <450000>;
+ regulator-min-microvolt = <430000>;
regulator-max-microvolt = <1400000>;
pwm-supply = <&vcc3v3_sys>;
};
@@ -536,7 +536,7 @@ fusb1: usb-typec@22 {
pinctrl-names = "default";
pinctrl-0 = <&fusb1_int>;
vbus-supply = <&vcc_vbus_typec1>;
- status = "okay";
+ status = "disabled";
};
};
@@ -553,7 +553,7 @@ fusb0: usb-typec@22 {
pinctrl-names = "default";
pinctrl-0 = <&fusb0_int>;
vbus-supply = <&vcc_vbus_typec0>;
- status = "okay";
+ status = "disabled";
};
mp8859: regulator@66 {

View file

@ -0,0 +1,37 @@
From e9d4e43dc5a6fbcdff3be92e4ec40c7bb787a897 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sun, 11 Oct 2020 14:48:44 +0200
Subject: [PATCH] ARM: dts: rockchip: Add IEP node for RK322x
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index de5727e0bc94..a2012a44421d 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -781,6 +781,21 @@ rga: rga@20060000 {
power-domains = <&power RK3228_PD_VIO>;
};
+ iep: iep@20070000 {
+ compatible = "rockchip,rk3228-iep";
+ reg = <0x20070000 0x800>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "iep";
+ clocks = <&cru ACLK_IEP>,
+ <&cru HCLK_IEP>;
+ clock-names = "axi", "ahb";
+ resets = <&cru SRST_IEP_A>,
+ <&cru SRST_IEP_H>;
+ reset-names = "axi", "ahb";
+ power-domains = <&power RK3228_PD_VIO>;
+ iommus = <&iep_mmu>;
+ };
+
iep_mmu: iommu@20070800 {
compatible = "rockchip,iommu";
reg = <0x20070800 0x100>;

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,234 @@
From e039790fb29227f646e91e6d7ec7c3e89c584243 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Tue, 6 Jul 2021 14:21:52 +0000
Subject: [PATCH 1/5] rk3228/rk3328: fix ddr clock gate, add SIP v2 calls
---
drivers/clk/rockchip/clk-ddr.c | 130 ++++++++++++++++++++++++++++++
drivers/clk/rockchip/clk-rk3228.c | 14 ++--
drivers/clk/rockchip/clk-rk3328.c | 7 +-
drivers/clk/rockchip/clk.h | 3 +-
4 files changed, 143 insertions(+), 11 deletions(-)
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
index 86718c54e..b16b3795f 100644
--- a/drivers/clk/rockchip/clk-ddr.c
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -87,6 +87,133 @@ static const struct clk_ops rockchip_ddrclk_sip_ops = {
.get_parent = rockchip_ddrclk_get_parent,
};
+/* See v4.4/include/dt-bindings/display/rk_fb.h */
+#define SCREEN_NULL 0
+#define SCREEN_HDMI 6
+
+static inline int rk_drm_get_lcdc_type(void)
+{
+ return SCREEN_NULL;
+}
+
+struct share_params {
+ u32 hz;
+ u32 lcdc_type;
+ u32 vop;
+ u32 vop_dclk_mode;
+ u32 sr_idle_en;
+ u32 addr_mcu_el3;
+ /*
+ * 1: need to wait flag1
+ * 0: never wait flag1
+ */
+ u32 wait_flag1;
+ /*
+ * 1: need to wait flag1
+ * 0: never wait flag1
+ */
+ u32 wait_flag0;
+ u32 complt_hwirq;
+ /* if need, add parameter after */
+};
+
+struct rockchip_ddrclk_data {
+ u32 inited_flag;
+ void __iomem *share_memory;
+};
+
+static struct rockchip_ddrclk_data ddr_data;
+
+static void rockchip_ddrclk_data_init(void)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM,
+ 1, SHARE_PAGE_TYPE_DDR, 0,
+ 0, 0, 0, 0, &res);
+
+ if (!res.a0) {
+ ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12);
+ ddr_data.inited_flag = 1;
+ }
+}
+
+static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw,
+ unsigned long drate,
+ unsigned long prate)
+{
+ struct share_params *p;
+ struct arm_smccc_res res;
+
+ if (!ddr_data.inited_flag)
+ rockchip_ddrclk_data_init();
+
+ p = (struct share_params *)ddr_data.share_memory;
+
+ p->hz = drate;
+ p->lcdc_type = rk_drm_get_lcdc_type();
+ p->wait_flag1 = 1;
+ p->wait_flag0 = 1;
+
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
+ SHARE_PAGE_TYPE_DDR, 0,
+ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE,
+ 0, 0, 0, 0, &res);
+
+ if ((int)res.a1 == -6) {
+ pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000);
+ /* TODO: rockchip_dmcfreq_wait_complete(); */
+ }
+
+ return res.a0;
+}
+
+static unsigned long rockchip_ddrclk_sip_recalc_rate_v2
+ (struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
+ SHARE_PAGE_TYPE_DDR, 0,
+ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE,
+ 0, 0, 0, 0, &res);
+ if (!res.a0)
+ return res.a1;
+ else
+ return 0;
+}
+
+static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *prate)
+{
+ struct share_params *p;
+ struct arm_smccc_res res;
+
+ if (!ddr_data.inited_flag)
+ rockchip_ddrclk_data_init();
+
+ p = (struct share_params *)ddr_data.share_memory;
+
+ p->hz = rate;
+
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
+ SHARE_PAGE_TYPE_DDR, 0,
+ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE,
+ 0, 0, 0, 0, &res);
+ if (!res.a0)
+ return res.a1;
+ else
+ return 0;
+}
+
+static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = {
+ .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2,
+ .set_rate = rockchip_ddrclk_sip_set_rate_v2,
+ .round_rate = rockchip_ddrclk_sip_round_rate_v2,
+ .get_parent = rockchip_ddrclk_get_parent,
+};
+
struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
const char *const *parent_names,
u8 num_parents, int mux_offset,
@@ -114,6 +241,9 @@ struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
case ROCKCHIP_DDRCLK_SIP:
init.ops = &rockchip_ddrclk_sip_ops;
break;
+ case ROCKCHIP_DDRCLK_SIP_V2:
+ init.ops = &rockchip_ddrclk_sip_ops_v2;
+ break;
default:
pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag);
kfree(ddrclk);
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index 1f9176a5c..96393aa16 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -218,9 +218,9 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),
/* PD_DDR */
- COMPOSITE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED,
- RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
- RK2928_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0,
+ RK2928_CLKSEL_CON(26), 8, 2, 0, 2,
+ ROCKCHIP_DDRCLK_SIP_V2),
GATE(0, "ddrphy4x", "clk_ddrphy_src", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(7), 1, GFLAGS),
FACTOR_GATE(0, "ddrc", "clk_ddrphy_src", CLK_IGNORE_UNUSED, 1, 4,
@@ -576,8 +576,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
- GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
- GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+ GATE(0, "pclk_ddr_upctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+ GATE(0, "pclk_ddr_mon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS),
GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
@@ -652,8 +652,8 @@ static const char *const rk3228_critical_clocks[] __initconst = {
"sclk_initmem_mbist",
"aclk_initmem",
"hclk_rom",
- "pclk_ddrupctl",
- "pclk_ddrmon",
+ "pclk_ddr_upctl",
+ "pclk_ddr_mon",
"pclk_msch_noc",
"pclk_stimer",
"pclk_ddrphy",
diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c
index cc18dbc18..5fdd611bb 100644
--- a/drivers/clk/rockchip/clk-rk3328.c
+++ b/drivers/clk/rockchip/clk-rk3328.c
@@ -317,9 +317,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
RK3328_CLKGATE_CON(14), 1, GFLAGS),
/* PD_DDR */
- COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED,
- RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
- RK3328_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0,
+ RK3328_CLKSEL_CON(3), 8, 2, 0, 3,
+ ROCKCHIP_DDRCLK_SIP_V2),
+
GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED,
RK3328_CLKGATE_CON(18), 6, GFLAGS),
GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index ae059b774..fdaa81ebb 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -363,7 +363,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
* DDRCLK flags, including method of setting the rate
* ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate.
*/
-#define ROCKCHIP_DDRCLK_SIP BIT(0)
+#define ROCKCHIP_DDRCLK_SIP 0x01
+#define ROCKCHIP_DDRCLK_SIP_V2 0x03
struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
const char *const *parent_names,
--
2.25.1

View file

@ -0,0 +1,914 @@
From b4f40590a4f946d8ee704faf8579930e53ef4650 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Sun, 12 Sep 2021 10:15:56 +0000
Subject: [PATCH] rk322x: analog audio codec
---
.../bindings/sound/rockchip,rk3228-codec.txt | 22 +
arch/arm/boot/dts/rockchip/rk322x.dtsi | 9 +
drivers/clk/rockchip/clk-rk3228.c | 2 +-
include/dt-bindings/clock/rk3228-cru.h | 1 +
sound/soc/codecs/Kconfig | 5 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/rk3228_codec.c | 545 ++++++++++++++++++
sound/soc/codecs/rk3228_codec.h | 218 +++++++
8 files changed, 803 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt
create mode 100644 sound/soc/codecs/rk3228_codec.c
create mode 100644 sound/soc/codecs/rk3228_codec.h
diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt
new file mode 100644
index 000000000..9191a8593
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,rk3228-codec.txt
@@ -0,0 +1,22 @@
+* Rockchip Rk3228 internal codec
+
+Required properties:
+
+- compatible: "rockchip,rk3228-codec"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
+- clock-names: a list of clock names, one for each entry in clocks.
+- spk-en-gpio: speaker enable gpio.
+- spk-depop-time-ms: speaker depop time msec.
+
+Example for rk3228 internal codec:
+
+codec: codec@12010000 {
+ compatible = "rockchip,rk3228-codec";
+ reg = <0x12010000 0x1000>;
+ clocks = <&cru SCLK_I2S_OUT>, <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>;
+ clock-names = "mclk", "pclk", "sclk";
+ spk-en-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index 75af99c76..c2670d498 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -145,6 +145,16 @@ i2s1: i2s1@100b0000 {
status = "disabled";
};
+ analog_codec: analog-codec@12010000 {
+ compatible = "rockchip,rk3228-codec";
+ reg = <0x12010000 0x1000>;
+ clocks = <&cru SCLK_I2S_OUT>, <&cru PCLK_ACODECPHY>, <&cru SCLK_I2S1>;
+ clock-names = "mclk", "pclk", "sclk";
+ spk-en-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
i2s0: i2s0@100c0000 {
compatible = "rockchip,rk3228-i2s", "rockchip,rk3066-i2s";
reg = <0x100c0000 0x4000>;
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index a24a35553..69f8c792f 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -620,7 +620,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS),
GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS),
- GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS),
+ GATE(PCLK_ACODECPHY, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS),
GATE(PCLK_HDMI_PHY, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS),
GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h
index de550ea56..30d44ce90 100644
--- a/include/dt-bindings/clock/rk3228-cru.h
+++ b/include/dt-bindings/clock/rk3228-cru.h
@@ -115,6 +115,7 @@
#define PCLK_HDMI_CTRL 364
#define PCLK_HDMI_PHY 365
#define PCLK_GMAC 367
+#define PCLK_ACODECPHY 368
/* hclk gates */
#define HCLK_I2S0_8CH 442
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index db1607120..5f7f01102 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -154,6 +154,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_PCM512x_I2C
imply SND_SOC_PCM512x_SPI
imply SND_SOC_PEB2466
+ imply SND_SOC_RK3228
imply SND_SOC_RK3328
imply SND_SOC_RK817
imply SND_SOC_RT274
@@ -1063,6 +1064,10 @@ config SND_SOC_PCM512x_SPI
select SND_SOC_PCM512x
select REGMAP_SPI
+config SND_SOC_RK3228
+ select REGMAP_MMIO
+ tristate "Rockchip RK3228 CODEC"
+
config SND_SOC_RK3328
tristate "Rockchip RK3328 audio CODEC"
select REGMAP_MMIO
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 7bb38c370..232b5c43e 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -165,6 +165,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-peb2466-objs := peb2466.o
+snd-soc-rk3228-objs := rk3228_codec.o
snd-soc-rk3328-objs := rk3328_codec.o
snd-soc-rk817-objs := rk817_codec.o
snd-soc-rl6231-objs := rl6231.o
@@ -491,6 +492,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o
+obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
diff --git a/sound/soc/codecs/rk3228_codec.c b/sound/soc/codecs/rk3228_codec.c
new file mode 100644
index 000000000..b65307435
--- /dev/null
+++ b/sound/soc/codecs/rk3228_codec.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// rk3228_codec.c -- rk3228 ALSA Soc Audio driver
+//
+// Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include "rk3228_codec.h"
+
+/*
+ * volume setting
+ * 0: -39dB
+ * 26: 0dB
+ * 31: 6dB
+ * Step: 1.5dB
+ */
+#define OUT_VOLUME (0x1a)
+#define INITIAL_FREQ (11289600)
+
+struct rk3228_codec_priv {
+ struct regmap *regmap;
+ struct clk *mclk;
+ struct clk *pclk;
+ struct clk *sclk;
+ struct gpio_desc *spk_en_gpio;
+ int spk_depop_time; /* msec */
+};
+
+static const struct reg_default rk3228_codec_reg_defaults[] = {
+ { CODEC_RESET, 0x03 },
+ { DAC_INIT_CTRL1, 0x00 },
+ { DAC_INIT_CTRL2, 0x50 },
+ { DAC_INIT_CTRL3, 0x0e },
+ { DAC_PRECHARGE_CTRL, 0x01 },
+ { DAC_PWR_CTRL, 0x00 },
+ { DAC_CLK_CTRL, 0x00 },
+ { HPMIX_CTRL, 0x00 },
+ { HPOUT_CTRL, 0x00 },
+ { HPOUTL_GAIN_CTRL, 0x00 },
+ { HPOUTR_GAIN_CTRL, 0x00 },
+ { HPOUT_POP_CTRL, 0x11 },
+};
+
+static int rk3228_codec_reset(struct snd_soc_component *component)
+{
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+
+ regmap_write(rk3228->regmap, CODEC_RESET, 0);
+ mdelay(10);
+ regmap_write(rk3228->regmap, CODEC_RESET, 0x03);
+
+ return 0;
+}
+
+static int rk3228_set_dai_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+ unsigned int val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ val |= PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ val |= PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL1,
+ PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
+
+ val = 0;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ val |= DAC_MODE_PCM;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ val |= DAC_MODE_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ val |= DAC_MODE_RJM;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ val |= DAC_MODE_LJM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL2,
+ DAC_MODE_MASK, val);
+ return 0;
+}
+
+static void rk3228_analog_output(struct rk3228_codec_priv *rk3228, int mute)
+{
+ if (rk3228->spk_en_gpio)
+ gpiod_set_value(rk3228->spk_en_gpio, mute);
+}
+
+static int rk3228_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+ unsigned int val = 0;
+
+ if (direction != SNDRV_PCM_STREAM_PLAYBACK)
+ return 0;
+
+ if (mute)
+ val = HPOUTL_MUTE | HPOUTR_MUTE;
+ else
+ val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
+
+ regmap_update_bits(rk3228->regmap, HPOUT_CTRL,
+ HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
+ return 0;
+}
+
+static int rk3228_codec_power_on(struct snd_soc_component *component, int wait_ms)
+{
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+
+ regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL,
+ DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
+ mdelay(10);
+ regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL,
+ DAC_CHARGE_CURRENT_ALL_MASK,
+ DAC_CHARGE_CURRENT_ALL_ON);
+
+ mdelay(wait_ms);
+
+ return 0;
+}
+
+static int rk3228_codec_power_off(struct snd_soc_component *component, int wait_ms)
+{
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+
+ regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL,
+ DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
+ mdelay(10);
+ regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL,
+ DAC_CHARGE_CURRENT_ALL_MASK,
+ DAC_CHARGE_CURRENT_ALL_ON);
+
+ mdelay(wait_ms);
+
+ return 0;
+}
+
+static struct rk3228_reg_msk_val playback_open_list[] = {
+ { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
+ { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
+ DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
+ { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON,
+ HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
+ { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
+ HPOUTR_POP_WORK | HPOUTL_POP_WORK },
+ { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
+ { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
+ HPMIXL_INIT_EN | HPMIXR_INIT_EN },
+ { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
+ { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
+ HPOUTL_INIT_EN | HPOUTR_INIT_EN },
+ { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
+ DACL_REFV_ON | DACR_REFV_ON },
+ { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
+ DACL_CLK_ON | DACR_CLK_ON },
+ { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
+ { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
+ DACL_INIT_ON | DACR_INIT_ON },
+ { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
+ DACL_SELECT | DACR_SELECT },
+ { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
+ HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
+ { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
+ HPOUTL_UNMUTE | HPOUTR_UNMUTE },
+};
+
+#define PLAYBACK_OPEN_LIST_LEN ARRAY_SIZE(playback_open_list)
+
+static int rk3228_codec_open_playback(struct snd_soc_component *component)
+{
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+ int i = 0;
+
+ regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL,
+ DAC_CHARGE_CURRENT_ALL_MASK,
+ DAC_CHARGE_CURRENT_I);
+
+ for (i = 0; i < PLAYBACK_OPEN_LIST_LEN; i++) {
+ regmap_update_bits(rk3228->regmap,
+ playback_open_list[i].reg,
+ playback_open_list[i].msk,
+ playback_open_list[i].val);
+ mdelay(1);
+ }
+
+ msleep(rk3228->spk_depop_time);
+ rk3228_analog_output(rk3228, 1);
+
+ regmap_update_bits(rk3228->regmap, HPOUTL_GAIN_CTRL,
+ HPOUTL_GAIN_MASK, OUT_VOLUME);
+ regmap_update_bits(rk3228->regmap, HPOUTR_GAIN_CTRL,
+ HPOUTR_GAIN_MASK, OUT_VOLUME);
+ return 0;
+}
+
+static struct rk3228_reg_msk_val playback_close_list[] = {
+ { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
+ HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
+ { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
+ DACL_DESELECT | DACR_DESELECT },
+ { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
+ HPOUTL_MUTE | HPOUTR_MUTE },
+ { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
+ HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
+ { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
+ { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
+ { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
+ { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
+ DACL_CLK_OFF | DACR_CLK_OFF },
+ { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
+ DACL_REFV_OFF | DACR_REFV_OFF },
+ { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
+ HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
+ { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
+ DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
+ { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
+ { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
+ HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
+ { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
+ DACL_INIT_OFF | DACR_INIT_OFF },
+};
+
+#define PLAYBACK_CLOSE_LIST_LEN ARRAY_SIZE(playback_close_list)
+
+static int rk3228_codec_close_playback(struct snd_soc_component *component)
+{
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+ int i = 0;
+
+ rk3228_analog_output(rk3228, 0);
+
+ regmap_update_bits(rk3228->regmap, HPOUTL_GAIN_CTRL,
+ HPOUTL_GAIN_MASK, 0);
+ regmap_update_bits(rk3228->regmap, HPOUTR_GAIN_CTRL,
+ HPOUTR_GAIN_MASK, 0);
+
+ for (i = 0; i < PLAYBACK_CLOSE_LIST_LEN; i++) {
+ regmap_update_bits(rk3228->regmap,
+ playback_close_list[i].reg,
+ playback_close_list[i].msk,
+ playback_close_list[i].val);
+ mdelay(1);
+ }
+
+ regmap_update_bits(rk3228->regmap, DAC_PRECHARGE_CTRL,
+ DAC_CHARGE_CURRENT_ALL_MASK,
+ DAC_CHARGE_CURRENT_I);
+ return 0;
+}
+
+static int rk3228_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct rk3228_codec_priv *rk3228 = snd_soc_component_get_drvdata(component);
+ unsigned int val = 0;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ val |= DAC_VDL_16BITS;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ val |= DAC_VDL_20BITS;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val |= DAC_VDL_24BITS;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ val |= DAC_VDL_32BITS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
+ val = DAC_WL_32BITS | DAC_RST_DIS;
+ regmap_update_bits(rk3228->regmap, DAC_INIT_CTRL3,
+ DAC_WL_MASK | DAC_RST_MASK, val);
+
+ return 0;
+}
+
+static int rk3228_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+
+ return rk3228_codec_open_playback(component);
+}
+
+static void rk3228_pcm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+
+ rk3228_codec_close_playback(component);
+}
+
+static struct snd_soc_dai_ops rk3228_dai_ops = {
+ .hw_params = rk3228_hw_params,
+ .set_fmt = rk3228_set_dai_fmt,
+ .mute_stream = rk3228_mute_stream,
+ .startup = rk3228_pcm_startup,
+ .shutdown = rk3228_pcm_shutdown,
+};
+
+static struct snd_soc_dai_driver rk3228_dai[] = {
+ {
+ .name = "rk3228-hifi",
+ .id = RK3228_HIFI,
+ .playback = {
+ .stream_name = "HIFI Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
+ },
+ /*.capture = {
+ .stream_name = "HIFI Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
+ },*/
+ .ops = &rk3228_dai_ops,
+ },
+};
+
+static int rk3228_codec_probe(struct snd_soc_component *component)
+{
+ rk3228_codec_reset(component);
+ rk3228_codec_power_on(component, 0);
+
+ return 0;
+}
+
+static void rk3228_codec_remove(struct snd_soc_component *component)
+{
+ rk3228_codec_close_playback(component);
+ rk3228_codec_power_off(component, 0);
+}
+
+static struct snd_soc_component_driver soc_codec_dev_rk3228 = {
+ .probe = rk3228_codec_probe,
+ .remove = rk3228_codec_remove,
+};
+
+static bool rk3228_codec_write_read_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CODEC_RESET:
+ case DAC_INIT_CTRL1:
+ case DAC_INIT_CTRL2:
+ case DAC_INIT_CTRL3:
+ case DAC_PRECHARGE_CTRL:
+ case DAC_PWR_CTRL:
+ case DAC_CLK_CTRL:
+ case HPMIX_CTRL:
+ case DAC_SELECT:
+ case HPOUT_CTRL:
+ case HPOUTL_GAIN_CTRL:
+ case HPOUTR_GAIN_CTRL:
+ case HPOUT_POP_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rk3228_codec_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CODEC_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config rk3228_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = HPOUT_POP_CTRL,
+ .writeable_reg = rk3228_codec_write_read_reg,
+ .readable_reg = rk3228_codec_write_read_reg,
+ .volatile_reg = rk3228_codec_volatile_reg,
+ .reg_defaults = rk3228_codec_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(rk3228_codec_reg_defaults),
+ .cache_type = REGCACHE_FLAT,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id rk3228codec_of_match[] = {
+ { .compatible = "rockchip,rk3228-codec", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rk3228codec_of_match);
+#endif
+
+static int rk3228_platform_probe(struct platform_device *pdev)
+{
+ struct device_node *rk3228_np = pdev->dev.of_node;
+ struct rk3228_codec_priv *rk3228;
+ struct resource *res;
+ void __iomem *base;
+ int ret = 0;
+
+ rk3228 = devm_kzalloc(&pdev->dev, sizeof(*rk3228), GFP_KERNEL);
+ if (!rk3228)
+ return -ENOMEM;
+
+ rk3228->mclk = devm_clk_get(&pdev->dev, "mclk");
+ if (PTR_ERR(rk3228->mclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ rk3228->pclk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(rk3228->pclk))
+ return PTR_ERR(rk3228->pclk);
+
+ rk3228->sclk = devm_clk_get(&pdev->dev, "sclk");
+ if (IS_ERR(rk3228->sclk))
+ return PTR_ERR(rk3228->sclk);
+
+ rk3228->spk_en_gpio = devm_gpiod_get_optional(&pdev->dev,
+ "spk-en",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(rk3228->spk_en_gpio))
+ return PTR_ERR(rk3228->spk_en_gpio);
+
+ ret = of_property_read_u32(rk3228_np, "spk-depop-time-ms",
+ &rk3228->spk_depop_time);
+ if (ret < 0) {
+ dev_info(&pdev->dev, "spk_depop_time use default value.\n");
+ rk3228->spk_depop_time = 100;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ ret = clk_prepare_enable(rk3228->mclk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(rk3228->pclk);
+ if (ret < 0)
+ goto err_pclk;
+
+ ret = clk_prepare_enable(rk3228->sclk);
+ if (ret)
+ goto err_sclk;
+
+ clk_set_rate(rk3228->sclk, INITIAL_FREQ);
+
+ rk3228->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &rk3228_codec_regmap_config);
+ if (IS_ERR(rk3228->regmap)) {
+ ret = PTR_ERR(rk3228->regmap);
+ goto err_clk;
+ }
+
+ platform_set_drvdata(pdev, rk3228);
+
+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3228,
+ rk3228_dai, ARRAY_SIZE(rk3228_dai));
+ if (!ret)
+ return 0;
+
+err_clk:
+ clk_disable_unprepare(rk3228->sclk);
+err_sclk:
+ clk_disable_unprepare(rk3228->pclk);
+err_pclk:
+ clk_disable_unprepare(rk3228->mclk);
+
+ return ret;
+}
+
+static int rk3228_platform_remove(struct platform_device *pdev)
+{
+ struct rk3228_codec_priv *rk3228 = platform_get_drvdata(pdev);
+
+ if (!IS_ERR(rk3228->mclk))
+ clk_disable_unprepare(rk3228->mclk);
+
+ if (!IS_ERR(rk3228->pclk))
+ clk_disable_unprepare(rk3228->pclk);
+
+ if (!IS_ERR(rk3228->sclk))
+ clk_disable_unprepare(rk3228->sclk);
+
+ return 0;
+}
+
+static struct platform_driver rk3228_codec_driver = {
+ .driver = {
+ .name = "rk3228-codec",
+ .of_match_table = of_match_ptr(rk3228codec_of_match),
+ },
+ .probe = rk3228_platform_probe,
+ .remove = rk3228_platform_remove,
+};
+module_platform_driver(rk3228_codec_driver);
+
+MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
+MODULE_DESCRIPTION("ASoC rk3228 codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rk3228_codec.h b/sound/soc/codecs/rk3228_codec.h
new file mode 100644
index 000000000..7283d0ba8
--- /dev/null
+++ b/sound/soc/codecs/rk3228_codec.h
@@ -0,0 +1,218 @@
+/*
+ * rk3228_codec.h -- rk3228 ALSA Soc Audio driver
+ *
+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _RK3228_CODEC_H
+#define _RK3228_CODEC_H
+
+/* codec register */
+#define CODEC_RESET (0x00 << 2)
+#define DAC_INIT_CTRL1 (0x03 << 2)
+#define DAC_INIT_CTRL2 (0x04 << 2)
+#define DAC_INIT_CTRL3 (0x05 << 2)
+#define DAC_PRECHARGE_CTRL (0x22 << 2)
+#define DAC_PWR_CTRL (0x23 << 2)
+#define DAC_CLK_CTRL (0x24 << 2)
+#define HPMIX_CTRL (0x25 << 2)
+#define DAC_SELECT (0x26 << 2)
+#define HPOUT_CTRL (0x27 << 2)
+#define HPOUTL_GAIN_CTRL (0x28 << 2)
+#define HPOUTR_GAIN_CTRL (0x29 << 2)
+#define HPOUT_POP_CTRL (0x2a << 2)
+
+/* REG00: CODEC_RESET */
+#define PWR_RST_BYPASS_DIS BIT(6)
+#define PWR_RST_BYPASS_EN BIT(6)
+#define DIG_CORE_RST (0 << 1)
+#define DIG_CORE_WORK BIT(1)
+#define SYS_RST (0)
+#define SYS_WORK BIT(0)
+
+/* REG03: DAC_INIT_CTRL1 */
+#define PIN_DIRECTION_MASK BIT(5)
+#define PIN_DIRECTION_IN (0 << 5)
+#define PIN_DIRECTION_OUT BIT(5)
+#define DAC_I2S_MODE_MASK BIT(4)
+#define DAC_I2S_MODE_SLAVE (0 << 4)
+#define DAC_I2S_MODE_MASTER BIT(4)
+
+/* REG04: DAC_INIT_CTRL2 */
+#define DAC_I2S_LRP_MASK BIT(7)
+#define DAC_I2S_LRP_NORMAL (0 << 7)
+#define DAC_I2S_LRP_REVERSAL BIT(7)
+#define DAC_VDL_MASK (3 << 5)
+#define DAC_VDL_16BITS (0 << 5)
+#define DAC_VDL_20BITS BIT(5)
+#define DAC_VDL_24BITS (2 << 5)
+#define DAC_VDL_32BITS (3 << 5)
+#define DAC_MODE_MASK (3 << 3)
+#define DAC_MODE_RJM (0 << 3)
+#define DAC_MODE_LJM BIT(3)
+#define DAC_MODE_I2S (2 << 3)
+#define DAC_MODE_PCM (3 << 3)
+#define DAC_LR_SWAP_MASK BIT(2)
+#define DAC_LR_SWAP_DIS (0 << 2)
+#define DAC_LR_SWAP_EN BIT(2)
+
+/* REG05: DAC_INIT_CTRL3 */
+#define DAC_WL_MASK (3 << 2)
+#define DAC_WL_16BITS (0 << 2)
+#define DAC_WL_20BITS BIT(2)
+#define DAC_WL_24BITS (2 << 2)
+#define DAC_WL_32BITS (3 << 2)
+#define DAC_RST_MASK BIT(1)
+#define DAC_RST_EN (0 << 1)
+#define DAC_RST_DIS BIT(1)
+#define DAC_BCP_MASK BIT(0)
+#define DAC_BCP_NORMAL (0 << 0)
+#define DAC_BCP_REVERSAL BIT(0)
+
+/* REG22: DAC_PRECHARGE_CTRL */
+#define DAC_CHARGE_PRECHARGE BIT(7)
+#define DAC_CHARGE_DISCHARGE (0 << 7)
+#define DAC_CHARGE_XCHARGE_MASK BIT(7)
+#define DAC_CHARGE_CURRENT_64I BIT(6)
+#define DAC_CHARGE_CURRENT_64I_MASK BIT(6)
+#define DAC_CHARGE_CURRENT_32I BIT(5)
+#define DAC_CHARGE_CURRENT_32I_MASK BIT(5)
+#define DAC_CHARGE_CURRENT_16I BIT(4)
+#define DAC_CHARGE_CURRENT_16I_MASK BIT(4)
+#define DAC_CHARGE_CURRENT_08I BIT(3)
+#define DAC_CHARGE_CURRENT_08I_MASK BIT(3)
+#define DAC_CHARGE_CURRENT_04I BIT(2)
+#define DAC_CHARGE_CURRENT_04I_MASK BIT(2)
+#define DAC_CHARGE_CURRENT_02I BIT(1)
+#define DAC_CHARGE_CURRENT_02I_MASK BIT(1)
+#define DAC_CHARGE_CURRENT_I BIT(0)
+#define DAC_CHARGE_CURRENT_I_MASK BIT(0)
+#define DAC_CHARGE_CURRENT_ALL_MASK (0x7f)
+#define DAC_CHARGE_CURRENT_ALL_OFF (0x0)
+#define DAC_CHARGE_CURRENT_ALL_ON (0x7f)
+
+/* REG23: DAC_PWR_CTRL */
+#define DAC_PWR_OFF (0 << 6)
+#define DAC_PWR_ON BIT(6)
+#define DAC_PWR_MASK BIT(6)
+#define DACL_PATH_REFV_OFF (0 << 5)
+#define DACL_PATH_REFV_ON BIT(5)
+#define DACL_PATH_REFV_MASK BIT(5)
+#define HPOUTL_ZERO_CROSSING_OFF (0 << 4)
+#define HPOUTL_ZERO_CROSSING_ON BIT(4)
+#define DACR_PATH_REFV_OFF (0 << 1)
+#define DACR_PATH_REFV_ON BIT(1)
+#define DACR_PATH_REFV_MASK BIT(1)
+#define HPOUTR_ZERO_CROSSING_OFF (0 << 0)
+#define HPOUTR_ZERO_CROSSING_ON BIT(0)
+
+/* REG24: DAC_CLK_CTRL */
+#define DACL_REFV_OFF (0 << 7)
+#define DACL_REFV_ON BIT(7)
+#define DACL_REFV_MASK BIT(7)
+#define DACL_CLK_OFF (0 << 6)
+#define DACL_CLK_ON BIT(6)
+#define DACL_CLK_MASK BIT(6)
+#define DACL_OFF (0 << 5)
+#define DACL_ON BIT(5)
+#define DACL_MASK BIT(5)
+#define DACL_INIT_OFF (0 << 4)
+#define DACL_INIT_ON BIT(4)
+#define DACL_INIT_MASK BIT(4)
+#define DACR_REFV_OFF (0 << 3)
+#define DACR_REFV_ON BIT(3)
+#define DACR_REFV_MASK BIT(3)
+#define DACR_CLK_OFF (0 << 2)
+#define DACR_CLK_ON BIT(2)
+#define DACR_CLK_MASK BIT(2)
+#define DACR_OFF (0 << 1)
+#define DACR_ON BIT(1)
+#define DACR_MASK BIT(1)
+#define DACR_INIT_OFF (0 << 0)
+#define DACR_INIT_ON BIT(0)
+#define DACR_INIT_MASK BIT(0)
+
+/* REG25: HPMIX_CTRL*/
+#define HPMIXL_DIS (0 << 6)
+#define HPMIXL_EN BIT(6)
+#define HPMIXL_MASK BIT(6)
+#define HPMIXL_INIT_DIS (0 << 5)
+#define HPMIXL_INIT_EN BIT(5)
+#define HPMIXL_INIT_MASK BIT(5)
+#define HPMIXL_INIT2_DIS (0 << 4)
+#define HPMIXL_INIT2_EN BIT(4)
+#define HPMIXL_INIT2_MASK BIT(4)
+#define HPMIXR_DIS (0 << 2)
+#define HPMIXR_EN BIT(2)
+#define HPMIXR_MASK BIT(2)
+#define HPMIXR_INIT_DIS (0 << 1)
+#define HPMIXR_INIT_EN BIT(1)
+#define HPMIXR_INIT_MASK BIT(1)
+#define HPMIXR_INIT2_DIS (0 << 0)
+#define HPMIXR_INIT2_EN BIT(0)
+#define HPMIXR_INIT2_MASK BIT(0)
+
+/* REG26: DAC_SELECT */
+#define DACL_SELECT BIT(4)
+#define DACL_SELECT_MASK BIT(4)
+#define DACL_DESELECT (0 << 4)
+#define DACR_SELECT BIT(0)
+#define DACR_SELECT_MASK BIT(0)
+#define DACR_DESELECT (0 << 0)
+
+/* REG27: HPOUT_CTRL */
+#define HPOUTL_DIS (0 << 7)
+#define HPOUTL_EN BIT(7)
+#define HPOUTL_MASK BIT(7)
+#define HPOUTL_INIT_DIS (0 << 6)
+#define HPOUTL_INIT_EN BIT(6)
+#define HPOUTL_INIT_MASK BIT(6)
+#define HPOUTL_MUTE (0 << 5)
+#define HPOUTL_UNMUTE BIT(5)
+#define HPOUTL_MUTE_MASK BIT(5)
+#define HPOUTR_DIS (0 << 4)
+#define HPOUTR_EN BIT(4)
+#define HPOUTR_MASK BIT(4)
+#define HPOUTR_INIT_DIS (0 << 3)
+#define HPOUTR_INIT_EN BIT(3)
+#define HPOUTR_INIT_MASK BIT(3)
+#define HPOUTR_MUTE (0 << 2)
+#define HPOUTR_UNMUTE BIT(2)
+#define HPOUTR_MUTE_MASK BIT(2)
+
+/* REG28: HPOUTL_GAIN_CTRL */
+#define HPOUTL_GAIN_MASK (0X1f << 0)
+
+/* REG29: HPOUTR_GAIN_CTRL */
+#define HPOUTR_GAIN_MASK (0X1f << 0)
+
+/* REG2a: HPOUT_POP_CTRL */
+#define HPOUTR_POP_XCHARGE BIT(4)
+#define HPOUTR_POP_WORK (2 << 4)
+#define HPOUTR_POP_MASK (3 << 4)
+#define HPOUTL_POP_XCHARGE BIT(0)
+#define HPOUTL_POP_WORK (2 << 0)
+#define HPOUTL_POP_MASK (3 << 0)
+
+#define RK3228_HIFI (0)
+
+struct rk3228_reg_msk_val {
+ unsigned int reg;
+ unsigned int msk;
+ unsigned int val;
+};
+
+#endif
--
2.25.1

View file

@ -0,0 +1,45 @@
From 01b579a527b5c77e6adfbb2c277fb2c7cc158b8b Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Thu, 10 Feb 2022 21:30:54 +0000
Subject: [PATCH] add broadcom bcm43342 chip id
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++
drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 8effeb7a726..f45c1056e42 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -611,6 +611,7 @@ BRCMF_FW_DEF(4329, "brcmfmac4329-sdio");
BRCMF_FW_DEF(4330, "brcmfmac4330-sdio");
BRCMF_FW_DEF(4334, "brcmfmac4334-sdio");
BRCMF_FW_DEF(43340, "brcmfmac43340-sdio");
+BRCMF_FW_DEF(43342, "brcmfmac43342-sdio");
BRCMF_FW_DEF(4335, "brcmfmac4335-sdio");
BRCMF_FW_DEF(43362, "brcmfmac43362-sdio");
BRCMF_FW_DEF(4339, "brcmfmac4339-sdio");
@@ -644,6 +645,7 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
BRCMF_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
BRCMF_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340),
+ BRCMF_FW_ENTRY(BRCM_CC_43342_CHIP_ID, 0xFFFFFFFF, 43342),
BRCMF_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index 9d81320164c..71de0dce4f4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -27,6 +27,7 @@
#define BRCM_CC_4334_CHIP_ID 0x4334
#define BRCM_CC_43340_CHIP_ID 43340
#define BRCM_CC_43341_CHIP_ID 43341
+#define BRCM_CC_43342_CHIP_ID 43342
#define BRCM_CC_43362_CHIP_ID 43362
#define BRCM_CC_4335_CHIP_ID 0x4335
#define BRCM_CC_4339_CHIP_ID 0x4339
--
2.30.2

View file

@ -0,0 +1,67 @@
From 95358ea4a4434ad4af5545b3f762508e4f015fc3 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Tue, 6 Jul 2021 14:23:36 +0000
Subject: [PATCH 2/5] rk3228/rk3328: add ddr clock and SIP related constants
and defines
---
include/dt-bindings/clock/rk3228-cru.h | 1 +
include/soc/rockchip/rockchip_sip.h | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h
index de550ea56..911824731 100644
--- a/include/dt-bindings/clock/rk3228-cru.h
+++ b/include/dt-bindings/clock/rk3228-cru.h
@@ -15,6 +15,7 @@
#define ARMCLK 5
/* sclk gates (special clocks) */
+#define SCLK_DDRCLK 64
#define SCLK_SPI0 65
#define SCLK_NANDC 67
#define SCLK_SDMMC 68
diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h
index c46a9ae2a..34e653751 100644
--- a/include/soc/rockchip/rockchip_sip.h
+++ b/include/soc/rockchip/rockchip_sip.h
@@ -6,6 +6,7 @@
#ifndef __SOC_ROCKCHIP_SIP_H
#define __SOC_ROCKCHIP_SIP_H
+#define ROCKCHIP_SIP_ATF_VERSION 0x82000001
#define ROCKCHIP_SIP_DRAM_FREQ 0x82000008
#define ROCKCHIP_SIP_CONFIG_DRAM_INIT 0x00
#define ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE 0x01
@@ -16,5 +17,28 @@
#define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06
#define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07
#define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08
+#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08
+#define ROCKCHIP_SIP_CONFIG_DRAM_POST_SET_RATE 0x09
+#define ROCKCHIP_SIP_CONFIG_DRAM_SET_MSCH_RL 0x0a
+#define ROCKCHIP_SIP_CONFIG_DRAM_DEBUG 0x0b
+
+#define ROCKCHIP_SIP_SHARE_MEM 0x82000009
+#define ROCKCHIP_SIP_SIP_VERSION 0x8200000a
+
+/* Rockchip Sip version */
+#define ROCKCHIP_SIP_IMPLEMENT_V1 (1)
+#define ROCKCHIP_SIP_IMPLEMENT_V2 (2)
+
+/* SIP_ACCESS_REG: read or write */
+#define SECURE_REG_RD 0x0
+#define SECURE_REG_WR 0x1
+
+/* Share mem page types */
+typedef enum {
+ SHARE_PAGE_TYPE_INVALID = 0,
+ SHARE_PAGE_TYPE_UARTDBG,
+ SHARE_PAGE_TYPE_DDR,
+ SHARE_PAGE_TYPE_MAX,
+} share_page_type_t;
#endif
--
2.25.1

View file

@ -0,0 +1,745 @@
From 415ed43c9b64ca38bc433bd5dc0359292dd80380 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Tue, 6 Jul 2021 14:25:41 +0000
Subject: [PATCH 3/5] rk3228/rk3328: extend rockchip dfi driver
---
arch/arm/boot/dts/rockchip/rk322x.dtsi | 7 +
drivers/devfreq/event/rockchip-dfi.c | 598 ++++++++++++++++++++++++---
2 files changed, 557 insertions(+), 48 deletions(-)
diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
index ad98fcf37..7e06acc31 100644
--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
+++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
@@ -97,6 +97,13 @@ opp-1200000000 {
};
};
+ dfi: dfi@11210000 {
+ reg = <0x11210000 0x400>;
+ compatible = "rockchip,rk3228-dfi";
+ rockchip,grf = <&grf>;
+ status = "okay";
+ };
+
arm-pmu {
compatible = "arm,cortex-a7-pmu";
interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index 9a88faaf8..01fb84b99 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -18,25 +18,68 @@
#include <linux/list.h>
#include <linux/of.h>
-#include <soc/rockchip/rk3399_grf.h>
-
-#define RK3399_DMC_NUM_CH 2
-
+#define PX30_PMUGRF_OS_REG2 0x208
+
+#define RK3128_GRF_SOC_CON0 0x140
+#define RK3128_GRF_OS_REG1 0x1cc
+#define RK3128_GRF_DFI_WRNUM 0x220
+#define RK3128_GRF_DFI_RDNUM 0x224
+#define RK3128_GRF_DFI_TIMERVAL 0x22c
+#define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6))
+#define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6))
+
+#define RK3228_GRF_OS_REG2 0x5d0
+
+#define RK3288_PMU_SYS_REG2 0x9c
+#define RK3288_GRF_SOC_CON4 0x254
+#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4)
+#define RK3288_DFI_EN (0x30003 << 14)
+#define RK3288_DFI_DIS (0x30000 << 14)
+#define RK3288_LPDDR_SEL (0x10001 << 13)
+#define RK3288_DDR3_SEL (0x10000 << 13)
+
+#define RK3328_GRF_OS_REG2 0x5d0
+
+#define RK3368_GRF_DDRC0_CON0 0x600
+#define RK3368_GRF_SOC_STATUS5 0x494
+#define RK3368_GRF_SOC_STATUS6 0x498
+#define RK3368_GRF_SOC_STATUS8 0x4a0
+#define RK3368_GRF_SOC_STATUS9 0x4a4
+#define RK3368_GRF_SOC_STATUS10 0x4a8
+#define RK3368_DFI_EN (0x30003 << 5)
+#define RK3368_DFI_DIS (0x30000 << 5)
+
+#define MAX_DMC_NUM_CH 2
+#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7)
+#define READ_CH_INFO(n) (((n) >> 28) & 0x3)
/* DDRMON_CTRL */
-#define DDRMON_CTRL 0x04
-#define CLR_DDRMON_CTRL (0x1f0000 << 0)
-#define LPDDR4_EN (0x10001 << 4)
-#define HARDWARE_EN (0x10001 << 3)
-#define LPDDR3_EN (0x10001 << 2)
-#define SOFTWARE_EN (0x10001 << 1)
-#define SOFTWARE_DIS (0x10000 << 1)
-#define TIME_CNT_EN (0x10001 << 0)
+#define DDRMON_CTRL 0x04
+#define CLR_DDRMON_CTRL (0x3f0000 << 0)
+#define DDR4_EN (0x10001 << 5)
+#define LPDDR4_EN (0x10001 << 4)
+#define HARDWARE_EN (0x10001 << 3)
+#define LPDDR2_3_EN (0x10001 << 2)
+#define SOFTWARE_EN (0x10001 << 1)
+#define SOFTWARE_DIS (0x10000 << 1)
+#define TIME_CNT_EN (0x10001 << 0)
#define DDRMON_CH0_COUNT_NUM 0x28
#define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
#define DDRMON_CH1_COUNT_NUM 0x3c
#define DDRMON_CH1_DFI_ACCESS_NUM 0x40
+/* pmu grf */
+#define PMUGRF_OS_REG2 0x308
+
+enum {
+ DDR4 = 0,
+ DDR3 = 3,
+ LPDDR2 = 5,
+ LPDDR3 = 6,
+ LPDDR4 = 7,
+ UNUSED = 0xFF
+};
+
struct dmc_usage {
u32 access;
u32 total;
@@ -50,33 +93,261 @@ struct dmc_usage {
struct rockchip_dfi {
struct devfreq_event_dev *edev;
struct devfreq_event_desc *desc;
- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+ struct dmc_usage ch_usage[MAX_DMC_NUM_CH];
struct device *dev;
void __iomem *regs;
struct regmap *regmap_pmu;
+ struct regmap *regmap_grf;
+ struct regmap *regmap_pmugrf;
struct clk *clk;
+ u32 dram_type;
+ /*
+ * available mask, 1: available, 0: not available
+ * each bit represent a channel
+ */
+ u32 ch_msk;
+};
+
+static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+
+ regmap_write(info->regmap_grf,
+ RK3128_GRF_SOC_CON0,
+ RK3128_DDR_MONITOR_EN);
+}
+
+static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+
+ regmap_write(info->regmap_grf,
+ RK3128_GRF_SOC_CON0,
+ RK3128_DDR_MONITOR_DISB);
+}
+
+static int rk3128_dfi_disable(struct devfreq_event_dev *edev)
+{
+ rk3128_dfi_stop_hardware_counter(edev);
+
+ return 0;
+}
+
+static int rk3128_dfi_enable(struct devfreq_event_dev *edev)
+{
+ rk3128_dfi_start_hardware_counter(edev);
+
+ return 0;
+}
+
+static int rk3128_dfi_set_event(struct devfreq_event_dev *edev)
+{
+ return 0;
+}
+
+static int rk3128_dfi_get_event(struct devfreq_event_dev *edev,
+ struct devfreq_event_data *edata)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ unsigned long flags;
+ u32 dfi_wr, dfi_rd, dfi_timer;
+
+ local_irq_save(flags);
+
+ rk3128_dfi_stop_hardware_counter(edev);
+
+ regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr);
+ regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd);
+ regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer);
+
+ edata->load_count = (dfi_wr + dfi_rd) * 4;
+ edata->total_count = dfi_timer;
+
+ rk3128_dfi_start_hardware_counter(edev);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static const struct devfreq_event_ops rk3128_dfi_ops = {
+ .disable = rk3128_dfi_disable,
+ .enable = rk3128_dfi_enable,
+ .get_event = rk3128_dfi_get_event,
+ .set_event = rk3128_dfi_set_event,
+};
+
+static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+
+ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN);
+}
+
+static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+
+ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS);
+}
+
+static int rk3288_dfi_disable(struct devfreq_event_dev *edev)
+{
+ rk3288_dfi_stop_hardware_counter(edev);
+
+ return 0;
+}
+
+static int rk3288_dfi_enable(struct devfreq_event_dev *edev)
+{
+ rk3288_dfi_start_hardware_counter(edev);
+
+ return 0;
+}
+
+static int rk3288_dfi_set_event(struct devfreq_event_dev *edev)
+{
+ return 0;
+}
+
+static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ u32 tmp, max = 0;
+ u32 i, busier_ch = 0;
+ u32 rd_count, wr_count, total_count;
+
+ rk3288_dfi_stop_hardware_counter(edev);
+
+ /* Find out which channel is busier */
+ for (i = 0; i < MAX_DMC_NUM_CH; i++) {
+ if (!(info->ch_msk & BIT(i)))
+ continue;
+ regmap_read(info->regmap_grf,
+ RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count);
+ regmap_read(info->regmap_grf,
+ RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count);
+ regmap_read(info->regmap_grf,
+ RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count);
+ info->ch_usage[i].access = (wr_count + rd_count) * 4;
+ info->ch_usage[i].total = total_count;
+ tmp = info->ch_usage[i].access;
+ if (tmp > max) {
+ busier_ch = i;
+ max = tmp;
+ }
+ }
+ rk3288_dfi_start_hardware_counter(edev);
+
+ return busier_ch;
+}
+
+static int rk3288_dfi_get_event(struct devfreq_event_dev *edev,
+ struct devfreq_event_data *edata)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ int busier_ch;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ busier_ch = rk3288_dfi_get_busier_ch(edev);
+ local_irq_restore(flags);
+
+ edata->load_count = info->ch_usage[busier_ch].access;
+ edata->total_count = info->ch_usage[busier_ch].total;
+
+ return 0;
+}
+
+static const struct devfreq_event_ops rk3288_dfi_ops = {
+ .disable = rk3288_dfi_disable,
+ .enable = rk3288_dfi_enable,
+ .get_event = rk3288_dfi_get_event,
+ .set_event = rk3288_dfi_set_event,
+};
+
+static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+
+ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN);
+}
+
+static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+
+ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS);
+}
+
+static int rk3368_dfi_disable(struct devfreq_event_dev *edev)
+{
+ rk3368_dfi_stop_hardware_counter(edev);
+
+ return 0;
+}
+
+static int rk3368_dfi_enable(struct devfreq_event_dev *edev)
+{
+ rk3368_dfi_start_hardware_counter(edev);
+
+ return 0;
+}
+
+static int rk3368_dfi_set_event(struct devfreq_event_dev *edev)
+{
+ return 0;
+}
+
+static int rk3368_dfi_get_event(struct devfreq_event_dev *edev,
+ struct devfreq_event_data *edata)
+{
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ unsigned long flags;
+ u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer;
+
+ local_irq_save(flags);
+
+ rk3368_dfi_stop_hardware_counter(edev);
+
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr);
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd);
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr);
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd);
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer);
+
+ edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2;
+ edata->total_count = dfi_timer;
+
+ rk3368_dfi_start_hardware_counter(edev);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static const struct devfreq_event_ops rk3368_dfi_ops = {
+ .disable = rk3368_dfi_disable,
+ .enable = rk3368_dfi_enable,
+ .get_event = rk3368_dfi_get_event,
+ .set_event = rk3368_dfi_set_event,
};
static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
{
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
void __iomem *dfi_regs = info->regs;
- u32 val;
- u32 ddr_type;
-
- /* get ddr type */
- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
- RK3399_PMUGRF_DDRTYPE_MASK;
/* clear DDRMON_CTRL setting */
writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
/* set ddr type to dfi */
- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3)
- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4)
+ if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2)
+ writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL);
+ else if (info->dram_type == LPDDR4)
writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+ else if (info->dram_type == DDR4)
+ writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL);
/* enable count, use software mode */
writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
@@ -100,12 +371,22 @@ static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
rockchip_dfi_stop_hardware_counter(edev);
/* Find out which channel is busier */
- for (i = 0; i < RK3399_DMC_NUM_CH; i++) {
- info->ch_usage[i].access = readl_relaxed(dfi_regs +
- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4;
+ for (i = 0; i < MAX_DMC_NUM_CH; i++) {
+ if (!(info->ch_msk & BIT(i)))
+ continue;
+
info->ch_usage[i].total = readl_relaxed(dfi_regs +
DDRMON_CH0_COUNT_NUM + i * 20);
- tmp = info->ch_usage[i].access;
+
+ /* LPDDR4 BL = 16,other DDR type BL = 8 */
+ tmp = readl_relaxed(dfi_regs +
+ DDRMON_CH0_DFI_ACCESS_NUM + i * 20);
+ if (info->dram_type == LPDDR4)
+ tmp *= 8;
+ else
+ tmp *= 4;
+ info->ch_usage[i].access = tmp;
+
if (tmp > max) {
busier_ch = i;
max = tmp;
@@ -118,10 +399,14 @@ static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
{
+ struct device *dev = &edev->dev;
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
rockchip_dfi_stop_hardware_counter(edev);
- clk_disable_unprepare(info->clk);
+ if (info->clk)
+ clk_disable_unprepare(info->clk);
+
+ dev_notice(dev,"Rockchip DFI interface disabled\n");
return 0;
}
@@ -129,20 +414,28 @@ static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
{
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+ struct device *dev = &edev->dev;
int ret;
- ret = clk_prepare_enable(info->clk);
- if (ret) {
- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
- return ret;
+ if (info->clk) {
+ ret = clk_prepare_enable(info->clk);
+ if (ret) {
+ dev_err(&edev->dev, "failed to enable dfi clk: %d\n",
+ ret);
+ return ret;
+ }
}
rockchip_dfi_start_hardware_counter(edev);
+
+ dev_notice(dev,"Rockchip DFI interface enabled\n");
+
return 0;
}
static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
{
+
return 0;
}
@@ -151,8 +444,11 @@ static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
{
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
int busier_ch;
+ unsigned long flags;
+ local_irq_save(flags);
busier_ch = rockchip_dfi_get_busier_ch(edev);
+ local_irq_restore(flags);
edata->load_count = info->ch_usage[busier_ch].access;
edata->total_count = info->ch_usage[busier_ch].total;
@@ -167,22 +463,151 @@ static const struct devfreq_event_ops rockchip_dfi_ops = {
.set_event = rockchip_dfi_set_event,
};
-static const struct of_device_id rockchip_dfi_id_match[] = {
- { .compatible = "rockchip,rk3399-dfi" },
- { },
-};
-MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
+static __init int px30_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
+{
+ struct device_node *np = pdev->dev.of_node, *node;
+ struct resource *res;
+ u32 val;
-static int rockchip_dfi_probe(struct platform_device *pdev)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->regs))
+ return PTR_ERR(data->regs);
+
+ node = of_parse_phandle(np, "rockchip,pmugrf", 0);
+ if (node) {
+ data->regmap_pmugrf = syscon_node_to_regmap(node);
+ if (IS_ERR(data->regmap_pmugrf))
+ return PTR_ERR(data->regmap_pmugrf);
+ }
+
+ regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val);
+ data->dram_type = READ_DRAMTYPE_INFO(val);
+ data->ch_msk = 1;
+ data->clk = NULL;
+
+ desc->ops = &rockchip_dfi_ops;
+
+ return 0;
+}
+
+static __init int rk3128_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
+{
+ struct device_node *np = pdev->dev.of_node, *node;
+
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ data->regmap_grf = syscon_node_to_regmap(node);
+ if (IS_ERR(data->regmap_grf))
+ return PTR_ERR(data->regmap_grf);
+ }
+
+ desc->ops = &rk3128_dfi_ops;
+
+ return 0;
+}
+
+static __init int rk3228_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
{
+ struct device_node *np = pdev->dev.of_node, *node;
+ struct resource *res;
struct device *dev = &pdev->dev;
- struct rockchip_dfi *data;
- struct devfreq_event_desc *desc;
+ u32 val;
+
+ dev_notice(dev,"rk3228_dfi_init enter\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->regs))
+ return PTR_ERR(data->regs);
+
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ data->regmap_grf = syscon_node_to_regmap(node);
+ if (IS_ERR(data->regmap_grf))
+ return PTR_ERR(data->regmap_grf);
+ }
+
+ regmap_read(data->regmap_grf, RK3228_GRF_OS_REG2, &val);
+ data->dram_type = READ_DRAMTYPE_INFO(val);
+ data->ch_msk = 1;
+ data->clk = NULL;
+
+ desc->ops = &rockchip_dfi_ops;
+
+ dev_notice(dev,"rk3228-dfi initialized, dram type: 0x%x, channels: %d\n", data->dram_type, data->ch_msk);
+
+ return 0;
+}
+
+static __init int rk3288_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
+{
struct device_node *np = pdev->dev.of_node, *node;
+ u32 val;
- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ node = of_parse_phandle(np, "rockchip,pmu", 0);
+ if (node) {
+ data->regmap_pmu = syscon_node_to_regmap(node);
+ if (IS_ERR(data->regmap_pmu))
+ return PTR_ERR(data->regmap_pmu);
+ }
+
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ data->regmap_grf = syscon_node_to_regmap(node);
+ if (IS_ERR(data->regmap_grf))
+ return PTR_ERR(data->regmap_grf);
+ }
+
+ regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val);
+ data->dram_type = READ_DRAMTYPE_INFO(val);
+ data->ch_msk = READ_CH_INFO(val);
+
+ if (data->dram_type == DDR3)
+ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4,
+ RK3288_DDR3_SEL);
+ else
+ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4,
+ RK3288_LPDDR_SEL);
+
+ desc->ops = &rk3288_dfi_ops;
+
+ return 0;
+}
+
+static __init int rk3368_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
+{
+ struct device *dev = &pdev->dev;
+
+ if (!dev->parent || !dev->parent->of_node)
+ return -EINVAL;
+
+ data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(data->regmap_grf))
+ return PTR_ERR(data->regmap_grf);
+
+ desc->ops = &rk3368_dfi_ops;
+
+ return 0;
+}
+
+static __init int rockchip_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node, *node;
+ u32 val;
data->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->regs))
@@ -202,21 +627,98 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
if (IS_ERR(data->regmap_pmu))
return PTR_ERR(data->regmap_pmu);
- data->dev = dev;
+
+ regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val);
+ data->dram_type = READ_DRAMTYPE_INFO(val);
+ data->ch_msk = READ_CH_INFO(val);
+
+ desc->ops = &rockchip_dfi_ops;
+
+ return 0;
+}
+
+static __init int rk3328_dfi_init(struct platform_device *pdev,
+ struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc)
+{
+ struct device_node *np = pdev->dev.of_node, *node;
+ struct resource *res;
+ u32 val;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->regs))
+ return PTR_ERR(data->regs);
+
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ data->regmap_grf = syscon_node_to_regmap(node);
+ if (IS_ERR(data->regmap_grf))
+ return PTR_ERR(data->regmap_grf);
+ }
+
+ regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val);
+ data->dram_type = READ_DRAMTYPE_INFO(val);
+ data->ch_msk = 1;
+ data->clk = NULL;
+
+ desc->ops = &rockchip_dfi_ops;
+
+ return 0;
+}
+
+static const struct of_device_id rockchip_dfi_id_match[] = {
+ { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init },
+ { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init },
+ { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init },
+ { .compatible = "rockchip,rk3228-dfi", .data = rk3228_dfi_init },
+ { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init },
+ { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init },
+ { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init },
+ { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
+
+static int rockchip_dfi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rockchip_dfi *data;
+ struct devfreq_event_desc *desc;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
+ int (*init)(struct platform_device *pdev, struct rockchip_dfi *data,
+ struct devfreq_event_desc *desc);
+
+ data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
- desc->ops = &rockchip_dfi_ops;
+ match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node);
+ if (match) {
+ init = match->data;
+ if (init) {
+ if (init(pdev, data, desc))
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
desc->driver_data = data;
desc->name = np->name;
data->desc = desc;
+ data->dev = dev;
- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
+ data->edev = devm_devfreq_event_add_edev(dev, desc);
if (IS_ERR(data->edev)) {
- dev_err(&pdev->dev,
- "failed to add devfreq-event device\n");
+ dev_err(dev, "failed to add devfreq-event device\n");
return PTR_ERR(data->edev);
}
--
2.25.1

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,38 @@
From 9e105544fcb63f8f79b199d1b194a36a354519b3 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Sun, 2 Apr 2023 10:53:07 +0000
Subject: [PATCH 2/2] rk322x: better handle mmc/sdio clocks
---
drivers/clk/rockchip/clk-rk3228.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index 996f8bfee..0f690dd84 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -371,17 +371,15 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS,
RK2928_CLKGATE_CON(2), 11, GFLAGS),
- COMPOSITE_NODIV(SCLK_SDIO_SRC, "sclk_sdio_src", mux_mmc_src_p, 0,
+ COMPOSITE_DIV_OFFSET(SCLK_SDIO, "sclk_sdio", mux_mmc_src_p, 0,
RK2928_CLKSEL_CON(11), 10, 2, MFLAGS,
+ RK2928_CLKSEL_CON(12), 0, 8, DFLAGS,
RK2928_CLKGATE_CON(2), 13, GFLAGS),
- DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
- RK2928_CLKSEL_CON(12), 0, 8, DFLAGS),
- COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+ COMPOSITE_DIV_OFFSET(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
RK2928_CLKSEL_CON(11), 12, 2, MFLAGS,
+ RK2928_CLKSEL_CON(12), 8, 8, DFLAGS,
RK2928_CLKGATE_CON(2), 14, GFLAGS),
- DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
- RK2928_CLKSEL_CON(12), 8, 8, DFLAGS),
/*
* Clock-Architecture Diagram 2
--
2.34.1

View file

@ -0,0 +1,785 @@
From 13498feb91614d59ebece61d0c278e31529bb8c8 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Tue, 10 Oct 2023 21:54:51 +0200
Subject: [PATCH] rockchip gpio IR driver
---
drivers/media/rc/Kconfig | 11 +
drivers/media/rc/Makefile | 1 +
drivers/media/rc/rockchip-ir.c | 723 +++++++++++++++++++++++++++++++++
3 files changed, 735 insertions(+)
create mode 100644 drivers/media/rc/rockchip-ir.c
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index f560fc38895f..b77fa83e90e8 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -333,6 +333,17 @@ config IR_REDRAT3
To compile this driver as a module, choose M here: the
module will be called redrat3.
+config IR_ROCKCHIP_CIR
+ tristate "Rockchip GPIO IR receiver"
+ depends on (OF && GPIOLIB) || COMPILE_TEST
+ help
+ Say Y here if you want to use the Rockchip IR receiver with
+ virtual poweroff features provided by rockchip Trust OS
+
+ To compile this driver as a module, choose M here: the
+ module will be called rockchip-ir
+
+
config IR_RX51
tristate "Nokia N900 IR transmitter diode"
depends on (OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS || COMPILE_TEST) && RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index a9285266e944..057d5b64c121 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_IR_MTK) += mtk-cir.o
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CONFIG_IR_PWM_TX) += pwm-ir-tx.o
obj-$(CONFIG_IR_REDRAT3) += redrat3.o
+obj-$(CONFIG_IR_ROCKCHIP_CIR) += rockchip-ir.o
obj-$(CONFIG_IR_RX51) += ir-rx51.o
obj-$(CONFIG_IR_SERIAL) += serial_ir.o
obj-$(CONFIG_IR_SPI) += ir-spi.o
diff --git a/drivers/media/rc/rockchip-ir.c b/drivers/media/rc/rockchip-ir.c
new file mode 100644
index 000000000000..43ade8c4adce
--- /dev/null
+++ b/drivers/media/rc/rockchip-ir.c
@@ -0,0 +1,733 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <linux/irq.h>
+#include <linux/arm-smccc.h>
+#include <linux/clk.h>
+#include <linux/reboot.h>
+#include <uapi/linux/psci.h>
+#include <media/rc-core.h>
+#include <soc/rockchip/rockchip_sip.h>
+
+#define ROCKCHIP_IR_DEVICE_NAME "rockchip_ir_recv"
+
+#ifdef CONFIG_64BIT
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
+#else
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
+#endif
+
+/*
+* SIP/TEE constants for remote calls
+*/
+#define SIP_REMOTECTL_CFG 0x8200000b
+#define SIP_SUSPEND_MODE 0x82000003
+#define SIP_REMOTECTL_CFG 0x8200000b
+#define SUSPEND_MODE_CONFIG 0x01
+#define WKUP_SOURCE_CONFIG 0x02
+#define PWM_REGULATOR_CONFIG 0x03
+#define GPIO_POWER_CONFIG 0x04
+#define SUSPEND_DEBUG_ENABLE 0x05
+#define APIOS_SUSPEND_CONFIG 0x06
+#define VIRTUAL_POWEROFF 0x07
+
+#define REMOTECTL_SET_IRQ 0xf0
+#define REMOTECTL_SET_PWM_CH 0xf1
+#define REMOTECTL_SET_PWRKEY 0xf2
+#define REMOTECTL_GET_WAKEUP_STATE 0xf3
+#define REMOTECTL_ENABLE 0xf4
+#define REMOTECTL_PWRKEY_WAKEUP 0xdeadbeaf /* wakeup state */
+
+/*
+* PWM Registers
+* Each PWM has its own control registers
+*/
+#define PWM_REG_CNTR 0x00 /* Counter Register */
+#define PWM_REG_HPR 0x04 /* Period Register */
+#define PWM_REG_LPR 0x08 /* Duty Cycle Register */
+#define PWM_REG_CTRL 0x0c /* Control Register */
+
+/*
+* PWM General registers
+* Registers shared among PWMs
+*/
+#define PWM_REG_INT_EN 0x44
+
+/*REG_CTRL bits definitions*/
+#define PWM_ENABLE (1 << 0)
+#define PWM_DISABLE (0 << 0)
+
+/*operation mode*/
+#define PWM_MODE_ONESHOT (0x00 << 1)
+#define PWM_MODE_CONTINUMOUS (0x01 << 1)
+#define PWM_MODE_CAPTURE (0x02 << 1)
+
+/* Channel interrupt enable bit */
+#define PWM_CH_INT_ENABLE(n) BIT(n)
+
+enum pwm_div {
+ PWM_DIV1 = (0x0 << 12),
+ PWM_DIV2 = (0x1 << 12),
+ PWM_DIV4 = (0x2 << 12),
+ PWM_DIV8 = (0x3 << 12),
+ PWM_DIV16 = (0x4 << 12),
+ PWM_DIV32 = (0x5 << 12),
+ PWM_DIV64 = (0x6 << 12),
+ PWM_DIV128 = (0x7 << 12),
+};
+
+#define PWM_INT_ENABLE 1
+#define PWM_INT_DISABLE 0
+
+struct rockchip_rc_dev {
+ struct rc_dev *rcdev;
+ struct gpio_desc *gpiod;
+ int irq;
+ struct device *pmdev;
+ struct pm_qos_request qos;
+ void __iomem *pwm_base;
+ int pwm_wake_irq;
+ int pwm_id;
+ bool use_shutdown_handler; // if true, installs a shutdown handler and triggers virtual poweroff
+ bool use_suspend_handler; // if true, virtual poweroff is used as suspend mode otherwise use as regular suspend
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_state_default;
+ struct pinctrl_state *pinctrl_state_suspend;
+};
+
+static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
+ unsigned long arg0,
+ unsigned long arg1,
+ unsigned long arg2)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+
+ return res;
+}
+
+int sip_smc_remotectl_config(u32 func, u32 data)
+{
+ struct arm_smccc_res res;
+
+ res = __invoke_sip_fn_smc(SIP_REMOTECTL_CFG, func, data, 0);
+
+ return res.a0;
+}
+
+int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
+{
+ struct arm_smccc_res res;
+
+ res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
+ return res.a0;
+}
+
+int sip_smc_virtual_poweroff(void)
+{
+ struct arm_smccc_res res;
+
+ res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND), 0, 0, 0);
+ return res.a0;
+}
+
+static irqreturn_t rockchip_ir_recv_irq(int irq, void *dev_id)
+{
+ int val;
+ struct rockchip_rc_dev *gpio_dev = dev_id;
+ struct device *pmdev = gpio_dev->pmdev;
+
+ /*
+ * For some cpuidle systems, not all:
+ * Respond to interrupt taking more latency when cpu in idle.
+ * Invoke asynchronous pm runtime get from interrupt context,
+ * this may introduce a millisecond delay to call resume callback,
+ * where to disable cpuilde.
+ *
+ * Two issues lead to fail to decode first frame, one is latency to
+ * respond to interrupt, another is delay introduced by async api.
+ */
+ if (pmdev)
+ pm_runtime_get(pmdev);
+
+ val = gpiod_get_value(gpio_dev->gpiod);
+ if (val >= 0)
+ ir_raw_event_store_edge(gpio_dev->rcdev, val == 1);
+
+ if (pmdev) {
+ pm_runtime_mark_last_busy(pmdev);
+ pm_runtime_put_autosuspend(pmdev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void rockchip_pwm_int_ctrl(struct rockchip_rc_dev *gpio_dev, bool enable)
+{
+
+ void __iomem *pwm_base = gpio_dev->pwm_base;
+ struct device *dev = &gpio_dev->rcdev->dev;
+ int pwm_id = gpio_dev->pwm_id;
+
+ void __iomem *reg_int_ctrl;
+ int val;
+
+ reg_int_ctrl= pwm_base - (0x10 * pwm_id) + PWM_REG_INT_EN;
+
+ val = readl_relaxed(reg_int_ctrl);
+
+ if (enable) {
+ val |= PWM_CH_INT_ENABLE(pwm_id);
+ dev_info(dev, "PWM interrupt enabled, register value %x\n", val);
+ } else {
+ val &= ~PWM_CH_INT_ENABLE(pwm_id);
+ dev_info(dev, "PWM interrupt disabled, register value %x\n", val);
+ }
+
+ writel_relaxed(val, reg_int_ctrl);
+
+}
+
+static int rockchip_pwm_hw_init(struct rockchip_rc_dev *gpio_dev)
+{
+
+ void __iomem *pwm_base = gpio_dev->pwm_base;
+ int val;
+
+ //1. disabled pwm
+ val = readl_relaxed(pwm_base + PWM_REG_CTRL);
+ val = (val & 0xFFFFFFFE) | PWM_DISABLE;
+ writel_relaxed(val, pwm_base + PWM_REG_CTRL);
+
+ //2. capture mode
+ val = readl_relaxed(pwm_base + PWM_REG_CTRL);
+ val = (val & 0xFFFFFFF9) | PWM_MODE_CAPTURE;
+ writel_relaxed(val, pwm_base + PWM_REG_CTRL);
+
+ //set clk div, clk div to 64
+ val = readl_relaxed(pwm_base + PWM_REG_CTRL);
+ val = (val & 0xFF0001FF) | PWM_DIV64;
+ writel_relaxed(val, pwm_base + PWM_REG_CTRL);
+
+ //4. enabled pwm int
+ rockchip_pwm_int_ctrl(gpio_dev, true);
+
+ //5. enabled pwm
+ val = readl_relaxed(pwm_base + PWM_REG_CTRL);
+ val = (val & 0xFFFFFFFE) | PWM_ENABLE;
+ writel_relaxed(val, pwm_base + PWM_REG_CTRL);
+
+ return 0;
+
+}
+
+static int rockchip_pwm_hw_stop(struct rockchip_rc_dev *gpio_dev)
+{
+
+ void __iomem *pwm_base = gpio_dev->pwm_base;
+ int val;
+
+ //disable pwm interrupt
+ rockchip_pwm_int_ctrl(gpio_dev, false);
+
+ //disable pwm
+ val = readl_relaxed(pwm_base + PWM_REG_CTRL);
+ val = (val & 0xFFFFFFFE) | PWM_DISABLE;
+ writel_relaxed(val, pwm_base + PWM_REG_CTRL);
+
+ return 0;
+
+}
+
+static int rockchip_pwm_sip_wakeup_init(struct rockchip_rc_dev *gpio_dev)
+{
+
+ struct device *dev = &gpio_dev->rcdev->dev;
+
+ struct irq_data *irq_data;
+ long hwirq;
+ int ret;
+
+ irq_data = irq_get_irq_data(gpio_dev->pwm_wake_irq);
+ if (!irq_data) {
+ dev_err(dev, "could not get irq data\n");
+ return -1;
+ }
+
+ hwirq = irq_data->hwirq;
+ dev_info(dev, "use hwirq %ld, pwm chip id %d for PWM SIP wakeup\n", hwirq, gpio_dev->pwm_id);
+
+ ret = 0;
+
+ ret |= sip_smc_remotectl_config(REMOTECTL_SET_IRQ, (int)hwirq);
+ ret |= sip_smc_remotectl_config(REMOTECTL_SET_PWM_CH, gpio_dev->pwm_id);
+ ret |= sip_smc_remotectl_config(REMOTECTL_ENABLE, 1);
+
+ if (ret) {
+ dev_err(dev, "SIP remote controller mode, TEE does not support feature\n");
+ return ret;
+ }
+
+ sip_smc_set_suspend_mode(SUSPEND_MODE_CONFIG, 0x10042, 0);
+ sip_smc_set_suspend_mode(WKUP_SOURCE_CONFIG, 0x0, 0);
+ sip_smc_set_suspend_mode(PWM_REGULATOR_CONFIG, 0x0, 0);
+ //sip_smc_set_suspend_mode(GPIO_POWER_CONFIG, i, gpio_temp[i]);
+ sip_smc_set_suspend_mode(SUSPEND_DEBUG_ENABLE, 0x1, 0);
+ sip_smc_set_suspend_mode(APIOS_SUSPEND_CONFIG, 0x0, 0);
+ sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 0, 1);
+
+ dev_info(dev, "TEE remote controller wakeup installed\n");
+
+ return 0;
+
+}
+
+static int rockchip_ir_recv_remove(struct platform_device *pdev)
+{
+ struct rockchip_rc_dev *gpio_dev = platform_get_drvdata(pdev);
+ struct device *pmdev = gpio_dev->pmdev;
+
+ if (pmdev) {
+ pm_runtime_get_sync(pmdev);
+ cpu_latency_qos_remove_request(&gpio_dev->qos);
+
+ pm_runtime_disable(pmdev);
+ pm_runtime_put_noidle(pmdev);
+ pm_runtime_set_suspended(pmdev);
+ }
+
+ // Disable the remote controller handling of the Trust OS
+ sip_smc_remotectl_config(REMOTECTL_ENABLE, 0);
+
+ // Disable the virtual poweroff of the Trust OS
+ sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 0, 0);
+
+ return 0;
+}
+
+static int rockchip_ir_register_power_key(struct device *dev)
+{
+
+ struct rockchip_rc_dev *gpio_dev = dev_get_drvdata(dev);
+
+ struct rc_map *key_map;
+ struct rc_map_table *key;
+ int idx, key_scancode, rev_scancode;
+ int tee_scancode;
+
+ key_map = &gpio_dev->rcdev->rc_map;
+
+ dev_info(dev, "remote key table %s, key map of %d items\n", key_map->name, key_map->len);
+
+ for (idx = 0; idx < key_map->len; idx++) {
+
+ key = &key_map->scan[idx];
+
+ if (key->keycode != KEY_POWER)
+ continue;
+
+ key_scancode = key->scancode;
+ rev_scancode = ~key_scancode;
+
+ // If key_scancode has higher 16 bits set to 0, then the scancode is NEC protocol, otherwise it is NECX/NEC32
+ if ((key_scancode & 0xffff) == key_scancode)
+ tee_scancode = (key_scancode & 0xff00) | ((rev_scancode & 0xff00) << 8); // NEC protocol
+ else
+ tee_scancode = ((key_scancode & 0xff0000) >> 8) | ((key_scancode & 0xff00) << 8); // NECX/NEC32 protocol
+
+ tee_scancode |= rev_scancode & 0xff;
+ tee_scancode <<= 8;
+
+ sip_smc_remotectl_config(REMOTECTL_SET_PWRKEY, tee_scancode);
+
+ dev_info(dev, "registered scancode %08x (SIP: %8x)\n", key_scancode, tee_scancode);
+
+ }
+
+ return 0;
+
+}
+
+static int rockchip_ir_recv_suspend_prepare(struct device *dev)
+{
+ struct rockchip_rc_dev *gpio_dev = dev_get_drvdata(dev);
+ int ret;
+
+ dev_info(dev, "initialize rockchip SIP virtual poweroff\n");
+ ret = rockchip_pwm_sip_wakeup_init(gpio_dev);
+
+ if (ret)
+ return ret;
+
+ rockchip_ir_register_power_key(dev);
+
+ disable_irq(gpio_dev->irq);
+ dev_info(dev, "GPIO IRQ disabled\n");
+
+ ret = pinctrl_select_state(gpio_dev->pinctrl, gpio_dev->pinctrl_state_suspend);
+ if (ret) {
+ dev_err(dev, "unable to set pin in PWM mode\n");
+ return ret;
+ }
+
+ dev_info(dev, "set pin configuration to PWM mode\n");
+
+ rockchip_pwm_hw_init(gpio_dev);
+ dev_info(dev, "started pin PWM mode\n");
+
+ return 0;
+
+}
+
+#ifdef CONFIG_PM
+static int rockchip_ir_recv_suspend(struct device *dev)
+{
+ struct rockchip_rc_dev *gpio_dev = dev_get_drvdata(dev);
+
+ /*
+ * if property suspend-is-virtual-poweroff is set, we can disable
+ * the regular gpio wakeup and enable the PWM mode for the Trust OS
+ * to take control and react to remote control.
+ * If the property is not set, we instead enable the wake up for the
+ * regular gpio.
+ */
+ if (gpio_dev->use_suspend_handler) {
+
+ rockchip_ir_recv_suspend_prepare(dev);
+
+ } else {
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(gpio_dev->irq);
+ else
+ disable_irq(gpio_dev->irq);
+
+ }
+
+ return 0;
+}
+
+static int rockchip_ir_recv_resume(struct device *dev)
+{
+ struct rockchip_rc_dev *gpio_dev = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * In case suspend-is-virtual-poweroff property is set,
+ * restore the pin from PWM mode to regular GPIO configuration
+ * and stop the PWM function.
+ * Otherwise, just enable the regular GPIO irq
+ */
+ if (gpio_dev->use_suspend_handler) {
+
+ rockchip_pwm_hw_stop(gpio_dev);
+ dev_info(dev, "stopped pin PWM mode\n");
+
+ ret = pinctrl_select_state(gpio_dev->pinctrl, gpio_dev->pinctrl_state_default);
+ if (ret) {
+ dev_err(dev, "unable to restore pin in GPIO mode\n");
+ return ret;
+ }
+ dev_info(dev, "restored pin configuration di GPIO\n");
+
+ enable_irq(gpio_dev->irq);
+ dev_info(dev, "restored GPIO IRQ\n");
+
+ } else {
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(gpio_dev->irq);
+ else
+ enable_irq(gpio_dev->irq);
+
+ }
+
+ return 0;
+}
+
+static void rockchip_ir_recv_shutdown(struct platform_device *pdev)
+{
+
+ struct device *dev = &pdev->dev;
+ struct rockchip_rc_dev *gpio_dev = dev_get_drvdata(dev);
+
+ if (gpio_dev->use_shutdown_handler)
+ rockchip_ir_recv_suspend_prepare(dev);
+
+ return;
+
+}
+
+static int rockchip_ir_recv_sys_off(struct sys_off_data *data)
+{
+
+ sip_smc_virtual_poweroff();
+
+ return 0;
+
+}
+
+static int rockchip_ir_recv_init_sip(void)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(ROCKCHIP_SIP_SIP_VERSION, ROCKCHIP_SIP_IMPLEMENT_V2, SECURE_REG_WR, 0, 0, 0, 0, 0, &res);
+
+ if (res.a0)
+ return 0;
+
+ return res.a1;
+
+}
+
+static int rockchip_ir_recv_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct rockchip_rc_dev *gpio_dev;
+ struct rc_dev *rcdev;
+ struct clk *clk;
+ struct clk *p_clk;
+ struct resource *res;
+ u32 period = 0;
+ int rc;
+ int ret;
+ int pwm_wake_irq;
+ int clocks;
+
+ if (!np)
+ return -ENODEV;
+
+ gpio_dev = devm_kzalloc(dev, sizeof(*gpio_dev), GFP_KERNEL);
+ if (!gpio_dev)
+ return -ENOMEM;
+
+ gpio_dev->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN);
+ if (IS_ERR(gpio_dev->gpiod)) {
+ rc = PTR_ERR(gpio_dev->gpiod);
+ /* Just try again if this happens */
+ if (rc != -EPROBE_DEFER)
+ dev_err(dev, "error getting gpio (%d)\n", rc);
+ return rc;
+ }
+ gpio_dev->irq = gpiod_to_irq(gpio_dev->gpiod);
+ if (gpio_dev->irq < 0)
+ return gpio_dev->irq;
+
+ rcdev = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
+ if (!rcdev)
+ return -ENOMEM;
+
+ rcdev->priv = gpio_dev;
+ rcdev->device_name = ROCKCHIP_IR_DEVICE_NAME;
+ rcdev->input_phys = ROCKCHIP_IR_DEVICE_NAME "/input0";
+ rcdev->input_id.bustype = BUS_HOST;
+ rcdev->input_id.vendor = 0x0001;
+ rcdev->input_id.product = 0x0001;
+ rcdev->input_id.version = 0x0100;
+ rcdev->dev.parent = dev;
+ rcdev->driver_name = KBUILD_MODNAME;
+ rcdev->min_timeout = 1;
+ rcdev->timeout = IR_DEFAULT_TIMEOUT;
+ rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
+ rcdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
+ rcdev->map_name = of_get_property(np, "linux,rc-map-name", NULL);
+ if (!rcdev->map_name)
+ rcdev->map_name = RC_MAP_EMPTY;
+
+ gpio_dev->rcdev = rcdev;
+ if (of_property_read_bool(np, "wakeup-source")) {
+
+ ret = device_init_wakeup(dev, true);
+
+ if (ret)
+ dev_err(dev, "could not init wakeup device\n");
+
+ }
+
+ rc = devm_rc_register_device(dev, rcdev);
+ if (rc < 0) {
+ dev_err(dev, "failed to register rc device (%d)\n", rc);
+ return rc;
+ }
+
+ of_property_read_u32(np, "linux,autosuspend-period", &period);
+ if (period) {
+ gpio_dev->pmdev = dev;
+ pm_runtime_set_autosuspend_delay(dev, period);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_enable(dev);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "no memory resources defined\n");
+ return -ENODEV;
+ }
+
+ gpio_dev->pwm_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(gpio_dev->pwm_base))
+ return PTR_ERR(gpio_dev->pwm_base);
+
+ clocks = of_property_count_strings(np, "clock-names");
+ if (clocks == 2) {
+ clk = devm_clk_get(dev, "pwm");
+ p_clk = devm_clk_get(dev, "pclk");
+ } else {
+ clk = devm_clk_get(dev, NULL);
+ p_clk = clk;
+ }
+
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Can't get bus clock: %d\n", ret);
+ return ret;
+ }
+
+ if (IS_ERR(p_clk)) {
+ ret = PTR_ERR(p_clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Can't get peripheral clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(dev, "Can't enable bus clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(p_clk);
+ if (ret) {
+ dev_err(dev, "Can't enable peripheral clk: %d\n", ret);
+ goto error_clk;
+ }
+
+ pwm_wake_irq = platform_get_irq(pdev, 0);
+ if (pwm_wake_irq < 0) {
+ dev_err(&pdev->dev, "cannot find PWM wake interrupt\n");
+ goto error_pclk;
+ }
+
+ gpio_dev->pwm_wake_irq = pwm_wake_irq;
+ ret = enable_irq_wake(pwm_wake_irq);
+ if (ret) {
+ dev_err(dev, "could not enable IRQ wakeup\n");
+ }
+
+ ret = of_property_read_u32(np, "pwm-id", &gpio_dev->pwm_id);
+ if (ret) {
+ dev_err(dev, "missing pwm-id property\n");
+ goto error_pclk;
+ }
+
+ if (gpio_dev->pwm_id > 3) {
+ dev_err(dev, "invalid pwm-id property\n");
+ goto error_pclk;
+ }
+
+ gpio_dev->use_shutdown_handler = of_property_read_bool(np, "shutdown-is-virtual-poweroff");
+ gpio_dev->use_suspend_handler = of_property_read_bool(np, "suspend-is-virtual-poweroff");
+
+ gpio_dev->pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(gpio_dev->pinctrl)) {
+ dev_err(dev, "Unable to get pinctrl\n");
+ goto error_pclk;
+ }
+
+ gpio_dev->pinctrl_state_default = pinctrl_lookup_state(gpio_dev->pinctrl, "default");
+ if (IS_ERR(gpio_dev->pinctrl_state_default)) {
+ dev_err(dev, "Unable to get default pinctrl state\n");
+ goto error_pclk;
+ }
+
+ gpio_dev->pinctrl_state_suspend = pinctrl_lookup_state(gpio_dev->pinctrl, "suspend");
+ if (IS_ERR(gpio_dev->pinctrl_state_suspend)) {
+ dev_err(dev, "Unable to get suspend pinctrl state\n");
+ goto error_pclk;
+ }
+
+ platform_set_drvdata(pdev, gpio_dev);
+
+ ret = devm_request_irq(dev, gpio_dev->irq, rockchip_ir_recv_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "gpio-ir-recv-irq", gpio_dev);
+ if (ret) {
+ dev_err(dev, "Can't request GPIO interrupt\n");
+ goto error_pclk;
+ }
+
+ if (gpio_dev->use_shutdown_handler) {
+
+ ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_FIRMWARE, rockchip_ir_recv_sys_off, NULL);
+
+ if (ret)
+ dev_err(dev, "could not register sys_off handler\n");
+
+ }
+
+ ret = rockchip_ir_recv_init_sip();
+ if (!ret) {
+ dev_err(dev, "Unable to initialize Rockchip SIP v2, virtual poweroff unavailable\n");
+ gpio_dev->use_shutdown_handler = false;
+ gpio_dev->use_suspend_handler = false;
+ } else {
+ dev_info(dev, "rockchip SIP initialized, version 0x%x\n", ret);
+ }
+
+ return 0;
+
+error_pclk:
+ clk_unprepare(p_clk);
+error_clk:
+ clk_unprepare(clk);
+
+ return -ENODEV;
+
+}
+
+static const struct dev_pm_ops rockchip_ir_recv_pm_ops = {
+ .suspend = rockchip_ir_recv_suspend,
+ .resume = rockchip_ir_recv_resume,
+};
+#endif
+
+static const struct of_device_id rockchip_ir_recv_of_match[] = {
+ { .compatible = "rockchip-ir-receiver", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rockchip_ir_recv_of_match);
+
+static struct platform_driver rockchip_ir_recv_driver = {
+ .probe = rockchip_ir_recv_probe,
+ .remove = rockchip_ir_recv_remove,
+ .shutdown = rockchip_ir_recv_shutdown,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = of_match_ptr(rockchip_ir_recv_of_match),
+#ifdef CONFIG_PM
+ .pm = &rockchip_ir_recv_pm_ops,
+#endif
+ },
+};
+module_platform_driver(rockchip_ir_recv_driver);
+
+MODULE_DESCRIPTION("Rockchip IR Receiver driver");
+MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
diff -ruPN linux-old/arch/arm/boot/dts/rockchip/rk322x-box-a95xr1.dts linux/arch/arm/boot/dts/rockchip/rk322x-box-a95xr1.dts
--- /dev/null 2025-01-06 10:17:07.467999996 +0100
+++ linux/arch/arm/boot/dts/rockchip/rk322x-box-a95xr1.dts 2025-01-06 23:46:00.126768116 +0100
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+#include "rk322x-box.dtsi"
+#include "rk322x-opp.dtsi"
+#include "rk322x-legacy.dtsi"
+
+/ {
+ model = "RK3229 A95X-R1";
+ compatible = "rockchip,rk322x-box-a95xr1", "rockchip,rk3229";
+
+ leds {
+ compatible = "gpio-leds";
+
+ blue_led {
+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+
+ red_led {
+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ enable-state-shutdown;
+ linux,default-trigger = "rc-feedback";
+ };
+ };
+};
+
+&cpu0_opp_table {
+
+ opp-1104000000 {
+ status = "okay";
+ };
+
+ opp-1200000000 {
+ status = "okay";
+ };
+
+};
+
+&dmc {
+ status = "okay";
+};
+
+&dmc_opp_table {
+ opp-666000000 {
+ status = "okay";
+ };
+};
+
+&emmc {
+ status = "okay";
+};
+

View file

@ -0,0 +1,74 @@
diff -ruPN linux-5.10.76/drivers/devfreq/rk3228_dmc.c linux-new/drivers/devfreq/rk3228_dmc.c
--- linux-5.10.76/drivers/devfreq/rk3228_dmc.c 2022-02-17 11:10:14.196295398 +0100
+++ linux-new/drivers/devfreq/rk3228_dmc.c 2022-02-17 11:13:37.163303895 +0100
@@ -442,17 +442,23 @@
struct rk3228_dmc *rdev = dev_get_drvdata(dev);
int ret = 0;
- ret = devfreq_event_disable_edev(rdev->edev);
- if (ret < 0) {
- dev_err(dev, "failed to disable the devfreq-event devices\n");
- return ret;
- }
-
- ret = devfreq_suspend_device(rdev->devfreq.devfreq);
- if (ret < 0) {
- dev_err(dev, "failed to suspend the devfreq devices\n");
- return ret;
- }
+ if (rdev->dram_type == DDR3 ||
+ rdev->dram_type == LPDDR3 ||
+ rdev->dram_type == DDR4 ||
+ rdev->dram_type == LPDDR4) {
+
+ ret = devfreq_event_disable_edev(rdev->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to disable the devfreq-event devices\n");
+ return ret;
+ }
+
+ ret = devfreq_suspend_device(rdev->devfreq.devfreq);
+ if (ret < 0) {
+ dev_err(dev, "failed to suspend the devfreq devices\n");
+ return ret;
+ }
+ }
return 0;
}
@@ -462,17 +468,24 @@
struct rk3228_dmc *rdev = dev_get_drvdata(dev);
int ret = 0;
- ret = devfreq_event_enable_edev(rdev->edev);
- if (ret < 0) {
- dev_err(dev, "failed to enable the devfreq-event devices\n");
- return ret;
- }
-
- ret = devfreq_resume_device(rdev->devfreq.devfreq);
- if (ret < 0) {
- dev_err(dev, "failed to resume the devfreq devices\n");
- return ret;
- }
+ if (rdev->dram_type == DDR3 ||
+ rdev->dram_type == LPDDR3 ||
+ rdev->dram_type == DDR4 ||
+ rdev->dram_type == LPDDR4) {
+
+ ret = devfreq_event_enable_edev(rdev->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable the devfreq-event devices\n");
+ return ret;
+ }
+
+ ret = devfreq_resume_device(rdev->devfreq.devfreq);
+ if (ret < 0) {
+ dev_err(dev, "failed to resume the devfreq devices\n");
+ return ret;
+ }
+ }
+
return ret;
}

View file

@ -0,0 +1,109 @@
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index d7e65c869415..2ea9f69d312b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -40,8 +40,11 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
{
struct dw_hdmi_i2s_audio_data *audio = data;
struct dw_hdmi *hdmi = audio->hdmi;
+ int sample_width = hparms->sample_width;
+ int ca = hparms->cea.channel_allocation;
u8 conf0 = 0;
u8 conf1 = 0;
+ u8 conf2 = 0;
u8 inputclkfs = 0;
/* it cares I2S only */
@@ -57,6 +60,17 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
inputclkfs = HDMI_AUD_INPUTCLKFS_64FS;
conf0 = (HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_EN0);
+ if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) {
+ conf2 |= HDMI_AUD_CONF2_NLPCM;
+ if (hparms->channels == 8)
+ conf2 |= HDMI_AUD_CONF2_HBR;
+
+ sample_width = 21;
+ ca = 0;
+ }
+
+ hdmi_write(audio, conf2, HDMI_AUD_CONF2);
+
/* Enable the required i2s lanes */
switch (hparms->channels) {
case 7 ... 8:
@@ -70,10 +84,13 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
/* Fall-thru */
}
- switch (hparms->sample_width) {
+ switch (sample_width) {
case 16:
conf1 = HDMI_AUD_CONF1_WIDTH_16;
break;
+ case 21:
+ conf1 = HDMI_AUD_CONF1_WIDTH_21;
+ break;
case 24:
case 32:
conf1 = HDMI_AUD_CONF1_WIDTH_24;
@@ -104,7 +121,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
dw_hdmi_set_channel_status(hdmi, hparms->iec.status);
dw_hdmi_set_channel_count(hdmi, hparms->channels);
- dw_hdmi_set_channel_allocation(hdmi, hparms->cea.channel_allocation);
+ dw_hdmi_set_channel_allocation(hdmi, ca);
hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
hdmi_write(audio, conf0, HDMI_AUD_CONF0);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
index 1999db05bc3b..bff849a336f7 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
@@ -917,8 +917,13 @@ enum {
HDMI_AUD_CONF1_MODE_BURST_1 = 0x60,
HDMI_AUD_CONF1_MODE_BURST_2 = 0x80,
HDMI_AUD_CONF1_WIDTH_16 = 0x10,
+ HDMI_AUD_CONF1_WIDTH_21 = 0x15,
HDMI_AUD_CONF1_WIDTH_24 = 0x18,
+/* AUD_CONF1 field values */
+ HDMI_AUD_CONF2_NLPCM = 0x02,
+ HDMI_AUD_CONF2_HBR = 0x01,
+
/* AUD_CTS3 field values */
HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
diff -ruPN linux/sound/soc/rockchip/rockchip_i2s.c linux-new/sound/soc/rockchip/rockchip_i2s.c
--- linux/sound/soc/rockchip/rockchip_i2s.c 2023-08-11 12:08:27.000000000 +0200
+++ linux-new/sound/soc/rockchip/rockchip_i2s.c 2023-08-16 16:15:37.839774276 +0200
@@ -391,6 +391,9 @@
case SNDRV_PCM_FORMAT_S32_LE:
val |= I2S_TXCR_VDW(32);
break;
+ case SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE:
+ val |= I2S_TXCR_VDW(21);
+ break;
default:
return -EINVAL;
}
@@ -693,7 +696,8 @@
SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE;
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
i2s->playback_dma_data.addr = res->start + I2S_TXDR;
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -714,7 +718,8 @@
SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE;
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
i2s->capture_dma_data.addr = res->start + I2S_RXDR;
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;

View file

@ -0,0 +1,37 @@
diff -ruPN linux/drivers/leds/led-class.c linux-new/drivers/leds/led-class.c
--- linux/drivers/leds/led-class.c 2023-08-11 12:08:27.000000000 +0200
+++ linux-new/drivers/leds/led-class.c 2023-09-28 18:56:46.822821117 +0200
@@ -362,6 +362,9 @@
if (fwnode_property_present(init_data->fwnode,
"retain-state-shutdown"))
led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
+ if (fwnode_property_present(init_data->fwnode,
+ "enable-state-shutdown"))
+ led_cdev->flags |= LED_ENABLE_AT_SHUTDOWN;
fwnode_property_read_u32(init_data->fwnode,
"max-brightness",
diff -ruPN linux/drivers/leds/leds-gpio.c linux-new/drivers/leds/leds-gpio.c
--- linux/drivers/leds/leds-gpio.c 2023-08-11 12:08:27.000000000 +0200
+++ linux-new/drivers/leds/leds-gpio.c 2023-09-28 18:58:09.997824599 +0200
@@ -293,6 +293,9 @@
if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
gpio_led_set(&led->cdev, LED_OFF);
+ if ((led->cdev.flags & LED_ENABLE_AT_SHUTDOWN))
+ gpio_led_set(&led->cdev, LED_FULL);
+
}
}
diff -ruPN linux/include/linux/leds.h linux-new/include/linux/leds.h
--- linux/include/linux/leds.h 2023-08-11 12:08:27.000000000 +0200
+++ linux-new/include/linux/leds.h 2023-09-28 18:18:54.678725996 +0200
@@ -85,6 +85,7 @@
#define LED_BRIGHT_HW_CHANGED BIT(21)
#define LED_RETAIN_AT_SHUTDOWN BIT(22)
#define LED_INIT_DEFAULT_TRIGGER BIT(23)
+#define LED_ENABLE_AT_SHUTDOWN BIT(24)
/* set_brightness_work / blink_timer flags, atomic, private. */
unsigned long work_flags;

View file

@ -0,0 +1,47 @@
diff -ruPN linux-6.1.19/drivers/gpu/drm/lima/lima_gem.c linux-new/drivers/gpu/drm/lima/lima_gem.c
--- linux-6.1.19/drivers/gpu/drm/lima/lima_gem.c 2023-03-13 10:21:32.000000000 +0100
+++ linux-new/drivers/gpu/drm/lima/lima_gem.c 2023-03-23 14:13:46.303639522 +0100
@@ -100,6 +100,16 @@
return 0;
}
+static void lima_gem_free_object(struct drm_gem_object *obj)
+{
+ struct lima_bo *bo = to_lima_bo(obj);
+
+ if (!list_empty(&bo->va))
+ dev_err(obj->dev->dev, "lima gem free bo still has va\n");
+
+ drm_gem_shmem_free(&bo->base);
+}
+
int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
u32 size, u32 flags, u32 *handle)
{
@@ -140,21 +150,15 @@
out:
/* drop reference from allocate - handle holds it now */
- drm_gem_object_put(obj);
+ if (!err) {
+ drm_gem_object_put(obj);
+ } else {
+ lima_gem_free_object(obj);
+ }
return err;
}
-static void lima_gem_free_object(struct drm_gem_object *obj)
-{
- struct lima_bo *bo = to_lima_bo(obj);
-
- if (!list_empty(&bo->va))
- dev_err(obj->dev->dev, "lima gem free bo still has va\n");
-
- drm_gem_shmem_free(&bo->base);
-}
-
static int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file)
{
struct lima_bo *bo = to_lima_bo(obj);

View file

@ -0,0 +1,12 @@
diff -ruPN linux/drivers/mmc/host/dw_mmc.c linux-new/drivers/mmc/host/dw_mmc.c
--- linux/drivers/mmc/host/dw_mmc.c 2023-11-20 11:52:19.000000000 +0100
+++ linux-new/drivers/mmc/host/dw_mmc.c 2023-12-05 18:56:42.971038136 +0100
@@ -3439,7 +3439,7 @@
tasklet_setup(&host->tasklet, dw_mci_tasklet_func);
ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
- host->irq_flags, "dw-mci", host);
+ host->irq_flags, dev_name(host->dev), host);
if (ret)
goto err_dmaunmap;

View file

@ -0,0 +1,122 @@
# Maintainer: leap123 <leap123@canaglie.org>
pkgname=linux-postmarketos-rockchip-rk322x
pkgver=6.6.102
pkgrel=0
pkgdesc="Rockchip RK322X kernel package"
arch="armv7"
_carch="arm"
_flavor="${pkgname#linux-}"
url="https://kernel.org"
license="GPL-2.0-only"
options="!strip !check !tracedeps pmb:cross-native"
makedepends="
bash
bc
bison
devicepkg-dev
findutils
flex
openssl-dev
perl
postmarketos-installkernel
xz
zstd
"
# Source
_config="config-$_flavor.$arch"
case $pkgver in
*.*.*) _kernver=${pkgver%.0};;
*.*) _kernver=$pkgver;;
esac
# Most of the patches are taken from Armbian and ilmich's LibreELEC port
# https://github.com/armbian/build
# https://github.com/rk-unofficial-cfw/LibreELEC.tv/tree/le12-rk322x-wip
source="
https://cdn.kernel.org/pub/linux/kernel/v${_kernver%%.*}.x/linux-$_kernver.tar.xz
$_config
0002-rockchip-from-list.patch
0011-v4l2-from-list.patch
0020-drm-from-list.patch
1000-drm-rockchip.patch
1000-rockchip-wip.patch
1001-drm-wip.patch
1001-v4l2-rockchip.patch
1002-for-libreelec.patch
1002-v4l-wip.patch
2000-v4l2-wip-rkvdec-hevc.patch
2001-v4l2-wip-iep-driver.patch
4001-fix-ddr-clock-gate-add-SIP-v2-calls.patch
4002-rk322x-analog-audio-codec.patch
4003-add-bcm43342-chip.patch
4003-add-ddr-clock-and-SIP-related-constant.patch
4003-extend-rockchip-dfi-driver.patch
4004-add-dmc-driver.patch
4009-rk322x-composite-mmc-clk.patch
4010-rk322x-gpio-ir-driver.patch
9000-rk322x-dts.patch
9001-a95xr1-dts.patch
9003-fix-dmc-suspend-ddr2.patch
9004-wip-audio-passtrough.patch
9006-led-enable-at-shutdown.patch
9007-lima-fix-null-pointer-dereference.patch
9008-dw-mmc-set-name-of-irq.patch
"
builddir="$srcdir/linux-$_kernver"
prepare() {
default_prepare
cp "$srcdir/config-$_flavor.$CARCH" .config
}
build() {
unset LDFLAGS
make ARCH="$_carch" \
KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-$_flavor"
}
package() {
mkdir -p "$pkgdir"/boot
make zinstall modules_install dtbs_install \
ARCH="$_carch" \
INSTALL_MOD_PATH="$pkgdir" \
INSTALL_MOD_STRIP=1 \
INSTALL_PATH="$pkgdir"/boot \
INSTALL_DTBS_PATH="$pkgdir"/boot/dtbs
rm -f "$pkgdir"/lib/modules/*/build "$pkgdir"/lib/modules/*/source
install -D "$builddir"/include/config/kernel.release \
"$pkgdir"/usr/share/kernel/$_flavor/kernel.release
}
sha512sums="
638b42029a92d1406e70ea2cafa8f3f7645785e4c6750e6d71eec6ba85b0c2be9f32fe63779b5b66cae3a85b4e3ac1b90abd90e667d88633e998a06ce4d3065d linux-6.6.102.tar.xz
066b69b2f34c0a3b844ff7ee0174cefc35e00619ec5a333959f5c8c046e706b1b9b358cd3432eda22694bc55fb452ebce004984dd0042e1c2e6592d131bfbaf0 config-postmarketos-rockchip-rk322x.armv7
eba4e26dbda02d8250d92b9d8991ab688ff87c3a2e00271e2fd277769656e2568c8978254e3bbdcbc92e384e28d4341dbcb85e39d329e85421e84785c5a26060 0002-rockchip-from-list.patch
caba86ec7b7ffb0f58b999daa83fba588df9962d9a731bce1f3d08d905451947087ebe1a4be748df05f1b6b70bbedf27edbae6f1cbbdd685272d2400b0428ab6 0011-v4l2-from-list.patch
1f33ffa48aa95ae8e5d5dd0950499e06e1c12af7071ce2b1a4ade03b18c9529a368f2179b2b7064317e398248e1348fa882149878a2a10282dafe3331bc5f09c 0020-drm-from-list.patch
7c1e5d14beb0105d5cbca17cd126e3136aac885dbdfd33bcc327667813ca999c1a1a3ee1decf3b4a897af77400e16fa77abd3a87a4eceb951563ed06dfc34b65 1000-drm-rockchip.patch
8b2ae0742675da28f6bd590aa4d1531f263f414bfbc79d4145f5b684d038b7f8a2fad2aa4e80c20f92b8e9fa96b80493b0996824adcec0f3455fcf9bf826beb4 1000-rockchip-wip.patch
6ffc57ef13c977899ac05b6ad480661065d574d5d9e2ebb061b865147408b0232fa5f639b27c0c6edd8038d1249ad9c2822abca51b854713f243250caa608d75 1001-drm-wip.patch
451a993447262a3f6024d2890277f1a781bac34209d8373ea9557f80357d93bc17b2a1b53bde7771b5c5fe7d797508a4f2054ac23961f6207ff1185a4d39a2d6 1001-v4l2-rockchip.patch
d4919c809d6a2ea5ec0e75b41645c397765fbb269d18de1ea0c417c99a05f39873e8083aa8f70d12e803e463be3a3f9aa8435dea829ac5ce455b163c1eef6617 1002-for-libreelec.patch
813614651fdf60d5689603c4778160e8689cbd6ab1317498b3653d0e39b94d116ff2acf420a67a4058292a8b269e4525f1722d7d9b4ac37d2d4707b848fc6b7f 1002-v4l-wip.patch
c6f11ccdacafded8f01d38ff00d268573611e2e6f5f7e8da276253e74c0bb203c77804d275e5592ba63010f07bdb33e73539b6d3263438deaf487a16d59b5351 2000-v4l2-wip-rkvdec-hevc.patch
c0ef9ca3438db54ef35647d652a36d541d9c3c8d7140164b84e9ec3b524ff06cfc77fbf803520039550e74f1b6c70070f8755dd3c3904461d6c57fad884c276a 2001-v4l2-wip-iep-driver.patch
dfc6b72899b863130632bd9afd352eefb76216137bc8eda02489bb787a08f4f9cd5045bf58303c139c50104b8a27a9f442d3967a6def0fce0c5a271699161ace 4001-fix-ddr-clock-gate-add-SIP-v2-calls.patch
402a81c62cc87f0dd254007b97e7728337ab28746066a2e497ab098318e8c1b0d23fbcbc694bf2d1e53c864cb0bc1ebeb57a5f11a7a690b1e45e721f9596633d 4002-rk322x-analog-audio-codec.patch
0a70e945c7fc312612bb311b492755acce8f5764fbfe56f5063f068c8c690f837e1cefc40586978a163099984d64b46dbda0455f08cc2343bf7dad07bfc5c383 4003-add-bcm43342-chip.patch
9e02e9f71ed87af9779524a6d42679b88c4867b53ecdf6b809f5dda1ab4cae36fa8c063da82181421e4dc552b6006b7a737d8004984e3ed6bff2ebd3cb6f9ae2 4003-add-ddr-clock-and-SIP-related-constant.patch
33860cab1d6eee7df8d2c2a49bda52d300507c486e61e1237f048045c8f4bd562ea01f3aec3637510dc623c0cbed815112771436e79a58b7bf823dfc8f803a03 4003-extend-rockchip-dfi-driver.patch
f2227244c52316f9a667a4f6c589d21e3e5fa9147fe1203c53741b631c53c81715de35f6b2b158d3a3d99fbe0b095fe202194dc8b9fe9804063da94f77241bbf 4004-add-dmc-driver.patch
34595ed17ccc773a79ba21602e7bc350fcd859c4ab50453fd5209a709439e03ef7ad2a0335344a2aaf18652f15449415a2883444dfedee9a8fd0612a7966cf50 4009-rk322x-composite-mmc-clk.patch
ed2c493b2f4e95010a3f82bad7b347ef6871dee3b828682e46574379faadc73976c99b8b60eb76a48571943d16cbc606b6ea10c4f8d095e541903d6919bca553 4010-rk322x-gpio-ir-driver.patch
18069043b29e4fce9c500c52857aea5ee966bfe37f7fe32dacf9cf78b139ba56cfadadae6ac41ad5a60f9480579f5d04ca32ae44b2c5501b07133fefcfa6ffb4 9000-rk322x-dts.patch
c0fe7f3a46415b097338bd0a2b674db772f72b86fc1c7e5b1db6859e49e12bdcc326b2b16090e539eca14ceab9f559b5e6e32374b4f1f9c89896453f398f11b7 9001-a95xr1-dts.patch
e0ea268eabdbeb382db0f23518d2c9020b3e357560cd175719f89f0b1e34272095516d8870d33cb2d459fedadf5154cf87a61de93bcbc84d831d1077b4302e72 9003-fix-dmc-suspend-ddr2.patch
91fb6b809401537a5ff648cba1d4e7a7f6730696059f3acce965c350c8e336a1d2092d128967a40731bec2dba479d4b50d657ab435d649f53faff25537ebdcaf 9004-wip-audio-passtrough.patch
2d9c8238406a1e2ded3703aa7c26227b170e2c4d19757b4fe499690ce2bb2d1eba8b1f01d21a5bee623e047217550c86ac614f9bd75c15d032444319a26bd749 9006-led-enable-at-shutdown.patch
a80265439dd2f57a8b93f0e7ceb2544718603a55db9dd3fddb85d90f90f648284ca7f0194847211da016c5be612d8c42ede5b33c79afeffedfef9653d06efa13 9007-lima-fix-null-pointer-dereference.patch
69826d24021ab408fca49cee3a91a0e190a51a475ec9163f372fc592b58cbd6cef32cf57d0cb53316e72ee4feec5c8d941242e8f0b6e2638d35f5bdb8188bf08 9008-dw-mmc-set-name-of-irq.patch
"

View file

@ -0,0 +1,338 @@
diff -ruPN u-boot-2025.07/arch/arm/dts/Makefile u-boot-2025.07-patched/arch/arm/dts/Makefile
--- u-boot-2025.07/arch/arm/dts/Makefile 2025-07-07 22:48:28.000000000 +0700
+++ u-boot-2025.07-patched/arch/arm/dts/Makefile 2025-08-24 13:41:12.150125560 +0700
@@ -56,7 +56,8 @@
rk3128-evb.dtb
dtb-$(CONFIG_ROCKCHIP_RK322X) += \
- rk3229-evb.dtb
+ rk3229-evb.dtb \
+ rk322x-box.dtb
dtb-$(CONFIG_ROCKCHIP_RK3288) += \
rk3288-evb.dtb \
--- u-boot-2025.07/arch/arm/dts/rk322x-box.dts 1970-01-01 07:00:00.000000000 +0700
+++ u-boot-2025.07-patched/arch/arm/dts/rk322x-box.dts 1970-01-01 07:00:00.000000000 +0700
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+ X11
+ */
+
+/dts-v1/;
+
+#include "rk322x-box.dtsi"
+#include "rk322x-u-boot.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Rockchip RK322x SoC (eMMC)";
+
+ aliases {
+ mmc1 = &emmc;
+ //mmc2 = &nandc;
+ };
+
+ chosen {
+ u-boot,spl-boot-order = &sdmmc, &emmc/*, &nandc*/;
+ };
+
+};
+
+&emmc {
+ u-boot,dm-spl;
+ clock-frequency = <50000000>;
+ clock-freq-min-max = <400000 50000000>;
+ broken-cd;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ supports-emmc;
+ disable-wp;
+ non-removable;
+ max-frequency = <50000000>;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ /delete-property/ default-sample-phase;
+ status = "okay";
+};
+
+/*&nandc {
+ status = "okay";
+};*/
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_phy {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
diff -ruPN u-boot-2025.07/arch/arm/dts/rk322x-box.dtsi u-boot-2025.07-patched/arch/arm/dts/rk322x-box.dtsi
--- u-boot-2025.07/arch/arm/dts/rk322x-box.dtsi 1970-01-01 07:00:00.000000000 +0700
+++ u-boot-2025.07-patched/arch/arm/dts/rk322x-box.dtsi 2025-08-24 13:40:14.110948109 +0700
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0+ X11
+ */
+
+/dts-v1/;
+
+#include "rk322x.dtsi"
+#include "rk322x-u-boot.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Rockchip RK322x SoC";
+ compatible = "rockchip,rk3229-evb", "rockchip,rk3229";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ mmc0 = &sdmmc;
+ };
+
+ ext_gmac: ext_gmac {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "ext_gmac";
+ #clock-cells = <0>;
+ };
+
+ vcc_phy: vcc-phy-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ regulator-name = "vcc_phy";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc_otg_vbus: otg-vbus-regulator {
+ compatible = "regulator-fixed";
+ gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&otg_vbus_drv>;
+ regulator-name = "vcc_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+
+ gpio-keys {
+ u-boot,dm-pre-reloc;
+ compatible = "gpio-keys";
+ status = "okay";
+
+ volume-up {
+ u-boot,dm-pre-reloc;
+ linux,code = <KEY_VOLUMEUP>;
+ label = "Volume Up";
+ gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+};
+
+/*&dmc {
+ rockchip,pctl-timing = <0x96 0xC8 0x1F3 0xF 0x8000004D 0x4 0x4E 0x6 0x3
+ 0x0 0x6 0x5 0xC 0x10 0x6 0x4 0x4
+ 0x5 0x4 0x200 0x3 0xA 0x40 0x0 0x1
+ 0x5 0x5 0x3 0xC 0x1E 0x100 0x0 0x4
+ 0x0 0x924>;
+ rockchip,phy-timing = <0x220 0x1 0x0 0x0 0x0 0x4 0x60>;
+ rockchip,sdram-params = <0x428B188 0x0 0x21 0x472 0x15
+ 0 300 3 0 120>;
+};*/
+
+&gmac {
+ assigned-clocks = <&cru SCLK_MAC_EXTCLK>, <&cru SCLK_MAC>;
+ assigned-clock-parents = <&ext_gmac>, <&cru SCLK_MAC_EXTCLK>;
+ clock_in_out = "input";
+ phy-supply = <&vcc_phy>;
+ phy-mode = "rgmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ snps,reset-gpio = <&gpio2 RK_PD0 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 1000000>;
+ tx_delay = <0x30>;
+ rx_delay = <0x10>;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ disable-wp;
+ num-slots = <1>;
+ supports-sd;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+
+ u2phy0_otg: otg-port {
+ status = "okay";
+ };
+
+ u2phy0_host: host-port {
+ status = "okay";
+ };
+};
+
+&usb_otg {
+ status = "okay";
+};
+
+
+&pinctrl {
+
+ gpio {
+ gpio_leds: gpio-leds {
+ rockchip,pins = <3 21 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ usb {
+ otg_vbus_drv: otg-vbus-drv {
+ rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+};
--- u-boot-2025.07/configs/box-rk322x_defconfig 1970-01-01 07:00:00.000000000 +0700
+++ u-boot-2025.07-patched/configs/box-rk322x_defconfig 1970-01-01 07:00:00.000000000 +0700
@@ -0,0 +1,113 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_SPL_SKIP_LOWLEVEL_INIT=y
+CONFIG_TPL_SKIP_LOWLEVEL_INIT=y
+CONFIG_SYS_ARCH_TIMER=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x61000000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x61100000
+CONFIG_ENV_OFFSET=0x3F8000
+CONFIG_DEFAULT_DEVICE_TREE="rk322x-box"
+CONFIG_ROCKCHIP_RK322X=y
+CONFIG_TARGET_EVB_RK3229=y
+CONFIG_SPL_STACK_R_ADDR=0x60600000
+CONFIG_SPL_TEXT_BASE=0x60000000
+CONFIG_SPL_STACK_R=y
+CONFIG_SYS_BOOTM_LEN=0x4000000
+CONFIG_SYS_LOAD_ADDR=0x61800800
+CONFIG_DEBUG_UART_BASE=0x11030000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_TPL_MAX_SIZE=28672
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SD_BOOT=y
+CONFIG_USE_PREBOOT=y
+CONFIG_DEFAULT_FDT_FILE="rk322x-box.dtb"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_MAX_SIZE=0x100000
+CONFIG_SPL_NO_BSS_LIMIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_CMD_BOOTDEV=y
+CONFIG_CMD_BOOTMENU=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_PWM=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_TPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_TPL_CLK=y
+CONFIG_CLK_CCF=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_GPIO=y
+CONFIG_FASTBOOT_BUF_SIZE=0x04000000
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_ROCKCHIP_INNO_HDMI=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PINCTRL=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_SPL_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
+CONFIG_BAUDRATE=152000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_SYSRESET=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_FUNCTION_ROCKUSB=y
+CONFIG_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_VIDEO_ROCKCHIP_MAX_XRES=1920
+CONFIG_VIDEO_ROCKCHIP_MAX_YRES=1080
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_TPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
+CONFIG_BOOTM_OPTEE=y

View file

@ -0,0 +1,11 @@
--- u-boot-2025.07/include/configs/rockchip-common.h 2025-07-07 22:48:28.000000000 +0700
+++ u-boot-2025.07-patched/include/configs/rockchip-common.h 2025-08-26 19:41:28.868853141 +0700
@@ -14,7 +14,7 @@
#ifndef CONFIG_XPL_BUILD
#ifndef BOOT_TARGETS
-#define BOOT_TARGETS "mmc1 mmc0 nvme scsi usb pxe dhcp spi"
+#define BOOT_TARGETS "mmc1 usb mmc0 nvme scsi pxe dhcp spi"
#endif
#ifdef CONFIG_ARM64

View file

@ -0,0 +1,68 @@
# Maintainer: leap123 <leap123@canaglie.org>
pkgname=u-boot-rockchip-rk322x
pkgver=2025.07
pkgrel=0
_ddr_ver=1.11
_trust_ver=51.1.0-333-gc9d95d1
_miniloader_ver=2.56
pkgdesc="u-boot bootloader for rk3228/rk3229"
url="https://gitlab.denx.de/u-boot/u-boot"
arch="armv7"
license="GPL-2.0-or-later OFL-1.1 BSD-2-Clause BSD-3-Clause eCos-2.0 IBM-pibs
ISC LGPL-2.0-only LGPL-2.1-only X11"
options="!check"
makedepends="
bc
bison
dtc
flex
gnutls-dev
libfdt
make
openssl-dev
py3-elftools
py3-setuptools
python3-dev
swig
"
_rkbin_commit="84f2356cf510319665874daf29df9ad8a94ac7e4"
builddir="$srcdir"/u-boot-$pkgver
source="
https://ftp.denx.de/pub/u-boot/u-boot-${pkgver//_/-}.tar.bz2
https://github.com/ilmich/rkbin/raw/$_rkbin_commit/rk32/rk322x_ddr_330MHz_v$_ddr_ver.bin
https://github.com/ilmich/rkbin/raw/$_rkbin_commit/rk32/rk3228_tee_ta-$_trust_ver.bin
https://github.com/ilmich/rkbin/raw/$_rkbin_commit/rk32/rk322x_miniloader_v$_miniloader_ver.bin
update-u-boot
0001-rk322x-defconfig-dts.patch
0002-rockchip-boot-order-usb.patch
"
build() {
export ROCKCHIP_TPL="$srcdir"/rk322x_ddr_330MHz_v$_ddr_ver.bin
export TEE="$srcdir"/rk3228_tee_ta-$_trust_ver.bin
make box-rk322x_defconfig
make
# make idbloader.img
tools/mkimage -n rk322x -T rksd -d "$ROCKCHIP_TPL:$srcdir"/rk322x_miniloader_v$_miniloader_ver.bin "$builddir"/idbloader.img
}
package() {
install -D -m755 "$srcdir"/update-u-boot "$pkgdir"/usr/sbin/update-u-boot
install -Dm644 \
"$builddir"/idbloader.img \
"$builddir"/u-boot.itb \
-t "$pkgdir"/usr/share/u-boot/rockchip-rk322x
}
sha512sums="
0d9a4906aaee134c6b6c496aaf7f54c653ede8e878f851e877ec7876e26cd14e356cd29112849295deeb72bee6b4d292151fb4d9db23d23608350c3fe567d955 u-boot-2025.07.tar.bz2
016e52d227a3648a29af71d07472bf1d4c5082aacb7716caf64033f55f711646e787bdfb049291d3259ea70c140dd2af587770776277de1dbcc540c9635e95dd rk322x_ddr_330MHz_v1.11.bin
ec6024ee74b501d97640527496ae530eb4d115b59a0303b6deb7c954f85881e5e1731e6a4694bf899e078a79fae82a3f8f436cff6eb521ee5f083ab138138fe7 rk3228_tee_ta-51.1.0-333-gc9d95d1.bin
11179b97856dbe6543e8fd7b5d9a2c7e954ad7d4d15d0315b933de8afc00f2249cd938ed53d8868591491cd1f6dd17edd8fc01f6b1377dc0071972cac9e1a661 rk322x_miniloader_v2.56.bin
2a01a6d0dedca464a25a9a02e58572857bf8aafa9bbf5a18f42e0bec1d9d452ab3347ad4f8ceea9df2cac55bd25eb0bdaae1967de6446fc7336afcbc6abeb4b5 update-u-boot
d749ef1c9ffb454efe66848ca820472c695631673327e81eb4091ba06ba862971566e9d566c456b06dd8630ce7138e91cf1f3dffd00d143db6acbdaa7c8d09c8 0001-rk322x-defconfig-dts.patch
9316278dfd60a35d4126160430b2f21ab8a4ae5c90883134dcf884325726e0a0a973f8a78dbcc1a4c515590bba33eb5b83df81930fba1ad390b9dd0ce89bf81b 0002-rockchip-boot-order-usb.patch
"

View file

@ -0,0 +1,110 @@
#!/bin/sh
verbose=
board=
device=
dryrun=
imagedir=
get_defaults() {
if [ -z "$board" -a -e /sys/firmware/devicetree/base/compatible ]; then
case "$(cat /sys/firmware/devicetree/base/compatible 2>/dev/null)" in
rockchip,rk322*) board=rk322x ;;
esac
fi
if [ -z "$device" ]; then
case "$board" in
rk3228|rk3229|rk322x) device=/dev/mmcblk1 ;;
esac
fi
if [ -z "$imagedir" ]; then
imagedir="$(realpath $(dirname $0))"
[ -f "$imagedir/README.txt" ] || imagedir="/usr/share/u-boot"
fi
}
die() {
echo "ERROR: $@"
exit 1
}
usage() {
get_defaults
cat <<EOF
usage: $0 [-n,--dry-run] [-i,--imagedir <imagedir>] [-b|--board <board-type>] [-d|--device <device>]
options:
-b,--board <board> Specify the board type: rk322x
(current default: ${board:-none})
-d,--device <device> Specify the device where to install u-boot
(current default: ${device:-none})
-i,--imagedir <imagedir> Specify u-boot image directory
(current default: ${imagedir:-none})
-n,--dry-run Print commands but don't execute them
EOF
}
while [ $# -gt 0 ]; do
opt="$1"
shift
case "$opt" in
-b|--board)
case "$1" in
rk3228|rk3229|rk322x) board="rk322x" ;;
*) usage; exit 1;;
esac
shift
;;
-d|--device)
device="$1"
shift
;;
-i|--imagedir)
imagedir="$1"
shift
;;
-n|--dry-run)
dryrun="echo"
;;
--)
break
;;
-*)
usage
exit 1
;;
esac
done
get_defaults
if [ -z "$board" -o -z "$device" -o -z "$imagedir" -o ! -e "$imagedir" ]; then
usage
exit 1
fi
if [ -z "$dryrun" ]; then
echo "Updating $board u-boot in $device in 3 seconds..."
sleep 3
fi
(
set -e
case "$board" in
rk3228|rk3229|rk322x)
[ -e "$imagedir/rockchip-rk322x/" ] || die "rk322x images not installed, apk add u-boot-rockchip-rk322x"
$dryrun dd if=$imagedir/rockchip-rk322x/idbloader.img of=$device seek=64 status=none
$dryrun dd if=$imagedir/rockchip-rk322x/u-boot.itb of=$device seek=16384 status=none
;;
esac
$dryrun sync
) || die "U-Boot installation in $device failed"
[ -z "$dryrun" ] && echo "Completed successfully."