I've been wondering where to place this piece of text. Own website is a possible candidate, or find some thread at superuser.com that's closest to my topic (and has possibly helped me). This is how I have arrived here :-)
My particular problem was, how to force a particular video mode to my text consoles. System setup: Debian 9 Stretch on Haswell hardware, its IGP handled by the i915 driver in Linux (now supporting KVM and DRI/DRM for quite a while). Some stupid analog KVM switch, telling the PC via DDC/EDID that the maximum resolution was 1600x1200, but in reality feeding an LCD display capable of 1280x1024 :-)
I started playing around with
fbset, which are however out of date / unfit for the purpose, because they are incompatible with KMS+DRM.
The "inteldrmfb" appears to be just a shim over KMS+DRM (and, doesn't appear to be embodied in a kernel module of its own). The geometry parameters are read-only.
Well at least fbset can passively display the active resolution, which has some informational value.
Yet, there appears to be a way for you and me to set the resolution and vertical refresh AKA frame rate from the kernel command line (bootloader parameters on the line starting with "linux", which happens to be located towards the end of a modern multi-line grub.conf section).
You can fiddle with the parameters at boot time, if you press
e while Grub counts down the timeout. Follow the help from there. Once you're happy with your edits, press Ctrl+X or F10 to boot the modified profile. (Your changes are ephemeral - they will appear in /proc/cmdline in your running kernel on that one boot, but do not get written to grub.conf.)
For persistent storage of your additional boot parameters (kernel cmdline args), in Debian you should enter them in
/etc/default/grub, in a variable called
GRUB_CMDLINE_LINUX_DEFAULT . And, run
Now for the args.
Firstly, you need
i915.modeset=1 (provided that your graphics subsystem is an Intel IGP). If you suffer from the same problem that I did, i.e. that the kernel sets up a resolution that's much too high, you likely have modeset=1 already in by default (compiled in the kernel).
While you're struggling with the syntax of the cmdline curses, and you sometimes want just any working graphics mode, you may want to try
i915.modeset=0 . That apparently prevents graphical mode changes altogether, and you're left with an almost classic 80x25 character console, all the way to the console login. You will also notice that there's no /dev/fb0, and no DRM debug messages in dmesg (read on for details).
Also mind the option
quiet. This works with or without modesetting. It apparently prevents printing of kernel
messages to your console (/dev/tty) = you get a blank dark screen
for a few seconds and then you're greeted with the login prompt.
This is a default in Debian. (Actually in modern Debian with systemd,
you probably get the systemd boot messages on your screen, instead of
the kernel log...)
The point is, that if you want the kernel messages back, you should just
erase the word "quiet" from the kernel command line, and use that command
line for just one boot (press "e" in Grub, edit, ctrl+x to continue)
or permanently (edit /etc/default/grub && update-grub).
Now finally to the point: once you have
you also need to add
Such as, in my case,
There are further possible options, see the relevant chapter at Arch wiki.
E.g., you can also specify the color depth,
or apply the mode to just one video output port
(called "connector" in the DRM guts).
Note that your specified mode probably needs to match one of the modes known to the kernel, i.e. one of the "EDID modelines". The kernel keeps a list of these data blocks, obtained either via DDC from a monitor, or from /lib/firmware, or possibly compiled in. I.e., you cannot specify just any odd geometry.
In some howtos, you will find just
video=<xres>x<yres>, such as
This does have the desired effect, in that the resolution does appear
on the output - but you've let the decision on frame rate up to the drivers,
which tend to pick the highest possible frame rate (among the "mode lines"
available in the set of EDID blocks). Such as, in my case it has turned out
that the driver chose
1024x768@85, which would've been a nice choice back in the CRT era, but is sorely out of range for many today's LCD's. Note that cheap modern LCD's (before FreeSync) typically take a 60 Hz frame rate, so this is what you need to set explicitly, if your DDC is absent or bonkers.
During my search for some answers, I kept stumbling over references to this patch set by Dave Airlie - which brings the video= cmdline arg processing. It turns out that this has been merged into vanilla Linux some years ago.
In my case, the monitor was driven by 1600x1200 and was reporting "out of range" because it couldn't cope. As I was trying various cmdline arguments,
I tried just
video=1024x768, which resulted in "out of range" on the monitor.
On the outside, by the vague error message, it seemd that the cmdline arg
had no effect at all. Only later I found out that all I was missing was an
@60 suffix :-)
The interesting bit here is, how I found out.
There's another kernel cmdline arg that makes the DRI/DRM subsystem
print a more chatty debug log:
kernel version less than 4.1:
kernel version 4.1 or newer:
I'm attaching an example debug log from my machine.
Things to focus on (keywords to search for):
Kernel command line,
The "connector names" can be gleaned from here:
and note that the video=... cmdline arg syntax does not take the
"card-" prefix that you can see in /sys/class/drm .
The syntax of video= and connector names is described in some detail
in a relevant chapter of the Arch Linux wiki.
Now let me shift gears / change the topic a bit.
The original question in this thread was, how to modify the video mode geometry.
I've done this before in X and in Windows (using the late Intel IEGD).
In Linux under kvm+drm, the only way to tweak geometry and timing
is apparently by handing in your own EDID file, which you first
have to hand-craft. Well almost.
The EDID construction is briefly described in one snippet of documentation included with the vanilla kernel source.
The Makefile and the example EDID definitions live in its parent directory.
Select some .S as an example, copy to your own file
(see the naming convention on top of the Makefile),
edit the timings, build your EDID binary and...
hopefully it solves your problem :-)
The timings / pixel counts take some maths to get right.
And, there are several alternative historical standards that
you'd better adhere to and that are in conflict with each other
(they're evolution stages of display timing standards):
- the CRT-era
- the LCD-era
- and then
CVT-RB (reduced blanking).
Either you can calculate the numbers by hand, or there are some tools and tables of standard modes.
Try googling for "EDID calculator" or "modeline calculator" or some such. There's even a neat Linux command-line tool
for the job.
See also the modeline database
Your particular problem could possibly be solved by shifting
the HSYNC pulse to the right (you can also try changing its polarity),
or by making the sync pulse and/or the total blanking time
relatively wider, or (as you suggested) by decreasing the
visible/displayed pixel resolution (in multiples of 8).
If you make blanking wider, you may need to increase
the pixel clock, to keep the original frame rate.