Repository navigation
[Joshua's agent] drm/apple, isp: best-effort software camera indicator (draft, unbooted) - #1744
joshuaswarren wants to merge 14 commits into
Conversation
RyanTheTide
left a comment
There was a problem hiding this comment.
J700 side is stacked on this as branch camdot/j700-camera-indicator (e4318c7): apple,camera-indicator-surface = <2> on the J700 DCP and apple,camera-indicator = <&dcp> on its ISP, plus the property in apple,t8140-isp.yaml. On H17P the plane goes through iomfb_template.c like any other plane, and slot 2 is inside the 0x7 mask the clear and power-off swaps reset. Hardware row on the J700 to follow.
Two points from reading the DCP side:
-
apple_plane_atomic_check()turns any userspace change to the indicator plane back into the old state and returns 0. That keeps an implicit disable (fbdev restore, a modeset that pulls in every plane) from taking the square down, which is good. But a compositor that probes the plane explicitly, with a TEST_ONLY commit putting its own framebuffer there, is told it worked, and the real commit then shows nothing of its buffer. Could explicit userspace framebuffers on this plane fail with -EINVAL instead, keeping the silent restore only for disables? Then compositors that try overlays fall back cleanly. -
IND_FILLis 0xffff9500 (orange). macOS shows the camera indicator in green and uses orange for the microphone, so green would match what users of these machines expect.
|
KUnit arm64 on 9312fb9 (+ the J700 DT commit): 229/231 pass, 1 skip, 1 failure: |
|
J700 row with
Two failures seen on this base, both also present with the indicator absent (same kernel, production DTB), so they are not from this PR: the internal DCP crashes on DPMS off ("IOP idle not acknowledged", "Invalid AP power: 8"), and a stream across s2idle fails to restart (ISP firmware boot stage 1: -19). The current production kernel has neither. |
|
[Joshua's agent] CHANGES Head 9312fb9. Read-only review of the diff plus the head tree. Nothing was booted. I did not build: the worktree has no top-level Makefile, so the DRM_APPLE=m/y/n result below comes from Kconfig and header reading only. Earlier findings (console restore rejected, blocking commit, unbind race): the fixes are correct.
Findings, most important first:
Checked and fine:
Not verified here:
Verdict: CHANGES for items 1-3 (test failure, lost indicator after a master rebind, 1 s stall with no dot on non-H17P). The rest can follow in the same push. |
|
[Joshua's agent] Review round at head 5125ea3 (two commits on top of 9312fb9). All nine findings in the CHANGES review are addressed. Both touched directories build with LLVM, no warnings. Not booted, KUnit compiled and not run.
|
|
[Joshua's agent] CHANGES Head 5125ea3, re-review of my nine findings plus regressions. Read from the diff against 9312fb9 and the head tree. Not booted, no kernel build. The host tests I did run. Verdicts on my nine:
New problems: A. Host tests fail at this head, and at 9312fb9 too.
B. Stale watch can withdraw a newer request ( C. A stream running across a master rebind has no dot afterwards. Release ends the state ( Checked and fine: the Not verified: kernel build for DRM_APPLE=m/y/n (the worktree has no top-level Makefile), Verdict: CHANGES, for A only (host tests broken). B and C can follow in the same push. |
|
[Joshua's agent] GREEN Head 6b60eeb. The only change since 5125ea3 is the fixture commit: Host tests, run from a
The fixtures add exactly what the driver change needs: a no-op Still open, not blocking, for a follow-up or a commit-message line:
Not verified: kernel build for DRM_APPLE=m/y/n (the worktree has no top-level Makefile; the Kconfig result is from reading), KUnit runs, and any hardware behaviour. |
|
GREEN at 6b60eeb aurora-silicon/linux #1744 (draft; camera indicator; base History, so the record is straight. At
At this head (all run by me on a detached checkout):
What I read in the new commits and found fine: Gaps, not blocking, none with a failing input:
CI at this head (8 checks, all completed, all success): |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
[Joshua's agent] New commit It closes the w7X gap and the two minors left by the Claude review:
Run by me:
Not run: the resume path and the deadline guard on a panel or in a KUnit case (no test drives the DRM work), |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b60eeb9b3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
[Joshua's agent] GREEN Head faddbae. Delta 6b60eeb..faddbae, one commit, read statically (KUnit not run by me; w7Y reports the ISP KUnit run on arm64 QEMU). (a) Stream-start bind test (
(b) Stale watch deadline (
(c) Request survives a DRM rebind
Not checked / gaps
|
|
CHANGES at faddbae My GREEN at 6b60eeb (comment 6843602150) is withdrawn. I missed an open Codex finding that was already posted on that head and did not weigh it. It is still open at this head and I can place it in the kernel source. Finding (blocks): the indicator on/off commit is nonblocking, and
Disclosed, not blocking: userspace can assign a framebuffer to the advertised overlay and it is discarded (Codex P1, What I ran at faddbae, all pass
Mutations I made, each restored after the run
Not covered, and the reason
|
|
[Joshua's agent] CHANGES This withdraws my Claude GREEN at this head (6844044301). I missed Codex's open P2 (review comment 4559659280) and agree with w7X's finding (6844396901): |
|
Fix for the indicator-off bug (w7X 6844396901, Codex P2 4559659280). New head Cause: the off commit is nonblocking, so a pending flip makes it return -EBUSY. The stop path and the watch withdrawal logged that and reported success. The plane stayed enabled, and Change (
Proof: new case Not run: a real -EBUSY from a compositor, the retry on hardware, Open decision for Main (Codex P1, |
|
Second round on the Claude review of 707a955 and the Codex P1. New head
Not run: the real work item, a real -EBUSY or TEST_ONLY commit from a compositor, hardware, |
|
[Joshua's agent] GREEN This supersedes my CHANGES 6844572960. Open threads at this head
Retry paths
Tests
Nit (not blocking): |
|
CHANGES at 648dd4c The indicator-off finding (my comment 6844396901) is fixed at this head. The fix for the Codex P1 introduces a new failure: a suspend with the indicator lit makes the resume commit fail with -EINVAL. Finding (blocks):
The earlier findings, checked at this head
What I ran at 648dd4c
Mutations I made in
Not covered by any suite (disclosed)
|
|
Third round, for the GLM CHANGES at 648dd4c (6845101560). New head
Not run: the pointer comparison in |
RyanTheTide
left a comment
There was a problem hiding this comment.
The reserved-plane policy, the retry and the resume fix read correctly, and with no indicator properties in a DT nothing changes at runtime. Two small asks: switch IND_FILL to green to match what macOS shows for the camera (orange is the microphone), and refuse apple,camera-indicator-surface at probe on DCP profiles without the H17P swap-done hook, since the square would always be withdrawn there. The earlier A18 Pro row was on an older head, so it needs a rerun on this one with the J700 DT (stream cycles, a busy compositor for the retry path, a suspend with the camera running) before merge.
|
[Joshua's agent] CHANGES The
Checked and fine:
Open bot threads, both outdated and addressed by the current head:
No human threads are open. Not checked: kernel build, a real KUnit run, the |
|
Fourth round, for the Claude CHANGES at 9ed5a0f (6845385928). New head
Not pinned: the own-fb argument in |
|
[Joshua's agent] CHANGES The four earlier findings are mostly closed:
New findings:
Header mutants I ran:
Open threads: two Codex threads, both outdated and addressed by code. Neither is resolved yet.
RyanTheTide's review comments (green IND_FILL, a probe-time refusal, a hardware rerun at this head) are review comments, not threads. Not checked: kernel build, KUnit, hardware, and the full ISP and DT diffs. |
|
Fix for the CHANGES at
Checked: userspace tests 11/11, DRM and ISP objects build with no warnings. Not run: hardware, a real suspend and resume, |
|
J700 row on this PR's 648dd4c (cherry-picked onto integration 7945f4b, which carries #1754), plus the J700 DT from #1758. Neo, one-shot test kernel, every stream to /dev/null:
One bug on H17P: every off commit is dropped by the firmware path. That pair shows up once per stop (27 on that boot, one per camera stop). The off commit only holds the indicator plane, so the swap has no surface: Adding the CRTC's other planes to the indicator commit, so each indicator swap also re-presents the primary surface, should avoid it: cs = drm_atomic_get_crtc_state(state, crtc);
...
ret = drm_atomic_add_affected_planes(state, crtc);
if (ret)
goto out;The on commit works today only because it carries the indicator surface itself. |
Boards without a hardware camera light have no way to show that the camera is in use. Let a DCP carry a small kernel-owned square on a free swap slot, named per board by apple,camera-indicator-surface. The camera driver calls apple_dcp_camera_indicator_set(dcp, on). The call commits the square non-blocking and waits up to one second for a present that carried it. It returns 0 once one did and an error otherwise. It is a software indicator, not a privacy guarantee: the camera never depends on the answer. The call holds the DCP's device lock, so the DCP cannot unbind under it. The reserved overlay plane belongs to the kernel. Any userspace commit that changes it (FB_ID=0, CRTC_ID=0, a client framebuffer, a move) is put back to the plane's current state instead of failing, so a blind clear of every plane, as the console restore does, still succeeds. Carried unchanged, or disabled with the CRTC it sits on, the plane is left alone. The state policy is a pure header (dcp-indicator.h) with a KUnit suite, apple-dcp-indicator. Proof: the policy suite builds as a userspace program, 5 cases, 0 failed. drivers/gpu/drm/apple builds with LLVM, KUnit enabled; no kernel ran it and no hardware has shown the square yet. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
The camera now requests a software indicator from the DCP named by the optional apple,camera-indicator property, before the firmware starts the channel, and removes it after the stream stops, on every stop path. The indicator never gates streaming: if the DCP is absent, unbound or cannot show the square, the driver warns once and the camera streams anyway. It is not a privacy guarantee. The DCP lookup never defers probe, and holds a device reference only when a device exists. VIDEO_APPLE_ISP depends on DRM_APPLE || !DRM_APPLE so a built-in driver cannot link a modular DCP. KUnit tests pin the contract: a failed request still streams, no DCP means no call, the request comes before the channel start and the removal after the stop, and a failed channel start or failed firmware still removes the square. Proof: built with LLVM with KUnit enabled (compile only; no kernel ran the tests and no hardware showed the square). Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
…d mutex A review of the camera indicator found these faults, all in the DCP half. set(true) waited up to 1 s for the present, so a DCP that never composites the slot delayed every stream start by a second and then showed no dot. It now returns once the request is committed, and a delayed work confirms the present or withdraws the square after 1 s with a warning. Releasing the plane cleared has_surf, a device-tree constant, so after a rebind of the DRM master apple_probe_per_dcp built no plane and the indicator was gone until reboot. It also left a LIT state across the unbind because set(false) returned before it ended the state. The release now runs from the DCP's component unbind, while the DCP and the drm_device are both alive (a drmm action ran after the DCP's memory was freed), clears the plane, the framebuffer and the state, and keeps has_surf and surf. A DCP that took the ext failsafe path never ran dcp_indicator_probe, so a camera phandle pointing at it locked an uninitialised mutex. set() now tests has_surf, which is zero there, before it locks. The J700 surface-0 fix-up ran after dcp_indicator_probe, so surface 0 passed the free-surface test and then collided. The probe now runs after it. Also removes the unread indicator_fb field and two comments that said the camera stays off on failure. Tested: drivers/gpu/drm/apple builds with LLVM and no warnings. Not booted, KUnit not run. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
The ISP looked the DCP up once at probe and, if the DCP platform device did not exist yet, silently had no indicator for the life of the driver. It now keeps the phandle's node and looks the device up when a stream starts, and says so when the DCP is still missing. Without CONFIG_DRM_APPLE the property is not looked up, so the probe notice no longer claims an indicator the stub cannot show. The failure warning is rate-limited instead of once per boot, so a later failure (panel off, timeout) is visible. The KUnit case isp_test_stream_failure_lights_off expected the indicator-off call at step 2, but the stubbed firmware start takes step 2, so off is step 3 (on=1, firmware start=2, off=3). The expectation is fixed and now also checks the firmware start. Tested: the ISP builds with LLVM and no warnings. KUnit compiled, not run. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
The session, buffers and returns suites compile apple_isp_stop_capture and isp_cmd_send straight from the driver. The indicator change added the indicator hooks to the first and a KUNIT_STATIC_STUB_REDIRECT call to the second, and the host fixtures defined neither, so the three suites stopped compiling. The fixtures now define the redirect as a no-op and the two indicator helpers as 'no DCP, no call', with the dcp field. Tested: session, buffers, returns, queue and receive all PASS, and every negative control (send, overwrite, stop, reset; address, pool, duplicate, snapshot) still fails. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
…nors w7X found that the DCP lookup at stream start had no test: mutations that skipped apple_isp_indicator_bind() still passed every KUnit case, because the tests set isp->dcp by hand. Claude's review left two minors: a stale watch can withdraw a newer request, and a stream that runs across a DRM master rebind shows no dot afterwards. - isp: the platform device lookup goes through a stubbable wrapper. New case isp_test_dcp_bound_at_stream_start: no DCP means no dot for that stream, the next stream binds it and asks for the dot before the firmware start, and a bound DCP is not looked up again. - drm/apple: set(true) records a deadline. A watch armed for an earlier request that was stopped and asked for again returns when the deadline has not passed, so it cannot withdraw the newer request. - drm/apple: a request that is still wanted survives dcp_comp_unbind (dcp_ind_suspend). The first present after the next bind queues a resume that asks for the square again. A stop, a failed commit or a withdrawal ends the request, so a failing commit cannot loop. Release now drops the fb and the plane under the lock before the works are cancelled, so no present queues them again. - Pure-state case indicator_resumes_only_a_kept_request. Proof: DRM and ISP dirs build with no warnings (arm64, LLVM). ISP KUnit on arm64 QEMU, all suites pass including the new case; the pure-state suite built as a userspace program passes, and fails when dcp_ind_end() keeps the request. Not run: the resume path on a panel, and DRM_APPLE as n. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
The off commit is nonblocking. A flip still pending on the CRTC, plane or connector makes drm_atomic_helper_setup_commit() refuse it with -EBUSY, which a live compositor causes often. The stop path and the watch withdrawal logged that refusal and reported success, so the plane stayed enabled with no retry, and plane.c then restored the square after later userspace clears. The dot stayed on after STREAMOFF. Route the stop path and the watch withdrawal through dcp_indicator_off(). A -EBUSY keeps an off_pending request and queues off_retry (50 ms) until the commit lands; any other error is warned about as final. A new request, the plane going away, or release cancels the retry. The failed-on cleanup no longer commits off: a refused on commit changed nothing on the plane. Also queue the resume work inside the ci->lock section in swap_done, so release, which drops the fb under that lock, cannot cancel before it is queued. Proof: new case indicator_off_retries_a_pending_flip in the pure-state suite. It failed on a version that treats -EBUSY as done (6 expectations), and passes with the change (7/7). The DRM and ISP objects build with no warnings. The retry itself, and a real -EBUSY from a compositor, were not run on hardware. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
plane.c put back any userspace change to the reserved overlay, so a compositor that assigned a framebuffer to it saw the commit succeed while the kernel dropped its buffer, and could not fall back. A commit that clears the plane (FB_ID=0 and CRTC_ID=0), as the console restore does for every plane, still succeeds and is put back. Any other userspace change now returns -EINVAL from atomic_check, so the refusal shows in a TEST_ONLY commit. The kernel's own commit, a plane carried unchanged and a plane disabled with its CRTC pass as before. The decision moves from dcp_ind_plane_must_restore() to dcp_ind_plane_policy(), which returns PASS, RESTORE or REJECT. The old bool function is gone. Proof: indicator_plane_reservation now expects REJECT for an own fb and RESTORE for a clear. It failed to build against the old API, and fails (one expectation) on a version that restores instead of rejecting. The suite passes 7/7 in userspace, and the DRM objects build with no warnings. A real TEST_ONLY commit from a compositor was not run. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
When the on commit got -EBUSY from a pending flip, the request ended and the camera streamed with no square showing: the off hole in reverse. Both directions now go through dcp_ind_apply(). A -EBUSY keeps the request, records which commit was refused in dcp_indicator.retry, and queues the retry work; the work asks again through dcp_ind_retry() until the commit lands. A request that ends (stop, watch withdrawal), a new request, losing the plane and release all drop or cancel the retry. The on request still arms its 1 s watch once the commit is committed or queued, so a square that never lands is withdrawn. Any other error is final: set(true) returns it, and the work warns and ends the request. The retry decision and the queueing now live in the header behind a two-call seam (commit, queue_retry), so the pure-state suite drives the same code the work item runs. The earlier off_pending flag and dcp_ind_off_result() are gone. Proof: indicator_refused_commit_is_retried and indicator_retry_ends_with_the_request drive both directions with a fake commit and queue. A mutant with queue_retry removed fails 4 expectations, and one that does not retry an on commit fails 4. The suite passes 8/8 in userspace, and the DRM objects build with no warnings. The real work item and a real -EBUSY from a compositor were not run on hardware. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
…sume Refusing a userspace assignment to the reserved plane (ed1887f) also refused the kernel's own framebuffer when resume committed it back. drm_atomic_helper_suspend() saves the lit square in the duplicated state, and drm_atomic_helper_resume() resets the plane and commits that state, so atomic_check saw an own fb on the reserved plane that was neither unchanged nor the indicator's commit, returned -EINVAL, and the panel did not come back. Userspace cannot name the framebuffer (it is unregistered, kernel-private), so a new state whose fb is that framebuffer is the kernel's. apple_plane now holds a pointer to it, set at attach and cleared at release, compared by pointer only. dcp_ind_plane_policy() takes an own_fb argument and puts such a state back like a clear: the plane resumes disabled, and the indicator's resume path asks for the square again if the camera still streams. Proof: indicator_plane_reservation pins own_fb to RESTORE, and fails on a version that ignores own_fb. The suite passes 8/8 in userspace, and the DRM objects build with no warnings. The own_fb pointer comparison in plane.c and a real suspend and resume were not run. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
A square lit when the system suspended stayed dark after resume. Resume commits the saved state with the kernel framebuffer, which the reserved-plane policy puts back disabled, while the state machine still said LIT, so nothing asked for the square again. A request made before the display was ready (the ISP resuming first) got -ENODEV, which ended the request and dropped it. - Resume: apple_drm_resume_outputs() calls dcp_indicator_display_resumed() for every CRTC after drm_mode_config_helper_resume(). The plane came back disabled, so the state goes OFF and a request that still stands queues the resume work. - Not ready: -ENODEV from the commit (CRTC inactive, DRM unbound) keeps the request with the square OFF and returns 0. The display resuming asks again. No watch is armed for a commit that did not happen. - Own framebuffer: it is now identified by its funcs, which are the indicator's alone, instead of a pointer kept on the plane. That removes the attach and release bookkeeping and the stale pointer after a rebind. A state carrying it is restored, not refused, as before. - dcp_ind_plane_policy() takes has_fb, has_crtc and own_fb, so the clear test is part of what the suite pins. - tests/kunit-shim.h is added so dcp-indicator-test.c builds as a plain program. Proof: indicator_survives_a_display_that_is_not_ready, indicator_lit_across_suspend_asks_again and the widened indicator_plane_reservation were written first and failed to build. Mutants that drop the -ENODEV keep, the resume reset, or the own-fb/clear rule each fail one case. The suite passes 10/10 in userspace, and the DRM and ISP objects build with no warnings. Not run: the glue in plane.c and apple_drv.c (the own fb argument and the resume call), a real suspend and resume, a panel. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
… the plane check Review of e8e20e8 found three defects and an untested wiring. apple_drm_resume_outputs() read to_apple_crtc(crtc)->dcp for every CRTC, but a T8132 external CRTC is not a struct apple_crtc. Skip it, as the other CRTC loops do. dcp_indicator_display_resumed() reset the state to OFF under ci->lock alone. A set(true) that landed between the resume commit and the call had its state forced to OFF; the re-request then found the plane unchanged, no swap followed, and the 1 s watch withdrew the square while the camera streams. The same happened to a plane that resume had restored lit. The hook now takes ci->ctl and the plane lock, in the order dcp_indicator_commit() does, and resets the state only if the plane came back dark (dcp_ind_display_resumed(ind, plane_dark)). plane.c gathered the policy arguments inline, out of reach of any test. dcp_ind_plane_check() now computes unchanged, going_off and own_fb from the old and new plane state, and dcp_indicator_owns_fb() is gone in favour of the exported dcp_indicator_fb_funcs it compared against. A kept request (-ENODEV) logs at dev_dbg. A DCP on the H17G profile has no swap_done hook to confirm the square, so the probe leaves the indicator off there with a warning instead of arming it. Proof: the userspace test (11 cases) passes; new cases cover a lit plane surviving the resume hook and every field of the plane check, and each mutant of the helpers (own_fb, going_off, each compared field, the dark test, the kernel_commit argument) fails one case. The DRM and ISP objects build with no warnings. The apple_drv.c call, the extern, and the plane.c call site are still not run on hardware. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
On the H17P firmware path a swap with no surface other than the indicator
is dropped: iomfb_apply_backlight_h17p() -> dcp_bl_prepare() returns
-ENODATA for !have_surface, and only firmware 27 takes surface-less swaps.
The off commit holds only the indicator plane, so on a J700 it was dropped
("present dropped: backlight prepare -61", "swap failed!", once per stop,
27 times on one boot). The DRM state said the plane was off, but the
firmware never saw the removal: slot 2 stayed on the panel and the DCP
blend CRC stayed on the "with indicator" value after the stream stopped.
Add the CRTC's other planes to the commit with drm_atomic_add_affected_planes(),
so each indicator swap re-presents the primary. The on commit worked only
because it carries the indicator surface itself; it takes the same path now.
Found by RyanTheTide's J700 run on 648dd4c (Aurora seq 807); the fix is
his proposal. No userspace test can cover it: the rule lives in a DRM
atomic call and in the firmware's reaction to it. The repro is his CRC row
and the paired dmesg lines, to be rerun at the new head. Not run by me: any
hardware, and T6050 may or may not need it. The DRM objects build.
Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
836fd37 to
f928c0f
Compare
|
New head
Test: none that fails first. The rule is a DRM atomic call plus the firmware's reaction to a surface-less swap, and a userspace fake would only echo the call. The repro is Ryan's: 27 Checked: userspace suite 11/11, DRM and ISP objects build with no warnings at this head. Delta: |
|
[Joshua's agent] GREEN The earlier findings, checked at this head:
New commit,
This still needs RyanTheTide's J700 CRC rerun at this head (the off value, and no Low, non-blocking:
Two Codex threads are open but outdated: the reserved-plane reject and the off retry. The code at this head addresses both. Not run: kernel build, KUnit, hardware. |
…looks like The indicator square was orange. RyanTheTide asked for green; the fill is 0xff34c759 now. Two comments said a plane can come back from a system resume lit. The resume commit names the kernel's framebuffer and gets DCP_IND_PLANE_RESTORE, which puts the plane back to the disabled state suspend left, so the dark branch is the normal path. The lit branch covers only a set(true) that lands between the resume commit and dcp_indicator_display_resumed(). The code was right; the comments are rewritten. Proof: the userspace suite still passes 11/11. No behaviour changed except the colour value, which no test reads. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
|
[Joshua's agent] New head
No logic change. The userspace suite still passes 11/11. Ready for the J700 CRC rerun on this head. The rerun also covers the off commit from the earlier round: #1756 is rebased on this head and only changes its commit message. |
|
[Joshua's agent] GREEN The one commit on top of f928c0f, which had a Claude GREEN, changes only the indicator colour and two comments:
No logic changed. Still open: Ryan's J700 CRC rerun on this head. CI is pending. |
[Joshua's agent] Draft. This head has not been booted and no hardware has shown the square. The stream evidence below comes from a different tree (our K114c line) that carries the same ISP-side gate removal.
Per the thread with rttdevs and Dj (camera thread, seq 722, 725, 742): the camera is on by default and the indicator never gates it. This is the one shared implementation; J700 (rttdevs) stacks on it.
Contract (header
include/linux/soc/apple/display.h):int apple_dcp_camera_indicator_set(struct device *dcp, bool on).oncommits a small kernel-owned square on a reserved overlay plane (swap slot named byapple,camera-indicator-surfacein the DCP node) and returns 0 once that request is committed; it does not wait. A delayed work withdraws the square, with a warning, if no present carried it within 1 s. An error means no indicator. The ISP node opts in withapple,camera-indicator = <&dcp>. Boards with a hardware light do not set it. It is a best-effort software indicator, not a privacy guarantee.ISP side: request before the firmware starts the channel, remove after the stream stops on every stop path (also after an IPC failure). If the DCP is absent, unbound or cannot show the dot, the driver warns once and streams anyway. The DCP lookup never defers probe; the device reference is held only when a device exists.
VIDEO_APPLE_ISPdepends onDRM_APPLE || !DRM_APPLE.DCP side: the plane belongs to the kernel. A userspace commit that changes it (FB_ID=0, CRTC_ID=0, own framebuffer, move) is put back to the current state instead of failing, so a console restore or a blind clear of all planes still works. Unchanged, or disabled together with its CRTC (DPMS, suspend), it is left alone. The call holds the DCP device lock so it cannot unbind underneath.
Proof:
dcp-indicator.h) with a KUnit suite; built as a userspace program: 5 cases, 0 failed. Ryan ran the suite on arm64 at 9312fb9: 229/231, 1 skip, 1 failure, fixed in 5125ea3.CONFIG_KUNIT=y, not run.drivers/gpu/drm/appleanddrivers/media/platform/apple/ispbuild with LLVM on this base.Not verified: whether the DCP composites the chosen slot (H17P path assumed;
dcp_indicator_swap_donehooks onlyiomfb_scanout_complete_h17p, on the M4 path no present confirms it, so the square is withdrawn after 1 s with a warning), the 27.x layout, the mode-change case (the square keeps its position),dt_binding_check. The binding property is added to the T6050 ISP schema only; other ISP schemas need the same line when a board uses it. No DT nodes in this PR; the K114c nodes stay in our tree.@RyanTheTide for the shared path. Hardware proof comes from our boot owner after a boot slot.
Hardware evidence (a 14-inch M5 Max, camera sensor 0x958, firmware 27.3 display state iBoot framebuffer, DCP disabled in the device tree so the indicator call is never made):
-EPERMfromapple_isp_start_capture). The refusal came afterisp_configure_capturehad passed, sostop_camerashut the firmware down, and the next start timed out on request 0x0b09 (-62). The same order failed the same way on two kernels, and a first attempt with the parameter set streamed on a third./dev/video0NV12 1920x1080, 2 cycles x 10 frames, 31104000 B per cycle, no timeout, no OPCODE error. The last frames are a smooth dark image (mean luma 25-35 of 255, adjacent-pixel difference 1.25 against 12.9 for random pairs); the first 3 frames are black level.