Skip to content

drm: apple: Adaptive Sync/ProMotion#477

Open
chadmed wants to merge 8 commits intoAsahiLinux:asahi-wipfrom
chadmed:dcp/vrr
Open

drm: apple: Adaptive Sync/ProMotion#477
chadmed wants to merge 8 commits intoAsahiLinux:asahi-wipfrom
chadmed:dcp/vrr

Conversation

@chadmed
Copy link
Copy Markdown
Member

@chadmed chadmed commented Apr 5, 2026

Tested:

  • Adaptive Sync over DisplayPort (Dell S2721DGF, [48, 165] Hz)
  • Apple ProMotion on 14" and 16" MacBook Pros (tested [24, 120] Hz)

Not tested:

  • Adaptive Sync over HDMI (I have no HDMI 2.x displays)

What works:

  • "Modesetting" in and out of Adaptive Sync
  • mpv... mostly
  • Games running via Proton via Steam via FEX via muvm
  • Native AArch64 games
  • Forcing Adaptive Sync on and sitting at the desktop at minimum refresh rate

What doesn't

  • Firefox will always render at the display's refresh rate
  • On the internal MBP displays only, mpv's gpu and gpu-next outputs leak file descriptors and halt the GPU when in fullscreen. Other backends work fine, other applications work fine, gpu and gpu-next work fine when not in fullscreen...

What needs work

  • The VRR timestamps are best guesses only. We know they are always within a few frames of each other, meaning that they are likely something to do with swap submission and presentation time, but what exactly remains unclear.
  • Wrapping set_digital_out_mode in a dcpep callback seems kind of silly? There's probably a smarter way to do this.

Copy link
Copy Markdown
Member

@jannau jannau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you verify this does anything at all on MacBook Pro internal displays? I would expect that this does nothing without EDID with adaptive sync data.

((horiz.active == 3024 && vert.active == 1964) ||
(horiz.active == 3456 && vert.active == 2234)))
(horiz.active == 3456 && vert.active == 2234))) {
out->min_vrr = 24 << 16;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the minimal refresh rate for ProMotion was was 10 Hz

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only on the iPhones and new iPad Pros apparently. There's scant concrete information available for the MacBooks, but Wikipedia lists 24 Hz and this matches what I've experienced. Setting it any lower results in stuttering.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apple documents 24 Hz as minimum for iPad Pros so it's probably the same for macbooks.

struct dcp_color_mode sdr;
struct dcp_color_mode best;
bool vrr;
s64 min_vrr;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32 bit should be enough and I assume this should be an unsigned value

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are expressed in TimingElements as 64-bit signed integers, so it is simpler to just store them the same way.

chadmed added 2 commits April 6, 2026 14:01
IOMFB exposes a method that allows firmware consumers to change
display behaviour parameters at runtime. One such parameter is
IOMFBParameter_adaptive_sync, which allows DCP to be informed
of the desired minimum refresh rate, media target rate, and
fractional rate.

Add an enum to define the supported parameters, and add
IOMFBPARAM_ADAPTIVE_SYNC to it as a starting point.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
This was actually unnecessary, and having dcp_on_set_parameter as
a dcp_callback_t will introduce some complicated duplication when
enabling VRR. Remove this callback and just set the display handle
on poweron instead.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
@chadmed chadmed force-pushed the dcp/vrr branch 2 times, most recently from 585c039 to ae20e32 Compare April 6, 2026 06:22
static void dcp_on_set_adaptive_sync(struct apple_dcp *dcp, void *out, void *cookie)
{
dcp_set_digital_out_mode(dcp, false, &dcp->mode,
complete_set_digital_out_mode, cookie);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unfortunately a full modeset. I initially assumed it wouldn't trigger full modeset like when trying to set the current mode without changing the minimal refresh rate.
It is even on macOS a full modeset both with USB-C/DP and HDMI (on M2 Pro) so I fear we can't make it work.
What we could possibly do is add a force_vrr module parameter and always set minRR when setting a VRR mode.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had an old implementation that set mode_changed and forced a full modeset. I will go back to that in the first instance if we can't get minRR to do anything without a modeset, and then add the module parameter to force VRR on at all times, ignoring userspace. I wonder if this has improved at all with newer firmware...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to force a modeset on VRR_ENABLED causes something to lock up, but since this is not expected to work anyway...

* like the actual value does not matter, as long as it is non zero.
* TODO: ascertain with certainty what these timestamps
* are. These names are guesses based on what macOS populates
* them with. These values seem to work well with VRR.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that these names make sense. Since setting them all to the same value enabled 120 Hz refresh rate on the ProMotion display my guess is that of the timestamps is the time base (could be submit time). The other two could intended/earliest display time and latest display time.

chadmed added 6 commits April 7, 2026 22:14
DCP supports VRR/Adaptive Sync, with its enormous firmware blob
handling the low-level details for us. Display refresh rate is
determined by the swap timing values provided to DCP on each
swap request.

VRR is activated by setting IOMFBadaptive_sync_parameter::minRR
and then requesting a modeset.

Wire up all of the required KMS properties to expose VRR to
userspace, and tell DCP to enable it when supported. This
enables VRR *unconditionally* for supported sinks, which will
be fixed in a future commit.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
DCP requires a "modeset" to trigger the upload of the SDP
to the display. On some monitors, this is instant. On others,
this seems to take as long as a real modeset. Given that in
either case we still blank the display, let's just force a
full modeset when VRR is toggled on or off.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
Setting these timestamps to a dummy value worked fine for enabling
a fixed 120 Hz mode on the MacBook Pros, however doing so causes
Adaptive Sync displays to simply switch between full and minimum
refresh rates. Setting these timestamps based on the swap pacing
seems to fix this, and makes the display's refresh rate match
the incoming swap rate.

Note that the names and values are best-guess only. These seem
to work fine for driving VRR displays, but may still be incorrect.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
Since these machines do not have proper EDID/DisplayID data, we need
to help the driver along a little bit. We know that "ProMotion" displays
can do 24-120 Hz VRR, so let's populate the mode with those values.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
macOS is inconsistent with how it uses DCP timestamps. Some swaps
don't use them at all. We know they are required for VRR display
modes to work properly, so let's just turn them on when we are
connected to a VRR display. This includes the 120 Hz mode on
the 14" and 16" MacBook Pros.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
Given that DCP requires a modeset to activate VRR, and given that
this is explicitly banned by KMS API contract and VESA DisplayPort
specification, hide this experimental support behind a module param.

Interestingly, the HDMI spec does not require a modeset-free VRR
transition. For this reason, it is expected that the KMS API contract
may change in the future, as both Intel and AMD hardware require
a modeset to enable VRR in some circumstances. Either VRR will be
expected to be enabled whenever it is supported, *or* modesetting
to toggle it on or off will be allowed. When that happens, this
commit *must* be reverted.

Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants