gma: Add option for VGA plane on the primary pipe
Add special VGA_PLANE_FRAMEBUFFER_OFFSET that, if set on the primary
pipe, toggles the use of the legacy VGA plane instead of the `hires`
plane.
The caller is responsible for the configuration of the VGA plane and
has to specify the framebuffer width and height accordingly.
Change-Id: I9f678fe033d835c9183fbb2d2b05b6585eb545ca
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/17276
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
diff --git a/common/hw-gfx-gma-pipe_setup.adb b/common/hw-gfx-gma-pipe_setup.adb
index b902b77..1f13c86 100644
--- a/common/hw-gfx-gma-pipe_setup.adb
+++ b/common/hw-gfx-gma-pipe_setup.adb
@@ -47,6 +47,22 @@
SPCNTR_ENABLE : constant := 1 * 2 ** 31;
+ VGA_SR01_SCREEN_OFF : constant := 1 * 2 ** 5;
+
+ VGA_CONTROL_VGA_DISPLAY_DISABLE : constant := 1 * 2 ** 31;
+ VGA_CONTROL_BLINK_DUTY_CYCLE_MASK : constant := 16#0003# * 2 ** 6;
+ VGA_CONTROL_BLINK_DUTY_CYCLE_50 : constant := 2 * 2 ** 6;
+ VGA_CONTROL_VSYNC_BLINK_RATE_MASK : constant := 16#003f# * 2 ** 0;
+
+ subtype VGA_Cycle_Count is Pos32 range 2 .. 128;
+ function VGA_CONTROL_VSYNC_BLINK_RATE
+ (Cycles : VGA_Cycle_Count)
+ return Word32
+ is
+ begin
+ return Word32 (Cycles) / 2 - 1;
+ end VGA_CONTROL_VSYNC_BLINK_RATE;
+
TRANS_CLK_SEL_PORT_NONE : constant := 0 * 2 ** 29;
type TRANS_CLK_SEL_PORT_Array is
@@ -311,9 +327,8 @@
----------------------------------------------------------------------------
- procedure Setup_Display
+ procedure Setup_Hires_Plane
(Controller : in Controller_Type;
- Head : in Head_Type;
Mode : in HW.GFX.Mode_Type;
Framebuffer : in HW.GFX.Framebuffer_Type)
with
@@ -323,7 +338,6 @@
=>+
(Registers.Register_State,
Controller,
- Head,
Mode,
Framebuffer))
is
@@ -341,13 +355,7 @@
begin
pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
- Registers.Write
- (Register => Controller.PIPESRC,
- Value => Encode
- (Pos16 (Framebuffer.Height), Pos16 (Framebuffer.Width)));
-
if Config.Has_Plane_Control then
- Setup_Watermarks (Controller);
Registers.Write
(Register => Controller.PLANE_CTL,
Value => PLANE_CTL_PLANE_ENABLE or
@@ -376,6 +384,57 @@
end if;
Registers.Write (Controller.DSPTILEOFF, 0);
end if;
+ end Setup_Hires_Plane;
+
+ procedure Setup_Display
+ (Controller : in Controller_Type;
+ Head : in Head_Type;
+ Mode : in HW.GFX.Mode_Type;
+ Framebuffer : in HW.GFX.Framebuffer_Type)
+ with
+ Global => (In_Out => (Registers.Register_State, Port_IO.State)),
+ Depends =>
+ (Registers.Register_State
+ =>+
+ (Registers.Register_State,
+ Controller,
+ Head,
+ Mode,
+ Framebuffer),
+ Port_IO.State
+ =>+
+ (Framebuffer))
+ is
+ use type Word8;
+
+ Reg8 : Word8;
+ begin
+ pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
+
+ if Config.Has_Plane_Control then
+ Setup_Watermarks (Controller);
+ end if;
+
+ if Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET then
+ Registers.Unset_And_Set_Mask
+ (Register => Registers.VGACNTRL,
+ Mask_Unset => VGA_CONTROL_VGA_DISPLAY_DISABLE or
+ VGA_CONTROL_BLINK_DUTY_CYCLE_MASK or
+ VGA_CONTROL_VSYNC_BLINK_RATE_MASK,
+ Mask_Set => VGA_CONTROL_BLINK_DUTY_CYCLE_50 or
+ VGA_CONTROL_VSYNC_BLINK_RATE (30));
+
+ Port_IO.OutB (VGA_SR_INDEX, VGA_SR01);
+ Port_IO.InB (Reg8, VGA_SR_DATA);
+ Port_IO.OutB (VGA_SR_DATA, Reg8 and not (VGA_SR01_SCREEN_OFF));
+ else
+ Setup_Hires_Plane (Controller, Mode, Framebuffer);
+ end if;
+
+ Registers.Write
+ (Register => Controller.PIPESRC,
+ Value => Encode
+ (Pos16 (Framebuffer.Height), Pos16 (Framebuffer.Width)));
Registers.Write (Head.HTOTAL, Encode (Mode.H_Visible, Mode.H_Total));
Registers.Write (Head.HBLANK, Encode (Mode.H_Visible, Mode.H_Total));
diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb
index f8b0e7b..c50d943 100644
--- a/common/hw-gfx-gma.adb
+++ b/common/hw-gfx-gma.adb
@@ -192,16 +192,19 @@
begin
-- No downscaling
-- Respect maximum scalable width
- -- Only 32bpp RGB
- -- Stride must be a multiple of 64
+ -- VGA plane is only allowed on the primary pipe
+ -- Only 32bpp RGB (ignored for VGA plane)
+ -- Stride must be a multiple of 64 (ignored for VGA plane)
return
((Framebuffer.Width = Pos32 (Port_Cfg.Mode.H_Visible) and
Framebuffer.Height = Pos32 (Port_Cfg.Mode.V_Visible)) or
(Framebuffer.Width <= Config.Maximum_Scalable_Width (I) and
Framebuffer.Width <= Pos32 (Port_Cfg.Mode.H_Visible) and
Framebuffer.Height <= Pos32 (Port_Cfg.Mode.V_Visible))) and
- Framebuffer.BPC = 8 and
- Framebuffer.Stride mod 64 = 0;
+ (Framebuffer.Offset /= VGA_PLANE_FRAMEBUFFER_OFFSET or I = Primary) and
+ (Framebuffer.Offset = VGA_PLANE_FRAMEBUFFER_OFFSET or
+ (Framebuffer.BPC = 8 and
+ Framebuffer.Stride mod 64 = 0));
end Validate_Config;
procedure Fill_Port_Config
diff --git a/common/hw-gfx-gma.ads b/common/hw-gfx-gma.ads
index 1e64cb4..ed240ca 100644
--- a/common/hw-gfx-gma.ads
+++ b/common/hw-gfx-gma.ads
@@ -58,6 +58,10 @@
type Config_Index is (Primary, Secondary, Tertiary);
type Configs_Type is array (Config_Index) of Config_Type;
+ -- Special framebuffer offset to indicate legacy VGA plane.
+ -- Only valid on primary pipe.
+ VGA_PLANE_FRAMEBUFFER_OFFSET : constant := 16#ffff_ffff#;
+
procedure Initialize
(MMIO_Base : in Word64 := 0;
Write_Delay : in Word64 := 0;