diff --git a/device/testing/linux-postmarketos-qcom-sm8550/APKBUILD b/device/testing/linux-postmarketos-qcom-sm8550/APKBUILD index 2ac04c596..47e45f32e 100644 --- a/device/testing/linux-postmarketos-qcom-sm8550/APKBUILD +++ b/device/testing/linux-postmarketos-qcom-sm8550/APKBUILD @@ -5,7 +5,7 @@ maintainer="snlavaise " _flavor="postmarketos-qcom-sm8550" pkgname=linux-$_flavor pkgver=7.2 -pkgrel=13 +pkgrel=48 pkgdesc="Mainline kernel for Qualcomm SM8550 (Snapdragon 8 Gen 2) + Motorola rtwo" arch="aarch64" _carch="arm64" @@ -47,6 +47,16 @@ source=" config-motorola-rtwo.aarch64 rtwo.config sm8550-motorola-rtwo.dts + ath12k-fix-regd-update-completion-hang.patch + ath12k-fix-regd-range-wideband.patch + icc-sm8550-keepalive-mm0-mdp-fetch.patch + ath12k-htc-log-every-rx-header.patch + ath12k-mhi-keep-awake.patch + msm-dsi-keep-panel-dsc-config.patch + msm-dp-ignore-invalid-lttpr-caps.patch + msm-dp-no-push-idle-when-link-down.patch + panel-novatek-nt37705.c + typec-mux-ps5169.c " builddir="$srcdir/linux-${pkgver/_/-}" @@ -60,6 +70,49 @@ prepare() { sed -i '/sm8550-mtp\.dtb/a dtb-$(CONFIG_ARCH_QCOM) += sm8550-motorola-rtwo.dtb' \ "$_dtsdir/Makefile" fi + # Not-yet-upstream panel driver (DSI command mode + DSC, Motorola rtwo). + cp "$srcdir/panel-novatek-nt37705.c" \ + drivers/gpu/drm/panel/panel-novatek-nt37705.c + if ! grep -q "CONFIG_DRM_PANEL_NOVATEK_NT37705" drivers/gpu/drm/panel/Kconfig; then + cat >> drivers/gpu/drm/panel/Kconfig <<'EOK' + +config DRM_PANEL_NOVATEK_NT37705 + tristate "Novatek NT37705 DSI panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + select DRM_DISPLAY_DSC_HELPER + select DRM_DISPLAY_HELPER + help + Say Y here if you want to enable support for Novatek NT37705 DSI + panel module. 1080x2400 command mode DSC panel from CSOT, used on + the Motorola rtwo. +EOK + fi + if ! grep -q "panel-novatek-nt37705" drivers/gpu/drm/panel/Makefile; then + echo 'obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37705) += panel-novatek-nt37705.o' \ + >> drivers/gpu/drm/panel/Makefile + fi + # Not-yet-upstream Parade PS5169 USB-C redriver (DisplayPort alt mode). + cp "$srcdir/typec-mux-ps5169.c" drivers/usb/typec/mux/ps5169.c + if ! grep -q "CONFIG_TYPEC_MUX_PS5169" drivers/usb/typec/mux/Kconfig; then + cat >> drivers/usb/typec/mux/Kconfig <<'EOK' + +config TYPEC_MUX_PS5169 + tristate "Parade PS5169 Type-C redriver driver" + depends on I2C + depends on DRM || DRM=n + select DRM_AUX_BRIDGE if DRM_BRIDGE && OF + select REGMAP_I2C + help + Say Y or M if your system has a Parade PS5169 USB/DP Type-C + redriver, as found on the Motorola rtwo. +EOK + fi + if ! grep -q "ps5169" drivers/usb/typec/mux/Makefile; then + echo 'obj-$(CONFIG_TYPEC_MUX_PS5169) += ps5169.o' \ + >> drivers/usb/typec/mux/Makefile + fi # Build this DTB with -@ so it gets a /__symbols__ node. The Motorola # SM8550 ABL runs its dtbo-apply path (libufdt) against the base DTB # and drops to the bootloader menu if the symbols are missing. @@ -110,7 +163,17 @@ package() { # (same tarball as linux-postmarketos-mainline, ~150 MB download). sha512sums=" 52d5aa7f94f6aa6141debf4ceb4fc7a2e75505a7cd38b8854e501be83c2b57863020f463f2fdb2fc93667e6cfe13274d077e5207a611e4797bd9404ee0e64c58 linux-postmarketos-qcom-sm8550-7.2.tar.gz -f9ae52489f6b9e6fef64952943cd09732a5bef90a0e8765db03c256483028368687d6d5a1d80dd813a513e7e80d91f8b47f49b91cff67266b76f1d6275a7fea0 config-motorola-rtwo.aarch64 -53441c23146d76bb0eaa358a25f6cce4f21740cfb65b755df52bbb218daf2cda30b3d80fa6ca4e283ea1afe2b0fa708307b678b421898100710b8fb99b08d6c5 rtwo.config -7f51d30b9e2d7fb781fbf066a8f8696816e881686c9a287b20d5d213955912c783e1534479c9bd9701cd29c1e1769132653a56f7b008eb7368083e5f523fd731 sm8550-motorola-rtwo.dts +0ab844d874289be5529c7f83a1bdd16d867ea6d5f3f873556779cbd27908316fd5076c201d6b6fee40991da648eadc982422cc0136fe2c9034b7b4846e08a028 config-motorola-rtwo.aarch64 +a03843765d996a4555f991b277dd9cc35f1c96da1b740330a3497202d355ec95406f380a0ec6a778d638bf9acfc1f28dbc441e156fb75b1cf00720af136f69b8 rtwo.config +ff2da1726b87210497d3d3961af5d95b9dfb160d48af90bb604dbb321b89c50689a06722c50db265aaf5c95b0078da278939efda8e1a8f30232827d27da1c8ca sm8550-motorola-rtwo.dts +a068e35a031858161e7a5ac00d7d2db9fd0d842fc19d3ebf08b03275ef470eff5462921e36390f535e2556619b6911192b6e2ccf7c313edafaf22d6da44c1d8e ath12k-fix-regd-update-completion-hang.patch +891b9b15e9113488667f2dcf9f1502aab24291228cc4096f358acbf4b67d299fb90b2d00b4e103139cd2160339a10833cddb781838d1f03721fef07ea45b3213 ath12k-fix-regd-range-wideband.patch +acbe599c08877065ea4419363da7ab75a16a557aad4b13161f22270f03b27efac1be487884896900c3e80d6df8e3545ca6b1df940d24badef1825fe0d27147ac icc-sm8550-keepalive-mm0-mdp-fetch.patch +cf4889c4dca8d3bac7544d71284e6b592d6014d9ad94badfc6d2cbe56a8402c61e4c0811c2f48d3352b446de9fbcf36b58226431c9276956d7ff3fe08c9eb589 ath12k-htc-log-every-rx-header.patch +6e01370d013278faba203e57ba20700d500639136672c040c0924a600fc3dcd8185a9f558ee7bf8a9ad5412113f6b6ab1901423006bb839e808dbcb151a16383 ath12k-mhi-keep-awake.patch +7673bec5661e692721bce41e72a330180e653d2b1b0a5cb3d36bdc869ad4a32ce23a6048d01c9cf2cf5c78c2a7e33899a0a149c65e9754d9d1c2cd71b542b84c msm-dsi-keep-panel-dsc-config.patch +3268835bcb539a77d16c888d933c856df6bb591861d30c7c61c6e0ab70751bac6248961ec30fedf9a62bebdcd63113cf1dd14e58a1b53262493d5e0e90dbbe3f msm-dp-ignore-invalid-lttpr-caps.patch +4f5ea9bfe01a6df166fdad601f6bd74d4b39049be924e8b4df58a8acbba7e9ebfc568bd81df70354209642f68e113804b9d1b62cbd3c83c319fae5fefcf07595 msm-dp-no-push-idle-when-link-down.patch +e8df16de9b413fedd0d36414311216e68e69363e1bfbba8c7b892120f860d217b58ceeffeb92566a5617177b0f190a64e9e2284d6d4285e72db35cf40770e41a panel-novatek-nt37705.c +dd95e80f62879d5167e7bfc7d74b4a64669a43dbf5aacb6a13e62d1ed4a88677ef1042f8cecc46e05e3d12ba75f070a5927df308c90fe846af93b78c6b310e80 typec-mux-ps5169.c " diff --git a/device/testing/linux-postmarketos-qcom-sm8550/ath12k-fix-regd-range-wideband.patch b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-fix-regd-range-wideband.patch new file mode 100644 index 000000000..099ec2e97 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-fix-regd-range-wideband.patch @@ -0,0 +1,41 @@ +Fix regulatory range for wideband radios (carried by OpenWrt/Quectel +trees for WCN7850 and wideband QCN9274; NOT in v7.2 mainline). + +ath12k_regd_update() assumes that a radio advertising 6 GHz cannot also +operate on 5 GHz. For the rtwo the WCN7850 is a single SMM radio whose +5 GHz band spans [4900-7125] (hw_mode 5, 2.4+5+6 GHz in one pdev), so +this old check picks only the 6 GHz portion of the band and drops the +real 5 GHz half from ar->freq_range. ath12k_mac_update_freq_range() +unions multiple calls, so the fixed conditions do not overwrite -- they +extend the advertised range to cover both portions. + +Diagnostic build 2026-09-22 (same experiment as the wcn7850-pmu pinctrl +DT change): determines whether the cropped regulatory range sent to the +WCN7850 WMI path is what stalls the firmware at ath12k_mac_start() +("wmi command 16387 timeout", -EAGAIN on insufficient HTC credits after +the WMI channel list). + +Blame/author: Robert Marko +From: https://git-03.infra.openwrt.org/openwrt/staging/stintel/plain/package/kernel/mac80211/patches/ath12k/104-wifi-ath12k-fix-regulatory-range-for-wideband-radios.patch +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -310,7 +310,8 @@ int ath12k_regd_update(struct ath12k *ar, bool init) + ath12k_mac_update_freq_range(ar, freq_low, freq_high); + } + +- if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && !ar->supports_6ghz) { ++ if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ++ reg_cap->low_5ghz_chan < ATH12K_MIN_6GHZ_FREQ) { + if (ab->hw_params->single_pdev_only) { + phy_id = ar->pdev->cap.band[WMI_HOST_WLAN_5GHZ_CAP].phy_id; + reg_cap = &ab->hal_reg_cap[phy_id]; +@@ -322,7 +323,8 @@ int ath12k_regd_update(struct ath12k *ar, bool init) + ath12k_mac_update_freq_range(ar, freq_low, freq_high); + } + +- if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ar->supports_6ghz) { ++ if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ++ reg_cap->high_5ghz_chan >= ATH12K_MIN_6GHZ_FREQ) { + freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_6ghz.start_freq); + freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_6ghz.end_freq); + diff --git a/device/testing/linux-postmarketos-qcom-sm8550/ath12k-fix-regd-update-completion-hang.patch b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-fix-regd-update-completion-hang.patch new file mode 100644 index 000000000..d6a519cdb --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-fix-regd-update-completion-hang.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/wireless/ath/ath12k/wmi.c 2026-09-20 02:48:13.191255011 -0300 ++++ b/drivers/net/wireless/ath/ath12k/wmi.c 2026-09-20 02:48:13.192653745 -0300 +@@ -6939,6 +6939,15 @@ + goto mem_free; + } + ++ /* Assign pdev_idx as soon as we have a valid reg_info, BEFORE the ++ * FALLBACK/DROP paths below, so ar->regd_update_completed still gets ++ * signalled even when the event is dropped because the country code ++ * already matches the default regd (fixes a permanent hang of any ++ * caller waiting on regd_update_completed, e.g. WMI_PDEV_SET_PARAM ++ * during mac80211 hw_register on bring-up). ++ */ ++ pdev_idx = reg_info->phy_id; ++ + ret = ath12k_reg_validate_reg_info(ab, reg_info); + if (ret == ATH12K_REG_STATUS_FALLBACK) { + ath12k_warn(ab, "failed to validate reg info %d\n", ret); +@@ -6955,7 +6964,6 @@ + } + + /* free old reg_info if it exist */ +- pdev_idx = reg_info->phy_id; + if (ab->reg_info[pdev_idx]) { + ath12k_reg_reset_reg_info(ab->reg_info[pdev_idx]); + kfree(ab->reg_info[pdev_idx]); diff --git a/device/testing/linux-postmarketos-qcom-sm8550/ath12k-htc-log-every-rx-header.patch b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-htc-log-every-rx-header.patch new file mode 100644 index 000000000..12022a29e --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-htc-log-every-rx-header.patch @@ -0,0 +1,39 @@ +Log the raw HTC header of every received message. + +Diagnostic-only, for the rtwo WiFi bring-up. ath12k_mac_start() dies on +the second WMI command with -EAGAIN out of ath12k_htc_send()'s +"insufficient credits" path, and the endpoint's credits are only ever +replenished by an ATH12K_HTC_RECORD_CREDITS record carried in the +*trailer* of a received HTC message -- there is no dedicated credit +event. /proc/interrupts shows ce2 (target->host WMI) taking real +interrupts, so messages do arrive; what cannot be seen from outside is +whether any of them ever carries a trailer at all. + +The existing "htc rx completion ep %d" debug line does not answer that: +it is printed at the very end of the handler, so it misses both the EP0 +control traffic and the "zero length packet with trailer data, just drop +these" early return -- which is exactly the shape a pure credit-report +message has. Print the decoded header right where the fields are read +instead, before anything can return early. + +Sits under the existing ATH12K_DBG_HTC (0x4) mask, so it costs one +branch per RX when the mask is unset and disappears entirely without +CONFIG_ATH12K_DEBUG. Drop this patch once WiFi works. + +--- a/drivers/net/wireless/ath/ath12k/htc.c ++++ b/drivers/net/wireless/ath/ath12k/htc.c +@@ -292,6 +292,14 @@ + trailer_present = le32_get_bits(hdr->htc_info, HTC_HDR_FLAGS) & + ATH12K_HTC_FLAG_TRAILER_PRESENT; + ++ ath12k_dbg(ab, ATH12K_DBG_HTC, ++ "htc rx hdr eid %d payload_len %d flags 0x%02x trailer %d trailer_len %d\n", ++ eid, payload_len, ++ (u8)le32_get_bits(hdr->htc_info, HTC_HDR_FLAGS), ++ trailer_present ? 1 : 0, ++ trailer_present ? ++ (int)le32_get_bits(hdr->ctrl_info, HTC_HDR_CONTROLBYTES0) : 0); ++ + if (trailer_present) { + u8 *trailer; + diff --git a/device/testing/linux-postmarketos-qcom-sm8550/ath12k-mhi-keep-awake.patch b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-mhi-keep-awake.patch new file mode 100644 index 000000000..81793fbd7 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/ath12k-mhi-keep-awake.patch @@ -0,0 +1,87 @@ +Add ath12k.mhi_keep_awake to keep the WCN7850 out of MHI M1/M2. + +Diagnostic for the rtwo WiFi bring-up. With CONFIG_ATH12K_DEBUG the log +shows that the firmware returns HTC credits for the WMI endpoint +normally (trailers on EP0, ~3 ms after each command) until the moment +the device reports M1 and the host moves it to M2 (MHI_CB_IDLE, 22 us +after the last credit is spent). After that the target sends nothing on +any endpoint and there is no RDDM/SYS_ERR, so it is asleep, not crashed. + +WCN7850 uses shadow registers for the CE doorbells (below +ACCESS_ALWAYS_OFF), so those writes never go through pci_ops->wakeup(). +mhi_keep_awake=1 takes an MHI device wake reference right after power +up and holds it until mhi_stop, so the device stays in M0. With it +off, MHI_CB_IDLE is logged at warn level to see when it happens. + +--- a/drivers/net/wireless/ath/ath12k/pci.h 2026-09-22 20:54:12.225709859 -0300 ++++ b/drivers/net/wireless/ath/ath12k/pci.h 2026-09-22 20:54:12.243985679 -0300 +@@ -93,6 +93,7 @@ + ATH12K_PCI_FLAG_IS_MSI_64, + ATH12K_PCI_ASPM_RESTORE, + ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, ++ ATH12K_PCI_FLAG_MHI_KEEP_AWAKE, + }; + + struct ath12k_pci_ops { +--- a/drivers/net/wireless/ath/ath12k/mhi.c 2026-09-22 20:54:12.223301456 -0300 ++++ b/drivers/net/wireless/ath/ath12k/mhi.c 2026-09-22 20:54:12.244083641 -0300 +@@ -18,6 +18,16 @@ + #define OTP_VALID_DUALMAC_BOARD_ID_MASK 0x1000 + #define MHI_CB_INVALID 0xff + ++/* rtwo bring-up: the WMI endpoint runs out of HTC credits at the exact ++ * moment the device reports M1 and the host moves it to M2 ++ * (MHI_CB_IDLE); after that the target never sends anything again. ++ * Holding MHI device wake for the whole session keeps it in M0, to ++ * tell whether the M1/M2 transition is what loses the WMI doorbells. ++ */ ++static bool ath12k_mhi_keep_awake; ++module_param_named(mhi_keep_awake, ath12k_mhi_keep_awake, bool, 0644); ++MODULE_PARM_DESC(mhi_keep_awake, "Hold MHI device wake while powered on (never enter M1/M2)"); ++ + void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab) + { + u32 val; +@@ -148,6 +158,11 @@ + case MHI_CB_SYS_ERROR: + ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); + break; ++ case MHI_CB_IDLE: ++ /* rtwo: log at warn level so it shows up without debug_mask */ ++ ath12k_warn(ab, "mhi idle: device moved to M2 (keep_awake %d)\n", ++ test_bit(ATH12K_PCI_FLAG_MHI_KEEP_AWAKE, &ab_pci->flags)); ++ break; + case MHI_CB_EE_RDDM: + if (ab_pci->mhi_pre_cb == MHI_CB_EE_RDDM) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, +@@ -493,6 +508,20 @@ + if (ret) + goto out; + ++ if (ath12k_mhi_keep_awake) { ++ ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); ++ if (ret) { ++ ath12k_warn(ab_pci->ab, ++ "mhi_keep_awake: failed to hold device wake: %d\n", ++ ret); ++ ret = 0; ++ } else { ++ set_bit(ATH12K_PCI_FLAG_MHI_KEEP_AWAKE, &ab_pci->flags); ++ ath12k_info(ab_pci->ab, ++ "mhi_keep_awake: holding device wake, M1/M2 disabled\n"); ++ } ++ } ++ + return 0; + + out: +@@ -501,6 +530,9 @@ + + void ath12k_mhi_stop(struct ath12k_pci *ab_pci, bool is_suspend) + { ++ if (test_and_clear_bit(ATH12K_PCI_FLAG_MHI_KEEP_AWAKE, &ab_pci->flags)) ++ mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); ++ + /* During suspend we need to use mhi_power_down_keep_dev() + * workaround, otherwise ath12k_core_resume() will timeout + * during resume. diff --git a/device/testing/linux-postmarketos-qcom-sm8550/config-motorola-rtwo.aarch64 b/device/testing/linux-postmarketos-qcom-sm8550/config-motorola-rtwo.aarch64 index 46cc9831d..73d1cb1b9 100644 --- a/device/testing/linux-postmarketos-qcom-sm8550/config-motorola-rtwo.aarch64 +++ b/device/testing/linux-postmarketos-qcom-sm8550/config-motorola-rtwo.aarch64 @@ -5464,7 +5464,7 @@ CONFIG_BCM7038_WDT=m # # CONFIG_USBPCWATCHDOG is not set # CONFIG_KEEMBAY_WATCHDOG is not set -# CONFIG_GUNYAH_WATCHDOG is not set +CONFIG_GUNYAH_WATCHDOG=y CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set CONFIG_BCMA_POSSIBLE=y @@ -11732,10 +11732,10 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 CONFIG_PSTORE=y CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 CONFIG_PSTORE_COMPRESS=y -# CONFIG_PSTORE_CONSOLE is not set +CONFIG_PSTORE_CONSOLE=y # CONFIG_PSTORE_PMSG is not set # CONFIG_PSTORE_FTRACE is not set -CONFIG_PSTORE_RAM=m +CONFIG_PSTORE_RAM=y # CONFIG_PSTORE_BLK is not set # CONFIG_UFS_FS is not set CONFIG_EROFS_FS=m diff --git a/device/testing/linux-postmarketos-qcom-sm8550/icc-sm8550-keepalive-mm0-mdp-fetch.patch b/device/testing/linux-postmarketos-qcom-sm8550/icc-sm8550-keepalive-mm0-mdp-fetch.patch new file mode 100644 index 000000000..1faf06f83 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/icc-sm8550-keepalive-mm0-mdp-fetch.patch @@ -0,0 +1,25 @@ +--- a/drivers/interconnect/qcom/sm8550.c ++++ b/drivers/interconnect/qcom/sm8550.c +@@ -1136,6 +1136,22 @@ static struct qcom_icc_bcm bcm_mc0 = { + + static struct qcom_icc_bcm bcm_mm0 = { + .name = "MM0", ++ /* ++ * qns_mem_noc_hf is the only node this BCM covers, and it's what ++ * qnm_mdp (the MDP's own interconnect master) feeds into. Our ++ * bring-up has no MDSS/DPU driver, so nothing in Linux ever calls ++ * icc_set_bw() on this path -- but the DPU hardware is still live, ++ * inherited from U-Boot, and keeps fetching the framebuffer over ++ * this exact bus. Without keepalive, icc_sync_state() (core.c, ++ * gated on every icc provider probing -- in practice on pcie0/ ++ * WiFi finishing last) zeroes the firmware's boot-time vote on ++ * this BCM and the display freezes mid-boot, at a random-looking ++ * point that always lines up with pcie0 finishing probe. MC0/SH0/ ++ * CN0/SN0/QUP0-2 already get this same treatment for the same ++ * reason (DDR/LLCC/config/system NoC/QUP buses that must never ++ * collapse to zero just because no driver claimed them yet). ++ */ ++ .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_mem_noc_hf }, + }; diff --git a/device/testing/linux-postmarketos-qcom-sm8550/msm-dp-ignore-invalid-lttpr-caps.patch b/device/testing/linux-postmarketos-qcom-sm8550/msm-dp-ignore-invalid-lttpr-caps.patch new file mode 100644 index 000000000..1534fd4d9 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/msm-dp-ignore-invalid-lttpr-caps.patch @@ -0,0 +1,54 @@ +--- a/drivers/gpu/drm/msm/dp/dp_display.c ++++ b/drivers/gpu/drm/msm/dp/dp_display.c +@@ -251,16 +251,34 @@ + int rc, lttpr_count; + + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->link->lttpr_common_caps)) +- return 0; ++ goto no_lttpr; ++ ++ /* ++ * Some sinks without LTTPR support (e.g. DP->HDMI converters) mirror ++ * their receiver caps at 0xf0000 instead of NAKing the read. Only ++ * trust the block if it carries a valid LTTPR structure revision and ++ * repeater count: otherwise the caps would clamp the link to whatever ++ * lands in the "max lane count"/"max link rate" slots, and writing ++ * PHY_REPEATER_MODE would end up in the sink's own DPCD. ++ */ ++ if (dp->link->lttpr_common_caps[0] < 0x14) ++ goto no_lttpr; + + lttpr_count = drm_dp_lttpr_count(dp->link->lttpr_common_caps); ++ if (lttpr_count < 0) ++ goto no_lttpr; ++ + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); + if (rc) { + DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); +- return 0; ++ goto no_lttpr; + } + + return lttpr_count; ++ ++no_lttpr: ++ memset(dp->link->lttpr_common_caps, 0, sizeof(dp->link->lttpr_common_caps)); ++ return 0; + } + + static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) +--- a/drivers/gpu/drm/msm/dp/dp_panel.c ++++ b/drivers/gpu/drm/msm/dp/dp_panel.c +@@ -101,6 +101,12 @@ + + msm_dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd); + link_info = &msm_dp_panel->link_info; ++ /* ++ * Everything below is derived from the current sink. Start from ++ * scratch so a rate from a previous sink (the fallback path only runs ++ * when rate is 0) does not stick across unplug/replug. ++ */ ++ memset(link_info, 0, sizeof(*link_info)); + link_info->revision = dpcd[DP_DPCD_REV]; + major = (link_info->revision >> 4) & 0x0f; + minor = link_info->revision & 0x0f; diff --git a/device/testing/linux-postmarketos-qcom-sm8550/msm-dp-no-push-idle-when-link-down.patch b/device/testing/linux-postmarketos-qcom-sm8550/msm-dp-no-push-idle-when-link-down.patch new file mode 100644 index 000000000..f7ff89ce0 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/msm-dp-no-push-idle-when-link-down.patch @@ -0,0 +1,18 @@ +--- a/drivers/gpu/drm/msm/dp/dp_display.c ++++ b/drivers/gpu/drm/msm/dp/dp_display.c +@@ -1434,6 +1434,15 @@ + + msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); + ++ /* ++ * If link training failed in atomic_enable, the mainlink was already ++ * deinitialized (link clocks and PHY off) and the stream never came ++ * up. Writing DP_STATE_CTRL then hits an unclocked block, which hangs ++ * the bus and resets the SoC on unplug or the next modeset. ++ */ ++ if (!dp->power_on) ++ return; ++ + msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + } + diff --git a/device/testing/linux-postmarketos-qcom-sm8550/msm-dsi-keep-panel-dsc-config.patch b/device/testing/linux-postmarketos-qcom-sm8550/msm-dsi-keep-panel-dsc-config.patch new file mode 100644 index 000000000..e70dc1c72 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/msm-dsi-keep-panel-dsc-config.patch @@ -0,0 +1,18 @@ +--- a/drivers/gpu/drm/msm/dsi/dsi_host.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c +@@ -1870,6 +1870,15 @@ + { + int ret; + ++ /* ++ * Some panels (e.g. Novatek DDICs with fixed rate control tables in ++ * the decoder) need the exact RC configuration the vendor encoder ++ * used, not the one derived here from the generic DSC tables. Keep a ++ * configuration the panel driver already filled in completely. ++ */ ++ if (dsc->rc_model_size && dsc->slice_chunk_size && dsc->initial_dec_delay) ++ return 0; ++ + if (dsc->bits_per_pixel & 0xf) { + DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support fractional bits_per_pixel\n"); + return -EINVAL; diff --git a/device/testing/linux-postmarketos-qcom-sm8550/panel-novatek-nt37705.c b/device/testing/linux-postmarketos-qcom-sm8550/panel-novatek-nt37705.c new file mode 100644 index 000000000..b0dd58847 --- /dev/null +++ b/device/testing/linux-postmarketos-qcom-sm8550/panel-novatek-nt37705.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 snlavaise + * + * DRM panel driver for the CSOT NT37705 (Novatek NT37705) command mode DSC + * panel used on the Motorola rtwo (Moto Edge 40 Pro, SM8550). + * + * Sequences transcribed byte-by-byte from the vendor device tree node + * "qcom,mdss_dsi_mot_csot_nt37705_667_curve_1080x2400_dsc_cmd_v1" + * (panel name mipi_mot_cmd_csot_1080p_dsc_667, panel supplier "csot"), + * see pmos/panel-nt37705-v1-dump.md. Only the 60 Hz timing (timing@0, 2f01 + + * e000) is exposed for the first bring-up. The other rates only differ in + * their timing-switch-command: 120 Hz 2f02/e041, 90 Hz 2f04/e000, + * 48 Hz 2f05/e000, 165 Hz 2f03/e041 (same porches and DSI clock). + * + * DSC: besides the Novatek MCS setup in the on command (0x90 enable, 0x91 + * parameters), the standard PPS and compression-mode packets are sent after + * it, same as the mainline NT37801 driver (same Novatek flow) and the + * downstream driver, which sends the PPS by itself. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include