gma: Add Intel i945 (Gen3) graphics init support
Add i945G (desktop) and i945GM (mobile) generation support, modeled
after the existing G45 generation code with hardware-specific
adaptations based on the Linux i915 DRM driver and coreboot.
Key hardware differences from G45 (Gen4):
- GTT on separate PCI BAR3 (not within BAR0)
- Simple 32-bit GTT PTEs (addr[31:12] | valid[0])
- No DSPSURF register (uses DSPADDR/DSPLINOFF instead)
- Gen3 fence registers: 32-bit at split 0x2000/0x3000 addresses
- Different PLL limits (VCO 1400-2800 MHz, 96 MHz refclk)
- SDVO multiplier in DPLL register bits[7:4]
- LVDS restricted to Pipe B (pre-i965 requirement)
- CDClk: fixed 400 MHz (desktop) or GCFGC-based (mobile)
- No HDMI/DP, only VGA, LVDS, and SDVO outputs
- PCI IDs: 0x2772 (I945G), 0x27a2/0x27ae (I945GM)
TESTED with thinkpad x60: LVDS & VGA works with a linear framebuffer.
Change-Id: Ib67b3d0ee5e06df427869dce4db926ba57a80fd8
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/476
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: Nico Huber <nico.h@gmx.de>
diff --git a/common/hw-gfx-gma-config.ads.template b/common/hw-gfx-gma-config.ads.template
index dd6c2f8..2c859c5 100644
--- a/common/hw-gfx-gma-config.ads.template
+++ b/common/hw-gfx-gma-config.ads.template
@@ -18,6 +18,7 @@
CPU_First : constant CPU_Type :=
(case Gen is
+ when I945 => I945G,
when G45 => G45,
when Ironlake => Ironlake,
when Haswell => Haswell,
@@ -26,6 +27,7 @@
when Tigerlake => Tigerlake);
CPU_Last : constant CPU_Type :=
(case Gen is
+ when I945 => I945GM,
when G45 => GM45,
when Ironlake => Ivybridge,
when Haswell => Broadwell,
@@ -45,6 +47,7 @@
PCH_First : constant PCH_Type :=
(case Gen is
+ when I945 => No_PCH,
when G45 => No_PCH,
when Ironlake => Ibex_Peak,
when Haswell => Lynx_Point,
@@ -53,6 +56,7 @@
when Tigerlake => Tiger_Point);
PCH_Last : constant PCH_Type :=
(case Gen is
+ when I945 => No_PCH,
when G45 => No_PCH,
when Ironlake => Cougar_Point,
when Haswell => Lynx_Point,
@@ -85,8 +89,8 @@
-- the CDClk rate. To ease proofs, we limit CDClk's range.
CDClk_Min : constant Frequency_Type :=
(case Gen is
- when G45 .. Ironlake => Frequency_Type'First * 100 / 90 + 1,
- when others => Frequency_Type'First);
+ when I945 .. Ironlake => Frequency_Type'First * 100 / 90 + 1,
+ when others => Frequency_Type'First);
subtype CDClk_Range is Frequency_Type range CDClk_Min .. Frequency_Type'Last;
----------------------------------------------------------------------------
@@ -137,6 +141,7 @@
-- To ease parsing, all multiline expressions of tagged config
-- values start after a line break.
+ Gen_I945 : <genbool> := Gen = I945;
Gen_G45 : <genbool> := Gen = G45;
Gen_Ironlake : <genbool> := Gen = Ironlake;
Gen_Haswell : <genbool> := Gen = Haswell;
@@ -144,13 +149,16 @@
Gen_Skylake : <genbool> := Gen = Skylake;
Gen_Tigerlake : <genbool> := Gen = Tigerlake;
+ Up_To_G45 : <genbool> := Gen <= G45;
Up_To_Ironlake : <genbool> := Gen <= Ironlake;
+ G45_On : <genbool> := Gen >= G45;
Ironlake_On : <genbool> := Gen >= Ironlake;
Haswell_On : <genbool> := Gen >= Haswell;
Broxton_On : <genbool> := Gen >= Broxton;
Skylake_On : <genbool> := Gen >= Skylake;
Tigerlake_On : <genbool> := Gen >= Tigerlake;
+ GMCH_I945GM : <i945bool> := Gen_I945 and then CPU = I945GM;
GMCH_GM45 : <g45bool> := Gen_G45 and then CPU = GM45;
CPU_Ironlake : <ilkbool> := Gen_Ironlake and then CPU = Ironlake;
CPU_Sandybridge : <ilkbool> := Gen_Ironlake and then CPU = Sandybridge;
@@ -185,7 +193,7 @@
Have_DVI_I : constant Boolean := Analog_I2C_Port /= PCH_DAC;
- Has_Presence_Straps : <genbool> := not Gen_Broxton;
+ Has_Presence_Straps : <genbool> := not Gen_Broxton and not Gen_I945;
Is_ULT : <hswskltglbool> :=
((Gen_Haswell or Gen_Skylake or Gen_Tigerlake) and then CPU_Var = ULT);
Is_ULX : <hswskltglbool> :=
@@ -194,7 +202,7 @@
---------- CPU pipe: ---------
Has_Tertiary_Pipe : <ilkbool> := Ivybridge_On;
- Disable_Trickle_Feed : <genbool> := not Gen_Haswell;
+ Disable_Trickle_Feed : <genbool> := not Gen_Haswell and not Gen_I945;
Pipe_Enabled_Workaround : <hswbool> := CPU_Broadwell;
Has_EDP_Transcoder : <genbool> := Haswell_On and not Tigerlake_On;
Use_PDW_For_EDP_Scaling : <hswbool> := CPU_Haswell;
@@ -205,12 +213,13 @@
Has_Pipeconf_BPC : <hswbool> := not CPU_Haswell;
Has_Plane_Control : <genbool> := Broxton_On;
Has_DSP_Linoff : <genbool> := Up_To_Ironlake;
+ Has_DSPSURF : <genbool> := G45_On;
Has_PF_Pipe_Select : <ilkhswbool> := CPU_Ivybridge or CPU_Haswell;
Has_Ivybridge_Cursors : <ilkbool> := Ivybridge_On;
VGA_Plane_Workaround : <ilkbool> := CPU_Ivybridge;
Has_GMCH_DP_Transcoder : <genbool> := Gen_G45;
- Has_GMCH_VGACNTRL : <genbool> := Gen_G45;
- Has_GMCH_PFIT_CONTROL : <genbool> := Gen_G45;
+ Has_GMCH_VGACNTRL : <genbool> := Up_To_G45;
+ Has_GMCH_PFIT_CONTROL : <genbool> := Up_To_G45;
----------- Transcoder -------
Need_Early_Transcoder_Setup : <genbool> := Tigerlake_On;
@@ -246,8 +255,19 @@
Has_FDI_RX_Power_Down : <genbool> := Gen_Haswell;
---------- Clocks: -----------
- Has_GMCH_RawClk : <genbool> := Gen_G45;
+ Has_GMCH_RawClk : <genbool> := Up_To_G45;
Has_GMCH_Mobile_VCO : <g45bool> := GMCH_GM45;
+
+ ---------- I945-specific: ----
+ Has_I945_GTT_BAR : <genbool> := Gen_I945;
+ Has_I945_Simple_GTT_PTE : <genbool> := Gen_I945;
+ Has_Gen3_Fences : <genbool> := Gen_I945;
+ -- Pre-i965: LVDS encoder can only source from Pipe B (Secondary)
+ LVDS_Needs_Pipe_B : <genbool> := Gen_I945;
+ -- Pre-Gen5: DSPCNTR has a pipe select field (bits 25:24)
+ Has_DSPCNTR_Pipe_Select : <genbool> := Up_To_G45;
+ -- Gen3: Plane A feeds Pipe B, Plane B feeds Pipe A (for FBC + LVDS)
+ Planes_Pipes_Swapped : <genbool> := Gen_I945;
Has_Broadwell_CDClk : <hswbool> := CPU_Broadwell;
Can_Switch_CDClk : <hswbool> := Broadwell_On;
Has_Fractional_RawClk : <genbool> := Cannon_Point_On;
@@ -283,6 +303,7 @@
Ungate_GMBUS_Unit_Level : <genbool> := Skylake_On and not Tigerlake_On;
GMBUS_Alternative_Pins : <genbool> := Gen_Broxton or Cannon_Point_On;
Has_PCH_GMBUS : <genbool> := Ironlake_On;
+ Has_GMCH_GMBUS : <genbool> := Up_To_G45;
----------- Power: -----------
Has_IPS : <hswbool> :=
@@ -344,8 +365,9 @@
----------------------------------------------------------------------------
- Default_CDClk_Freq : <ilkhswvar> CDClk_Range :=
- (if Gen_G45 then 320_000_000 -- unused
+ Default_CDClk_Freq : <i945ilkhswvar> CDClk_Range :=
+ (if Gen_I945 then 200_000_000 -- unused, depends on GCFGC
+ elsif Gen_G45 then 320_000_000 -- unused
elsif CPU_Ironlake then 450_000_000
elsif CPU_Sandybridge or CPU_Ivybridge then 400_000_000
elsif Gen_Haswell and then Is_ULX then 337_500_000
@@ -356,7 +378,8 @@
else CDClk_Range'First);
Default_RawClk_Freq : <hswvar> Frequency_Type :=
- (if Gen_G45 then 100_000_000 -- unused, depends on FSB
+ (if Gen_I945 then 100_000_000 -- unused, depends on FSB
+ elsif Gen_G45 then 100_000_000 -- unused, depends on FSB
elsif Gen_Ironlake then 125_000_000
elsif Gen_Haswell then (if Is_LP then 24_000_000 else 125_000_000)
elsif Gen_Broxton then Frequency_Type'First -- none needed
@@ -372,7 +395,7 @@
type Width_Per_Pipe is array (Pipe_Index) of Width_Type;
Maximum_Scalable_Width : <hswvar> Width_Per_Pipe :=
- (if Gen_G45 then -- TODO: Is this true?
+ (if Gen_I945 or Gen_G45 then
(Primary => 4096,
Secondary => 2048,
Tertiary => Pos32'First)
@@ -388,7 +411,7 @@
-- Maximum X position of hardware cursors
Maximum_Cursor_X : constant :=
(case Gen is
- when G45 .. Ironlake => 4095,
+ when I945 .. Ironlake => 4095,
when Haswell .. Tigerlake => 8191);
Maximum_Cursor_Y : constant := 4095;
@@ -398,7 +421,7 @@
-- FIXME: Unknown for Broxton, Linux' i915 contains a fixme too :-D
HDMI_Max_Clock_24bpp : constant Frequency_Type :=
(case Gen is
- when Generation'First .. G45 => 165_000_000,
+ when Generation'First .. G45 => 165_000_000, -- i945: no HDMI, moot
when Ironlake => 225_000_000,
when Haswell .. Skylake => 300_000_000,
when Tigerlake .. Generation'Last => 600_000_000);
@@ -412,8 +435,10 @@
GTT_PTE_Size : <hswvar> Natural := (if Has_64bit_GTT then 8 else 4);
- Fence_Base : <ilkvar> Natural :=
- (if not Sandybridge_On then 16#0000_3000# else 16#0010_0000#);
+ Fence_Base : <i945ilkvar> Natural :=
+ (if Gen_I945 then 16#0000_2000#
+ elsif not Sandybridge_On then 16#0000_3000#
+ else 16#0010_0000#);
Fence_Count : <ilkvar> Natural :=
(if not Ivybridge_On then 16 else 32);
@@ -560,6 +585,8 @@
function Is_GPU (Device_Id : Word16; CPU : CPU_Type; CPU_Var : CPU_Variant)
return Boolean is
(case CPU is
+ when I945G => Device_Id = 16#2772#,
+ when I945GM => Device_Id = 16#27a2# or Device_Id = 16#27ae#,
when G45 => (Device_Id and 16#ff02#) = 16#2e02#,
when GM45 => (Device_Id and 16#fffe#) = 16#2a42#,
when Ironlake => (Device_Id and 16#fff3#) = 16#0042#,