pll: Cleanup PLL post dividers, add VLV and CHV limits

This commit is contained in:
Alexander von Gluck IV 2015-12-05 11:26:14 -06:00
parent 3cfe299798
commit e587aa9fa3
2 changed files with 60 additions and 23 deletions

View File

@ -216,6 +216,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock,
if (gInfo->shared_info->device_type.Generation() >= 4 if (gInfo->shared_info->device_type.Generation() >= 4
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
// post1 divisor << 1 , 1-8
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
pll |= ((1 << (divisors.post1 - 1)) pll |= ((1 << (divisors.post1 - 1))
<< DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT)
@ -228,16 +229,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock,
// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
} }
#if 0 // p2 clock divider. 5 or 7 high
// TODO: ??? LVDS?
switch (divisors.post2) {
case 5:
case 7:
pll |= DISPLAY_PLL_DIVIDE_HIGH;
break;
}
#endif
if (divisors.post2_high) if (divisors.post2_high)
pll |= DISPLAY_PLL_DIVIDE_HIGH; pll |= DISPLAY_PLL_DIVIDE_HIGH;

View File

@ -44,19 +44,41 @@ get_pll_limits(pll_limits* limits, bool isLVDS)
// Note, the limits are taken from the X driver; they have not yet been // Note, the limits are taken from the X driver; they have not yet been
// tested // tested
if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) // TODO: Breakout BXT
|| gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) {
// TODO: support LVDS output limits as well if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) {
pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2
{ 5, 2, 14, false, 1, 79, 2, 24 << 22}, // min
{ 80, 4, 1, true, 1, 127, 2, 175 << 22}, // max
225000, 4800000, 6480000
};
memcpy(limits, &kLimits, sizeof(pll_limits));
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) {
pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2
{ 5, 2, 20, false, 1, 79, 2, 11}, // min
{ 80, 3, 2, true, 7, 127, 3, 156}, // max
225000, 4000000, 6000000
};
memcpy(limits, &kLimits, sizeof(pll_limits));
} else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5)
|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BXT)) {
pll_limits kLimits = { pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2 // p, p1, p2, high, n, m, m1, m2
{ 5, 1, 10, false, 1, 79, 12, 5}, // min { 5, 1, 10, false, 1, 79, 12, 5}, // min
{ 80, 8, 5, true, 5, 127, 22, 9}, // max { 80, 8, 5, true, 5, 127, 22, 9}, // max
225000, 1760000, 3510000 225000, 1760000, 3510000
}; };
// TODO: validate these LVDS dividers!
if (isLVDS) {
kLimits.min.post = 7;
kLimits.max.post = 98;
kLimits.min.post2 = 14;
kLimits.max.post2 = 7;
}
memcpy(limits, &kLimits, sizeof(pll_limits)); memcpy(limits, &kLimits, sizeof(pll_limits));
} else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) {
// (Update: Output limits are adjusted in the computation (post2=7/14))
// Should move them here!
pll_limits kLimits = { pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2 // p, p1, p2, high, n, m, m1, m2
{ 5, 1, 10, false, 1, 70, 8, 3}, // min { 5, 1, 10, false, 1, 70, 8, 3}, // min
@ -71,32 +93,49 @@ get_pll_limits(pll_limits* limits, bool isLVDS)
} }
memcpy(limits, &kLimits, sizeof(pll_limits)); memcpy(limits, &kLimits, sizeof(pll_limits));
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) {
// TODO: support LVDS output limits as well
pll_limits kLimits = { pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2 // p, p1, p2, high, n, m, m1, m2
{ 10, 1, 10, false, 1, 104, 17, 5}, // min { 10, 1, 10, false, 1, 104, 17, 5}, // min
{ 30, 3, 10, true, 4, 138, 23, 11}, // max { 30, 3, 10, true, 4, 138, 23, 11}, // max
270000, 1750000, 3500000 270000, 1750000, 3500000
}; };
// TODO: validate these LVDS dividers!
if (isLVDS) {
kLimits.min.post = 7;
kLimits.max.post = 98;
kLimits.min.post2 = 14;
kLimits.max.post2 = 7;
}
memcpy(limits, &kLimits, sizeof(pll_limits)); memcpy(limits, &kLimits, sizeof(pll_limits));
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
// TODO: support LVDS output limits as well
// m1 is reserved and must be 0 // m1 is reserved and must be 0
pll_limits kLimits = { pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2 // p, p1, p2, high, n, m, m1, m2
{ 5, 1, 10, false, 3, 2, 0, 2}, // min { 5, 1, 10, false, 3, 2, 0, 2}, // min
{ 80, 8, 5, true, 6, 256, 0, 256}, // max { 80, 8, 5, true, 6, 256, 0, 254}, // max
200000, 1700000, 3500000 200000, 1700000, 3500000
}; };
if (isLVDS) {
kLimits.min.post = 7;
kLimits.max.post = 112;
kLimits.min.post2 = 14;
kLimits.max.post2 = 14;
}
memcpy(limits, &kLimits, sizeof(pll_limits)); memcpy(limits, &kLimits, sizeof(pll_limits));
} else { } else {
// TODO: support LVDS output limits as well
static pll_limits kLimits = { static pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2 // p, p1, p2, high, n, m, m1, m2
{ 4, 2, 4, false, 5, 96, 20, 8}, { 4, 2, 4, false, 5, 96, 20, 8},
{128, 33, 2, true, 18, 140, 28, 18}, {128, 33, 2, true, 18, 140, 28, 18},
165000, 930000, 1400000 165000, 930000, 1400000
}; };
// TODO: Validate these LVDS dividers!
if (isLVDS) {
kLimits.min.post = 7;
kLimits.max.post = 98;
kLimits.min.post2 = 14;
kLimits.max.post2 = 7;
}
memcpy(limits, &kLimits, sizeof(pll_limits)); memcpy(limits, &kLimits, sizeof(pll_limits));
} }
@ -171,13 +210,19 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors,
TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
// Calculate p2
if (isLVDS) { if (isLVDS) {
if (requestedPixelClock > 112.999 if (requestedPixelClock > 112.999
|| (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) || (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
== LVDS_CLKB_POWER_UP) == LVDS_CLKB_POWER_UP) {
divisors->post2 = LVDS_POST2_RATE_FAST; // slow DAC timing
else divisors->post2 = limits.min.post2;
divisors->post2 = LVDS_POST2_RATE_SLOW; divisors->post2_high = limits.min.post2_high;
} else {
// fast DAC timing
divisors->post2 = limits.max.post2;
divisors->post2_high = limits.max.post2_high;
}
} else { } else {
if (current->timing.pixel_clock < limits.min_post2_frequency) { if (current->timing.pixel_clock < limits.min_post2_frequency) {
// slow DAC timing // slow DAC timing