* [BUG] DP-CEC wake NACKs after S3 with UGREEN DP-to-HDMI adapter
@ 2026-09-08 15:59 jason.boukheir
2026-09-11 7:28 ` Hans Verkuil
0 siblings, 1 reply; 2+ messages in thread
From: jason.boukheir @ 2026-09-08 15:59 UTC (permalink / raw)
To: hverkuil@kernel.org
Cc: linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org
[-- Attachment #1.1: Type: text/plain, Size: 2445 bytes --]
Hi Hans,
I'm reporting a CEC resume problem on my desktop and would appreciate help identifying the right subsystem and next diagnostic steps.
AI disclosure: I used OpenAI Codex to inspect retained local logs and kernel source and prepare this report. The observations below come from those logs; the proposed cause is AI-assisted analysis, not an independently confirmed diagnoses. The attached local patch is an experimental workaround without independent upstream review, not a merge-ready submission.
Hardware/setup:
- Sapphire Pulse Radeon RX 9070 XT (Navi 48), amdgpu.
- GPU DP-1 -> UGREEN 8K@60Hz Active DisplayPort to HDMI Unidirectional Adapter, 0.66FT -> Samsung QBQ90S TV, HDMI 2.
- Exact adapter SKU, chipset, and firmware are unknown.
- NixOS, locally customized CachyOS-derived kernels; deep / ACPI S3 sleep.
In a July 31 capture (CEC driver version 7.1.5), the TV replied to power status queries before suspend. After S3, the adapter still reported physical address 2.0.0.0 and Playback logical address 8, but all 30 directed Image View On attempts to the TV returned "Not Acknowledged ... Max Retries". The kernel journal independently confirms S3 entry and exit.
A later setup with a local kernel patch plus separate cecd retry changes logged restored CEC tunneling state, TV wake ACKs, and an active-source announcement after resume. It did not receive a confirmed TV power-status reply. This is not a controlled comparison: the kernel version and userspace both changed, and another CEC wake service ran during the baseline capture. I have not reproduced this on current vanilla mainline.
The suspected mechanism is converter CEC state becoming lost or stale while Linux retains its enabled adapter state. The patch checks the tunneling-control and logical-address-mask registers during unchanged adapter attachment and replays cached state if needed. However, we have no raw register capture proving state loss, and the normal EDID removal path should invalidate the physical address and trigger reconfiguration.
Would you recommend investigating the common DP-CEC helper or the amdgpu resume/HPD lifecycle first? Which tracepoints or register captures would best distinguish these possibilities? No known-good kernel has been established, so I'm not claiming a regression.
Attached are selected log excerpts, detailed investigation notes (including limitations), and the experimental patch for context.
Thanks,Jason
[-- Attachment #1.2: Type: text/html, Size: 3667 bytes --]
[-- Attachment #2: investigation.txt --]
[-- Type: text/plain, Size: 6920 bytes --]
To: Hans Verkuil <hverkuil@kernel.org>
Cc: linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org
Subject: [BUG] drm/dp-cec: CEC transmit NACKs after S3 with retained adapter state
Hello,
Disclosure: OpenAI Codex assisted with the source/log investigation and
preparation of this report. The proposed mechanism and experimental patch
have not received independent upstream review. The attached excerpts are
from retained local logs, not generated examples.
I would like to report a suspected DP-CEC resume issue and ask whether an
experimental state-replay workaround belongs in the common DP-CEC helper or
in the GPU/converter resume path. This is a bug report with a candidate
workaround, not a claim that the attached patch is ready to merge.
On my AMD desktop, CEC requests to a Samsung TV succeeded before S3 but
repeatedly received NACKs after resume, while the CEC adapter remained
registered with the same physical and logical addresses. A later setup
using a local kernel register-replay patch and a separate cecd retry patch
has logged successful wake acknowledgments and active-source announcement.
The historical runs are not a controlled, same-kernel A/B comparison.
Hardware and software
---------------------
- GPU: Sapphire Pulse Radeon RX 9070 XT, Navi 48; PCI 1002:7550,
subsystem 1da2:e490; amdgpu.
- Connection: GPU DP-1 -> active DP-to-HDMI converter -> Samsung TV HDMI 2.
- TV EDID model: Samsung QBQ90S.
- Adapter (owner supplied): UGREEN 8K@60Hz Active DisplayPort to HDMI
Unidirectional Adapter, 0.66FT. Exact SKU, chipset, and firmware unknown.
The CEC adapter's 0x000c03 vendor ID is not a verified converter identity.
- OS: NixOS with a CachyOS-derived, locally customized kernel.
- Failure capture: 2026-07-31, cec-ctl reported driver version 7.1.5.
- Later recovery capture: 2026-09-05, kernel 7.2.3-cachyos, with both the
attached kernel patch and a separate locally patched cecd 0.3.0.
- Suspend mode: deep / ACPI S3, independently confirmed in the kernel log.
- Exact taint state and complete kernel config for the historical failure
have not been collected. No current vanilla-mainline reproduction yet.
Historical reproduction and observed results
-------------------------------------------
1. With the TV connected, claim a Playback logical address and verify CEC
transport using Give Device Power Status. Put the TV in standby and
confirm a Report Power Status reply indicating standby.
2. Suspend the PC to S3 and wake it with the controller without changing
the display connection.
3. Inspect the CEC adapter and send directed Image View On requests to TV
logical address 0.
The July 31 adapter snapshots reported /dev/cec0, amdgpu DP-1, physical
address 2.0.0.0, logical address 8, and logical-address mask 0x0100 both
before and after suspend. All 30 subsequent Image View On attempts logged:
Tx, Not Acknowledged (1), Max Retries
Independent journal records show PM: suspend entry (deep) at 21:10:10 and
ACPI S3 wake plus PM: suspend exit at 21:12:17, local UTC-07:00 time.
Important qualification: the old lab script printed "returned from S3"
immediately after systemctl suspend returned, before a proper lifecycle
barrier. The later adapter snapshot was taken at 21:12:17, matching the
independent resume log. The journal also shows the normal TV wake service
starting at resume despite the lab's intended masking. Competing userspace
CEC activity therefore cannot be ruled out in this baseline capture.
With the later patched setup, a September 5 S3 cycle logged:
12:19:05 DP-1: restored CEC tunnelling state
12:19:05 PM: suspend exit
12:19:06 TV acknowledged wake request
12:19:15 TV power status is unavailable after 3 attempts;
continuing wake based on transport ACK
12:19:16 Activated source after wake
This shows successful CEC transport acknowledgment and completion of the
daemon's active-source sequence. It is not a confirmed TV power-on reply.
The cecd retry changes and kernel-version change are confounding factors.
An ACK is a transport-level signal, not proof that the TV acted on it.
Suspected mechanism and candidate workaround
-------------------------------------------
The proposed failure mode is converter CEC register state becoming stale
or lost while Linux retains its enabled adapter and physical address.
In current upstream drm_dp_cec_attach(), unchanged adapter capabilities
take a fast path through cec_s_phys_addr(). If the physical address is also
unchanged, the CEC core can return without reprogramming the converter.
The attached patch checks hardware state before that call and, when needed,
replays CEC tunneling enable, monitor-all state, and the logical-address
mask from the existing adapter state.
However, the normal drm_dp_cec_unset_edid() path invalidates the physical
address, which should force reconfiguration. More tracing is needed to
establish exactly why that normal path does not repair this hardware case.
The "restored" diagnostic only proves the replay path completed its writes.
The patch enters that path on a register mismatch OR a failed register
read, so it does not by itself prove register state loss. Raw before/after
DPCD register snapshots are not available in the retained logs.
Patch status and questions
--------------------------
The local patch applies with zero fuzz to the upstream driver at Linux
commit 28924df2a08f440c73991b83028032c901de2ae4 (checked 2026-09-08).
It has been built and used locally, but not built or boot-tested against
that upstream commit. The accompanying userspace VM tests exercise wake,
hotplug, and teardown behavior; they do not emulate converter state loss.
Known review points in this experimental patch:
- If a transmission is active, it returns -EBUSY without scheduling another
replay. AUX read/write failures likewise do not schedule recovery.
- Successful register writes are not read back for verification.
- The hook affects unchanged adapter attachments/reprobes in general;
whether it should be resume-specific or a converter quirk needs review.
- The success-level diagnostics would likely need reducing for upstream.
Is the common DP-CEC helper the right place to reconcile converter state
after resume, or should the amdgpu/HPD lifecycle invalidate/reinitialize
the adapter instead? What tracing or register captures would best resolve
that distinction? I have not identified a known-good kernel, so I am not
labeling this a regression.
Attachments:
- evidence.txt: narrowly selected local adapter and journal excerpts.
- drm-dp-cec-replay-state.patch: the unmodified local experimental patch.
Upstream code inspected:
https://github.com/torvalds/linux/blob/28924df2a08f440c73991b83028032c901de2ae4/drivers/gpu/drm/display/drm_dp_cec.c
https://github.com/torvalds/linux/blob/28924df2a08f440c73991b83028032c901de2ae4/drivers/media/cec/core/cec-adap.c
Thank you.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: drm-dp-cec-replay-state.patch --]
[-- Type: text/x-patch; name=drm-dp-cec-replay-state.patch, Size: 4644 bytes --]
--- a/drivers/gpu/drm/display/drm_dp_cec.c
+++ b/drivers/gpu/drm/display/drm_dp_cec.c
@@ -5,6 +5,7 @@
* Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
+#include <linux/errno.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -16,6 +17,7 @@
#include <drm/drm_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
/*
* Unfortunately it turns out that we have a chicken-and-egg situation
@@ -155,6 +157,91 @@ static int drm_dp_cec_adap_monitor_all_enable(struct cec_adapter *adap,
return (enable && err < 0) ? err : 0;
}
+/*
+ * A DP-to-HDMI protocol converter can lose its CEC tunnelling registers while
+ * the CEC core keeps the adapter enabled across a system suspend. Replaying
+ * the cached software state is harmless for an unchanged converter, and
+ * avoids leaving the CEC core and the converter out of sync after resume.
+ *
+ * This is called with aux->cec.lock held. Keep the established lock order used
+ * by cec_s_phys_addr(): aux->cec.lock, then adap->lock.
+ */
+enum drm_dp_cec_restore_result {
+ DRM_DP_CEC_RESTORE_REPLAYED = 1,
+ DRM_DP_CEC_RESTORE_VERIFIED,
+};
+
+static int drm_dp_cec_restore_state(struct cec_adapter *adap, u16 phys_addr)
+{
+ struct drm_dp_aux *aux = cec_get_drvdata(adap);
+ u8 expected_control = DP_CEC_TUNNELING_ENABLE;
+ u8 hw_control;
+ u8 hw_mask[2];
+ u16 hw_la_mask;
+ u16 la_mask;
+ u8 mask[2];
+ int control_err;
+ int mask_err;
+ int err = 0;
+
+ mutex_lock(&adap->lock);
+ if (!adap->is_enabled || adap->phys_addr != phys_addr)
+ goto unlock;
+
+ la_mask = BIT(CEC_LOG_ADDR_BROADCAST) |
+ adap->log_addrs.log_addr_mask;
+ if (adap->monitor_all_cnt)
+ expected_control |= DP_CEC_SNOOPING_ENABLE;
+ control_err = drm_dp_dpcd_read_byte(aux, DP_CEC_TUNNELING_CONTROL,
+ &hw_control);
+ mask_err = drm_dp_dpcd_read_data(aux, DP_CEC_LOGICAL_ADDRESS_MASK,
+ hw_mask, sizeof(hw_mask));
+ if (!control_err && !mask_err)
+ drm_dbg_kms(aux->cec.connector->dev,
+ "%s: CEC replay snapshot: control %#04x, logical mask %#06x; cached monitor-all %u, logical mask %#06x\n",
+ aux->cec.connector->name, hw_control,
+ hw_mask[0] | (hw_mask[1] << 8),
+ adap->monitor_all_cnt, la_mask);
+ else
+ drm_dbg_kms(aux->cec.connector->dev,
+ "%s: CEC replay snapshot unavailable: control %d, logical mask %d\n",
+ aux->cec.connector->name, control_err, mask_err);
+ if (!control_err && !mask_err) {
+ hw_la_mask = hw_mask[0] | (hw_mask[1] << 8);
+ if ((hw_control & (DP_CEC_TUNNELING_ENABLE |
+ DP_CEC_SNOOPING_ENABLE)) == expected_control &&
+ hw_la_mask == la_mask) {
+ err = DRM_DP_CEC_RESTORE_VERIFIED;
+ goto unlock;
+ }
+ }
+
+ if (adap->transmit_in_progress) {
+ err = -EBUSY;
+ goto unlock;
+ }
+
+ err = drm_dp_cec_adap_enable(adap, true);
+ if (err)
+ goto unlock;
+
+ if (adap->monitor_all_cnt) {
+ err = drm_dp_cec_adap_monitor_all_enable(adap, true);
+ if (err)
+ goto unlock;
+ }
+
+ mask[0] = la_mask & 0xff;
+ mask[1] = la_mask >> 8;
+ err = drm_dp_dpcd_write_data(aux, DP_CEC_LOGICAL_ADDRESS_MASK,
+ mask, sizeof(mask));
+ if (err >= 0)
+ err = DRM_DP_CEC_RESTORE_REPLAYED;
+unlock:
+ mutex_unlock(&adap->lock);
+ return err;
+}
+
static void drm_dp_cec_adap_status(struct cec_adapter *adap,
struct seq_file *file)
{
@@ -331,7 +418,30 @@ void drm_dp_cec_attach(struct drm_dp_aux *aux, u16 source_physical_address)
if ((aux->cec.adap->capabilities & CEC_CAP_MONITOR_ALL) ==
(cec_caps & CEC_CAP_MONITOR_ALL) &&
aux->cec.adap->available_log_addrs == num_las) {
- /* Unchanged, so just set the phys addr */
+ int err;
+
+ /*
+ * The converter can lose its CEC tunnelling enable and
+ * logical-address mask while the adapter remains registered
+ * across suspend. Restore them before the unchanged physical
+ * address makes cec_s_phys_addr() a no-op.
+ */
+ err = drm_dp_cec_restore_state(aux->cec.adap,
+ source_physical_address);
+ if (err < 0)
+ drm_warn(connector->dev,
+ "%s: failed to restore CEC tunnelling state: %d\n",
+ connector->name, err);
+ else if (err == DRM_DP_CEC_RESTORE_REPLAYED)
+ drm_info(connector->dev,
+ "%s: restored CEC tunnelling state\n",
+ connector->name);
+ else if (err == DRM_DP_CEC_RESTORE_VERIFIED)
+ drm_info(connector->dev,
+ "%s: verified CEC tunnelling state\n",
+ connector->name);
+
+ /* Unchanged, so set the physical address if needed. */
cec_s_phys_addr(aux->cec.adap, source_physical_address, false);
goto unlock;
}
[-- Attachment #4: evidence.txt --]
[-- Type: text/plain, Size: 10759 bytes --]
DP-CEC S3 evidence excerpts, prepared 2026-09-08
Selected by OpenAI Codex from retained local logs. These are actual log
excerpts, not generated examples. Sections and source line labels were
added; omitted unrelated diagnostics are not reproduced.
The baseline had competing CEC userspace activity and an unreliable early
"returned from S3" marker. Use the independent journal timestamps below.
The later run changed both kernel and userspace; it is not a kernel-only A/B.
--- 20260731-210948-baseline.log, lines 12-41 ---
===== snapshot: before-standby (2026-07-31T21:09:50-07:00) =====
Driver Info:
Driver Name : amdgpu
Adapter Name : DP-1
Capabilities : 0x0000037e
Logical Addresses
Transmit
Passthrough
Remote Control Support
Monitor All
Needs HPD
Connector Info
Reply Vendor ID
Driver version : 7.1.5
Available Logical Addresses: 4
DRM Connector Info : card 1, connector 438
Physical Address : 2.0.0.0
Logical Address Mask : 0x0100
CEC Version : 2.0
Vendor ID : 0x000c03 (HDMI)
OSD Name : 'thebeast'
Logical Addresses : 1 (Allow RC Passthrough)
Logical Address : 8 (Playback Device 2)
Primary Device Type : Playback
Logical Address Type : Playback
All Device Types : Playback
RC TV Profile : None
Device Features :
None
--- 20260731-210948-baseline.log, lines 234-242 ---
Transmit from Playback Device 2 to TV (8 to 0):
GIVE_DEVICE_POWER_STATUS (0x8f)
Received from TV (0):
REPORT_POWER_STATUS (0x90):
pwr-state: standby (0x01)
Sequence: 361 Tx Timestamp: 2489.268790s Rx Timestamp: 2489.364644s
Approximate response time: 23 ms
Tx, OK, Rx, OK
TV reported standby
--- 20260731-210948-baseline.log, lines 312-341 ---
===== snapshot: after-s3-before-recovery (2026-07-31T21:12:17-07:00) =====
Driver Info:
Driver Name : amdgpu
Adapter Name : DP-1
Capabilities : 0x0000037e
Logical Addresses
Transmit
Passthrough
Remote Control Support
Monitor All
Needs HPD
Connector Info
Reply Vendor ID
Driver version : 7.1.5
Available Logical Addresses: 4
DRM Connector Info : card 1, connector 438
Physical Address : 2.0.0.0
Logical Address Mask : 0x0100
CEC Version : 2.0
Vendor ID : 0x000c03 (HDMI)
OSD Name : 'thebeast'
Logical Addresses : 1 (Allow RC Passthrough)
Logical Address : 8 (Playback Device 2)
Primary Device Type : Playback
Logical Address Type : Playback
All Device Types : Playback
RC TV Profile : None
Device Features :
None
--- 20260731-210948-baseline.log, lines 377-557 ---
strategy: current claim-if-empty Playback wake
wake attempt 1/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 362 Tx Timestamp: 2495.587706s
Tx, Not Acknowledged (1), Max Retries
wake attempt 2/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 364 Tx Timestamp: 2496.635951s
Tx, Not Acknowledged (1), Max Retries
wake attempt 3/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 366 Tx Timestamp: 2497.683949s
Tx, Not Acknowledged (1), Max Retries
wake attempt 4/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 368 Tx Timestamp: 2498.732962s
Tx, Not Acknowledged (1), Max Retries
wake attempt 5/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 370 Tx Timestamp: 2499.780740s
Tx, Not Acknowledged (1), Max Retries
wake attempt 6/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 372 Tx Timestamp: 2500.830013s
Tx, Not Acknowledged (1), Max Retries
wake attempt 7/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 374 Tx Timestamp: 2502.110309s
Tx, Not Acknowledged (1), Max Retries
wake attempt 8/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 376 Tx Timestamp: 2503.159066s
Tx, Not Acknowledged (1), Max Retries
wake attempt 9/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 378 Tx Timestamp: 2504.207117s
Tx, Not Acknowledged (1), Max Retries
wake attempt 10/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 380 Tx Timestamp: 2505.256131s
Tx, Not Acknowledged (1), Max Retries
wake attempt 11/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 382 Tx Timestamp: 2506.304239s
Tx, Not Acknowledged (1), Max Retries
wake attempt 12/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 384 Tx Timestamp: 2507.352951s
Tx, Not Acknowledged (1), Max Retries
wake attempt 13/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 386 Tx Timestamp: 2508.401214s
Tx, Not Acknowledged (1), Max Retries
wake attempt 14/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 388 Tx Timestamp: 2509.450227s
Tx, Not Acknowledged (1), Max Retries
wake attempt 15/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 390 Tx Timestamp: 2510.498281s
Tx, Not Acknowledged (1), Max Retries
wake attempt 16/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 392 Tx Timestamp: 2511.547320s
Tx, Not Acknowledged (1), Max Retries
wake attempt 17/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 394 Tx Timestamp: 2512.595140s
Tx, Not Acknowledged (1), Max Retries
wake attempt 18/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 396 Tx Timestamp: 2513.644412s
Tx, Not Acknowledged (1), Max Retries
wake attempt 19/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 398 Tx Timestamp: 2514.693024s
Tx, Not Acknowledged (1), Max Retries
wake attempt 20/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 400 Tx Timestamp: 2515.741951s
Tx, Not Acknowledged (1), Max Retries
wake attempt 21/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 402 Tx Timestamp: 2516.789400s
Tx, Not Acknowledged (1), Max Retries
wake attempt 22/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 404 Tx Timestamp: 2517.838552s
Tx, Not Acknowledged (1), Max Retries
wake attempt 23/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 406 Tx Timestamp: 2518.886598s
Tx, Not Acknowledged (1), Max Retries
wake attempt 24/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 408 Tx Timestamp: 2519.934611s
Tx, Not Acknowledged (1), Max Retries
wake attempt 25/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 410 Tx Timestamp: 2520.983680s
Tx, Not Acknowledged (1), Max Retries
wake attempt 26/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 412 Tx Timestamp: 2522.031702s
Tx, Not Acknowledged (1), Max Retries
wake attempt 27/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 414 Tx Timestamp: 2523.080718s
Tx, Not Acknowledged (1), Max Retries
wake attempt 28/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 416 Tx Timestamp: 2524.128772s
Tx, Not Acknowledged (1), Max Retries
wake attempt 29/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 418 Tx Timestamp: 2525.177814s
Tx, Not Acknowledged (1), Max Retries
wake attempt 30/30 (playback, pa=2.0.0.0)
Transmit from Playback Device 2 to TV (8 to 0):
IMAGE_VIEW_ON (0x04)
Sequence: 420 Tx Timestamp: 2526.225840s
Tx, Not Acknowledged (1), Max Retries
--- Independent baseline journal, 2026-07-31 ---
2026-07-31T21:10:10-07:00 thebeast kernel: PM: suspend entry (deep)
2026-07-31T21:12:17-07:00 thebeast kernel: ACPI: PM: Preparing to enter system sleep state S3
2026-07-31T21:12:17-07:00 thebeast systemd[1]: tv-cec-tv-on-resume.service: Deactivated successfully.
2026-07-31T21:12:17-07:00 thebeast systemd[1]: Starting One Touch Play: power on the TV over CEC and become the active source...
2026-07-31T21:12:17-07:00 thebeast kernel: ACPI: PM: Waking up from system sleep state S3
2026-07-31T21:12:17-07:00 thebeast kernel: PM: suspend exit
--- Later patched journal, 2026-09-05 (kernel and cecd both patched) ---
2026-09-05T12:19:05-07:00 thebeast kernel: ACPI: PM: Preparing to enter system sleep state S3
2026-09-05T12:19:05-07:00 thebeast kernel: ACPI: PM: Saving platform NVS memory
2026-09-05T12:19:05-07:00 thebeast kernel: ACPI: PM: Low-level resume complete
2026-09-05T12:19:05-07:00 thebeast kernel: ACPI: PM: Restoring platform NVS memory
2026-09-05T12:19:05-07:00 thebeast kernel: ACPI: PM: Waking up from system sleep state S3
2026-09-05T12:19:05-07:00 thebeast kernel: amdgpu 0000:03:00.0: [drm] DP-1: restored CEC tunnelling state
2026-09-05T12:19:05-07:00 thebeast kernel: PM: suspend exit
2026-09-05T12:19:06-07:00 thebeast cecd[1583]: 2026-09-05T19:19:06.927103Z INFO cecd::device: TV acknowledged wake request
2026-09-05T12:19:11-07:00 thebeast cecd[1583]: 2026-09-05T19:19:11.081173Z INFO cecd::device: TV acknowledged wake request
2026-09-05T12:19:13-07:00 thebeast cecd[1583]: 2026-09-05T19:19:13.058200Z INFO cecd::device: TV acknowledged wake request
2026-09-05T12:19:14-07:00 thebeast cecd[1583]: 2026-09-05T19:19:14.931199Z INFO cecd::device: TV acknowledged wake request
2026-09-05T12:19:15-07:00 thebeast cecd[1583]: 2026-09-05T19:19:15.497036Z INFO cecd::device: TV power status is unavailable after 3 attempts; continuing wake based on transport ACK
2026-09-05T12:19:16-07:00 thebeast cecd[1583]: 2026-09-05T19:19:16.076263Z INFO cecd::device: Activated source after wake
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [BUG] DP-CEC wake NACKs after S3 with UGREEN DP-to-HDMI adapter
2026-09-08 15:59 [BUG] DP-CEC wake NACKs after S3 with UGREEN DP-to-HDMI adapter jason.boukheir
@ 2026-09-11 7:28 ` Hans Verkuil
0 siblings, 0 replies; 2+ messages in thread
From: Hans Verkuil @ 2026-09-11 7:28 UTC (permalink / raw)
To: jason.boukheir, hverkuil@kernel.org
Cc: linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org
Hi Jason,
On 08/09/2026 17:59, jason.boukheir wrote:
> Hi Hans,
>
> I'm reporting a CEC resume problem on my desktop and would appreciate help identifying the right subsystem and next diagnostic steps.
>
> AI disclosure: I used OpenAI Codex to inspect retained local logs and kernel source and prepare this report. The observations below come from those logs; the proposed cause is AI-assisted analysis,
> not an independently confirmed diagnoses. The attached local patch is an experimental workaround without independent upstream review, not a merge-ready submission.
>
> Hardware/setup:
> - Sapphire Pulse Radeon RX 9070 XT (Navi 48), amdgpu.
> - GPU DP-1 -> UGREEN 8K@60Hz Active DisplayPort to HDMI Unidirectional Adapter, 0.66FT -> Samsung QBQ90S TV, HDMI 2.
> - Exact adapter SKU, chipset, and firmware are unknown.
> - NixOS, locally customized CachyOS-derived kernels; deep / ACPI S3 sleep.
>
> In a July 31 capture (CEC driver version 7.1.5), the TV replied to power status queries before suspend. After S3, the adapter still reported physical address 2.0.0.0 and Playback logical address 8,
> but all 30 directed Image View On attempts to the TV returned "Not Acknowledged ... Max Retries". The kernel journal independently confirms S3 entry and exit.
>
> A later setup with a local kernel patch plus separate cecd retry changes logged restored CEC tunneling state, TV wake ACKs, and an active-source announcement after resume. It did not receive a
> confirmed TV power-status reply. This is not a controlled comparison: the kernel version and userspace both changed, and another CEC wake service ran during the baseline capture. I have not reproduced
> this on current vanilla mainline.
>
> The suspected mechanism is converter CEC state becoming lost or stale while Linux retains its enabled adapter state. The patch checks the tunneling-control and logical-address-mask registers during
> unchanged adapter attachment and replays cached state if needed. However, we have no raw register capture proving state loss, and the normal EDID removal path should invalidate the physical address
> and trigger reconfiguration.
>
> Would you recommend investigating the common DP-CEC helper or the amdgpu resume/HPD lifecycle first? Which tracepoints or register captures would best distinguish these possibilities? No known-good
> kernel has been established, so I'm not claiming a regression.
>
> Attached are selected log excerpts, detailed investigation notes (including limitations), and the experimental patch for context.
After reading the long, rambling AI generated report I conclude that it boils down
to the fact that after suspending, then resuming the video source, the CEC adapter
no longer works because it has lost all state.
I don't think I ever tested this scenario, although I'm not sure about that since it's
a long time ago that I worked on this. Most likely, when suspended the 5V line of the
HDMI output is pulled low, and the DP-to-HDMI adapter loses power.
I will debug this, but it may take a few weeks before I get around to it. I'm not
very familiar with how suspend/resume works in drm: after resume, does it assume
the same display is still connected, or does it do a full 'discover what displays
there are' process? It depends a bit on how it works to determine the right solution.
Your patch may actually be on the right track.
Regards,
Hans
>
> Thanks,
> Jason
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-11 7:28 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 15:59 [BUG] DP-CEC wake NACKs after S3 with UGREEN DP-to-HDMI adapter jason.boukheir
2026-09-11 7:28 ` Hans Verkuil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox