Changing refresh rate on Microsoft Surface Pro 8


I have a Microsoft Surface Pro 8 running Ubuntu 22 and have installed and successfully tested MATLAB 2022a and psych toolbox. Works great! Only problem is, I have thus far been unable to change the refresh rate on the display to anything other than 60 or 120 Hz, using both the display settings as well as lower level routines such as Xrandr. Does anybody know if it is possible to get the display to run at 75 or 100 Hz? If it is possible, how?

Lee Lovejoy

Good to know it works on Linux. Did you require some special hacks, kernels etc. or such, like with the SurfacePro 6?

Interesting question. Post your paid support membership authentication token and we can try to find out. → ‘help PsychPaidSupportAndServices’. If you don’t have one yet, you might still get the 99 Euro christmas offer. We decided last tuesday that the whole discounted membership program sadly is another colossal failure to get our users to use their brains and give something back, and end the discount and substantially raise the price anytime now, but afaics my boss hasn’t made the update yet.



It was a relatively easy process and it did require installing a special surface kernel. Some very good instructions are available on the GitHub repo for the kernel:

The multitouch support seems to work quite well.

Pasting in my authentication token below. We’ve had the paid support membership for a couple of years now.

CORRECTED TOKEN: LQ9WM49U-202339174250:9af6af30e1cb6b4233c3b2be7de388f652f20ab02e6c6d1f8462051ef8ca6406

Great. Yeah, I also have the surface-linux kernel and stuff on my MS Surface Pro 6, to make touch screen and battery reporting etc. working, and it was straightforward. Just wondered if the SP 8 may be “standard” enough to work without such customizations.

Good that the multitouch touchscreen continues to work nicely on SP 8. Does the webcam work? That required quite a lot of hacks on my SP6 iirc.

This license has run out over a month ago, and no renewal is so far registered in my database, despite it being a “yearly auto-renewing” one, first purchased 4th February 2022, no earlier purchases recorded, unless those were one-time licenses instead? How did you pay it? If it was with credit card, is that card still valid? Delays or errors can happen, also on our side, but if the renewal lapses by more than a month, you’ll lose the substantial 40% discount on extra work hours if needed. Please clarify.

The cameras aren’t supported. Haven’t been on 7, 7+, or 8.

Ouch I asked our admin to renew the subscription when the auto renewal didn’t work. I’ll follow up.


Ok, so I assume the renewed license will show by Monday, so far it hasn’t, and we go on for now without proof of payment. Swift payment is important, as is keeping the old license key around, to take advantage of possible discounts. Technically we are already beyond the grace period for lapsing the license.

So I did a bit of research, and the MS SP 8 should be quite a nice thing if one needs fine-grained stimulus timing and flexible framerates. It has an Intel Tigerlake cpu + gpu, with Gen 12 Intel Xe integrated graphics. The graphics chip and the touchscreen display should be fully (V)ariable (R)efresh (R)ate (VRR) capable and some internet searches seem to confirm that for Linux.

So in VRR mode with current PTB on Ubuntu 22.04-LTS and later (with required X-Server 21 and later), thanks to some unique PTB+Linux only features, you should be able to get any dynamically changeable framerate for animations from 30 fps - 120 fps, corresponding to ISI’s from 8.333 msecs to 33.333 msecs, and with a bit luck and careful use, ISI’s from 8.333 msecs to 20 minutes, or 0 fps - 120 fps. That said, PTB’s code so far has only been developed and tested on AMD graphics cards, and I specifically tweaked and improved AMD’s display drivers to work great with PTB. The status/quality of the Intel drivers wrt. VRR is so far unknown to me, especially if the crucially needed high precision stimulus onset timestamping is ready for this task in VRR mode, or if it would need extra work from myself. I don’t have suitable Intel graphics chips to test this atm., so I’m interested in your results.

You can test VRR mode by:

  1. Have a reasonably up to date Psychtoolbox. The feature was introduced sometime in PTB 3.0.16.

  2. Running XOrgConfCreator and answer 'y’es when it asks if you want VRR mode support, then run XOrgConfSelector to enable that new config file setting, and logout + login again to enable the machinery. Setup details to be found in help VRRSupport.

  3. Now you can use it in your own scripts. The test script provided with PTB is VRRTest, e.g., VRRTest('upsweep', [], 0.032) for an animation that should start fast at 120 fps / 8.333 msecs ISI, then linearly slow down to ~31 fps (aka 32 msecs ISI), or VRRTest(‘upsweep’) to test a range down to 5 fps / 200 msecs ISI.

