xref: /haiku/src/add-ons/accelerants/intel_extreme/pll.cpp (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
1 /*
2  * Copyright 2006-2016, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  *		Alexander von Gluck IV, kallisti5@unixzen.com
8  *
9  * PLL TEST MODE
10  *  pll's on Intel can be extremely difficult. After
11  *  making any changes, it is advised to run PLL_TEST_MODE
12  *  to simulate your pll calculations on every card.
13  *  Example:
14  *  gcc pll.cpp \
15  *    -I $TOP/headers/private/graphics/intel_extreme/
16  *    -I $TOP/headers/private/graphics/common/
17  *    -I $TOP/headers/private/graphics/ -D PLL_TEST_MODE
18  */
19 
20 
21 #include "pll.h"
22 
23 #include <math.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include <Debug.h>
28 
29 #include <create_display_modes.h>
30 #include <ddc.h>
31 #include <edid.h>
32 #include <validate_display_mode.h>
33 
34 #include "accelerant_protos.h"
35 #include "accelerant.h"
36 #include "utility.h"
37 
38 
39 #undef TRACE
40 #define TRACE_MODE
41 #ifdef TRACE_MODE
42 #	define TRACE(x...) _sPrintf("intel_extreme: " x)
43 #else
44 #	define TRACE(x...)
45 #endif
46 
47 #define ERROR(x...) _sPrintf("intel_extreme: " x)
48 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
49 
50 
51 #ifdef PLL_TEST_MODE
52 #undef ERROR
53 #undef CALLED
54 #undef TRACE
55 
56 #define TRACE(x...) printf("intel_extreme: " x)
57 #define ERROR(x...) printf("intel_extreme: " x)
58 #define CALLED(X...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
59 struct accelerant_info* gInfo;
60 #endif
61 
62 // Static pll limits taken from Linux kernel KMS
63 
64 static pll_limits kLimitsIlkDac = {
65 	// p, p1, p2, n,   m, m1, m2
66 	{  5,  2, 14, 1,  79, 12,  5}, // min
67 	{ 80,  8, 14, 3, 118, 22,  9}, // max
68 	225000, 1760000, 3510000
69 };
70 
71 static pll_limits kLimitsIlkLvdsSingle = {
72 	// p, p1, p2, n,   m, m1, m2
73 	{ 28,  2, 14, 1,  79, 12,  5}, // min
74 	{112,  8, 14, 3, 118, 22,  9}, // max
75 	225000, 1760000, 3510000
76 };
77 
78 static pll_limits kLimitsIlkLvdsDual = {
79 	// p, p1, p2, n,   m, m1, m2
80 	{ 14,  2,  7, 1,  79, 12,  5}, // min
81 	{ 56,  8,  7, 3, 127, 22,  9}, // max
82 	225000, 1760000, 3510000
83 };
84 
85 // 100Mhz RefClock
86 static pll_limits kLimitsIlkLvdsSingle100 = {
87 	// p, p1, p2, n,   m, m1, m2
88 	{ 28,  2, 14, 1,  79, 12,  5}, // min
89 	{112,  8, 14, 2, 126, 22,  9}, // max
90 	225000, 1760000, 3510000
91 };
92 
93 static pll_limits kLimitsIlkLvdsDual100 = {
94 	// p, p1, p2, n,   m, m1, m2
95 	{ 14,  2,  7, 1,  79, 12,  5}, // min
96 	{ 42,  6,  7, 3, 126, 22,  9}, // max
97 	225000, 1760000, 3510000
98 };
99 
100 #if 0
101 static pll_limits kLimitsChv = {
102 	// p, p1, p2, n,   m, m1, m2
103 	{  0,  2, 14, 1,  79, 2,   24 << 22}, // min
104 	{  0,  4,  1, 1, 127, 2,  175 << 22}, // max
105 	0, 4800000, 6480000
106 };
107 
108 static pll_limits kLimitsVlv = {
109 	// p, p1, p2, n,   m, m1, m2
110 	{  0,  2, 20, 1,  79, 2,   11},	// min
111 	{  0,  3,  2, 7, 127, 3,  156},	// max
112 	0, 4000000, 6000000
113 };
114 
115 static pll_limits kLimitsBxt = {
116 	// p, p1, p2, n,  m, m1, m2
117 	{  0,  2,  1, 1,  0,  2,   2 << 22}, // min
118 	{  0,  4, 20, 1,  0,  2, 255 << 22}, // max
119 	0, 4800000, 6700000
120 };
121 #endif
122 
123 static pll_limits kLimits9xxSdvo = {
124 	// p, p1, p2,  n,   m, m1, m2
125 	{  5,  1, 10,  5,  70, 12,  7},	// min
126 	{ 80,  8,  5, 10, 120, 22, 11},	// max
127 	200000, 1400000, 2800000
128 };
129 
130 static pll_limits kLimits9xxLvds = {
131 	// p, p1, p2,  n,   m, m1, m2
132 	{  7,  1, 14,  1,  70,  8,  3},	// min
133 	{ 98,  8,  7,  6, 120, 18,  7},	// max
134 	112000, 1400000, 2800000
135 };
136 
137 static pll_limits kLimitsG4xSdvo = {
138 	// p, p1, p2, n,   m, m1, m2
139 	{ 10,  1, 10, 1, 104, 17,  5},	// min
140 	{ 30,  3, 10, 4, 138, 23, 11},	// max
141 	270000, 1750000, 3500000
142 };
143 
144 #if 0
145 static pll_limits kLimitsG4xHdmi = {
146 	// p, p1, p2, n,   m, m1, m2
147 	{  5,  1, 10, 1, 104, 16,  5},	// min
148 	{ 80,  8,  5, 4, 138, 23, 11},	// max
149 	165000, 1750000, 3500000
150 };
151 #endif
152 
153 static pll_limits kLimitsG4xLvdsSingle = {
154 	// p,  p1, p2, n,   m, m1, m2
155 	{ 28,   2, 14, 1, 104, 17,  5},	// min
156 	{ 112,  8, 14, 3, 138, 23, 11},	// max
157 	0, 1750000, 3500000
158 };
159 
160 static pll_limits kLimitsG4xLvdsDual = {
161 	// p, p1, p2, n,   m, m1, m2
162 	{ 14,  2,  7, 1, 104, 17,  5},	// min
163 	{ 42,  6,  7, 3, 138, 23, 11},	// max
164 	0, 1750000, 3500000
165 };
166 
167 static pll_limits kLimitsPinSdvo = {
168 	// p, p1, p2, n,   m, m1,  m2
169 	{  5,  1, 10, 3,   2,  0,   0},	// min
170 	{ 80,  8,  5, 6, 256,  0, 254},	// max
171 	200000, 1700000, 3500000
172 };
173 
174 static pll_limits kLimitsPinLvds = {
175 	// p, p1, p2, n,   m, m1,  m2
176 	{  7,  1, 14, 3,   2,  0,   0},	// min
177 	{112,  8, 14, 6, 256,  0, 254},	// max
178 	112000, 1700000, 3500000
179 };
180 
181 static pll_limits kLimits85x = {
182 	// p, p1, p2,  n,   m, m1, m2
183 	{  4,  2,  4,  5,  96, 20,  8},
184 	{128, 33,  2, 18, 140, 28, 18},
185 	165000, 930000, 1400000
186 };
187 
188 
189 static bool
190 lvds_dual_link(display_mode* current)
191 {
192 	float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
193 	if (requestedPixelClock > 112.999)
194 		return true;
195 
196 	// TODO: Force dual link on MacBookPro6,2  MacBookPro8,2  MacBookPro9,1
197 
198 	return ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
199 		== LVDS_CLKB_POWER_UP);
200 }
201 
202 
203 bool
204 valid_pll_divisors(pll_divisors* divisors, pll_limits* limits)
205 {
206 	pll_info &info = gInfo->shared_info->pll_info;
207 	uint32 vco = info.reference_frequency * divisors->m / divisors->n;
208 	uint32 frequency = vco / divisors->p;
209 
210 	if (divisors->p < limits->min.p || divisors->p > limits->max.p
211 		|| divisors->m < limits->min.m || divisors->m > limits->max.m
212 		|| vco < limits->min_vco || vco > limits->max_vco
213 		|| frequency < info.min_frequency || frequency > info.max_frequency)
214 		return false;
215 
216 	return true;
217 }
218 
219 
220 static void
221 compute_pll_p2(display_mode* current, pll_divisors* divisors,
222 	pll_limits* limits, bool isLVDS)
223 {
224 	if (isLVDS) {
225 		if (lvds_dual_link(current)) {
226 			// fast DAC timing via 2 channels (dual link LVDS)
227 			divisors->p2 = limits->max.p2;
228 		} else {
229 			// slow DAC timing
230 			divisors->p2 = limits->min.p2;
231 		}
232 	} else {
233 		if (current->timing.pixel_clock < limits->dot_limit) {
234 			// slow DAC timing
235 			divisors->p2 = limits->min.p2;
236 		} else {
237 			// fast DAC timing
238 			divisors->p2 = limits->max.p2;
239 		}
240 	}
241 }
242 
243 
244 static uint32
245 compute_pll_m(pll_divisors* divisors)
246 {
247 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)
248 		|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) {
249 		return divisors->m1 * divisors->m2;
250 	}
251 
252 	// Pineview, m1 is reserved
253 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN))
254 		return divisors->m2 + 2;
255 
256 	if (gInfo->shared_info->device_type.Generation() >= 3)
257 		return 5 * (divisors->m1 + 2) + (divisors->m2 + 2);
258 
259 	// TODO: This logic needs validated... PLL's were calculated differently
260 	// on 8xx chipsets
261 
262 	return 5 * divisors->m1 + divisors->m2;
263 }
264 
265 
266 static uint32
267 compute_pll_p(pll_divisors* divisors)
268 {
269 	return divisors->p1 * divisors->p2;
270 }
271 
272 
273 static void
274 compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS)
275 {
276 	float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
277 	float referenceClock
278 		= gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
279 
280 	TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
281 
282 	pll_limits limits;
283 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) {
284 		// TODO: Pass port type via video_configuration
285 		if (isLVDS) {
286 			if (lvds_dual_link(current))
287 				memcpy(&limits, &kLimitsG4xLvdsDual, sizeof(pll_limits));
288 			else
289 				memcpy(&limits, &kLimitsG4xLvdsSingle, sizeof(pll_limits));
290 		//} else if (type == INTEL_PORT_TYPE_HDMI) {
291 		//	memcpy(&limits, &kLimitsG4xHdmi, sizeof(pll_limits));
292 		} else
293 			memcpy(&limits, &kLimitsG4xSdvo, sizeof(pll_limits));
294 	} else {
295 		if (isLVDS) {
296 			if (lvds_dual_link(current)) {
297 				if (referenceClock == 100.0)
298 					memcpy(&limits, &kLimitsIlkLvdsDual100, sizeof(pll_limits));
299 				else
300 					memcpy(&limits, &kLimitsIlkLvdsDual, sizeof(pll_limits));
301 			} else {
302 				if (referenceClock == 100.0) {
303 					memcpy(&limits, &kLimitsIlkLvdsSingle100,
304 						sizeof(pll_limits));
305 				} else {
306 					memcpy(&limits, &kLimitsIlkLvdsSingle, sizeof(pll_limits));
307 				}
308 			}
309 		} else {
310 			memcpy(&limits, &kLimitsIlkDac, sizeof(pll_limits));
311 		}
312 	}
313 
314 	compute_pll_p2(current, divisors, &limits, isLVDS);
315 
316 	TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", "
317 		"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
318 		"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p,
319 		limits.min.p1, limits.min.p2, limits.min.n, limits.min.m,
320 		limits.min.m1, limits.min.m2);
321 	TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", "
322 		"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
323 		"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p,
324 		limits.max.p1, limits.max.p2, limits.max.n, limits.max.m,
325 		limits.max.m1, limits.max.m2);
326 
327 	float best = requestedPixelClock;
328 	pll_divisors bestDivisors;
329 
330 	uint32 maxn = limits.max.n;
331 	for (divisors->n = limits.min.n; divisors->n <= maxn; divisors->n++) {
332 		for (divisors->m1 = limits.max.m1; divisors->m1 >= limits.min.m1;
333 				divisors->m1--) {
334 			for (divisors->m2 = limits.max.m2; divisors->m2 >= limits.min.m2;
335 					divisors->m2--) {
336 				for (divisors->p1 = limits.max.p1;
337 						divisors->p1 >= limits.min.p1; divisors->p1--) {
338 					divisors->m = compute_pll_m(divisors);
339 					divisors->p = compute_pll_p(divisors);
340 
341 					if (!valid_pll_divisors(divisors, &limits))
342 						continue;
343 
344 					float error = fabs(requestedPixelClock
345 						- ((referenceClock * divisors->m) / divisors->n)
346 						/ divisors->p);
347 					if (error < best) {
348 						best = error;
349 						bestDivisors = *divisors;
350 						maxn = divisors->n;
351 
352 						if (error == 0)
353 							break;
354 					}
355 				}
356 			}
357 		}
358 	}
359 	*divisors = bestDivisors;
360 	TRACE("%s: best MHz: %g (error: %g)\n", __func__,
361 		((referenceClock * divisors->m) / divisors->n) / divisors->p,
362 		best);
363 }
364 
365 
366 static void
367 compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS)
368 {
369 	float requestedPixelClock = current->timing.pixel_clock / 1000.0f;
370 	float referenceClock
371 		= gInfo->shared_info->pll_info.reference_frequency / 1000.0f;
372 
373 	TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock);
374 
375 	pll_limits limits;
376 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) {
377 		if (isLVDS)
378 			memcpy(&limits, &kLimitsPinLvds, sizeof(pll_limits));
379 		else
380 			memcpy(&limits, &kLimitsPinSdvo, sizeof(pll_limits));
381 	} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_85x)) {
382 		memcpy(&limits, &kLimits85x, sizeof(pll_limits));
383 	} else {
384 		if (isLVDS)
385 			memcpy(&limits, &kLimits9xxLvds, sizeof(pll_limits));
386 		else
387 			memcpy(&limits, &kLimits9xxSdvo, sizeof(pll_limits));
388 	}
389 
390 	compute_pll_p2(current, divisors, &limits, isLVDS);
391 
392 	TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", "
393 		"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
394 		"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p,
395 		limits.min.p1, limits.min.p2, limits.min.n, limits.min.m,
396 		limits.min.m1, limits.min.m2);
397 	TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", "
398 		"p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " "
399 		"(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p,
400 		limits.max.p1, limits.max.p2, limits.max.n, limits.max.m,
401 		limits.max.m1, limits.max.m2);
402 
403 	bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN);
404 
405 	float best = requestedPixelClock;
406 	pll_divisors bestDivisors;
407 
408 	for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1;
409 			divisors->m1++) {
410 		for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2
411 				&& ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) {
412 			for (divisors->n = limits.min.n; divisors->n <= limits.max.n;
413 					divisors->n++) {
414 				for (divisors->p1 = limits.min.p1;
415 						divisors->p1 <= limits.max.p1; divisors->p1++) {
416 					divisors->m = compute_pll_m(divisors);
417 					divisors->p = compute_pll_p(divisors);
418 
419 					if (!valid_pll_divisors(divisors, &limits))
420 						continue;
421 
422 					float error = fabs(requestedPixelClock
423 						- ((referenceClock * divisors->m) / divisors->n)
424 						/ divisors->p);
425 					if (error < best) {
426 						best = error;
427 						bestDivisors = *divisors;
428 
429 						if (error == 0)
430 							break;
431 					}
432 				}
433 			}
434 		}
435 	}
436 
437 	*divisors = bestDivisors;
438 
439 	TRACE("%s: best MHz: %g (error: %g)\n", __func__,
440 		((referenceClock * divisors->m) / divisors->n) / divisors->p,
441 		best);
442 }
443 
444 
445 void
446 compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS)
447 {
448 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)
449 		|| (gInfo->shared_info->pch_info != INTEL_PCH_NONE)) {
450 		compute_dpll_g4x(current, divisors, isLVDS);
451 	} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) {
452 		ERROR("%s: TODO: CherryView\n", __func__);
453 	} else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) {
454 		ERROR("%s: TODO: VallyView\n", __func__);
455 	} else
456 		compute_dpll_9xx(current, divisors, isLVDS);
457 
458 	TRACE("%s: found: p = %" B_PRId32 " (p1 = %" B_PRId32 ", "
459 		"p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " "
460 		"(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__,
461 		divisors->p, divisors->p1, divisors->p2, divisors->n,
462 		divisors->m, divisors->m1, divisors->m2);
463 }
464 
465 
466 void
467 refclk_activate_ilk(bool hasPanel)
468 {
469 	CALLED();
470 
471 	// aka, our engineers hate you
472 
473 	bool wantsSSC;
474 	bool hasCK505;
475 	if (gInfo->shared_info->pch_info == INTEL_PCH_IBX) {
476 		//XXX: This should be == vbt display_clock_mode
477 		hasCK505 = true;
478 		wantsSSC = hasCK505;
479 	} else {
480 		hasCK505 = false;
481 		wantsSSC = true;
482 	}
483 
484 	uint32 clkRef = read32(PCH_DREF_CONTROL);
485 	uint32 newRef = clkRef;
486 
487 	newRef &= ~DREF_NONSPREAD_SOURCE_MASK;
488 
489 	if (hasCK505)
490 		newRef |= DREF_NONSPREAD_CK505_ENABLE;
491 	else
492 		newRef |= DREF_NONSPREAD_SOURCE_ENABLE;
493 
494 	newRef &= ~DREF_SSC_SOURCE_MASK;
495 	newRef &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
496 	newRef &= ~DREF_SSC1_ENABLE;
497 
498 	if (newRef == clkRef) {
499 		TRACE("%s: No changes to reference clock.\n", __func__);
500 		return;
501 	}
502 
503 	if (hasPanel) {
504 		newRef &= ~DREF_SSC_SOURCE_MASK;
505 		newRef |= DREF_SSC_SOURCE_ENABLE;
506 
507 		if (wantsSSC)
508 			newRef |= DREF_SSC1_ENABLE;
509 		else
510 			newRef &= ~DREF_SSC1_ENABLE;
511 
512 		// Power up SSC before enabling outputs
513 		write32(PCH_DREF_CONTROL, newRef);
514 		read32(PCH_DREF_CONTROL);
515 		spin(200);
516 
517 		newRef &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
518 
519 		bool hasEDP = true;
520 		if (hasEDP) {
521 			if (wantsSSC)
522 				newRef |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
523 			else
524 				newRef |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
525 		} else
526 			newRef |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
527 
528 		write32(PCH_DREF_CONTROL, newRef);
529 		read32(PCH_DREF_CONTROL);
530 		spin(200);
531 	} else {
532 		newRef &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
533 		newRef |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
534 
535 		write32(PCH_DREF_CONTROL, newRef);
536 		read32(PCH_DREF_CONTROL);
537 		spin(200);
538 
539 		if (!wantsSSC) {
540 			newRef &= ~DREF_SSC_SOURCE_MASK;
541 			newRef |= DREF_SSC_SOURCE_DISABLE;
542 			newRef &= ~DREF_SSC1_ENABLE;
543 
544 			write32(PCH_DREF_CONTROL, newRef);
545 			read32(PCH_DREF_CONTROL);
546 			spin(200);
547 		}
548 	}
549 }
550 
551 
552 #ifdef PLL_TEST_MODE
553 
554 const struct  test_device {
555 	uint32 type;
556 	const char* name;
557 } kTestDevices[] = {
558 	{INTEL_MODEL_915, "915"},
559 	{INTEL_MODEL_945, "945"},
560 	{INTEL_MODEL_965, "965"},
561 	{INTEL_MODEL_G33, "G33"},
562 	{INTEL_MODEL_G45, "G45"},
563 	{INTEL_MODEL_PINE, "PineView"},
564 	{INTEL_MODEL_ILKG, "IronLake"},
565 	{INTEL_MODEL_SNBG, "SandyBridge"},
566 	{INTEL_MODEL_IVBG, "IvyBridge"}
567 };
568 
569 
570 static void
571 simulate_mode(display_mode* mode)
572 {
573 	mode->timing.flags = 0;
574 	mode->timing.pixel_clock = uint32(75.2 * 1000);
575 	mode->timing.h_display = 1366;
576 	mode->timing.h_sync_start = 1414;
577 	mode->timing.h_sync_end = 1478;
578 	mode->timing.h_total = 1582;
579 
580 	mode->timing.v_display = 768;
581 	mode->timing.v_sync_start = 772;
582 	mode->timing.v_sync_end = 779;
583 	mode->timing.v_total = 792;
584 
585 	mode->virtual_width = 1366;
586 	mode->virtual_height = 768;
587 }
588 
589 
590 int
591 main(void)
592 {
593 	display_mode fakeMode;
594 	simulate_mode(&fakeMode);
595 
596 	// First we simulate our global card info structs
597 	gInfo = (accelerant_info*)malloc(sizeof(accelerant_info));
598 	if (gInfo == NULL) {
599 		ERROR("Unable to malloc artificial gInfo!\n");
600 		return 1;
601 	}
602 	gInfo->shared_info = (intel_shared_info*)malloc(sizeof(intel_shared_info));
603 
604 	for (uint32 index = 0; index < (sizeof(kTestDevices) / sizeof(test_device));
605 		index++) {
606 		gInfo->shared_info->device_type = kTestDevices[index].type;
607 		ERROR("=== %s (Generation %d)\n",  kTestDevices[index].name,
608 			gInfo->shared_info->device_type.Generation());
609 
610 		if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)
611 			| gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5)) {
612 			gInfo->shared_info->pll_info.reference_frequency = 96000;
613 			gInfo->shared_info->pll_info.max_frequency = 400000;
614 			gInfo->shared_info->pll_info.min_frequency = 20000;
615 		} else {
616 			gInfo->shared_info->pll_info.reference_frequency = 96000;
617 			gInfo->shared_info->pll_info.max_frequency = 400000;
618 			gInfo->shared_info->pll_info.min_frequency = 20000;
619 		}
620 
621 		pll_divisors output;
622 		compute_pll_divisors(&fakeMode, &output, false);
623 	}
624 
625 	free(gInfo->shared_info);
626 	free(gInfo);
627 	return 0;
628 }
629 #endif
630