gma g45: Add support for Intel GM965 (Crestline)
Add GM965 as a new CPU type under the G45 generation. GM965 shares
the GMCH display architecture with G45/GM45 (no PCH, same connector
registers) but differs in PLL limits, VCO/CDClk tables, and register
field encoding.
Key differences from G45/GM45:
- PLL limits: Uses i9xx limits (VCO 1.4-2.8 GHz) instead of g4x
limits. Add I9XX_LVDS_Limits; refactor Calculate_Clock_Parameters
to take Limits as a parameter, with a new Select_Limits function.
- VCO: Uses Crestline (CL) VCO tables with different frequencies
and divisors than GM45's Cantiga (CTG) tables.
- CDClk: GCFGC register decoding uses bits 12:8 minus 1 (3 possible
divisor selections), unlike GM45's single bit 12.
- No native DisplayPort (SDVO B/C only).
- No HD Audio (G4X_AUD_VID_DID reads as 0).
- Has integrated LVDS transmitter (mobile platform).
- PCI IDs: 0x2a02 (I965_GM), 0x2a12 (I965_GME).
All implementation details cross-referenced against the Linux kernel
i915 driver (intel_dpll.c, intel_cdclk.c, intel_display_device.c).
Change-Id: I0d5d698cc1c2aa84778f0fc6c2752cb5ce4f1cb2
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/499
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: Nico Huber <nico.h@gmx.de>
diff --git a/common/g45/hw-gfx-gma-plls.adb b/common/g45/hw-gfx-gma-plls.adb
index 5db76d6..fcc08ad 100644
--- a/common/g45/hw-gfx-gma-plls.adb
+++ b/common/g45/hw-gfx-gma-plls.adb
@@ -140,6 +140,18 @@
P2_Fast => 5, P2_Slow => 10,
P2_Threshold => 165_000_000,
VCO_Lower => 1_750_000_000, VCO_Upper => 3_500_000_000);
+ -- I9XX limits are used by GM965 (Crestline) and older non-G4x chips.
+ I9XX_LVDS_Limits : constant Limits_Type := Limits_Type'
+ (N_Lower => 3, N_Upper => 8,
+ M_Lower => 70, M_Upper => 120,
+ M1_Lower => 10, M1_Upper => 20,
+ M2_Lower => 5, M2_Upper => 9,
+ P_Lower => 7, P_Upper => 98,
+ P1_Lower => 1, P1_Upper => 8,
+ P2_Fast => 7, P2_Slow => 14,
+ P2_Threshold => 112_000_000,
+ VCO_Lower => 1_400_000_000, VCO_Upper => 2_800_000_000);
+ -- The All_Other/I9XX_SDVO limits match Linux' intel_limits_i9xx_sdvo.
All_Other_Limits : constant Limits_Type := Limits_Type'
(N_Lower => 3, N_Upper => 8,
M_Lower => 70, M_Upper => 120,
@@ -279,9 +291,9 @@
end Verify_Parameters;
procedure Calculate_Clock_Parameters
- (Display : in Display_Type;
- Target_Dotclock : in Clock_Range;
+ (Target_Dotclock : in Clock_Range;
Reference_Clock : in Clock_Range;
+ Limits : in Limits_Type;
Best_Clock : out Clock_Type;
Valid : out Boolean)
with
@@ -289,17 +301,6 @@
Pre => True,
Post => True
is
- Limits : constant Limits_Type :=
- (case Display is
- when LVDS =>
- (if Target_Dotclock >= Config.LVDS_Dual_Threshold then
- LVDS_Dual_Limits
- else
- LVDS_Single_Limits),
- when HDMI => HDMI_Analog_Limits,
- when VGA => HDMI_Analog_Limits,
- when others => All_Other_Limits); --TODO add SDVO type, needs other limits
-
P2 : P2_Range;
Best_Delta : Int64 := Int64'Last;
Current_Delta : Int64;
@@ -420,6 +421,34 @@
Shift_Left (Encoded_P1, DPLL_P1_DIVIDER_SHIFT));
end Program_DPLL;
+ function Select_Limits
+ (Display : Display_Type;
+ Target_Dotclock : Clock_Range)
+ return Limits_Type
+ is
+ begin
+ if Config.GMCH_GM965 then
+ -- i9xx PLL limits for GM965 (Crestline)
+ case Display is
+ when LVDS => return I9XX_LVDS_Limits;
+ when others => return All_Other_Limits;
+ end case;
+ else
+ -- G4x PLL limits for G45/GM45
+ case Display is
+ when LVDS =>
+ if Target_Dotclock >= Config.LVDS_Dual_Threshold then
+ return LVDS_Dual_Limits;
+ else
+ return LVDS_Single_Limits;
+ end if;
+ when HDMI => return HDMI_Analog_Limits;
+ when VGA => return HDMI_Analog_Limits;
+ when others => return All_Other_Limits;
+ end case;
+ end if;
+ end Select_Limits;
+
procedure On
(PLL : in T;
Port_Cfg : in Port_Config;
@@ -459,10 +488,10 @@
end case;
elsif Target_Clock <= 340_000_000 then
Calculate_Clock_Parameters
- (Display => Port_Cfg.Display,
- Target_Dotclock => Target_Clock,
+ (Target_Dotclock => Target_Clock,
-- should be, but doesn't has to be always the same:
Reference_Clock => 96_000_000,
+ Limits => Select_Limits (Port_Cfg.Display, Target_Clock),
Best_Clock => Clk,
Valid => Success);
else