So this is useful for fine-grained presentation timing control or choosing any framerate, changeable on each Flip. Assuming the Intel driver works as well in VRR mode as the AMD driver.

If you really only want to run the display at a fixed refresh rate of 75 or 100 Hz, then we’ll have to figure out a suitable video modeline to set via xrandr together. And then see how the panel responds to fixed rates other than 60 Hz or 120 Hz officially supported by Microsoft and defined in the panels EDID.

[30 out of 60 minutes of not-yet-paid support used.]

Hello Mario

Thanks for that! I very much hope the license has renewed by now. If not, I will investigate again.

I will update this reply with the plot results from VRRTest, but I wanted to let you know sooner rather than later that my testing with VRRTest revealed that I could, in fact, drive the display with a frame intervals from 8.333 msecs to 200 msecs! Not perfect but promising–when I attempted to run with a constant refresh rate I was unable to do so, but I didn’t have a chance to do much more investigation other than an initial proof of concept.

Will update soon.

So far, nothing has been renewed, according to my current record.

Good to know it works in principle, certainly interesting to look at different plots from VRRTest(). The ‘sine’ plot, ‘upstep’ and ‘downstep’ plots or ‘random’ are interesting., as is the ‘const’ one for an arbitrary constant framerate. The stability of this rises and falls with the quality of the display drivers implementation, which was specifically improved and tuned by myself for AMD graphics on Linux. A bit of noise is expected though, and less stability outside your displays native range of 30 fps - 120 fps, ie. for lower than 30 fps. Ofc. to be sure everything works in a trustworthy fashion, one would need to validate with external measurement hardware, of which the VRRTest() script supports plenty - although everything but photo-diodes won’t be usable on the MS Surface Pro 8’s internal display screen ofc.

But I still don’t know your use case. If you need a fixed rate of only e.g., 75 Hz, not the flexibility of VRR, we can still try to manually add a proper video mode for standard fixed rate operation?

Here’s another go with my support token

My use case is displaying random dot motion stimuli, so I need either 75 or 100 Hz refresh rate consistently. Seems to me that the easiest for me would be finding that appropriate video mode line.

Here are some plots:

The license has not been renewed yet, or at least the payment hasn’t come through so far, or it hasn’t been entered into my database by our sales guy.

Ok. So lets try something. I’m working off the reported decoded EDID from this GitHub issue… SP8 120Hz mode not available · Issue #825 · linux-surface/linux-surface · GitHub
… which states a maximum pixelclock of 720 Mhz for the MS Surface Pro 8 panel. We should double-check that, so can you please post the full output of the terminal command xrandr --verbose ?

Assuming those limits would be right, it could be difficult to create a fixed refresh rate video mode for 100 Hz refresh, but might be possible for 75 Hz:

The gtf command line tool (Generalized Timing Formula) gives this:
gtf 2880 1920 75

“# 2880x1920 @ 75.00 Hz (GTF) hsync: 150.30 kHz; pclk: 601.20 MHz”
Modeline “2880x1920_75.00” 601.20 2880 3120 3440 4000 1920 1921 1924 2004 -HSync +Vsync

The cvt tool gives:
cvt 2880 1920 75

“# 2880x1920 74.96 Hz (CVT) hsync: 150.38 kHz; pclk: 601.50 MHz”
Modeline “2880x1920_75.00” 601.50 2880 3128 3440 4000 1920 1923 1933 2006 -hsync +vsync

In both cases the dotclock stays below the 720 Mhz limit. Unfortunately trying those tools with 100 Hz will yield dot clocks of 817 and 819 Mhz beyond the hardware limit, so unlikely to work. And we can’t use reduced blanking modes to stay within limits, because these only work for refresh rates that are multiples of 60 Hz, ie. not 75 Hz or 100 Hz.

Anyhow, if you want to try the 75 Hz mode, this would be a command to enter:

  1. xrandr --newmode "2880x1920_75.00" 601.20 2880 3120 3440 4000 1920 1921 1924 2004 -HSync +Vsync

