Hi Michal, hi Matt,
On 15.03.20 06:41, Matt B wrote:
You probably want to speak with Nico. He's a libgfxinit expert afaik.
thanks for the heads up :)
On Wed, Mar 11, 2020 at 9:45 AM Michal Zygowski michal.zygowski@3mdeb.com wrote:
Particularly I would like to implement Braswell support for native graphics init with libgfxinit.
Angel is also looking forward to Braswell support. He mentioned it as a possible summer-of-code stretch goal (after Bay Trail support), IIRC. But applications are not written yet (start tomorrow).
I see the programming manuals from Intel
are in place: https://01.org/linuxgraphics/documentation/hardware-specification-prms
Alas, this is a pitfall for Braswell. The only part that matters for libgfxinit (information about the display engine) is 100% scrubbed away. If you look into the `Display` chapter, it only contains legacy VGA registers and audio verbs, nothing about display at all. And if you search for any of "hdmi", "lvds", "mipi", "dsi", or "lane" in the `Register` chapter: nothing :-/
So for Braswell, the only public information source I know is the Linux driver i915. It's the one exception btw. All other chips have a proper `Display` chapter. Hence also the idea to add Bay Trail support first. Even if it turns out to be much different, we could at least tell if Brasswell is closer to Bay Trail or the newer Haswell/Apollo Lake engine.
What do I need to implement a new microarchitecture in libgfxinit? Where to start and what should I focus on?
This may get a little longer... but I knew I'll have to write it down eventually.
In Ada, the code is organized in so called `packages`. In the way they are used in libgfxinit, one can simply see them as compilation units. Each package has a specification (.ads) file with declarations and a body (.adb) with code. Much like a header and a c file. Packages form a hierarchy and the name of the file has to reflect the package name, including its parents (stupid, imho).
Libgfxinit has two major mechanisms in place to support different hardware generations:
1. Alternative implementations of packages. These are organized in sub-directories (also because every alternative package body has to have the same file name). For instance, we have different implementations for the package `HW.GFX.GMA.Connectors` in g45/, ironlake/, haswell_shared/ (the latter is shared with all newer generations since Haswell).
Having alternative implementations of packages also means we can't build one binary that supports all generations. Luckily, we don't have to, so far :)
2. Configuration flags that are tested in shared code. Much like we have `if (CONFIG(FOO_BAR))` in coreboot, we have `if Config.Foo_Bar then` in libgfxinit.
All these flags are gathered in a single package `HW.GFX.GMA.Config` which keeps conditions on specific hardware generations in a central place. The file, `hw-gfx-gma-config.ads.template`, is pre-processed with some sed-foo (see `common/Makefile.inc`). The comment from `hw-gfx-gma-config.ads.template:99` on explains some of the rea- soning.
How much code sharing makes sense depends on the similarity to other hardware generations. I wouldn't be surprised if Bay Trail and Braswell end up using the g45/ code (no PCH and probably pre DDI which was intro- duced with Haswell), but I don't know that yet.
Some more about the central packages:
HW.GFX* (excluding HW.GFX.GMA*) ===============================
There's some vendor-agnostic code around. Mostly for DP training and EDID interpretation.
HW.GFX.GMA ==========
This exposes the primary interface (procedure Update_Outputs()) and contains the overall control flow for setting up displays. Update_Outputs() takes a list of configurations for each graphics pipeline (up to three) and will try to set things up according to the configuration.
Assuming a pipe is unconfigured, roughly the following steps are performed (by procedure Enable_Output()):
* Optionally select a link configuration (e.g. for DP, how many lanes at what rate). * Allocate a PLL for the pixel/DP clock. * Try to train the selected link configuration (if there is none, the loops simply run once): - Prepare output connectors (Pre_On) - Enable the graphics pipeline (On) - Finalize the output-connector configuration (Post_On)
This usually doesn't need changes for new hardware.
HW.GFX.GMA.Pipe_Setup* (formerly Display_Controller) ====================================================
At the heart of the display engine is the pipe setup. Here we configure the framebuffer format (how to interpret bytes from DRAM), image pro- cessing (e.g. scaling) and the `Transcoders` that turn the image into a continuous stream of bits (including blank times) for a given pixel clock. IOW, everything from the framebuffer to a modeline.
This was called `Display_Controller` earlier (probably for historical Linux reasons) and is still inside `hw-gfx-gma.adb` (easy to fix, but I didn't care to so far).
It's mostly configured by flags from the `Config` package. Configu- ration of scalers is often implemented very differently, but most of it didn't change much over the years.
HW.GFX.GMA.Connectors =====================
The `Connectors` package dispatches the Pre_On() and Post_On() calls (before and after configuring the graphics pipeline) to sub-packages for the individual connector types.
This is a bit subtle. In a sense, `Connectors` reflect the outputs of the CPU package. In the first generations with a PCH (Ironlake including Sandy and Ivy Bridge) the CPU didn't have actual display outputs (like VGA, LVDS, HDMI etc.) but only links to the PCH which contained the final outputs. Later, the final outputs went back onto the CPU die. So we have three very different versions of this package:
* g45/ outputs are in the GMCH (or CPU if one would add Bay Trail, it shouldn't matter). * ironlake/ FDI links in the CPU and (most) outputs in the PCH. * haswell_shared/ newer outputs (DDI) in the CPU (no legacy interfaces like VGA/LVDS, and HDMI/DP configuration changed since g45/).
If none of these match the hardware to be added, one would have to write a new one.
HW.GFX.GMA.PLLs ===============
Usually there are some similarities but often changes between hardware generations.
HW.GFX.GMA.Power_And_Clocks ===========================
This started with some setup for generation specific things that didn't find another place. Newer generations have configurable clocks and can turn individual parts of the display engine on and off. Older ones often just have to report a pre-set Core Display Clock (CDClk).
To wrap it up, `Power_And_Clocks` and `PLLs` most often need changes for new hardware. Followed by `Connectors` if these changed significantly, but most often one can add some code controlled by `Config` flags here. And, not to forget, all flags in the `Config` package need to be checked how they should be set for the new hardware.
tl;dr; Haven't written anything in SPARK/Ada yet. It will be a new adventure for me.
Can be fun but can also be exhausting ;) Depends much on how you can cope with nagging compilers and related tools.
Nico
On 15.03.20 20:37, Nico Huber wrote:
On Wed, Mar 11, 2020 at 9:45 AM Michal Zygowski michal.zygowski@3mdeb.com wrote: I see the programming manuals from Intel
are in place: https://01.org/linuxgraphics/documentation/hardware-specification-prms
Alas, this is a pitfall for Braswell. The only part that matters for libgfxinit (information about the display engine) is 100% scrubbed away. If you look into the `Display` chapter, it only contains legacy VGA registers and audio verbs, nothing about display at all. And if you search for any of "hdmi", "lvds", "mipi", "dsi", or "lane" in the `Register` chapter: nothing :-/
Update: There are some register descriptions in the Braswell datasheet vol2. Probably enough for HDMI and (e)DP support.
Nico
Hi Nico,
Thank you for your extensive answer. That helps a lot.
Regarding the registers description, maybe EDS or other documents have better situation? I have Braswell EDS so i can check it, but if you have any documents that describe display registers for Braswell, let me know which ID it is so I can get it myself.
Thanks again.
Best regards,
Hi,
On 16.03.20 13:01, Michal Zygowski wrote:
Regarding the registers description, maybe EDS or other documents have better situation? I have Braswell EDS so i can check it, but if you have any documents that describe display registers for Braswell, let me know which ID it is so I can get it myself.
the EDS looks the same to me as the public datasheet. Intel seems to have a separate document system for the graphics stuff. I never got access there. Though, stopped asking a few years ago, so maybe there is a chance. But you'd have to poke Intel directly about it, I guess.
Nico
Another question about libgfxinit.
Up till Skylake the libgfxinit worked great for me, however after enabling it on a Kaby Lake platform I noticed the colors are flipped. I.e. when using VGA ROM the bootsplash image is correctly displayed in RGB, but when using libgfxinit and hires FB the colors are BGR (the same image is not displayed in same way). Do you possibly know what may the cause?
Michał
On 3/17/20 8:34 PM, Nico Huber wrote:
Hi,
On 16.03.20 13:01, Michal Zygowski wrote:
Regarding the registers description, maybe EDS or other documents have better situation? I have Braswell EDS so i can check it, but if you have any documents that describe display registers for Braswell, let me know which ID it is so I can get it myself.
the EDS looks the same to me as the public datasheet. Intel seems to have a separate document system for the graphics stuff. I never got access there. Though, stopped asking a few years ago, so maybe there is a chance. But you'd have to poke Intel directly about it, I guess.
Nico _______________________________________________ coreboot mailing list -- coreboot@coreboot.org To unsubscribe send an email to coreboot-leave@coreboot.org
Hi Michal,
On 27.03.20 15:49, Michal Zygowski wrote:
Another question about libgfxinit.
Up till Skylake the libgfxinit worked great for me, however after enabling it on a Kaby Lake platform I noticed the colors are flipped. I.e. when using VGA ROM the bootsplash image is correctly displayed in RGB, but when using libgfxinit and hires FB the colors are BGR (the same image is not displayed in same way). Do you possibly know what may the cause?
all I know is that with libgfxinit, so far you get the exact same pixel encoding for every platform (where I tested colors). I think it's BGRX.
What mode do you set with the VGA ROM? In the end it should be reported in a `struct lb_framebuffer` so you could compare the two encodings. Also, the code that loads the picture should write the pixels according to the reported format. Unless somebody took too many shortcuts.
Nico
Thanks for pointers Nico.
I used the same picture laoding code and the same image. The only thing that changed was the graphics initialization: VGA ROM vs libgfxinit.
I have used SeaBIOS with the same bootsplash image. AFAIK it searches for a compatible (for given image resolution) VESA mode and displays the boot splash. The image was a JPG 1024x768 pixels (32bpp I guess).
On 3/27/20 9:35 PM, Nico Huber wrote:
Hi Michal,
On 27.03.20 15:49, Michal Zygowski wrote:
Another question about libgfxinit.
Up till Skylake the libgfxinit worked great for me, however after enabling it on a Kaby Lake platform I noticed the colors are flipped. I.e. when using VGA ROM the bootsplash image is correctly displayed in RGB, but when using libgfxinit and hires FB the colors are BGR (the same image is not displayed in same way). Do you possibly know what may the cause?
all I know is that with libgfxinit, so far you get the exact same pixel encoding for every platform (where I tested colors). I think it's BGRX.
What mode do you set with the VGA ROM? In the end it should be reported in a `struct lb_framebuffer` so you could compare the two encodings. Also, the code that loads the picture should write the pixels according to the reported format. Unless somebody took too many shortcuts.
Nico _______________________________________________ coreboot mailing list -- coreboot@coreboot.org To unsubscribe send an email to coreboot-leave@coreboot.org
On 28.03.20 11:43, Michal Zygowski wrote:
I used the same picture laoding code and the same image. The only thing that changed was the graphics initialization: VGA ROM vs libgfxinit.
If you want to change the encoding (I never tried this) PLANE_CTL bit 20 seems to do the trick. For older generations, 0xe << 26 instead of 0x6 << 26 in PRI_CTL.
I have used SeaBIOS with the same bootsplash image. AFAIK it searches for a compatible (for given image resolution) VESA mode and displays the boot splash. The image was a JPG 1024x768 pixels (32bpp I guess).
Looks like SeaBIOS hard-codes the RGB encoding deep in the jpeg decoder. The macro PIC_32() in `src/jpeg.c`. Would be better to take the frame- buffer format into account there.
Nico
On 3/29/20 1:54 AM, Nico Huber wrote:
On 28.03.20 11:43, Michal Zygowski wrote:
I used the same picture laoding code and the same image. The only thing that changed was the graphics initialization: VGA ROM vs libgfxinit.
If you want to change the encoding (I never tried this) PLANE_CTL bit 20 seems to do the trick. For older generations, 0xe << 26 instead of 0x6 << 26 in PRI_CTL.
I have used SeaBIOS with the same bootsplash image. AFAIK it searches for a compatible (for given image resolution) VESA mode and displays the boot splash. The image was a JPG 1024x768 pixels (32bpp I guess).
Looks like SeaBIOS hard-codes the RGB encoding deep in the jpeg decoder. The macro PIC_32() in `src/jpeg.c`. Would be better to take the frame- buffer format into account there.
If the framebuffer holds information about the decoding, I think this will be better way of handling the issue. At this point it will be quite trivial. IIRC coreboot has the same problem with its jpeg decoder, noticed same color pattern BGR. Thanks again.
Michał
Nico _______________________________________________ coreboot mailing list -- coreboot@coreboot.org To unsubscribe send an email to coreboot-leave@coreboot.org
Hi Nico,
I found some time to get back to the topic and actually I am clueless...
What I have tried:
1. Use libgfxinit to initialize graphics in coreboot and display the bootsplash image in JPG and BMP formats. JPG has the mentioned issue with colors, while BMP doesn't. 2. Compared the libgfxinit provided framebuffer with the one provided by VGA option rom and they are identical. Despite that the JPG bootsplash is displayed differently in coreboot. 3. Used VGA option rom to initialize graphics and display the bootsplash in coreboot and SeaBIOS as well. What surprised me is that coreboot displayed the bootsplash incorrectly (the same color issues as with libgfxinit) while SeaBIOS displayed it with the expected colors.
Now the only thing that comes to my mind are the VGA interrupts, because SeaBIOS has more complete interrupt services than coreboot. Any comments or suggestions on that? I think my next step would be to trace all INT 10h and compare the differences and fix it possibly in SeaVGABIOS.
Thanks in advance.
Regards,
Hi Michal,
On 22.06.20 10:29, Michal Zygowski wrote:
- Used VGA option rom to initialize graphics and display the bootsplash
in coreboot and SeaBIOS as well. What surprised me is that coreboot displayed the bootsplash incorrectly (the same color issues as with libgfxinit) while SeaBIOS displayed it with the expected colors.
are you 100% sure that it's the same mode? AIUI, SeaBIOS would automati- cally pick one at runtime, should be visible in the log which.
Now the only thing that comes to my mind are the VGA interrupts, because SeaBIOS has more complete interrupt services than coreboot. Any comments or suggestions on that? I think my next step would be to trace all INT 10h and compare the differences and fix it possibly in SeaVGABIOS.
Not sure what you are up to. Libgfxinit sets a specific mode. After that is set, SeaVGABIOS can't change it, only report the mode info. And if SeaBIOS' JPEG parser ignores the info, it doesn't matter what SeaVGABIOS reports.
Nico
Hi Nico,
On 22.06.2020 23:40, Nico Huber wrote:
Hi Michal,
On 22.06.20 10:29, Michal Zygowski wrote:
- Used VGA option rom to initialize graphics and display the bootsplash
in coreboot and SeaBIOS as well. What surprised me is that coreboot displayed the bootsplash incorrectly (the same color issues as with libgfxinit) while SeaBIOS displayed it with the expected colors.
are you 100% sure that it's the same mode? AIUI, SeaBIOS would automati- cally pick one at runtime, should be visible in the log which.
I have set VESA mode 1024x768 16.8M-color (8:8:8) in coreboot when using option ROM (the same resolution and colors as my bootsplash). It seems that SeaBIOS picks different mode then... I will check with the debug output as you suggest.
Now the only thing that comes to my mind are the VGA interrupts, because SeaBIOS has more complete interrupt services than coreboot. Any comments or suggestions on that? I think my next step would be to trace all INT 10h and compare the differences and fix it possibly in SeaVGABIOS.
Not sure what you are up to. Libgfxinit sets a specific mode. After that is set, SeaVGABIOS can't change it, only report the mode info. And if SeaBIOS' JPEG parser ignores the info, it doesn't matter what SeaVGABIOS reports.
Okay, I see. How do I know which mode is set by libgfxinit?
Nico _______________________________________________ coreboot mailing list -- coreboot@coreboot.org To unsubscribe send an email to coreboot-leave@coreboot.org
Best regards,
On 23.06.20 16:51, Michal Zygowski wrote:
Now the only thing that comes to my mind are the VGA interrupts, because SeaBIOS has more complete interrupt services than coreboot. Any comments or suggestions on that? I think my next step would be to trace all INT 10h and compare the differences and fix it possibly in SeaVGABIOS.
Not sure what you are up to. Libgfxinit sets a specific mode. After that is set, SeaVGABIOS can't change it, only report the mode info. And if SeaBIOS' JPEG parser ignores the info, it doesn't matter what SeaVGABIOS reports.
Okay, I see. How do I know which mode is set by libgfxinit?
The resolution will be picked according to the attached monitors (either native resolution or lower if another monitor has lower resolution). The color format is currently hardcoded: 32-bit BGRX, or in terms of coreboot's `struct lb_framebuffer`:
bits_per_pixel => 32, reserved_mask_pos => 24, reserved_mask_size => 8, red_mask_pos => 16, red_mask_size => 8, green_mask_pos => 8, green_mask_size => 8, blue_mask_pos => 0, blue_mask_size => 8);
Nico
Hi Nico,
On 6/23/20 7:55 PM, Nico Huber wrote:
On 23.06.20 16:51, Michal Zygowski wrote:
Now the only thing that comes to my mind are the VGA interrupts, because SeaBIOS has more complete interrupt services than coreboot. Any comments or suggestions on that? I think my next step would be to trace all INT 10h and compare the differences and fix it possibly in SeaVGABIOS.
Not sure what you are up to. Libgfxinit sets a specific mode. After that is set, SeaVGABIOS can't change it, only report the mode info. And if SeaBIOS' JPEG parser ignores the info, it doesn't matter what SeaVGABIOS reports.
Okay, I see. How do I know which mode is set by libgfxinit?
The resolution will be picked according to the attached monitors (either native resolution or lower if another monitor has lower resolution). The color format is currently hardcoded: 32-bit BGRX, or in terms of coreboot's `struct lb_framebuffer`:
bits_per_pixel => 32, reserved_mask_pos => 24, reserved_mask_size => 8, red_mask_pos => 16, red_mask_size => 8, green_mask_pos => 8, green_mask_size => 8, blue_mask_pos => 0, blue_mask_size => 8);
Nico
Thank you. It looks like I can't use JPG bootsplash with libgfxinit, because it requires 16bpp mode (according to SeaBIOS logs). A workaround I have found is to convert it to BMP, then it uses 32bpp and everything is allright.
But for example, when VGA option rom is used, SeaBIOS finds the mode it fits the bootsplash resolution and bpp. Additionaly the display area is adjusted to cover whole screen, i.e. when using 1024x768 bootsplash on 1920x1080 screen the bootsplash covers whole screen, while in libgfxinit it is centered leaving unused bars on the both sides of the screen. Any ideas how to improve that?
Best regards,
Michal Zygowski wrote:
when VGA option rom is used, SeaBIOS finds the mode it fits the bootsplash resolution and bpp. Additionaly the display area is adjusted to cover whole screen, i.e. when using 1024x768 bootsplash on 1920x1080 screen the bootsplash covers whole screen,
Stretching the graphic e.g. from 4:3 to 16:9 as in your example makes it appear distorted - stretched wide, right? Is that really desirable?
If yes, you would have to implement a bitmap scaler in coreboot/libgfxinit.
//Peter
On 24.06.20 15:25, Peter Stuge wrote:
Michal Zygowski wrote:
when VGA option rom is used, SeaBIOS finds the mode it fits the bootsplash resolution and bpp. Additionaly the display area is adjusted to cover whole screen, i.e. when using 1024x768 bootsplash on 1920x1080 screen the bootsplash covers whole screen,
Stretching the graphic e.g. from 4:3 to 16:9 as in your example makes it appear distorted - stretched wide, right? Is that really desirable?
If yes, you would have to implement a bitmap scaler in coreboot/libgfxinit.
libgfxinit can have the hardware scale the image, but it won't stretch it. You can use
config LINEAR_FRAMEBUFFER_MAX_WIDTH and config LINEAR_FRAMEBUFFER_MAX_HEIGHT
to reduce the framebuffer resolution, then the image would be scaled to fit in height, but with a pillarbox.
Nico
Hi Nico, Peter,
On 6/24/20 8:50 PM, Nico Huber wrote:
On 24.06.20 15:25, Peter Stuge wrote:
Michal Zygowski wrote:
when VGA option rom is used, SeaBIOS finds the mode it fits the bootsplash resolution and bpp. Additionaly the display area is adjusted to cover whole screen, i.e. when using 1024x768 bootsplash on 1920x1080 screen the bootsplash covers whole screen,
Stretching the graphic e.g. from 4:3 to 16:9 as in your example makes it appear distorted - stretched wide, right? Is that really desirable?
If yes, you would have to implement a bitmap scaler in coreboot/libgfxinit.
As Nico mentioned below, it looks like a pillarbox. Imagine GRUB graphical menu which starts automatically at 800x600 as a tiny box inside this pillarbox. Even more weird. Yes it is stretched, but it doesn't look that awful. I am more concerned about this weird resolution switches. One will have different max resolution display and everything will fall apart and look differently. AFAIK libgfxinit reads out the display information (EDID right?) so it is possible to calculate the scalers. Peter could you elaborate a little bit more about the bitmap scalers? What would it take to implement that?
libgfxinit can have the hardware scale the image, but it won't stretch it. You can use
config LINEAR_FRAMEBUFFER_MAX_WIDTH and config LINEAR_FRAMEBUFFER_MAX_HEIGHT
to reduce the framebuffer resolution, then the image would be scaled to fit in height, but with a pillarbox.
Indeed this is what I have currently. I have limited the resolution with these options to fit the bootsplash.
Libgfxinit is very cool when one has a built-in display like in a laptop, then the max resolution may be the same all the time. However for desktops the user experience for desktops with varying display types, it is not that beautiful. Personally I don't care that much about it, because I can always rebuild the coreboot, set the framebuffer resolution I need for my display and set GRUB gfx resolution to match my display. However, the problem occurs when I would like to offer more open silicon initialization by getting rid of closed VGA option rom. Of course I also would like to preserve the user experience I had previously (or even better).
Best regards,
Hi Michal,
On 25.06.20 10:56, Michal Zygowski wrote:
One will have different max resolution display and everything will fall apart and look differently. AFAIK libgfxinit reads out the display information (EDID right?) so it is possible to calculate the scalers.
that's one use case for below options. If you set them, the framebuffer resolution will not grow above that. It may be limited by a lower reso- lution display, but then a bootsplash wouldn't fit either. libgfxinit calculates scaling such that the aspect ratio is maintained. I guess you could patch that code out or we could make it optional if need be. But stretching an image doesn't feel right. You can also avoid/reduce the pillars by choosing a more modern aspect ratio, e.g. 1280x800?
config LINEAR_FRAMEBUFFER_MAX_WIDTH and config LINEAR_FRAMEBUFFER_MAX_HEIGHT
Libgfxinit is very cool when one has a built-in display like in a laptop, then the max resolution may be the same all the time. However for desktops the user experience for desktops with varying display types, it is not that beautiful. Personally I don't care that much about it, because I can always rebuild the coreboot, set the framebuffer resolution I need for my display and set GRUB gfx resolution to match my display. However, the problem occurs when I would like to offer more open silicon initialization by getting rid of closed VGA option rom. Of course I also would like to preserve the user experience I had previously (or even better).
If you want a full-legacy experience, I suggest to look into integrating libgfxinit into SeaVGABIOS. I never did, because I don't use any kind of legacy boot. Once you disabled all boot menus, it won't matter how they would look like (probably odd on my 24:10 screen).
There are also things that your programs could do better. GRUB for instance can be configured to use the full resolution. It's just its default configurations that expect to be able to switch to a random one. The 1980s clashing with 2020 ;)
Nico