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.zygow...@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
_______________________________________________
coreboot mailing list -- coreboot@coreboot.org
To unsubscribe send an email to coreboot-le...@coreboot.org

Reply via email to