intel_extreme: Rework PLL calculation

* More like linux, improved G4x calculations
* Reduce un-needed pll limit complexity
* Improved pll limits on ports based on type
This commit is contained in:
Alexander von Gluck IV
2016-05-11 12:34:51 -05:00
parent 95e38537e0
commit 9407ab29c4
4 changed files with 328 additions and 168 deletions
@@ -239,7 +239,7 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
float refFreq = gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) {
float adjusted = ((refFreq * divisors.m) / divisors.n) / divisors.post;
float adjusted = ((refFreq * divisors.m) / divisors.n) / divisors.p;
uint32 pixelMultiply = uint32(adjusted / (pixelClock / 1000.0f));
write32(pllMD, (0 << 24) | ((pixelMultiply - 1) << 8));
}
@@ -273,34 +273,33 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL | extraFlags;
if (gInfo->shared_info->device_type.Generation() >= 3) {
// post1 divisor << 1 , 1-8
// p1 divisor << 1 , 1-8
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
pll |= ((1 << (divisors.post1 - 1))
pll |= ((1 << (divisors.p1 - 1))
<< DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT)
& DISPLAY_PLL_IGD_POST1_DIVISOR_MASK;
} else {
pll |= ((1 << (divisors.post1 - 1))
pll |= ((1 << (divisors.p1 - 1))
<< DISPLAY_PLL_POST1_DIVISOR_SHIFT)
& DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
// pll |= ((divisors.p1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK;
}
// p2 clock divider. 5 or 7 high
if (divisors.post2_high)
if (divisors.p2 == 5 || divisors.p2 == 7)
pll |= DISPLAY_PLL_DIVIDE_HIGH;
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x))
pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT;
} else {
if (!divisors.post2_high)
if (divisors.p2 != 5 && divisors.p2 != 7)
pll |= DISPLAY_PLL_DIVIDE_4X;
pll |= DISPLAY_PLL_2X_CLOCK;
// TODO: Is this supposed to be DISPLAY_PLL_IGD_POST1_DIVISOR_MASK??
if (divisors.post1 > 2) {
pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
if (divisors.p1 > 2) {
pll |= ((divisors.p1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)
& DISPLAY_PLL_POST1_DIVISOR_MASK;
} else
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
@@ -506,7 +506,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
// Set the B0-B3 data pairs corresponding to whether we're going to
// set the DPLLs for dual-channel mode or not.
if (divisors.post2_high) {
if (divisors.p2 == 5 || divisors.p2 == 7) {
TRACE("LVDS: dual channel\n");
lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
} else {
+314 -151
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2015, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2016, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -38,117 +38,146 @@
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
void
get_pll_limits(pll_limits* limits, bool isLVDS)
// Static pll limits taken from Linux kernel KMS
static pll_limits kLimitsIlkDac = {
// p, p1, p2, n, m, m1, m2
{ 5, 2, 14, 1, 79, 12, 5}, // min
{ 80, 8, 14, 3, 118, 22, 9}, // max
225000, 1760000, 3510000
};
static pll_limits kLimitsIlkLvdsSingle = {
// p, p1, p2, n, m, m1, m2
{ 28, 2, 14, 1, 79, 12, 5}, // min
{112, 8, 14, 3, 118, 22, 9}, // max
225000, 1760000, 3510000
};
static pll_limits kLimitsIlkLvdsDual = {
// p, p1, p2, n, m, m1, m2
{ 14, 2, 7, 1, 79, 12, 5}, // min
{ 56, 8, 7, 3, 127, 22, 9}, // max
225000, 1760000, 3510000
};
// 100Mhz RefClock
static pll_limits kLimitsIlkLvdsSingle100 = {
// p, p1, p2, n, m, m1, m2
{ 28, 2, 14, 1, 79, 12, 5}, // min
{112, 8, 14, 2, 126, 22, 9}, // max
225000, 1760000, 3510000
};
static pll_limits kLimitsIlkLvdsDual100 = {
// p, p1, p2, n, m, m1, m2
{ 14, 2, 7, 1, 79, 12, 5}, // min
{ 42, 6, 7, 3, 126, 22, 9}, // max
225000, 1760000, 3510000
};
#if 0
static pll_limits kLimitsChv = {
// p, p1, p2, n, m, m1, m2
{ 0, 2, 14, 1, 79, 2, 24 << 22}, // min
{ 0, 4, 1, 1, 127, 2, 175 << 22}, // max
0, 4800000, 6480000
};
static pll_limits kLimitsVlv = {
// p, p1, p2, n, m, m1, m2
{ 0, 2, 20, 1, 79, 2, 11}, // min
{ 0, 3, 2, 7, 127, 3, 156}, // max
0, 4000000, 6000000
};
static pll_limits kLimitsBxt = {
// p, p1, p2, n, m, m1, m2
{ 0, 2, 1, 1, 0, 2, 2 << 22}, // min
{ 0, 4, 20, 1, 0, 2, 255 << 22}, // max
0, 4800000, 6700000
};
#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
{ 80, 8, 5, 6, 256, 0, 254}, // max
200000, 1700000, 3500000
};
static pll_limits kLimitsPinLvds = {
// p, p1, p2, n, m, m1, m2
{ 7, 1, 14, 3, 2, 0, 0}, // min
{112, 8, 14, 6, 256, 0, 254}, // max
112000, 1700000, 3500000
};
#if 0
static pll_limits kLimits = {
// p, p1, p2, n, m, m1, m2
{ 4, 2, 4, 5, 96, 20, 8},
{128, 33, 2, 18, 140, 28, 18},
165000, 930000, 1400000
};
#endif
static bool
lvds_dual_link(display_mode* current)
{
// Note, the limits are taken from the X driver; they have not yet been
// tested
float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
if (requestedPixelClock > 112.999)
return true;
// TODO: Breakout BXT
// TODO: Force dual link on MacBookPro6,2 MacBookPro8,2 MacBookPro9,1
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 = {
// p, p1, p2, high, n, m, m1, m2
{ 5, 1, 10, false, 1, 79, 12, 5}, // min
{ 80, 8, 5, true, 5, 127, 22, 9}, // max
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));
} else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) {
pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2
{ 5, 1, 10, false, 1, 70, 8, 3}, // min
{ 80, 8, 5, true, 6, 120, 18, 7}, // max
200000, 1400000, 2800000
};
if (isLVDS) {
kLimits.min.post = 7;
kLimits.max.post = 98;
kLimits.min.post2 = 14;
kLimits.max.post2 = 7;
}
memcpy(limits, &kLimits, sizeof(pll_limits));
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) {
pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2
{ 10, 1, 10, false, 1, 104, 17, 5}, // min
{ 30, 3, 10, true, 4, 138, 23, 11}, // max
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));
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
// m1 is reserved and must be 0
pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2
{ 5, 1, 10, false, 3, 2, 0, 2}, // min
{ 80, 8, 5, true, 6, 256, 0, 254}, // max
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));
} else {
static pll_limits kLimits = {
// p, p1, p2, high, n, m, m1, m2
{ 4, 2, 4, false, 5, 96, 20, 8},
{128, 33, 2, true, 18, 140, 28, 18},
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));
}
TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", "
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits->min.post,
limits->min.post1, limits->min.post2, limits->min.n, limits->min.m,
limits->min.m1, limits->min.m2);
TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", "
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits->max.post,
limits->max.post1, limits->max.post2, limits->max.n, limits->max.m,
limits->max.m1, limits->max.m2);
return ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
== LVDS_CLKB_POWER_UP);
}
@@ -157,9 +186,9 @@ valid_pll_divisors(pll_divisors* divisors, pll_limits* limits)
{
pll_info &info = gInfo->shared_info->pll_info;
uint32 vco = info.reference_frequency * divisors->m / divisors->n;
uint32 frequency = vco / divisors->post;
uint32 frequency = vco / divisors->p;
if (divisors->post < limits->min.post || divisors->post > limits->max.post
if (divisors->p < limits->min.p || divisors->p > limits->max.p
|| divisors->m < limits->min.m || divisors->m > limits->max.m
|| vco < limits->min_vco || vco > limits->max_vco
|| frequency < info.min_frequency || frequency > info.max_frequency)
@@ -169,6 +198,30 @@ valid_pll_divisors(pll_divisors* divisors, pll_limits* limits)
}
static void
compute_pll_p2(display_mode* current, pll_divisors* divisors,
pll_limits* limits, bool isLVDS)
{
if (isLVDS) {
if (lvds_dual_link(current)) {
// fast DAC timing via 2 channels (dual link LVDS)
divisors->p2 = limits->max.p2;
} else {
// slow DAC timing
divisors->p2 = limits->min.p2;
}
} else {
if (current->timing.pixel_clock < limits->dot_limit) {
// slow DAC timing
divisors->p2 = limits->min.p2;
} else {
// fast DAC timing
divisors->p2 = limits->max.p2;
}
}
}
static uint32
compute_pll_m(pll_divisors* divisors)
{
@@ -194,68 +247,160 @@ compute_pll_m(pll_divisors* divisors)
static uint32
compute_pll_p(pll_divisors* divisors)
{
return divisors->post1 * divisors->post2;
return divisors->p1 * divisors->p2;
}
void
compute_pll_divisors(display_mode* current, pll_divisors* divisors,
bool isLVDS)
static void
compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS)
{
float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
float referenceClock
= gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
pll_limits limits;
get_pll_limits(&limits, isLVDS);
TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
// Calculate p2
if (isLVDS) {
if (requestedPixelClock > 112.999
|| (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
== LVDS_CLKB_POWER_UP) {
// fast DAC timing via 2 channels
divisors->post2 = limits.max.post2;
divisors->post2_high = limits.max.post2_high;
} else {
// slow DAC timing
divisors->post2 = limits.min.post2;
divisors->post2_high = limits.min.post2_high;
}
pll_limits limits;
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) {
// TODO: Pass port type via video_configuration
if (isLVDS) {
if (lvds_dual_link(current))
memcpy(&limits, &kLimitsG4xLvdsDual, sizeof(pll_limits));
else
memcpy(&limits, &kLimitsG4xLvdsSingle, sizeof(pll_limits));
//} else if (type == INTEL_PORT_TYPE_HDMI) {
// memcpy(&limits, &kLimitsG4xHdmi, sizeof(pll_limits));
} else
memcpy(&limits, &kLimitsG4xSdvo, sizeof(pll_limits));
} else {
if (current->timing.pixel_clock < limits.min_post2_frequency) {
// slow DAC timing
divisors->post2 = limits.min.post2;
divisors->post2_high = limits.min.post2_high;
if (isLVDS) {
if (lvds_dual_link(current)) {
if (referenceClock == 100.0)
memcpy(&limits, &kLimitsIlkLvdsDual100, sizeof(pll_limits));
else
memcpy(&limits, &kLimitsIlkLvdsDual, sizeof(pll_limits));
} else {
if (referenceClock == 100.0) {
memcpy(&limits, &kLimitsIlkLvdsSingle100,
sizeof(pll_limits));
} else {
memcpy(&limits, &kLimitsIlkLvdsSingle, sizeof(pll_limits));
}
}
} else {
// fast DAC timing
divisors->post2 = limits.max.post2;
divisors->post2_high = limits.max.post2_high;
memcpy(&limits, &kLimitsIlkDac, sizeof(pll_limits));
}
}
compute_pll_p2(current, divisors, &limits, isLVDS);
TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", "
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p,
limits.min.p1, limits.min.p2, limits.min.n, limits.min.m,
limits.min.m1, limits.min.m2);
TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", "
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p,
limits.max.p1, limits.max.p2, limits.max.n, limits.max.m,
limits.max.m1, limits.max.m2);
float best = requestedPixelClock;
pll_divisors bestDivisors;
bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN);
for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1;
divisors->m1++) {
for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2
&& ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) {
for (divisors->n = limits.min.n; divisors->n <= limits.max.n;
divisors->n++) {
for (divisors->post1 = limits.min.post1;
divisors->post1 <= limits.max.post1; divisors->post1++) {
uint32 maxn = limits.max.n;
for (divisors->n = limits.min.n; divisors->n <= maxn; divisors->n++) {
for (divisors->m1 = limits.max.m1; divisors->m1 >= limits.min.m1;
divisors->m1--) {
for (divisors->m2 = limits.max.m2; divisors->m2 >= limits.min.m2;
divisors->m2--) {
for (divisors->p1 = limits.max.p1;
divisors->p1 >= limits.max.p1; divisors->p1--) {
divisors->m = compute_pll_m(divisors);
divisors->post = compute_pll_p(divisors);
divisors->p = compute_pll_p(divisors);
if (!valid_pll_divisors(divisors, &limits))
continue;
float error = fabs(requestedPixelClock
- ((referenceClock * divisors->m) / divisors->n)
/ divisors->post);
/ divisors->p);
if (error < best) {
best = error;
bestDivisors = *divisors;
maxn = divisors->n;
if (error == 0)
break;
}
}
}
}
}
*divisors = bestDivisors;
TRACE("%s: best MHz: %g (error: %g)\n", __func__,
((referenceClock * divisors->m) / divisors->n) / divisors->p,
best);
}
static void
compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS)
{
float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
float referenceClock
= gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
pll_limits limits;
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
if (isLVDS)
memcpy(&limits, &kLimitsPinLvds, sizeof(pll_limits));
else
memcpy(&limits, &kLimitsPinSdvo, sizeof(pll_limits));
} else {
if (isLVDS)
memcpy(&limits, &kLimits9xxLvds, sizeof(pll_limits));
else
memcpy(&limits, &kLimits9xxSdvo, sizeof(pll_limits));
}
compute_pll_p2(current, divisors, &limits, isLVDS);
TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", "
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p,
limits.min.p1, limits.min.p2, limits.min.n, limits.min.m,
limits.min.m1, limits.min.m2);
TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", "
"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p,
limits.max.p1, limits.max.p2, limits.max.n, limits.max.m,
limits.max.m1, limits.max.m2);
bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN);
float best = requestedPixelClock;
pll_divisors bestDivisors;
for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1;
divisors->m1++) {
for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2
&& ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) {
for (divisors->n = limits.min.n; divisors->n <= limits.max.n;
divisors->n++) {
for (divisors->p1 = limits.min.p1;
divisors->p1 <= limits.max.p1; divisors->p1++) {
divisors->m = compute_pll_m(divisors);
divisors->p = compute_pll_p(divisors);
if (!valid_pll_divisors(divisors, &limits))
continue;
float error = fabs(requestedPixelClock
- ((referenceClock * divisors->m) / divisors->n)
/ divisors->p);
if (error < best) {
best = error;
bestDivisors = *divisors;
@@ -270,10 +415,28 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors,
*divisors = bestDivisors;
TRACE("%s: found: %g MHz, p = %" B_PRId32 " (p1 = %" B_PRId32 ", "
TRACE("%s: best MHz: %g (error: %g)\n", __func__,
((referenceClock * divisors->m) / divisors->n) / divisors->p,
best);
}
void
compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS)
{
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)
|| gInfo->shared_info->device_type.HasPlatformControlHub()) {
compute_dpll_g4x(current, divisors, isLVDS);
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) {
// TODO: CherryView
} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) {
// TODO: VallyView
} else
compute_dpll_9xx(current, divisors, isLVDS);
TRACE("%s: found: p = %" B_PRId32 " (p1 = %" B_PRId32 ", "
"p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " "
"(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__,
((referenceClock * divisors->m) / divisors->n) / divisors->post,
divisors->post, divisors->post1, divisors->post2, divisors->n,
divisors->p, divisors->p1, divisors->p2, divisors->n,
divisors->m, divisors->m1, divisors->m2);
}
+4 -6
View File
@@ -14,10 +14,9 @@
struct pll_divisors {
uint32 post;
uint32 post1;
uint32 post2;
bool post2_high;
uint32 p;
uint32 p1;
uint32 p2;
uint32 n;
uint32 m;
uint32 m1;
@@ -27,13 +26,12 @@ struct pll_divisors {
struct pll_limits {
pll_divisors min;
pll_divisors max;
uint32 min_post2_frequency;
uint32 dot_limit;
uint32 min_vco;
uint32 max_vco;
};
void get_pll_limits(pll_limits* limits, bool isLVDS);
bool valid_pll_divisors(pll_divisors* divisors, pll_limits* limits);
void compute_pll_divisors(display_mode* current, pll_divisors* divisors,
bool isLVDS);