kernel: RV1106 6.18.46 patch series + hermetic build wrapper (P1)

- patches/: the pristine-6.18.46 -> WardenOS delta as a 13-patch, subsystem-split
  series (223 files, ~136K lines: clk, pinctrl, DTs/mach, usb-phy, VOP/panel/rgb,
  mailbox, pvtm, rknpu, rga, aic8800 wifi, audio codec, thermal/rtc/adc/gmac/touch).
  Verified: every patch applies cleanly onto pristine (git apply --check), the full
  series reproduces the hardware-verified tree, and the applied source configures +
  builds the warden dtb + rockchip DRM drivers (rc=0).
- build/build-kernel.sh: fetch+verify pristine (sha256-pinned) -> apply series ->
  warden_defconfig -> zImage + rv1106-warden.dtb. build/warden_defconfig captured.
- CI: `patches-apply` (GitHub-hosted, cached tarball) enforces the series applies;
  `kernel-build` (self-hosted warden-sdk runner, dispatch-gated until registered)
  runs the full build and uploads the image.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
This commit is contained in:
BFE Engineering
2026-08-25 14:26:04 -06:00
co-authored by Claude Opus 4.8
parent c7ff63b3f6
commit f2a9c0a32c
18 changed files with 139345 additions and 0 deletions
+43
View File
@@ -81,6 +81,49 @@ jobs:
echo "== timings =="; cat bench.txt
echo "== trend json =="; grep '"bench"' bench.json
patches-apply:
# The RV1106 series must apply cleanly onto pristine linux-6.18.46.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: cache pristine kernel tarball
uses: actions/cache@v4
with:
path: ~/linux-6.18.46.tar.xz
key: linux-6.18.46-tarball
- name: fetch + verify pristine
run: |
[ -f ~/linux-6.18.46.tar.xz ] || \
curl -fSL https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.18.46.tar.xz -o ~/linux-6.18.46.tar.xz
echo "$(cat build/linux-6.18.46.tar.xz.sha256) $HOME/linux-6.18.46.tar.xz" | sha256sum -c -
- name: apply the series in order
run: |
tar -C /tmp -xf ~/linux-6.18.46.tar.xz
for p in patches/*.patch; do
git -C /tmp/linux-6.18.46 apply --whitespace=nowarn "$GITHUB_WORKSPACE/$p" \
&& echo "applied $p" || { echo "FAILED to apply $p"; exit 1; }
done
echo "full series applied cleanly onto pristine 6.18.46"
kernel-build:
# Full hermetic build on the warden-sdk self-hosted runner (bfe-mpc-0640,
# ADR-0004). Gated on manual dispatch until that runner is registered.
if: github.event_name == 'workflow_dispatch'
runs-on: [self-hosted, warden-sdk]
steps:
- uses: actions/checkout@v4
- name: build zImage + rv1106-warden.dtb
env:
WORK: ${{ github.workspace }}/kbuild-out
run: bash build/build-kernel.sh
- uses: actions/upload-artifact@v4
with:
name: kernel-rv1106
path: |
${{ github.workspace }}/kbuild-out/linux-6.18.46/arch/arm/boot/zImage
${{ github.workspace }}/kbuild-out/linux-6.18.46/arch/arm/boot/dts/rockchip/rv1106-warden.dtb
retention-days: 14
badges:
needs: [test]
if: github.event_name == 'push' && github.ref == 'refs/heads/bringup'
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
# Hermetic-ish kernel build for the WardenOS 86-Panel (RV1106).
#
# fetch pristine linux-6.18.46 -> apply patches/ in order -> configure with
# build/warden_defconfig -> build zImage + rv1106-warden.dtb.
#
# The pristine tree is the ONLY external input; the delta is patches/. A build
# from a clean checkout + a verified tarball is reproducible.
#
# Env:
# KERNEL_TARBALL path to a local linux-6.18.46.tar.xz (skips the download)
# SDK_TC dir holding the arm-rockchip830 uclibc cross toolchain bin/
# WORK build scratch dir (default: a mktemp under $TMPDIR)
# JOBS parallel make jobs (default: nproc)
#
# Requires: `python` (not python3) on PATH — the SDK quirk; the CI runner provides
# a project-local venv. Builds are SERIAL on the shared SDK box — never run two.
set -euo pipefail
KVER=6.18.46
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # build/
REPO="$(cd "$HERE/.." && pwd)"
PATCHES="$REPO/patches"
SHA_FILE="$HERE/linux-$KVER.tar.xz.sha256"
JOBS="${JOBS:-$(nproc)}"
WORK="${WORK:-$(mktemp -d "${TMPDIR:-/tmp}/warden-kbuild.XXXXXX")}"
URL="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$KVER.tar.xz"
log() { printf '\033[36m== %s\033[0m\n' "$*"; }
command -v python >/dev/null || { echo "need 'python' (not python3) on PATH — SDK quirk" >&2; exit 1; }
# 1. obtain + verify the pristine tarball
mkdir -p "$WORK"
TB="${KERNEL_TARBALL:-$WORK/linux-$KVER.tar.xz}"
if [ ! -f "$TB" ]; then
log "downloading $URL"
curl -fSL "$URL" -o "$TB"
fi
if [ -f "$SHA_FILE" ]; then
want="$(cat "$SHA_FILE")"
got="$(sha256sum "$TB" | awk '{print $1}')"
[ "$want" = "$got" ] || { echo "tarball sha256 mismatch: want $want got $got" >&2; exit 1; }
log "tarball sha256 verified"
fi
# 2. extract pristine
SRC="$WORK/linux-$KVER"
rm -rf "$SRC"
log "extracting pristine"
tar -C "$WORK" -xf "$TB"
# 3. apply the patch series in order
log "applying patch series"
for p in "$PATCHES"/*.patch; do
git -C "$SRC" apply --whitespace=nowarn "$p" 2>/dev/null \
|| patch -d "$SRC" -p1 --no-backup-if-mismatch < "$p"
echo " applied $(basename "$p")"
done
# 4. configure
log "configuring (warden_defconfig)"
cp "$HERE/warden_defconfig" "$SRC/.config"
export ARCH=arm CROSS_COMPILE=arm-rockchip830-linux-uclibcgnueabihf-
if [ -n "${SDK_TC:-}" ]; then export PATH="$SDK_TC:$PATH"; fi
command -v "${CROSS_COMPILE}gcc" >/dev/null \
|| { echo "cross toolchain ${CROSS_COMPILE}gcc not on PATH (set SDK_TC)" >&2; exit 1; }
make -C "$SRC" ARCH=arm CROSS_COMPILE="$CROSS_COMPILE" olddefconfig >/dev/null
# 5. build zImage + the board dtb
log "building zImage + rv1106-warden.dtb (-j$JOBS)"
make -C "$SRC" ARCH=arm CROSS_COMPILE="$CROSS_COMPILE" -j"$JOBS" \
zImage rockchip/rv1106-warden.dtb
Z="$SRC/arch/arm/boot/zImage"
D="$SRC/arch/arm/boot/dts/rockchip/rv1106-warden.dtb"
log "build OK"
ls -la "$Z" "$D"
echo "zImage: $Z"
echo "dtb: $D"
+1
View File
@@ -0,0 +1 @@
f5d44b93808b02cc2969c5404ba081d97523719c9fd2ba2de6db318b4141cca0
File diff suppressed because it is too large Load Diff
+28
View File
@@ -0,0 +1,28 @@
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4915a6386..f6d41eb71 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -113,6 +113,8 @@ source "drivers/video/Kconfig"
source "drivers/accel/Kconfig"
+source "drivers/rknpu/Kconfig"
+
source "sound/Kconfig"
source "drivers/hid/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 8e1ffa435..82ed17463 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -67,6 +67,10 @@ obj-y += iommu/
# gpu/ comes after char for AGP vs DRM startup and after iommu
obj-y += gpu/
+# rknpu registers a classic DRM device (not drivers/accel/) -- must come
+# after gpu/ for the same reason (DRM core needs to be ready first).
+obj-$(CONFIG_ROCKCHIP_RKNPU) += rknpu/
+
obj-$(CONFIG_CONNECTOR) += connector/
# i810fb depends on char/agp/
File diff suppressed because it is too large Load Diff
+275
View File
@@ -0,0 +1,275 @@
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index f1cba3d23..71ec73d41 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1466,6 +1466,166 @@ static int rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
#define RV1108_DRV_PINS_PER_REG 8
#define RV1108_DRV_BANK_STRIDE 16
+#define RV1106_DRV_BITS_PER_PIN 8
+#define RV1106_DRV_PINS_PER_REG 2
+#define RV1106_DRV_GPIO0_OFFSET 0x10
+#define RV1106_DRV_GPIO1_OFFSET 0x80
+#define RV1106_DRV_GPIO2_OFFSET 0x100C0
+#define RV1106_DRV_GPIO3_OFFSET 0x20100
+#define RV1106_DRV_GPIO4_OFFSET 0x30020
+
+static int rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* GPIO0_IOC is located in PMU */
+ switch (bank->bank_num) {
+ case 0:
+ *regmap = info->regmap_pmu;
+ *reg = RV1106_DRV_GPIO0_OFFSET;
+ break;
+
+ case 1:
+ *regmap = info->regmap_base;
+ *reg = RV1106_DRV_GPIO1_OFFSET;
+ break;
+
+ case 2:
+ *regmap = info->regmap_base;
+ *reg = RV1106_DRV_GPIO2_OFFSET;
+ break;
+
+ case 3:
+ *regmap = info->regmap_base;
+ *reg = RV1106_DRV_GPIO3_OFFSET;
+ break;
+
+ case 4:
+ *regmap = info->regmap_base;
+ *reg = RV1106_DRV_GPIO4_OFFSET;
+ break;
+
+ default:
+ dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
+ break;
+ }
+
+ *reg += ((pin_num / RV1106_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RV1106_DRV_PINS_PER_REG;
+ *bit *= RV1106_DRV_BITS_PER_PIN;
+
+ return 0;
+}
+
+#define RV1106_PULL_BITS_PER_PIN 2
+#define RV1106_PULL_PINS_PER_REG 8
+#define RV1106_PULL_GPIO0_OFFSET 0x38
+#define RV1106_PULL_GPIO1_OFFSET 0x1C0
+#define RV1106_PULL_GPIO2_OFFSET 0x101D0
+#define RV1106_PULL_GPIO3_OFFSET 0x201E0
+#define RV1106_PULL_GPIO4_OFFSET 0x30070
+
+static int rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* GPIO0_IOC is located in PMU */
+ switch (bank->bank_num) {
+ case 0:
+ *regmap = info->regmap_pmu;
+ *reg = RV1106_PULL_GPIO0_OFFSET;
+ break;
+
+ case 1:
+ *regmap = info->regmap_base;
+ *reg = RV1106_PULL_GPIO1_OFFSET;
+ break;
+
+ case 2:
+ *regmap = info->regmap_base;
+ *reg = RV1106_PULL_GPIO2_OFFSET;
+ break;
+
+ case 3:
+ *regmap = info->regmap_base;
+ *reg = RV1106_PULL_GPIO3_OFFSET;
+ break;
+
+ case 4:
+ *regmap = info->regmap_base;
+ *reg = RV1106_PULL_GPIO4_OFFSET;
+ break;
+
+ default:
+ dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
+ break;
+ }
+
+ *reg += ((pin_num / RV1106_PULL_PINS_PER_REG) * 4);
+ *bit = pin_num % RV1106_PULL_PINS_PER_REG;
+ *bit *= RV1106_PULL_BITS_PER_PIN;
+
+ return 0;
+}
+
+#define RV1106_SMT_BITS_PER_PIN 1
+#define RV1106_SMT_PINS_PER_REG 8
+#define RV1106_SMT_GPIO0_OFFSET 0x40
+#define RV1106_SMT_GPIO1_OFFSET 0x280
+#define RV1106_SMT_GPIO2_OFFSET 0x10290
+#define RV1106_SMT_GPIO3_OFFSET 0x202A0
+#define RV1106_SMT_GPIO4_OFFSET 0x300A0
+
+static int rv1106_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num,
+ struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* GPIO0_IOC is located in PMU */
+ switch (bank->bank_num) {
+ case 0:
+ *regmap = info->regmap_pmu;
+ *reg = RV1106_SMT_GPIO0_OFFSET;
+ break;
+
+ case 1:
+ *regmap = info->regmap_base;
+ *reg = RV1106_SMT_GPIO1_OFFSET;
+ break;
+
+ case 2:
+ *regmap = info->regmap_base;
+ *reg = RV1106_SMT_GPIO2_OFFSET;
+ break;
+
+ case 3:
+ *regmap = info->regmap_base;
+ *reg = RV1106_SMT_GPIO3_OFFSET;
+ break;
+
+ case 4:
+ *regmap = info->regmap_base;
+ *reg = RV1106_SMT_GPIO4_OFFSET;
+ break;
+
+ default:
+ dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
+ break;
+ }
+
+ *reg += ((pin_num / RV1106_SMT_PINS_PER_REG) * 4);
+ *bit = pin_num % RV1106_SMT_PINS_PER_REG;
+ *bit *= RV1106_SMT_BITS_PER_PIN;
+
+ return 0;
+}
+
static int rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
@@ -2751,7 +2911,8 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
goto config;
} else if (ctrl->type == RK3528 ||
ctrl->type == RK3562 ||
- ctrl->type == RK3568) {
+ ctrl->type == RK3568 ||
+ ctrl->type == RV1106) {
rmask_bits = RK3568_DRV_BITS_PER_PIN;
ret = (1 << (strength + 1)) - 1;
goto config;
@@ -2888,6 +3049,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
: PIN_CONFIG_BIAS_DISABLE;
case PX30:
+ case RV1106:
case RV1108:
case RK3188:
case RK3288:
@@ -2949,6 +3111,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
ret = regmap_write(regmap, reg, data);
break;
case PX30:
+ case RV1106:
case RV1108:
case RV1126:
case RK3188:
@@ -3218,6 +3381,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
case RK3066B:
return pull ? false : true;
case PX30:
+ case RV1106:
case RV1108:
case RV1126:
case RK3188:
@@ -3960,6 +4124,48 @@ static struct rockchip_pin_ctrl px30_pin_ctrl = {
.schmitt_calc_reg = px30_calc_schmitt_reg_and_bit,
};
+static struct rockchip_pin_bank rv1106_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
+ IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+ IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+ IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+ IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0, 0x08, 0x10, 0x18),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x10020, 0x10028, 0, 0),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x20040, 0x20048, 0x20050, 0x20058),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(4, 24, "gpio4",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0,
+ 0x30000, 0x30008, 0x30010, 0),
+};
+
+static struct rockchip_pin_ctrl rv1106_pin_ctrl __maybe_unused = {
+ .pin_banks = rv1106_pin_banks,
+ .nr_banks = ARRAY_SIZE(rv1106_pin_banks),
+ .label = "RV1106-GPIO",
+ .type = RV1106,
+ .pull_calc_reg = rv1106_calc_pull_reg_and_bit,
+ .drv_calc_reg = rv1106_calc_drv_reg_and_bit,
+ .schmitt_calc_reg = rv1106_calc_schmitt_reg_and_bit,
+};
+
static struct rockchip_pin_bank rv1108_pin_banks[] = {
PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
@@ -4531,6 +4737,8 @@ static struct rockchip_pin_ctrl rk3588_pin_ctrl = {
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
{ .compatible = "rockchip,px30-pinctrl",
.data = &px30_pin_ctrl },
+ { .compatible = "rockchip,rv1106-pinctrl",
+ .data = &rv1106_pin_ctrl },
{ .compatible = "rockchip,rv1108-pinctrl",
.data = &rv1108_pin_ctrl },
{ .compatible = "rockchip,rv1126-pinctrl",
diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
index 35cd38079..8d4b753ba 100644
--- a/drivers/pinctrl/pinctrl-rockchip.h
+++ b/drivers/pinctrl/pinctrl-rockchip.h
@@ -185,6 +185,7 @@
enum rockchip_pinctrl_type {
PX30,
+ RV1106,
RV1108,
RV1126,
RK2928,
File diff suppressed because it is too large Load Diff
+61
View File
@@ -0,0 +1,61 @@
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 8f4c08e59..1d0d254a7 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -2285,7 +2285,56 @@ static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
{ /* sentinel */ }
};
+/*
+ * RV1106 USB2 PHY: single OTG port at 0xff3e0000 (ported from the vendor driver;
+ * fields map 1:1 to 6.18 except utmi_iddig -> utmi_id, and the 5.10-only
+ * iddig_output/iddig_en/bvalid_grf_sel are dropped). Signal-quality phy_tuning is
+ * left off for now (guarded, so NULL is safe) — the phy is functional without it.
+ */
+static const struct rockchip_usb2phy_cfg rv1106_phy_cfgs[] = {
+ {
+ .reg = 0xff3e0000,
+ .num_ports = 1,
+ .clkout_ctl = { 0x0058, 4, 4, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x0050, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x0100, 2, 2, 0, 1 },
+ .bvalid_det_st = { 0x0104, 2, 2, 0, 1 },
+ .bvalid_det_clr = { 0x0108, 2, 2, 0, 1 },
+ .idfall_det_en = { 0x0100, 5, 5, 0, 1 },
+ .idfall_det_st = { 0x0104, 5, 5, 0, 1 },
+ .idfall_det_clr = { 0x0108, 5, 5, 0, 1 },
+ .idrise_det_en = { 0x0100, 4, 4, 0, 1 },
+ .idrise_det_st = { 0x0104, 4, 4, 0, 1 },
+ .idrise_det_clr = { 0x0108, 4, 4, 0, 1 },
+ .ls_det_en = { 0x0100, 0, 0, 0, 1 },
+ .ls_det_st = { 0x0104, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x0108, 0, 0, 0, 1 },
+ .utmi_avalid = { 0x0060, 10, 10, 0, 1 },
+ .utmi_bvalid = { 0x0060, 9, 9, 0, 1 },
+ .utmi_id = { 0x0060, 6, 6, 0, 1 },
+ .utmi_ls = { 0x0060, 5, 4, 0, 1 },
+ },
+ },
+ .chg_det = {
+ .opmode = { 0x0050, 8, 0, 0, 0x1d7 },
+ .cp_det = { 0x0060, 13, 13, 0, 1 },
+ .dcp_det = { 0x0060, 12, 12, 0, 1 },
+ .dp_det = { 0x0060, 14, 14, 0, 1 },
+ .idm_sink_en = { 0x0058, 8, 8, 0, 1 },
+ .idp_sink_en = { 0x0058, 7, 7, 0, 1 },
+ .idp_src_en = { 0x0058, 9, 9, 0, 1 },
+ .rdm_pdwn_en = { 0x0058, 10, 10, 0, 1 },
+ .vdm_src_en = { 0x0058, 12, 12, 0, 1 },
+ .vdp_src_en = { 0x0058, 11, 11, 0, 1 },
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct of_device_id rockchip_usb2phy_dt_match[] = {
+ { .compatible = "rockchip,rv1106-usb2phy", .data = &rv1106_phy_cfgs },
{ .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3036-usb2phy", .data = &rk3036_phy_cfgs },
{ .compatible = "rockchip,rk3128-usb2phy", .data = &rk3128_phy_cfgs },
+107
View File
@@ -0,0 +1,107 @@
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index ef1c4b929..1b286f081 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -476,6 +476,26 @@ static struct panel_desc *panel_dpi_probe(struct device *dev)
drm_bus_flags_from_videomode(&vm, &bus_flags);
desc->bus_flags = bus_flags;
+ /*
+ * Optional bus-format (a MEDIA_BUS_FMT_* code, e.g. RGB666_1X18) so the
+ * RGB/parallel output can be configured for the panel's real data width.
+ * Upstream panel-dpi doesn't read this, but a parallel RGB panel with no
+ * bus_format leaves the encoder guessing and the screen black. Match the
+ * vendor bindings, which carry bus-format on the panel node. Derive bpc
+ * from the width so panel-simple's {6,8} check is satisfied.
+ */
+ if (!of_property_read_u32(np, "bus-format", &desc->bus_format)) {
+ switch (desc->bus_format) {
+ case MEDIA_BUS_FMT_RGB666_1X18:
+ case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+ desc->bpc = 6;
+ break;
+ default:
+ desc->bpc = 8;
+ break;
+ }
+ }
+
/* We do not know the connector for the DT node, so guess it */
desc->connector_type = DRM_MODE_CONNECTOR_DPI;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index ba6b0528d..f678ad891 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1406,7 +1406,19 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
switch (s->output_type) {
case DRM_MODE_CONNECTOR_LVDS:
- VOP_REG_SET(vop, output, rgb_dclk_pol, 1);
+ /*
+ * WardenOS 86-Panel (RV1106 internal parallel RGB): the panel
+ * latches pixel data on the NON-inverted dclk edge. Mainline
+ * hardcodes rgb_dclk_pol=1 here (inverted), which makes the
+ * panel sample RGB on the wrong clock edge -> fully healthy
+ * pipeline (connector connected, VOP streaming, backlight on)
+ * but a physically BLACK screen. Verified by reading the working
+ * vendor-5.10 _a slot's VOP register PX30_DSP_CTRL0 (0xff990020)
+ * on real hardware: rgb_dclk_pol (bit1) = 0. The vendor 5.10 VOP
+ * driver derives this as (bus_flags & PIXDATA_DRIVE_NEGEDGE)?1:0,
+ * which resolves to 0 for this panel. Match that.
+ */
+ VOP_REG_SET(vop, output, rgb_dclk_pol, 0);
VOP_REG_SET(vop, output, rgb_pin_pol, pin_pol);
VOP_REG_SET(vop, output, rgb_en, 1);
break;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index d1f788763..e0d09595f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -1232,6 +1232,37 @@ static const struct vop_data rv1126_vop = {
.lut_size = 1024,
};
+/*
+ * RV1106 VOP: the same RV-series "lite" VOP as rv1126 (VOP_VERSION 2.0xc vs
+ * 2.0xb), so it reuses rv1126's register sub-structs. Only the version and the
+ * smaller max raster differ. Ported for the WardenOS 86-Panel (720x720 RGB).
+ */
+/*
+ * RV1106 uses WIN1 as its (only) primary scanout plane -- see px30_win1_data.
+ * The vendor rv1106_vop_win_data is { NULL-win0, win1-primary }; mirror that
+ * as a single primary win1 here (mainline registers one plane per non-NULL
+ * entry). Reusing rv1126's { win0-overlay, win2-primary } set left the panel
+ * black because WIN2 does not drive this SoC's RGB output.
+ */
+static const struct vop_win_data rv1106_vop_win_data[] = {
+ { .base = 0x00, .phy = &px30_win1_data,
+ .type = DRM_PLANE_TYPE_PRIMARY },
+};
+
+static const struct vop_data rv1106_vop = {
+ .version = VOP_VERSION(2, 0xc),
+ .feature = VOP_FEATURE_INTERNAL_RGB, /* RV1106 drives a parallel-RGB panel */
+ .intr = &px30_intr,
+ .common = &rv1126_common,
+ .modeset = &rv1126_modeset,
+ .output = &rv1126_output,
+ .misc = &rv1126_misc,
+ .win = rv1106_vop_win_data,
+ .win_size = ARRAY_SIZE(rv1106_vop_win_data),
+ .max_output = { 1280, 1280 },
+ .lut_size = 1024,
+};
+
static const struct of_device_id vop_driver_dt_match[] = {
{ .compatible = "rockchip,rk3036-vop",
.data = &rk3036_vop },
@@ -1261,6 +1292,8 @@ static const struct of_device_id vop_driver_dt_match[] = {
.data = &rk3328_vop },
{ .compatible = "rockchip,rv1126-vop",
.data = &rv1126_vop },
+ { .compatible = "rockchip,rv1106-vop",
+ .data = &rv1106_vop },
{},
};
MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
+25
View File
@@ -0,0 +1,25 @@
diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c
index 4d966cb2e..31c5a693f 100644
--- a/drivers/mailbox/rockchip-mailbox.c
+++ b/drivers/mailbox/rockchip-mailbox.c
@@ -155,7 +155,20 @@ static const struct rockchip_mbox_data rk3368_drv_data = {
.num_chans = 4,
};
+/*
+ * RV1106's mailbox IP is register-identical to rk3368's, but the SoC wires a
+ * single shared interrupt (GIC_SPI 1) rather than one IRQ per channel. The
+ * per-channel-IRQ probe loop below would fail requesting IRQ index 1, so
+ * declare a single channel (channel 0) — which is all the A7<->HPMCU doorbell
+ * needs. (Matched ahead of the rk3368 fallback via the more-specific
+ * "rockchip,rv1106-mailbox" compatible the DT node also carries.)
+ */
+static const struct rockchip_mbox_data rv1106_drv_data = {
+ .num_chans = 1,
+};
+
static const struct of_device_id rockchip_mbox_of_match[] = {
+ { .compatible = "rockchip,rv1106-mailbox", .data = &rv1106_drv_data},
{ .compatible = "rockchip,rk3368-mailbox", .data = &rk3368_drv_data},
{ },
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+17108
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
# RV1106 kernel patch series (pristine linux-6.18.46 → WardenOS)
The delta that forward-ports the vendor Rockchip 5.10.160 RV1106 support onto a
pristine upstream **linux-6.18.46**, as a reviewable, subsystem-split series. Every
patch applies cleanly onto pristine 6.18.46 (`git apply --check`), and the whole set
reproduces the 223-file / ~136K-line delta that boots and is hardware-verified on
`warden-c8a3` (see `../kernel/rv1106-enablement/`).
Build it with `../build/build-kernel.sh` (fetch pristine → apply these → configure
with `../build/warden_defconfig``zImage` + `rv1106-warden.dtb`).
## The series
| Patch | Scope |
|---|---|
| `05-build-wiring.patch` | top-level `drivers/{Kconfig,Makefile}` (wire in rknpu) |
| `10-clk-rv1106.patch` | CRU clock driver (`clk-rv1106.c`, reuses rv1126 data) |
| `15-pinctrl.patch` | `pinctrl-rockchip` RV1106 iomux |
| `20-arch-dts-bindings.patch` | `arch/arm` DTs (`rv1106.dtsi`, `rv1106-warden.dts`, pinctrl), mach, configs, `include/dt-bindings` |
| `25-usb-phy.patch` | inno-usb2 phy |
| `30-drm-vop-panel-rgb.patch` | VOP (`rgb_dclk_pol`=0 + WIN1 scanout), panel-simple bus-format, rockchip_rgb |
| `35-mailbox-hpmcu.patch` | rockchip-mailbox (rv1106 num_chans=1) |
| `40-pvtm-soc.patch` | PVTM (core+pmu) + `include/soc/rockchip/pvtm.h` |
| `45-npu-rknpu.patch` | open GPL rknpu 0.9.2 driver + `rknpu_ioctl.h` uapi |
| `50-rga.patch` | RGA 2D (rga3) + `drivers/video` wiring |
| `60-wifi-aic8800.patch` | out-of-tree AIC8800 wifi/BT (the 88.5K-line vendor blob) |
| `70-audio-codec.patch` | `rv1106_codec` + I2S wiring |
| `80-misc-thermal-rtc-adc.patch` | tsadc, rtc-rockchip, saradc, trng, otp, gmac, goodix touch |
## Provenance & regeneration
Baseline: `linux-6.18.46` from kernel.org (`build/linux-6.18.46.tar.xz.sha256`
pins the tarball). The series was generated by overlaying the hardware-verified
source tree onto pristine (build artifacts excluded) and splitting `git diff` by
subsystem. Licensing/origin of each block is tracked in
`../kernel/rv1106-enablement/PROVENANCE.md`.
Whitespace: `60-wifi-aic8800.patch` carries the vendor blob's trailing-whitespace
verbatim; `git apply --whitespace=nowarn` (the build wrapper) accepts it. Do not
re-flow vendor code — it must stay diffable against future vendor drops.