intel_extreme: fix PLL limits for G4x

As for other devices, N=1 makes no sense because N-2 is eventually
written to the hardware register, so wherever these values come from,
they can't be correct. Replace with the values from the Intel manual.

Also fix confusion as to when the + 2 or - 2 is applied to M1 and M2
values. The documentation says M1+2 and M2+2 are used in frequency
computations, but we instead write M1-2 and M2-2 to the registers, so
the M1 and M2 in our limit structs has an offset of 2 from the docs.

Should fix #13694.

Change-Id: I87157154d22a5e6caf622d71a2f0e0b9ff21a2fa
Reviewed-on: https://review.haiku-os.org/c/haiku/+/1902
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Adrien Destugues 2019-10-05 19:03:20 +02:00 committed by waddlesplash
parent 91cc452e90
commit b8f6e4813d

View File

@ -39,45 +39,115 @@
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
// PLL limits, taken from programming manual when available, and from Linux KMS
// drivers otherwise. However, note that we use the values of N+2, M1+2 and
// M2+2 here, the - 2 being applied when we write the values to the registers.
// Static pll limits taken from Linux kernel KMS
static pll_limits kLimits85x = {
// p, p1, p2, n, m, m1, m2
{ 4, 2, 4, 5, 96, 20, 8},
{128, 33, 2, 18, 140, 28, 18},
165000, 930000, 1400000
};
// TODO according to the docs, the limits for 9xx anf G45 should be the same.
// For Iron Lake, a new set of timings is introduced along with the FDI system,
// and carried on to later cards with just one further change (to the P2 cutoff
// frequency) in Sandy Bridge.
//
// So, it makes no sense to have separa limits and algorithm for 9xx and G45.
static pll_limits kLimits9xxSdvo = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 10, 5, 70, 12, 7}, // min
{ 80, 8, 5, 10, 120, 22, 11}, // max
200000, 1400000, 2800000
};
static pll_limits kLimits9xxLvds = {
// p, p1, p2, n, m, m1, m2
{ 7, 1, 14, 1, 70, 8, 3}, // min
{ 98, 8, 7, 6, 120, 18, 7}, // max
112000, 1400000, 2800000
};
// Limits for G45 cards taken from g45_vlo3_register_0_0_0.pdf, page 46
// Note that n here is actually n+2, but m1 and m2 are as in the datasheet.
static pll_limits kLimitsG4xSdvo = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 5, 5, 70, 12, 7}, // min
{ 80, 8, 10, 10, 120, 22, 11}, // max
270000, 1400000, 2800000
};
#if 0
static pll_limits kLimitsG4xHdmi = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 10, 5, 70, 12, 7}, // min
{ 80, 8, 5, 10, 120, 22, 11}, // max
165000, 1400000, 2800000
};
#endif
static pll_limits kLimitsG4xLvdsSingle = {
// p, p1, p2, n, m, m1, m2
{ 7, 1, 14, 5, 70, 12, 7}, // min
{ 98, 8, 14, 10, 120, 22, 11}, // max
0, 1400000, 2800000
};
static pll_limits kLimitsG4xLvdsDual = {
// p, p1, p2, n, m, m1, m2
{ 14, 2, 7, 5, 70, 12, 7}, // min
{ 42, 6, 7, 10, 120, 22, 11}, // max
0, 1400000, 2800000
};
static pll_limits kLimitsIlkDac = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 5, 3, 79, 12, 5}, // min
{ 80, 8, 10, 8, 118, 22, 9}, // max
{ 5, 1, 5, 3, 79, 14, 7}, // min
{ 80, 8, 10, 8, 118, 24, 11}, // max
225000, 1760000, 3510000
};
static pll_limits kLimitsIlkLvdsSingle = {
// p, p1, p2, n, m, m1, m2
{ 28, 2, 14, 3, 79, 12, 5}, // min
{112, 8, 14, 8, 118, 22, 9}, // max
{ 28, 2, 14, 3, 79, 14, 7}, // min
{112, 8, 14, 8, 118, 24, 11}, // max
225000, 1760000, 3510000
};
static pll_limits kLimitsIlkLvdsDual = {
// p, p1, p2, n, m, m1, m2
{ 14, 2, 7, 3, 79, 12, 5}, // min
{ 56, 8, 7, 8, 127, 22, 9}, // max
{ 14, 2, 7, 3, 79, 14, 7}, // min
{ 56, 8, 7, 8, 127, 24, 11}, // max
225000, 1760000, 3510000
};
// 100Mhz RefClock
static pll_limits kLimitsIlkLvdsSingle100 = {
// p, p1, p2, n, m, m1, m2
{ 28, 2, 14, 3, 79, 12, 5}, // min
{112, 8, 14, 8, 126, 22, 9}, // max
{ 28, 2, 14, 3, 79, 14, 7}, // min
{112, 8, 14, 8, 126, 24, 11}, // max
225000, 1760000, 3510000
};
static pll_limits kLimitsIlkLvdsDual100 = {
// p, p1, p2, n, m, m1, m2
{ 14, 2, 7, 3, 79, 12, 5}, // min
{ 42, 6, 7, 8, 126, 22, 9}, // max
{ 14, 2, 7, 3, 79, 14, 7}, // min
{ 42, 6, 7, 8, 126, 24, 11}, // max
225000, 1760000, 3510000
};
// TODO From haswell onwards, a completely different PLL design is used
// (intel_gfx-prm-osrc-hsw-display_0.pdf, page 268 for VGA). It uses a "virtual
// root frequency" and one just has to set a single divider (integer and
// fractional parts), so it makes no sense to reuse the same code and limit
// structures there.
//
// For other display connections, the clock is handled differently, as there is
// no need for a precise timing to send things in sync with the display.
#if 0
static pll_limits kLimitsChv = {
// p, p1, p2, n, m, m1, m2
@ -101,50 +171,6 @@ static pll_limits kLimitsBxt = {
};
#endif
static pll_limits kLimits9xxSdvo = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 10, 5, 70, 12, 7}, // min
{ 80, 8, 5, 10, 120, 22, 11}, // max
200000, 1400000, 2800000
};
static pll_limits kLimits9xxLvds = {
// p, p1, p2, n, m, m1, m2
{ 7, 1, 14, 1, 70, 8, 3}, // min
{ 98, 8, 7, 6, 120, 18, 7}, // max
112000, 1400000, 2800000
};
static pll_limits kLimitsG4xSdvo = {
// p, p1, p2, n, m, m1, m2
{ 10, 1, 10, 1, 104, 17, 5}, // min
{ 30, 3, 10, 4, 138, 23, 11}, // max
270000, 1750000, 3500000
};
#if 0
static pll_limits kLimitsG4xHdmi = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 10, 1, 104, 16, 5}, // min
{ 80, 8, 5, 4, 138, 23, 11}, // max
165000, 1750000, 3500000
};
#endif
static pll_limits kLimitsG4xLvdsSingle = {
// p, p1, p2, n, m, m1, m2
{ 28, 2, 14, 1, 104, 17, 5}, // min
{ 112, 8, 14, 3, 138, 23, 11}, // max
0, 1750000, 3500000
};
static pll_limits kLimitsG4xLvdsDual = {
// p, p1, p2, n, m, m1, m2
{ 14, 2, 7, 1, 104, 17, 5}, // min
{ 42, 6, 7, 3, 138, 23, 11}, // max
0, 1750000, 3500000
};
static pll_limits kLimitsPinSdvo = {
// p, p1, p2, n, m, m1, m2
{ 5, 1, 10, 3, 2, 0, 0}, // min
@ -159,13 +185,6 @@ static pll_limits kLimitsPinLvds = {
112000, 1700000, 3500000
};
static pll_limits kLimits85x = {
// p, p1, p2, n, m, m1, m2
{ 4, 2, 4, 5, 96, 20, 8},
{128, 33, 2, 18, 140, 28, 18},
165000, 930000, 1400000
};
static bool
lvds_dual_link(display_mode* current)
@ -222,6 +241,13 @@ compute_pll_p2(display_mode* current, pll_divisors* divisors,
}
// TODO we can simplify this computation, with the way the dividers are set, we
// know that all values in the valid range for M are reachable. M1 allows to
// generate any multiple of 5 in the range and M2 allows to reach the 4 next
// values. Therefore, we don't need to loop over the range of values for M1 and
// M2 separately, we could instead just loop over possible values for M.
// For this to work, the logic of this function must be reversed: for a given M,
// it should give the resulting M1 and M2 values for programming the registers.
static uint32
compute_pll_m(pll_divisors* divisors)
{
@ -232,13 +258,7 @@ compute_pll_m(pll_divisors* divisors)
// Pineview, m1 is reserved
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN))
return divisors->m2 + 2;
if (gInfo->shared_info->device_type.Generation() >= 3)
return 5 * (divisors->m1 + 2) + (divisors->m2 + 2);
// TODO: This logic needs validated... PLL's were calculated differently
// on 8xx chipsets
return divisors->m2;
return 5 * divisors->m1 + divisors->m2;
}