Ticket #12716: 0001-intel_extreme-Rewrite-PLL-calculations.patch
File 0001-intel_extreme-Rewrite-PLL-calculations.patch, 21.5 KB (added by , 9 years ago) |
---|
-
src/add-ons/accelerants/intel_extreme/Pipes.cpp
From 8d0e424f94628ba1a03125af10bd6eea5cc9f140 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV <kallisti5@unixzen.com> Date: Tue, 12 Apr 2016 01:11:30 -0500 Subject: [PATCH] intel_extreme: Rewrite PLL calculations * More like linux, improved G4x calculations * Reduce un-needed pll limit complexity * Improved pll limits on ports based on type --- src/add-ons/accelerants/intel_extreme/Pipes.cpp | 19 +- src/add-ons/accelerants/intel_extreme/Ports.cpp | 4 +- src/add-ons/accelerants/intel_extreme/pll.cpp | 456 ++++++++++++++++-------- src/add-ons/accelerants/intel_extreme/pll.h | 10 +- 4 files changed, 324 insertions(+), 165 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 4f36f62..b5705ad 100644
a b Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock, 233 233 float refFreq = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 234 234 235 235 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { 236 float adjusted = ((refFreq * divisors.m) / divisors.n) / divisors.p ost;236 float adjusted = ((refFreq * divisors.m) / divisors.n) / divisors.p; 237 237 uint32 pixelMultiply = uint32(adjusted / (pixelClock / 1000.0f)); 238 238 write32(pllMD, (0 << 24) | ((pixelMultiply - 1) << 8)); 239 239 } … … Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock, 267 267 uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL | extraFlags; 268 268 269 269 if (gInfo->shared_info->device_type.Generation() >= 3) { 270 // p ost1 divisor << 1 , 1-8270 // p1 divisor << 1 , 1-8 271 271 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { 272 pll |= ((1 << (divisors.p ost1 - 1))272 pll |= ((1 << (divisors.p1 - 1)) 273 273 << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) 274 274 & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; 275 275 } else { 276 pll |= ((1 << (divisors.p ost1 - 1))276 pll |= ((1 << (divisors.p1 - 1)) 277 277 << DISPLAY_PLL_POST1_DIVISOR_SHIFT) 278 278 & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; 279 // pll |= ((divisors.p ost1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)279 // pll |= ((divisors.p1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) 280 280 // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; 281 281 } 282 282 283 // p2 clock divider. 5 or 7 high 284 if (divisors.post2_high) 283 if (divisors.p2 == 5 || divisors.p2 == 7) 285 284 pll |= DISPLAY_PLL_DIVIDE_HIGH; 286 285 287 286 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) 288 287 pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; 289 288 } else { 290 if ( !divisors.post2_high)289 if (divisors.p2 != 5 && divisors.p2 != 7) 291 290 pll |= DISPLAY_PLL_DIVIDE_4X; 292 291 293 292 pll |= DISPLAY_PLL_2X_CLOCK; 294 293 295 294 // TODO: Is this supposed to be DISPLAY_PLL_IGD_POST1_DIVISOR_MASK?? 296 if (divisors.p ost1 > 2) {297 pll |= ((divisors.p ost1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT)295 if (divisors.p1 > 2) { 296 pll |= ((divisors.p1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) 298 297 & DISPLAY_PLL_POST1_DIVISOR_MASK; 299 298 } else 300 299 pll |= DISPLAY_PLL_POST1_DIVIDE_2; -
src/add-ons/accelerants/intel_extreme/Ports.cpp
diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index f5a5d45..4ea1c8c 100644
a b LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) 497 497 dpll |= (1 << (divisors.post1 - 1)) 498 498 << DISPLAY_PLL_POST1_DIVISOR_SHIFT; 499 499 } 500 switch (divisors.p ost2) {500 switch (divisors.p2) { 501 501 case 5: 502 502 case 7: 503 503 dpll |= DISPLAY_PLL_DIVIDE_HIGH; … … LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) 547 547 548 548 // Set the B0-B3 data pairs corresponding to whether we're going to 549 549 // set the DPLLs for dual-channel mode or not. 550 if (divisors.p ost2_high) {550 if (divisors.p2 == 5 || divisors.p2 == 7) { 551 551 TRACE("LVDS: dual channel\n"); 552 552 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; 553 553 } else { -
src/add-ons/accelerants/intel_extreme/pll.cpp
diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index f6126d7..f7ac865 100644
a b 1 1 /* 2 * Copyright 2006-201 5, Haiku, Inc. All Rights Reserved.2 * Copyright 2006-2016, Haiku, Inc. All Rights Reserved. 3 3 * Distributed under the terms of the MIT License. 4 4 * 5 5 * Authors: … … 38 38 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 39 39 40 40 41 void 42 get_pll_limits(pll_limits* limits, bool isLVDS) 43 { 44 // Note, the limits are taken from the X driver; they have not yet been 45 // tested 46 47 // TODO: Breakout BXT 48 49 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { 50 pll_limits kLimits = { 51 // p, p1, p2, high, n, m, m1, m2 52 { 5, 2, 14, false, 1, 79, 2, 24 << 22}, // min 53 { 80, 4, 1, true, 1, 127, 2, 175 << 22}, // max 54 225000, 4800000, 6480000 55 }; 56 memcpy(limits, &kLimits, sizeof(pll_limits)); 57 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) { 58 pll_limits kLimits = { 59 // p, p1, p2, high, n, m, m1, m2 60 { 5, 2, 20, false, 1, 79, 2, 11}, // min 61 { 80, 3, 2, true, 7, 127, 3, 156}, // max 62 225000, 4000000, 6000000 63 }; 64 memcpy(limits, &kLimits, sizeof(pll_limits)); 65 } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) 66 || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BXT)) { 67 pll_limits kLimits = { 68 // p, p1, p2, high, n, m, m1, m2 69 { 5, 1, 10, false, 1, 79, 12, 5}, // min 70 { 80, 8, 5, true, 5, 127, 22, 9}, // max 71 225000, 1760000, 3510000 72 }; 73 // TODO: validate these LVDS dividers! 74 if (isLVDS) { 75 kLimits.min.post = 7; 76 kLimits.max.post = 98; 77 kLimits.min.post2 = 14; 78 kLimits.max.post2 = 7; 79 } 80 memcpy(limits, &kLimits, sizeof(pll_limits)); 81 } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { 82 pll_limits kLimits = { 83 // p, p1, p2, high, n, m, m1, m2 84 { 5, 1, 10, false, 1, 70, 8, 3}, // min 85 { 80, 8, 5, true, 6, 120, 18, 7}, // max 86 200000, 1400000, 2800000 87 }; 88 if (isLVDS) { 89 kLimits.min.post = 7; 90 kLimits.max.post = 98; 91 kLimits.min.post2 = 14; 92 kLimits.max.post2 = 7; 93 } 94 memcpy(limits, &kLimits, sizeof(pll_limits)); 95 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { 96 pll_limits kLimits = { 97 // p, p1, p2, high, n, m, m1, m2 98 { 10, 1, 10, false, 1, 104, 17, 5}, // min 99 { 30, 3, 10, true, 4, 138, 23, 11}, // max 100 270000, 1750000, 3500000 101 }; 102 // TODO: validate these LVDS dividers! 103 if (isLVDS) { 104 kLimits.min.post = 7; 105 kLimits.max.post = 98; 106 kLimits.min.post2 = 14; 107 kLimits.max.post2 = 7; 108 } 109 memcpy(limits, &kLimits, sizeof(pll_limits)); 110 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { 111 // m1 is reserved and must be 0 112 pll_limits kLimits = { 113 // p, p1, p2, high, n, m, m1, m2 114 { 5, 1, 10, false, 3, 2, 0, 2}, // min 115 { 80, 8, 5, true, 6, 256, 0, 254}, // max 116 200000, 1700000, 3500000 117 }; 118 if (isLVDS) { 119 kLimits.min.post = 7; 120 kLimits.max.post = 112; 121 kLimits.min.post2 = 14; 122 kLimits.max.post2 = 14; 123 } 124 memcpy(limits, &kLimits, sizeof(pll_limits)); 125 } else { 126 static pll_limits kLimits = { 127 // p, p1, p2, high, n, m, m1, m2 128 { 4, 2, 4, false, 5, 96, 20, 8}, 129 {128, 33, 2, true, 18, 140, 28, 18}, 130 165000, 930000, 1400000 131 }; 132 // TODO: Validate these LVDS dividers! 133 if (isLVDS) { 134 kLimits.min.post = 7; 135 kLimits.max.post = 98; 136 kLimits.min.post2 = 14; 137 kLimits.max.post2 = 7; 138 } 139 memcpy(limits, &kLimits, sizeof(pll_limits)); 140 } 41 // Static pll limits taken from Linux kernel KMS 42 43 static pll_limits kLimitsIlkDac = { 44 // p, p1, p2, n, m, m1, m2 45 { 5, 2, 14, 1, 79, 12, 5}, // min 46 { 80, 8, 14, 3, 118, 22, 9}, // max 47 225000, 1760000, 3510000 48 }; 49 50 static pll_limits kLimitsIlkLvdsSingle = { 51 // p, p1, p2, n, m, m1, m2 52 { 28, 2, 14, 1, 79, 12, 5}, // min 53 {112, 8, 14, 3, 118, 22, 9}, // max 54 225000, 1760000, 3510000 55 }; 56 57 static pll_limits kLimitsIlkLvdsDual = { 58 // p, p1, p2, n, m, m1, m2 59 { 14, 2, 7, 1, 79, 12, 5}, // min 60 { 56, 8, 7, 3, 127, 22, 9}, // max 61 225000, 1760000, 3510000 62 }; 63 64 // 100Mhz RefClock 65 static pll_limits kLimitsIlkLvdsSingle100 = { 66 // p, p1, p2, n, m, m1, m2 67 { 28, 2, 14, 1, 79, 12, 5}, // min 68 {112, 8, 14, 2, 126, 22, 9}, // max 69 225000, 1760000, 3510000 70 }; 71 72 static pll_limits kLimitsIlkLvdsDual100 = { 73 // p, p1, p2, n, m, m1, m2 74 { 14, 2, 7, 1, 79, 12, 5}, // min 75 { 42, 6, 7, 3, 126, 22, 9}, // max 76 225000, 1760000, 3510000 77 }; 78 79 #if 0 80 static pll_limits kLimitsChv = { 81 // p, p1, p2, n, m, m1, m2 82 { 0, 2, 14, 1, 79, 2, 24 << 22}, // min 83 { 0, 4, 1, 1, 127, 2, 175 << 22}, // max 84 0, 4800000, 6480000 85 }; 86 87 static pll_limits kLimitsVlv = { 88 // p, p1, p2, n, m, m1, m2 89 { 0, 2, 20, 1, 79, 2, 11}, // min 90 { 0, 3, 2, 7, 127, 3, 156}, // max 91 0, 4000000, 6000000 92 }; 93 94 static pll_limits kLimitsBxt = { 95 // p, p1, p2, n, m, m1, m2 96 { 0, 2, 1, 1, 0, 2, 2 << 22}, // min 97 { 0, 4, 20, 1, 0, 2, 255 << 22}, // max 98 0, 4800000, 6700000 99 }; 100 #endif 141 101 142 TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " 143 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 144 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits->min.post, 145 limits->min.post1, limits->min.post2, limits->min.n, limits->min.m, 146 limits->min.m1, limits->min.m2); 147 TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " 148 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 149 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits->max.post, 150 limits->max.post1, limits->max.post2, limits->max.n, limits->max.m, 151 limits->max.m1, limits->max.m2); 152 } 102 static pll_limits kLimits9xxSdvo = { 103 // p, p1, p2, n, m, m1, m2 104 { 5, 1, 10, 5, 70, 12, 7}, // min 105 { 80, 8, 5, 10, 120, 22, 11}, // max 106 200000, 1400000, 2800000 107 }; 108 109 static pll_limits kLimits9xxLvds = { 110 // p, p1, p2, n, m, m1, m2 111 { 7, 1, 14, 1, 70, 8, 3}, // min 112 { 98, 8, 7, 6, 120, 18, 7}, // max 113 112000, 1400000, 2800000 114 }; 115 116 static pll_limits kLimitsG4xSdvo = { 117 // p, p1, p2, n, m, m1, m2 118 { 10, 1, 10, 1, 104, 17, 5}, // min 119 { 30, 3, 10, 4, 138, 23, 11}, // max 120 270000, 1750000, 3500000 121 }; 122 123 #if 0 124 static pll_limits kLimitsG4xHdmi = { 125 // p, p1, p2, n, m, m1, m2 126 { 5, 1, 10, 1, 104, 16, 5}, // min 127 { 80, 8, 5, 4, 138, 23, 11}, // max 128 165000, 1750000, 3500000 129 }; 130 #endif 131 132 static pll_limits kLimitsG4xLvdsSingle = { 133 // p, p1, p2, n, m, m1, m2 134 { 28, 2, 14, 1, 104, 17, 5}, // min 135 { 112, 8, 14, 3, 138, 23, 11}, // max 136 0, 1750000, 3500000 137 }; 138 139 static pll_limits kLimitsG4xLvdsDual = { 140 // p, p1, p2, n, m, m1, m2 141 { 14, 2, 7, 1, 104, 17, 5}, // min 142 { 42, 6, 7, 3, 138, 23, 11}, // max 143 0, 1750000, 3500000 144 }; 145 146 static pll_limits kLimitsPinSdvo = { 147 // p, p1, p2, n, m, m1, m2 148 { 5, 1, 10, 3, 2, 0, 0}, // min 149 { 80, 8, 5, 6, 256, 0, 254}, // max 150 200000, 1700000, 3500000 151 }; 152 153 static pll_limits kLimitsPinLvds = { 154 // p, p1, p2, n, m, m1, m2 155 { 7, 1, 14, 3, 2, 0, 0}, // min 156 {112, 8, 14, 6, 256, 0, 254}, // max 157 112000, 1700000, 3500000 158 }; 159 160 #if 0 161 static pll_limits kLimits = { 162 // p, p1, p2, n, m, m1, m2 163 { 4, 2, 4, 5, 96, 20, 8}, 164 {128, 33, 2, 18, 140, 28, 18}, 165 165000, 930000, 1400000 166 }; 167 #endif 168 169 170 static bool 171 lvds_dual_link(display_mode* current) 172 { 173 float requestedPixelClock = current->timing.pixel_clock / 1000.0f; 174 if (requestedPixelClock > 112.999) 175 return true; 153 176 177 // TODO: Force dual link on MacBookPro6,2 MacBookPro8,2 MacBookPro9,1 154 178 179 return ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) 180 == LVDS_CLKB_POWER_UP); 181 } 182 155 183 bool 156 184 valid_pll_divisors(pll_divisors* divisors, pll_limits* limits) 157 185 { 158 186 pll_info &info = gInfo->shared_info->pll_info; 159 187 uint32 vco = info.reference_frequency * divisors->m / divisors->n; 160 uint32 frequency = vco / divisors->p ost;188 uint32 frequency = vco / divisors->p; 161 189 162 if (divisors->p ost < limits->min.post || divisors->post > limits->max.post190 if (divisors->p < limits->min.p || divisors->p > limits->max.p 163 191 || divisors->m < limits->min.m || divisors->m > limits->max.m 164 192 || vco < limits->min_vco || vco > limits->max_vco 165 193 || frequency < info.min_frequency || frequency > info.max_frequency) … … valid_pll_divisors(pll_divisors* divisors, pll_limits* limits) 169 197 } 170 198 171 199 200 static void 201 compute_pll_p2(display_mode* current, pll_divisors* divisors, 202 pll_limits* limits, bool isLVDS) 203 { 204 if (isLVDS) { 205 if (lvds_dual_link(current)) { 206 // fast DAC timing via 2 channels (dual link LVDS) 207 divisors->p2 = limits->max.p2; 208 } else { 209 // slow DAC timing 210 divisors->p2 = limits->min.p2; 211 } 212 } else { 213 if (current->timing.pixel_clock < limits->dot_limit) { 214 // slow DAC timing 215 divisors->p2 = limits->min.p2; 216 } else { 217 // fast DAC timing 218 divisors->p2 = limits->max.p2; 219 } 220 } 221 } 222 223 172 224 static uint32 173 225 compute_pll_m(pll_divisors* divisors) 174 226 { … … compute_pll_m(pll_divisors* divisors) 194 246 static uint32 195 247 compute_pll_p(pll_divisors* divisors) 196 248 { 197 return divisors->p ost1 * divisors->post2;249 return divisors->p1 * divisors->p2; 198 250 } 199 251 200 252 201 void 202 compute_pll_divisors(display_mode* current, pll_divisors* divisors, 203 bool isLVDS) 253 static void 254 compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS) 204 255 { 205 256 float requestedPixelClock = current->timing.pixel_clock / 1000.0f; 206 257 float referenceClock 207 258 = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 208 pll_limits limits;209 get_pll_limits(&limits, isLVDS);210 259 211 260 TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); 212 261 213 // Calculate p2 214 if (isLVDS) { 215 if (requestedPixelClock > 112.999 216 || (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) 217 == LVDS_CLKB_POWER_UP) { 218 // fast DAC timing via 2 channels 219 divisors->post2 = limits.max.post2; 220 divisors->post2_high = limits.max.post2_high; 221 } else { 222 // slow DAC timing 223 divisors->post2 = limits.min.post2; 224 divisors->post2_high = limits.min.post2_high; 225 } 262 pll_limits limits; 263 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { 264 // TODO: Single vs Double LVDS 265 if (isLVDS) { 266 if (lvds_dual_link(current)) 267 memcpy(&limits, &kLimitsG4xLvdsDual, sizeof(pll_limits)); 268 else 269 memcpy(&limits, &kLimitsG4xLvdsSingle, sizeof(pll_limits)); 270 //} else if (type == INTEL_PORT_TYPE_HDMI) { 271 // memcpy(&limits, &kLimitsG4xHdmi, sizeof(pll_limits)); 272 } else 273 memcpy(&limits, &kLimitsG4xSdvo, sizeof(pll_limits)); 226 274 } else { 227 if (current->timing.pixel_clock < limits.min_post2_frequency) { 228 // slow DAC timing 229 divisors->post2 = limits.min.post2; 230 divisors->post2_high = limits.min.post2_high; 275 if (isLVDS) { 276 if (lvds_dual_link(current)) { 277 if (referenceClock == 100.0) 278 memcpy(&limits, &kLimitsIlkLvdsDual100, sizeof(pll_limits)); 279 else 280 memcpy(&limits, &kLimitsIlkLvdsDual, sizeof(pll_limits)); 281 } else { 282 if (referenceClock == 100.0) { 283 memcpy(&limits, &kLimitsIlkLvdsSingle100, 284 sizeof(pll_limits)); 285 } else { 286 memcpy(&limits, &kLimitsIlkLvdsSingle, sizeof(pll_limits)); 287 } 288 } 231 289 } else { 232 // fast DAC timing 233 divisors->post2 = limits.max.post2; 234 divisors->post2_high = limits.max.post2_high; 290 memcpy(&limits, &kLimitsIlkDac, sizeof(pll_limits)); 235 291 } 236 292 } 237 293 294 compute_pll_p2(current, divisors, &limits, isLVDS); 295 296 TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " 297 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 298 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p, 299 limits.min.p1, limits.min.p2, limits.min.n, limits.min.m, 300 limits.min.m1, limits.min.m2); 301 TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " 302 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 303 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p, 304 limits.max.p1, limits.max.p2, limits.max.n, limits.max.m, 305 limits.max.m1, limits.max.m2); 306 238 307 float best = requestedPixelClock; 239 308 pll_divisors bestDivisors; 240 309 310 uint32 maxn = limits.max.n; 311 for (divisors->n = limits.min.n; divisors->n <= maxn; divisors->n++) { 312 for (divisors->m1 = limits.max.m1; divisors->m1 >= limits.min.m1; 313 divisors->m1--) { 314 for (divisors->m2 = limits.max.m2; divisors->m2 >= limits.min.m2; 315 divisors->m2--) { 316 for (divisors->p1 = limits.max.p1; 317 divisors->p1 >= limits.max.p1; divisors->p1--) { 318 divisors->m = compute_pll_m(divisors); 319 divisors->p = compute_pll_p(divisors); 320 321 if (!valid_pll_divisors(divisors, &limits)) 322 continue; 323 324 float error = fabs(requestedPixelClock 325 - ((referenceClock * divisors->m) / divisors->n) 326 / divisors->p); 327 if (error < best) { 328 best = error; 329 bestDivisors = *divisors; 330 maxn = divisors->n; 331 332 if (error == 0) 333 break; 334 } 335 } 336 } 337 } 338 } 339 *divisors = bestDivisors; 340 TRACE("%s: best MHz: %g (error: %g)\n", __func__, 341 ((referenceClock * divisors->m) / divisors->n) / divisors->p, 342 best); 343 } 344 345 346 static void 347 compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS) 348 { 349 float requestedPixelClock = current->timing.pixel_clock / 1000.0f; 350 float referenceClock 351 = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 352 353 TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); 354 355 pll_limits limits; 356 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { 357 if (isLVDS) 358 memcpy(&limits, &kLimitsPinLvds, sizeof(pll_limits)); 359 else 360 memcpy(&limits, &kLimitsPinSdvo, sizeof(pll_limits)); 361 } else { 362 if (isLVDS) 363 memcpy(&limits, &kLimits9xxLvds, sizeof(pll_limits)); 364 else 365 memcpy(&limits, &kLimits9xxSdvo, sizeof(pll_limits)); 366 } 367 368 compute_pll_p2(current, divisors, &limits, isLVDS); 369 370 TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " 371 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 372 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p, 373 limits.min.p1, limits.min.p2, limits.min.n, limits.min.m, 374 limits.min.m1, limits.min.m2); 375 TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " 376 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 377 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p, 378 limits.max.p1, limits.max.p2, limits.max.n, limits.max.m, 379 limits.max.m1, limits.max.m2); 380 241 381 bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN); 382 383 float best = requestedPixelClock; 384 pll_divisors bestDivisors; 385 242 386 for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1; 243 387 divisors->m1++) { 244 388 for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2 245 389 && ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) { 246 390 for (divisors->n = limits.min.n; divisors->n <= limits.max.n; 247 391 divisors->n++) { 248 for (divisors->p ost1 = limits.min.post1;249 divisors->p ost1 <= limits.max.post1; divisors->post1++) {392 for (divisors->p1 = limits.min.p1; 393 divisors->p1 <= limits.max.p1; divisors->p1++) { 250 394 divisors->m = compute_pll_m(divisors); 251 divisors->p ost= compute_pll_p(divisors);395 divisors->p = compute_pll_p(divisors); 252 396 253 397 if (!valid_pll_divisors(divisors, &limits)) 254 398 continue; 255 399 256 400 float error = fabs(requestedPixelClock 257 401 - ((referenceClock * divisors->m) / divisors->n) 258 / divisors->p ost);402 / divisors->p); 259 403 if (error < best) { 260 404 best = error; 261 405 bestDivisors = *divisors; … … compute_pll_divisors(display_mode* current, pll_divisors* divisors, 270 414 271 415 *divisors = bestDivisors; 272 416 273 TRACE("%s: found: %g MHz, p = %" B_PRId32 " (p1 = %" B_PRId32 ", " 417 TRACE("%s: best MHz: %g (error: %g)\n", __func__, 418 ((referenceClock * divisors->m) / divisors->n) / divisors->p, 419 best); 420 } 421 422 423 void 424 compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS) 425 { 426 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x) 427 || gInfo->shared_info->device_type.HasPlatformControlHub()) { 428 compute_dpll_g4x(current, divisors, isLVDS); 429 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { 430 // TODO: CherryView 431 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) { 432 // TODO: VallyView 433 } else 434 compute_dpll_9xx(current, divisors, isLVDS); 435 436 TRACE("%s: found: p = %" B_PRId32 " (p1 = %" B_PRId32 ", " 274 437 "p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " " 275 438 "(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__, 276 ((referenceClock * divisors->m) / divisors->n) / divisors->post, 277 divisors->post, divisors->post1, divisors->post2, divisors->n, 439 divisors->p, divisors->p1, divisors->p2, divisors->n, 278 440 divisors->m, divisors->m1, divisors->m2); 279 441 } -
src/add-ons/accelerants/intel_extreme/pll.h
diff --git a/src/add-ons/accelerants/intel_extreme/pll.h b/src/add-ons/accelerants/intel_extreme/pll.h index bc243a5..88253f4 100644
a b 14 14 15 15 16 16 struct pll_divisors { 17 uint32 post; 18 uint32 post1; 19 uint32 post2; 20 bool post2_high; 17 uint32 p; 18 uint32 p1; 19 uint32 p2; 21 20 uint32 n; 22 21 uint32 m; 23 22 uint32 m1; … … struct pll_divisors { 27 26 struct pll_limits { 28 27 pll_divisors min; 29 28 pll_divisors max; 30 uint32 min_post2_frequency;29 uint32 dot_limit; 31 30 uint32 min_vco; 32 31 uint32 max_vco; 33 32 }; 34 33 35 34 36 void get_pll_limits(pll_limits* limits, bool isLVDS);37 35 bool valid_pll_divisors(pll_divisors* divisors, pll_limits* limits); 38 36 void compute_pll_divisors(display_mode* current, pll_divisors* divisors, 39 37 bool isLVDS);