To define a mode based on the gtf output from above - a copy and paste of the modeline.

  1. xrandr --addmode eDP-1 2880x1920_75.00

To make that mode available on video output eDP-1 which I think would be your touchscreen.

  1. xrandr --output eDP-1 --mode 2880x1920_75.00 --rate 75

To switch to 75 Hz, or you can also use the display settings GUI. Be aware that an invalid mode could end with a black screen. So maybe using the GUI is better for the last step, if it gets you one of those auto-reverts if proper setting is not confirmed within 10 seconds. Or blindly typing `xrandr --output eDP-1 --rate 120`` should also do the trick.

This as a first test. If the EDID output of that linked GitHub issue is correct, it looks like as if Microsoft does use non-standard mode timings for the 60 and 120 Hz modes, so it could be that the panel doesn’t like fixed refresh rate modes other than 60 and 120 Hz.

The VRR mode we tried works very different from the panels perspective - as if it is always running at 120 Hz, but then tricks are played with dynamically extending the vblank to get all the intermediate rates from 30 Hz - 120 Hz.

Those plots look as if it works in principle, and within the hardware supported range from 8.33 msecs to 33.33 msecs, I’m not displeased with these results. But outside that range, ie. for framerates lower than ~ 30 fps, the current PTB algorithm can’t get stable results on Intel. That would need some parameter tweaking + luck, or possibly enhancements to the Linux Intel display driver, the latter impossible without me having such hardware myself and the time and funding to do.

Seems within the display native range it is reasonably stable, with a fixed offset between “wanted” and reality of about 2 msecs, an offset one could correct for. PTB does some calibration during startup, but for various reasons that can be thrown off a bit, hence the median error of around 2 msecs.

I guess you’d only need a fixed rate for your case, so you could try VRRTest('const') to see how stable it is under the constant condition, which is also the most easy to handle. If you edit line 33 of VRRTest.m you can define your own target delay, e.g., delay = 0.010 for 10 msecs / 100 Hz target, or delay = 0.013333 for 13.333 msecs / 75 Hz target.

Setting the optional useVulkan flag to 1 in VRRTest is another thing one can try to reduce jitter. May or may not make things better or worse. Technically the Vulkan mode is part of some experimental prototype enhancements to the Linux Vulkan and display drivers that I have developed here to get some fantastics, rock-solid and accurate results on AMD gpu’s already 1.5 years ago. Unfortunately I have not found the time to turn that into something production ready, again mostly due to lack of funding, caused by our unsupportive “penny wise, pound foolish” user-base. So it sits on my disc drive and collects dust. But maybe even standard Vulkan setups may give some improvement in jitter…


[80 of 60 minutes paid support used, not yet paid support fully exhausted.]

Here’s another modeline to try:

Modeline “2880x1920_100” 595.848 2880 2888 2920 2960 1920 1999 2007 2013 +HSync -VSync

which results in:

xrandr --newmode "2880x1920_100" 595.848 2880 2888 2920 2960 1920 1999 2007 2013 +HSync -VSync

This would get 100 Hz refresh with 595.848 Mhz clock - within hw limits. Apparently reduced blanking is also possible at other than multples of 60 Hz with some more recent standards than what the cvt tool can compute.

I used this online calculator to get this new modeline:

Btw. seems our sales person intentionally held back the new “renewed” license from entry into our database, because he is unclear from the fresh info provided by Digistore24 if the license was now actually renewed and paid for, or if the renewed purchase was cancelled - which is what he thinks happened.

Edit: Payment has now finally been received and your license renewed - happy end. Of course with 80 minutes of work rendered for 60 minutes of work paid, it is already completely used up. But we did decide to let you keep your 40% discount on the 300 Euros extra hours work packages, should they be needed, although technically that grace period has also already expired.

Please provide feedback swiftly if the proposed solution from my last postings wrt. how to add a 75 Hz or 100 Hz fixed refresh rate mode works. If it works, I’ll provide you with another 5 minutes of work for free to get to an easier “plug and play” solution for this use case. If too much time passes and I forget about this discussion, you’ll have to pay for the full extra hour package for what would only be a few minutes of work.