Add linux user-space app `gfx_test`
This simple program scans all ports and configures pipes for the first three available displays. It presumes that there is enough framebuffer mapped for all pipes and fills it with test images. The only command line parameter ist the path to a PCI-device node in sysfs. On exit, the hardware is left in the configured state. So the user has to make sure, that he either can work without the gfx hard- ware or has another driver to restore a working state. Change-Id: I2144300589e113e711db7959aa68fa96c3844568 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/18786 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
3586101e0b
commit
1d0abe468b
10
Makefile
10
Makefile
|
@ -1,6 +1,16 @@
|
|||
name := gfxinit
|
||||
|
||||
ifeq ($(MAKECMDGOALS),gfx_test)
|
||||
prefixed-name := gfx_test
|
||||
link-type := program
|
||||
GFXINIT_TEST := y
|
||||
endif
|
||||
|
||||
gfxinit-deplibs := libhw
|
||||
|
||||
libhw-dir ?= ../libhwbase/dest
|
||||
include $(libhw-dir)/Makefile
|
||||
|
||||
gfx_test: $(binary)
|
||||
|
||||
.PHONY: gfx_test
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
subdirs-y += common
|
||||
|
||||
subdirs-$(GFXINIT_TEST) += gfxtest
|
||||
|
|
2
TODO
2
TODO
|
@ -5,3 +5,5 @@ unknown DP honor SINK_STATUS after training
|
|||
low LVDS 8bit colors, data format???
|
||||
|
||||
medium SKL check if DPLL_CTRL2 really defaults to `Clock Off` => 0
|
||||
|
||||
medium gfxtest take care of our own framebuffer mapping
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
gfxinit-y += gfx_test.adb
|
||||
gfxinit-y += gfx_test.ads
|
||||
|
||||
gfxinit-main-y = gfx_test_main.adb
|
|
@ -0,0 +1,215 @@
|
|||
with System.Storage_Elements;
|
||||
with Ada.Command_Line;
|
||||
with Interfaces.C;
|
||||
|
||||
with HW.File;
|
||||
with HW.Debug;
|
||||
with HW.GFX.GMA;
|
||||
with HW.GFX.GMA.Display_Probing;
|
||||
|
||||
use HW;
|
||||
use HW.GFX;
|
||||
|
||||
package body GFX_Test is
|
||||
|
||||
MMIO_Size : constant := 2 * 1024 * 1024;
|
||||
subtype MMIO_Range is Natural range 0 .. MMIO_Size - 1;
|
||||
subtype MMIO_Buffer is Buffer (MMIO_Range);
|
||||
MMIO_Dummy : MMIO_Buffer
|
||||
with
|
||||
Alignment => 16#1000#,
|
||||
Volatile;
|
||||
|
||||
type Pixel_Type is record
|
||||
Red : Byte;
|
||||
Green : Byte;
|
||||
Blue : Byte;
|
||||
Alpha : Byte;
|
||||
end record;
|
||||
|
||||
for Pixel_Type use record
|
||||
Blue at 0 range 0 .. 7;
|
||||
Green at 1 range 0 .. 7;
|
||||
Red at 2 range 0 .. 7;
|
||||
Alpha at 3 range 0 .. 7;
|
||||
end record;
|
||||
|
||||
Max_W : constant := 4096;
|
||||
Max_H : constant := 2160;
|
||||
FB_Align : constant := 16#0004_0000#;
|
||||
type Screen_Type is
|
||||
array (0 .. 3 * (Max_W * Max_H + FB_Align / 4) - 1) of Pixel_Type;
|
||||
|
||||
Screen : Screen_Type
|
||||
with
|
||||
Alignment => 16#1000#,
|
||||
Volatile;
|
||||
|
||||
Pipes : GMA.Pipe_Configs;
|
||||
|
||||
function Fill
|
||||
(X, Y : Natural;
|
||||
Framebuffer : Framebuffer_Type;
|
||||
Pipe : GMA.Pipe_Index)
|
||||
return Pixel_Type
|
||||
is
|
||||
use type HW.Byte;
|
||||
|
||||
Xp : constant Natural := X * 256 / Natural (Framebuffer.Width);
|
||||
Yp : constant Natural := Y * 256 / Natural (Framebuffer.Height);
|
||||
Xn : constant Natural := 255 - Xp;
|
||||
Yn : constant Natural := 255 - Yp;
|
||||
|
||||
function Map (X, Y : Natural) return Byte is
|
||||
begin
|
||||
return Byte (X * Y / 255);
|
||||
end Map;
|
||||
begin
|
||||
return
|
||||
(case Pipe is
|
||||
when GMA.Primary => (Map (Xn, Yn), Map (Xp, Yn), Map (Xp, Yp), 255),
|
||||
when GMA.Secondary => (Map (Xn, Yp), Map (Xn, Yn), Map (Xp, Yn), 255),
|
||||
when GMA.Tertiary => (Map (Xp, Yp), Map (Xn, Yp), Map (Xn, Yn), 255));
|
||||
end Fill;
|
||||
|
||||
procedure Test_Screen
|
||||
(Framebuffer : Framebuffer_Type;
|
||||
Pipe : GMA.Pipe_Index)
|
||||
is
|
||||
use type HW.Word32;
|
||||
P : Pixel_Type;
|
||||
-- We have pixel offset wheras the framebuffer has a byte offset
|
||||
Offset_Y : Natural := Natural (Framebuffer.Offset / 4);
|
||||
Offset : Natural;
|
||||
begin
|
||||
for Y in 0 .. Natural (Framebuffer.Height) - 1 loop
|
||||
Offset := Offset_Y;
|
||||
for X in 0 .. Natural (Framebuffer.Width) - 1 loop
|
||||
if Y mod 16 = 0 or X mod 16 = 0 then
|
||||
P := (0, 0, 0, 0);
|
||||
else
|
||||
P := Fill (X, Y, Framebuffer, Pipe);
|
||||
end if;
|
||||
Screen (Offset) := P;
|
||||
Offset := Offset + 1;
|
||||
end loop;
|
||||
Offset_Y := Offset_Y + Natural (Framebuffer.Stride);
|
||||
end loop;
|
||||
end Test_Screen;
|
||||
|
||||
procedure Calc_Framebuffer
|
||||
(FB : out Framebuffer_Type;
|
||||
Mode : in Mode_Type;
|
||||
Offset : in out Word32)
|
||||
is
|
||||
use type HW.Int32;
|
||||
use type HW.Word32;
|
||||
begin
|
||||
Offset := (Offset + FB_Align - 1) and not (FB_Align - 1);
|
||||
FB :=
|
||||
(Width => Width_Type (Mode.H_Visible),
|
||||
Height => Height_Type (Mode.V_Visible),
|
||||
BPC => 8,
|
||||
Stride => Width_Type ((Word32 (Mode.H_Visible) + 15) and not 15),
|
||||
Offset => Offset);
|
||||
Offset := Offset + Word32 (FB.Stride * FB.Height * 4);
|
||||
end Calc_Framebuffer;
|
||||
|
||||
procedure Prepare_Configs
|
||||
is
|
||||
use type HW.GFX.GMA.Port_Type;
|
||||
|
||||
Offset : HW.Word32 := 0;
|
||||
begin
|
||||
GMA.Display_Probing.Scan_Ports (Pipes);
|
||||
|
||||
for Pipe in GMA.Pipe_Index loop
|
||||
if Pipes (Pipe).Port /= GMA.Disabled then
|
||||
Calc_Framebuffer
|
||||
(FB => Pipes (Pipe).Framebuffer,
|
||||
Mode => Pipes (Pipe).Mode,
|
||||
Offset => Offset);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
GMA.Dump_Configs (Pipes);
|
||||
end Prepare_Configs;
|
||||
|
||||
procedure Print_Usage is
|
||||
begin
|
||||
Debug.Put_Line
|
||||
("Usage: " & Ada.Command_Line.Command_Name & " <sysfs-pci-path>");
|
||||
Debug.New_Line;
|
||||
end Print_Usage;
|
||||
|
||||
procedure Main
|
||||
is
|
||||
use System.Storage_Elements;
|
||||
|
||||
use type HW.GFX.GMA.Port_Type;
|
||||
use type Interfaces.C.int;
|
||||
|
||||
MMIO_Mapped,
|
||||
Screen_Mapped,
|
||||
Initialized : Boolean;
|
||||
|
||||
function iopl (level : Interfaces.C.int) return Interfaces.C.int;
|
||||
pragma Import (C, iopl, "iopl");
|
||||
begin
|
||||
if Ada.Command_Line.Argument_Count /= 1 then
|
||||
Print_Usage;
|
||||
return;
|
||||
end if;
|
||||
|
||||
if iopl (3) /= 0 then
|
||||
Debug.Put_Line ("Failed to change i/o privilege level.");
|
||||
return;
|
||||
end if;
|
||||
|
||||
File.Map
|
||||
(Path => Ada.Command_Line.Argument (1) & "/resource0",
|
||||
Addr => Word64 (To_Integer (MMIO_Dummy'Address)),
|
||||
Len => MMIO_Dummy'Size / 8,
|
||||
Readable => True,
|
||||
Writable => True,
|
||||
Success => MMIO_Mapped);
|
||||
if not MMIO_Mapped then
|
||||
Debug.Put_Line
|
||||
("Failed to map '" & Ada.Command_Line.Argument (1) & "/resource0'.");
|
||||
return;
|
||||
end if;
|
||||
|
||||
File.Map
|
||||
(Path => Ada.Command_Line.Argument (1) & "/resource2",
|
||||
Addr => Word64 (To_Integer (Screen'Address)),
|
||||
Len => Screen'Size / 8,
|
||||
Readable => True,
|
||||
Writable => True,
|
||||
Success => Screen_Mapped);
|
||||
if not Screen_Mapped then
|
||||
Debug.Put_Line
|
||||
("Failed to map '" & Ada.Command_Line.Argument (1) & "/resource2'.");
|
||||
return;
|
||||
end if;
|
||||
|
||||
GMA.Initialize
|
||||
(MMIO_Base => Word64 (To_Integer (MMIO_Dummy'Address)),
|
||||
Clean_State => True,
|
||||
Success => Initialized);
|
||||
|
||||
if Initialized then
|
||||
Prepare_Configs;
|
||||
|
||||
GMA.Update_Outputs (Pipes);
|
||||
|
||||
for Pipe in GMA.Pipe_Index loop
|
||||
if Pipes (Pipe).Port /= GMA.Disabled then
|
||||
Test_Screen
|
||||
(Framebuffer => Pipes (Pipe).Framebuffer,
|
||||
Pipe => Pipe);
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end Main;
|
||||
|
||||
end GFX_Test;
|
|
@ -0,0 +1,5 @@
|
|||
package GFX_Test is
|
||||
|
||||
procedure Main;
|
||||
|
||||
end GFX_Test;
|
|
@ -0,0 +1,6 @@
|
|||
with GFX_Test;
|
||||
|
||||
procedure GFX_Test_Main is
|
||||
begin
|
||||
GFX_Test.Main;
|
||||
end GFX_Test_Main;
|
Loading…
Reference in New Issue