xref: /haiku/src/add-ons/accelerants/intel_extreme/Ports.cpp (revision b5a859ad6285b14769a5ede7b81e4261044faf7e)
1 /*
2  * Copyright 2006-2015, 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  *		Michael Lotz, mmlr@mlotz.ch
8  *		Alexander von Gluck IV, kallisti5@unixzen.com
9  */
10 
11 
12 #include "Ports.h"
13 
14 #include <ddc.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <Debug.h>
18 #include <KernelExport.h>
19 
20 #include "accelerant.h"
21 #include "accelerant_protos.h"
22 #include "FlexibleDisplayInterface.h"
23 #include "intel_extreme.h"
24 #include "PanelFitter.h"
25 
26 #include <new>
27 
28 
29 #undef TRACE
30 #define TRACE_PORTS
31 #ifdef TRACE_PORTS
32 #   define TRACE(x...) _sPrintf("intel_extreme: " x)
33 #else
34 #   define TRACE(x...)
35 #endif
36 
37 #define ERROR(x...) _sPrintf("intel_extreme: " x)
38 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
39 
40 
41 static bool
42 wait_for_set(addr_t address, uint32 mask, uint32 timeout)
43 {
44 	int interval = 50;
45 	uint32 i = 0;
46 	for(i = 0; i <= timeout; i += interval) {
47 		spin(interval);
48 		if ((read32(address) & mask) != 0)
49 			return true;
50 	}
51 	return false;
52 }
53 
54 
55 static bool
56 wait_for_clear(addr_t address, uint32 mask, uint32 timeout)
57 {
58 	int interval = 50;
59 	uint32 i = 0;
60 	for(i = 0; i <= timeout; i += interval) {
61 		spin(interval);
62 		if ((read32(address) & mask) == 0)
63 			return true;
64 	}
65 	return false;
66 }
67 
68 
69 Port::Port(port_index index, const char* baseName)
70 	:
71 	fPipe(NULL),
72 	fEDIDState(B_NO_INIT),
73 	fPortIndex(index),
74 	fPortName(NULL)
75 {
76 	char portID[2];
77 	portID[0] = 'A' + index - INTEL_PORT_A;
78 	portID[1] = 0;
79 
80 	char buffer[32];
81 	buffer[0] = 0;
82 
83 	strlcat(buffer, baseName, sizeof(buffer));
84 	strlcat(buffer, " ", sizeof(buffer));
85 	strlcat(buffer, portID, sizeof(buffer));
86 	fPortName = strdup(buffer);
87 }
88 
89 
90 Port::~Port()
91 {
92 	free(fPortName);
93 }
94 
95 
96 bool
97 Port::HasEDID()
98 {
99 	if (fEDIDState == B_NO_INIT)
100 		GetEDID(NULL);
101 
102 	return fEDIDState == B_OK;
103 }
104 
105 
106 status_t
107 Port::SetPipe(Pipe* pipe)
108 {
109 	CALLED();
110 
111 	if (pipe == NULL) {
112 		ERROR("%s: Invalid pipe provided!\n", __func__);
113 		return B_ERROR;
114 	}
115 
116 	uint32 portRegister = _PortRegister();
117 	if (portRegister == 0) {
118 		ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__,
119 			portRegister, PortName());
120 		return B_ERROR;
121 	}
122 
123 	// TODO: UnAssignPipe?  This likely needs reworked a little
124 	if (fPipe != NULL) {
125 		ERROR("%s: Can't reassign display pipe (yet)\n", __func__);
126 		return B_ERROR;
127 	}
128 
129 	TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__,
130 		PortName(), portRegister, (pipe->Index() == INTEL_PIPE_A) ? "A" : "B");
131 
132 	uint32 portState = read32(portRegister);
133 
134 	// FIXME is the use of PORT_TRANS_* constants correct for Sandy Bridge /
135 	// Cougar Point? Or is it only for Ivy Bridge / Panther point onwards?
136 	if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
137 		portState &= ~PORT_TRANS_SEL_MASK;
138 		if (pipe->Index() == INTEL_PIPE_A)
139 			write32(portRegister, portState | PORT_TRANS_A_SEL_CPT);
140 		else
141 			write32(portRegister, portState | PORT_TRANS_B_SEL_CPT);
142 	} else {
143 		if (pipe->Index() == INTEL_PIPE_A)
144 			write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B);
145 		else
146 			write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B);
147 	}
148 	fPipe = pipe;
149 
150 	if (fPipe == NULL)
151 		return B_NO_MEMORY;
152 
153 	// Disable display pipe until modesetting enables it
154 	if (fPipe->IsEnabled())
155 		fPipe->Enable(false);
156 
157 	read32(portRegister);
158 
159 	return B_OK;
160 }
161 
162 
163 status_t
164 Port::Power(bool enabled)
165 {
166 	if (fPipe == NULL) {
167 		ERROR("%s: Setting power mode without assigned pipe!\n", __func__);
168 		return B_ERROR;
169 	}
170 
171 	fPipe->Enable(enabled);
172 
173 	return B_OK;
174 }
175 
176 
177 status_t
178 Port::GetEDID(edid1_info* edid, bool forceRead)
179 {
180 	CALLED();
181 
182 	if (fEDIDState == B_NO_INIT || forceRead) {
183 		TRACE("%s: trying to read EDID\n", PortName());
184 
185 		addr_t ddcRegister = _DDCRegister();
186 		if (ddcRegister == 0) {
187 			TRACE("%s: no DDC register found\n", PortName());
188 			fEDIDState = B_ERROR;
189 			return fEDIDState;
190 		}
191 
192 		TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister);
193 
194 		i2c_bus bus;
195 		bus.cookie = (void*)ddcRegister;
196 		bus.set_signals = &_SetI2CSignals;
197 		bus.get_signals = &_GetI2CSignals;
198 		ddc2_init_timing(&bus);
199 
200 		fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL);
201 
202 		if (fEDIDState == B_OK) {
203 			TRACE("%s: found EDID information!\n", PortName());
204 			edid_dump(&fEDIDInfo);
205 		}
206 	}
207 
208 	if (fEDIDState != B_OK) {
209 		TRACE("%s: no EDID information found.\n", PortName());
210 		return fEDIDState;
211 	}
212 
213 	if (edid != NULL)
214 		memcpy(edid, &fEDIDInfo, sizeof(edid1_info));
215 
216 	return B_OK;
217 }
218 
219 
220 status_t
221 Port::GetPLLLimits(pll_limits& limits)
222 {
223 	return B_ERROR;
224 }
225 
226 
227 pipe_index
228 Port::PipePreference()
229 {
230 	CALLED();
231 	// Ideally we could just return INTEL_PIPE_ANY for all devices by default, but
232 	// this doesn't quite work yet. We need to use the BIOS presetup pipes for now.
233 	if (gInfo->shared_info->device_type.Generation() < 4)
234 		return INTEL_PIPE_ANY;
235 
236 	// Notes:
237 	// - The BIOSes seen sofar do not use PIPE C by default.
238 	// - The BIOSes seen sofar program transcoder A to PIPE A, etc.
239 	// - Later devices add a pipe C alongside the added transcoder C.
240 
241 	// FIXME How's this setup in newer gens? Currently return INTEL_PIPE_ANY there..
242 	if ((gInfo->shared_info->device_type.Generation() <= 7) &&
243 		(!gInfo->shared_info->device_type.HasDDI())) {
244 		uint32 portState = read32(_PortRegister());
245 		if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
246 			portState &= PORT_TRANS_SEL_MASK;
247 			if (portState == PORT_TRANS_B_SEL_CPT)
248 				return INTEL_PIPE_B;
249 			else
250 				return INTEL_PIPE_A;
251 		} else {
252 			if (portState & DISPLAY_MONITOR_PIPE_B)
253 				return INTEL_PIPE_B;
254 			else
255 				return INTEL_PIPE_A;
256 		}
257 	}
258 
259 	if (gInfo->shared_info->device_type.HasDDI()) {
260 		//fixme implement detection via PIPE_DDI_FUNC_CTL_x scan..
261 	}
262 
263 	return INTEL_PIPE_ANY;
264 }
265 
266 
267 status_t
268 Port::_GetI2CSignals(void* cookie, int* _clock, int* _data)
269 {
270 	addr_t ioRegister = (addr_t)cookie;
271 	uint32 value = read32(ioRegister);
272 
273 	*_clock = (value & I2C_CLOCK_VALUE_IN) != 0;
274 	*_data = (value & I2C_DATA_VALUE_IN) != 0;
275 
276 	return B_OK;
277 }
278 
279 
280 status_t
281 Port::_SetI2CSignals(void* cookie, int clock, int data)
282 {
283 	addr_t ioRegister = (addr_t)cookie;
284 	uint32 value;
285 
286 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_83x)) {
287 		// on these chips, the reserved values are fixed
288 		value = 0;
289 	} else {
290 		// on all others, we have to preserve them manually
291 		value = read32(ioRegister) & I2C_RESERVED;
292 	}
293 
294 	if (data != 0)
295 		value |= I2C_DATA_DIRECTION_MASK;
296 	else {
297 		value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT
298 			| I2C_DATA_VALUE_MASK;
299 	}
300 
301 	if (clock != 0)
302 		value |= I2C_CLOCK_DIRECTION_MASK;
303 	else {
304 		value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT
305 			| I2C_CLOCK_VALUE_MASK;
306 	}
307 
308 	write32(ioRegister, value);
309 	read32(ioRegister);
310 		// make sure the PCI bus has flushed the write
311 
312 	return B_OK;
313 }
314 
315 
316 // #pragma mark - Analog Port
317 
318 
319 AnalogPort::AnalogPort()
320 	:
321 	Port(INTEL_PORT_A, "Analog")
322 {
323 }
324 
325 
326 bool
327 AnalogPort::IsConnected()
328 {
329 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
330 		_PortRegister());
331 	return HasEDID();
332 }
333 
334 
335 addr_t
336 AnalogPort::_DDCRegister()
337 {
338 	// always fixed
339 	return INTEL_I2C_IO_A;
340 }
341 
342 
343 addr_t
344 AnalogPort::_PortRegister()
345 {
346 	// always fixed
347 	return INTEL_ANALOG_PORT;
348 }
349 
350 
351 status_t
352 AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
353 {
354 	CALLED();
355 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
356 		target->virtual_height);
357 
358 	if (fPipe == NULL) {
359 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
360 		return B_ERROR;
361 	}
362 
363 	// Setup PanelFitter and Train FDI if it exists
364 	PanelFitter* fitter = fPipe->PFT();
365 	if (fitter != NULL)
366 		fitter->Enable(*target);
367 	FDILink* link = fPipe->FDI();
368 	if (link != NULL)
369 		link->Train(target);
370 
371 	pll_divisors divisors;
372 	compute_pll_divisors(target, &divisors, false);
373 
374 	uint32 extraPLLFlags = 0;
375 	if (gInfo->shared_info->device_type.Generation() >= 3)
376 		extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
377 
378 	// Program general pipe config
379 	fPipe->Configure(target);
380 
381 	// Program pipe PLL's
382 	fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
383 
384 	write32(_PortRegister(), (read32(_PortRegister())
385 		& ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY))
386 		| ((target->timing.flags & B_POSITIVE_HSYNC) != 0
387 			? DISPLAY_MONITOR_POSITIVE_HSYNC : 0)
388 		| ((target->timing.flags & B_POSITIVE_VSYNC) != 0
389 			? DISPLAY_MONITOR_POSITIVE_VSYNC : 0));
390 
391 	// Program target display mode
392 	fPipe->ConfigureTimings(target);
393 
394 	// Set fCurrentMode to our set display mode
395 	memcpy(&fCurrentMode, target, sizeof(display_mode));
396 
397 	return B_OK;
398 }
399 
400 
401 // #pragma mark - LVDS Panel
402 
403 
404 LVDSPort::LVDSPort()
405 	:
406 	Port(INTEL_PORT_C, "LVDS")
407 {
408 	// Always unlock LVDS port as soon as we start messing with it.
409 	uint32 panelControl = INTEL_PANEL_CONTROL;
410 	if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
411 		// FIXME writing there results in black screen on SandyBridge
412 		return;
413 		// panelControl = PCH_PANEL_CONTROL;
414 	}
415 	write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK);
416 }
417 
418 
419 pipe_index
420 LVDSPort::PipePreference()
421 {
422 	CALLED();
423 	// Older devices have hardcoded pipe/port mappings, so just use that
424 	if (gInfo->shared_info->device_type.Generation() < 4)
425 		return INTEL_PIPE_B;
426 
427 	// Ideally we could just return INTEL_PIPE_ANY for the newer devices, but
428 	// this doesn't quite work yet.
429 
430 	// On SandyBridge and later, there is a transcoder C. On SandyBridge at least
431 	// that can't be used by the LVDS port (but A and B would be fine).
432 	// On Ibex Point, SandyBridge and IvyBridge (tested) changing pipes does not
433 	// work yet.
434 	// Notes:
435 	// - Switching Pipes only works reliably when a 'full modeswitch' is executed
436 	//   (FDI training) so we have to reuse the BIOS preset setup always for now.
437 	// - The BIOSes seen sofar do not use PIPE C by default.
438 	// - The BIOSes seen sofar program transcoder A to PIPE A, etc.
439 	// - Later devices add a pipe C alongside the added transcoder C.
440 
441 	// FIXME How's this setup in newer gens? Currently return Pipe B fixed there..
442 	if (gInfo->shared_info->device_type.Generation() <= 7) {
443 		uint32 portState = read32(_PortRegister());
444 		if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
445 			portState &= PORT_TRANS_SEL_MASK;
446 			if (portState == PORT_TRANS_B_SEL_CPT)
447 				return INTEL_PIPE_B;
448 			else
449 				return INTEL_PIPE_A;
450 		} else {
451 			if (portState & DISPLAY_MONITOR_PIPE_B)
452 				return INTEL_PIPE_B;
453 			else
454 				return INTEL_PIPE_A;
455 		}
456 	}
457 
458 	return INTEL_PIPE_B;
459 }
460 
461 
462 bool
463 LVDSPort::IsConnected()
464 {
465 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
466 		_PortRegister());
467 
468 	if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
469 		uint32 registerValue = read32(_PortRegister());
470 		// there's a detection bit we can use
471 		if ((registerValue & PCH_LVDS_DETECTED) == 0) {
472 			TRACE("LVDS: Not detected\n");
473 			return false;
474 		}
475 		// TODO: Skip if eDP support
476 	} else if (gInfo->shared_info->device_type.Generation() <= 4) {
477 		// Older generations don't have LVDS detection. If not mobile skip.
478 		if (!gInfo->shared_info->device_type.IsMobile()) {
479 			TRACE("LVDS: Skipping LVDS detection due to gen and not mobile\n");
480 			return false;
481 		}
482 		// If mobile, try to grab EDID
483 		// Linux seems to look at lid status for LVDS port detection
484 		// If we don't get EDID, we can use vbios native mode or vesa?
485 		if (!HasEDID()) {
486 			if (gInfo->shared_info->has_vesa_edid_info) {
487 				TRACE("LVDS: Using VESA edid info\n");
488 				memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
489 					sizeof(edid1_info));
490 				fEDIDState = B_OK;
491 				// HasEDID now true
492 			} else if (gInfo->shared_info->got_vbt) {
493 				TRACE("LVDS: No EDID, but force enabled as we have a VBT\n");
494 				return true;
495 			} else {
496 				TRACE("LVDS: Couldn't find any valid EDID!\n");
497 				return false;
498 			}
499 		}
500 	}
501 
502 	// Try getting EDID, as the LVDS port doesn't overlap with anything else,
503 	// we don't run the risk of getting someone else's data.
504 	return HasEDID();
505 }
506 
507 
508 addr_t
509 LVDSPort::_DDCRegister()
510 {
511 	// always fixed
512 	return INTEL_I2C_IO_C;
513 }
514 
515 
516 addr_t
517 LVDSPort::_PortRegister()
518 {
519 	// always fixed
520 	return INTEL_DIGITAL_LVDS_PORT;
521 }
522 
523 
524 status_t
525 LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
526 {
527 	CALLED();
528 	if (target == NULL) {
529 		ERROR("%s: Invalid target mode passed!\n", __func__);
530 		return B_ERROR;
531 	}
532 
533 	TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(),
534 		target->virtual_width, target->virtual_height);
535 
536 	if (fPipe == NULL) {
537 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
538 		return B_ERROR;
539 	}
540 
541 	addr_t panelControl = INTEL_PANEL_CONTROL;
542 	addr_t panelStatus = INTEL_PANEL_STATUS;
543 	if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
544 		panelControl = PCH_PANEL_CONTROL;
545 		panelStatus = PCH_PANEL_STATUS;
546 	}
547 
548 	if (gInfo->shared_info->device_type.Generation() != 4) {
549 		// TODO not needed on any generation if we are using the panel fitter
550 		// Power off Panel
551 		write32(panelControl,
552 			read32(panelControl) & ~PANEL_CONTROL_POWER_TARGET_ON);
553 		read32(panelControl);
554 
555 		if (!wait_for_clear(panelStatus, PANEL_STATUS_POWER_ON, 1000)) {
556 			ERROR("%s: %s didn't power off within 1000ms!\n", __func__,
557 				PortName());
558 		}
559 	}
560 
561 	// For LVDS panels, we may need to set the timings according to the panel
562 	// native video mode, and let the panel fitter do the scaling. But the
563 	// place where the scaling happens varies accross generations of devices.
564 	display_mode hardwareTarget;
565 	bool needsScaling = false;
566 
567 	// TODO figure out how it's done (or if we need to configure something at
568 	// all) for other generations
569 	if (gInfo->shared_info->device_type.Generation() <= 6
570 		&& gInfo->shared_info->device_type.Generation() >= 3
571 		&& gInfo->shared_info->got_vbt) {
572 		// Set vbios hardware panel mode as base
573 		hardwareTarget = gInfo->shared_info->panel_mode;
574 
575 		if (hardwareTarget.virtual_width == target->virtual_width
576 				&& hardwareTarget.virtual_height == target->virtual_height) {
577 			// We are setting the native video mode, nothing special to do
578 			TRACE("Setting LVDS to native mode\n");
579 			hardwareTarget = *target;
580 		} else {
581 			// We need to enable the panel fitter
582 			TRACE("%s: hardware mode will actually be %dx%d\n", __func__,
583 				hardwareTarget.virtual_width, hardwareTarget.virtual_height);
584 
585 			hardwareTarget.space = target->space;
586 			// FIXME we should also get the refresh frequency from the target
587 			// mode, and then "sanitize" the resulting mode we made up.
588 
589 			needsScaling = true;
590 		}
591 	} else {
592 		TRACE("Setting LVDS mode without VBT info or on unhandled hardware "
593 			"generation, scaling may not work\n");
594 		// We don't have VBT data, try to set the requested mode directly
595 		// and hope for the best
596 		hardwareTarget = *target;
597 	}
598 
599 	// Setup PanelFitter and Train FDI if it exists
600 	PanelFitter* fitter = fPipe->PFT();
601 	if (fitter != NULL)
602 		fitter->Enable(hardwareTarget);
603 	FDILink* link = fPipe->FDI();
604 	if (link != NULL)
605 		link->Train(&hardwareTarget);
606 
607 	pll_divisors divisors;
608 	compute_pll_divisors(&hardwareTarget, &divisors, true);
609 
610 	uint32 lvds = read32(_PortRegister())
611 		| LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
612 
613 	if (gInfo->shared_info->device_type.Generation() == 4) {
614 		// LVDS_A3_POWER_UP == 24bpp
615 		// otherwise, 18bpp
616 		if ((lvds & LVDS_A3_POWER_MASK) != LVDS_A3_POWER_UP)
617 			lvds |= LVDS_18BIT_DITHER;
618 	}
619 
620 	// LVDS on PCH needs set before display enable
621 	if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
622 		lvds &= ~PORT_TRANS_SEL_MASK;
623 		if (fPipe->Index() == INTEL_PIPE_A)
624 			lvds |= PORT_TRANS_A_SEL_CPT;
625 		else
626 			lvds |= PORT_TRANS_B_SEL_CPT;
627 	}
628 
629 	// Set the B0-B3 data pairs corresponding to whether we're going to
630 	// set the DPLLs for dual-channel mode or not.
631 	if (divisors.p2 == 5 || divisors.p2 == 7) {
632 		TRACE("LVDS: dual channel\n");
633 		lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
634 	} else {
635 		TRACE("LVDS: single channel\n");
636 		lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
637 	}
638 
639 	// LVDS port control moves polarity bits because Intel hates you.
640 	// Set LVDS sync polarity
641 	lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
642 
643 	// set on - polarity.
644 	if ((target->timing.flags & B_POSITIVE_HSYNC) == 0)
645 		lvds |= LVDS_HSYNC_POLARITY;
646 	if ((target->timing.flags & B_POSITIVE_VSYNC) == 0)
647 		lvds |= LVDS_VSYNC_POLARITY;
648 
649 	TRACE("%s: LVDS Write: 0x%" B_PRIx32 "\n", __func__, lvds);
650 	write32(_PortRegister(), lvds);
651 	read32(_PortRegister());
652 
653 	uint32 extraPLLFlags = 0;
654 
655 	// DPLL mode LVDS for i915+
656 	if (gInfo->shared_info->device_type.Generation() >= 3)
657 		extraPLLFlags |= DISPLAY_PLL_MODE_LVDS | DISPLAY_PLL_2X_CLOCK;
658 
659 	// Program general pipe config
660 	fPipe->Configure(target);
661 
662 	// Program pipe PLL's (using the hardware mode timings, since that's what
663 	// the PLL is used for)
664 	fPipe->ConfigureClocks(divisors, hardwareTarget.timing.pixel_clock,
665 		extraPLLFlags);
666 
667 	if (gInfo->shared_info->device_type.Generation() != 4) {
668 		// G45: no need to power the panel off
669 		// Power on Panel
670 		write32(panelControl,
671 			read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON);
672 		read32(panelControl);
673 
674 		if (!wait_for_set(panelStatus, PANEL_STATUS_POWER_ON, 1000)) {
675 			ERROR("%s: %s didn't power on within 1000ms!\n", __func__,
676 				PortName());
677 		}
678 	}
679 
680 	// Program target display mode
681 	fPipe->ConfigureTimings(target, !needsScaling);
682 
683 	if (needsScaling) {
684 		if (gInfo->shared_info->device_type.Generation() <= 4) {
685 			// Enable panel fitter in automatic mode. It will figure out
686 			// the scaling ratios automatically.
687 			uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL);
688 			panelFitterControl |= PANEL_FITTER_ENABLED;
689 			panelFitterControl &= ~(PANEL_FITTER_SCALING_MODE_MASK
690 				| PANEL_FITTER_PIPE_MASK);
691 			panelFitterControl |= PANEL_FITTER_PIPE_B;
692 			// LVDS is always on pipe B.
693 			write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl);
694 		}
695 		// TODO do we need to do anything on later generations?
696 	} else {
697 		if (gInfo->shared_info->device_type.Generation() == 4
698 			|| gInfo->shared_info->device_type.Generation() == 3) {
699 			// Bypass the panel fitter
700 			uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL);
701 			panelFitterControl &= ~PANEL_FITTER_ENABLED;
702 			write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl);
703 		} else {
704 			// We don't need to do anything more for later generations, the
705 			// scaling is handled at the transcoder level. We may want to
706 			// configure dithering, but the code below ignores the previous
707 			// value in the register and may mess things up so we should do
708 			// this in a safeer way. For now, assume the BIOS did the right
709 			// thing.
710 #if 0
711 			// Disable panel fitting, but enable 8 to 6-bit dithering
712 			write32(INTEL_PANEL_FIT_CONTROL, 0x4);
713 				// TODO: do not do this if the connected panel is 24-bit
714 				// (I don't know how to detect that)
715 #endif
716 		}
717 	}
718 
719 	// Set fCurrentMode to our set display mode
720 	memcpy(&fCurrentMode, target, sizeof(display_mode));
721 
722 	return B_OK;
723 }
724 
725 
726 // #pragma mark - DVI/SDVO/generic
727 
728 
729 DigitalPort::DigitalPort(port_index index, const char* baseName)
730 	:
731 	Port(index, baseName)
732 {
733 }
734 
735 
736 bool
737 DigitalPort::IsConnected()
738 {
739 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
740 		_PortRegister());
741 
742 	// As this port overlaps with pretty much everything, this must be called
743 	// after having ruled out all other port types.
744 	return HasEDID();
745 }
746 
747 
748 addr_t
749 DigitalPort::_DDCRegister()
750 {
751 	//TODO: IS BROXTON, B = B, C = C, D = NIL
752 	switch (PortIndex()) {
753 		case INTEL_PORT_B:
754 			return INTEL_I2C_IO_E;
755 		case INTEL_PORT_C:
756 			return INTEL_I2C_IO_D;
757 		case INTEL_PORT_D:
758 			return INTEL_I2C_IO_F;
759 		default:
760 			return 0;
761 	}
762 
763 	return 0;
764 }
765 
766 
767 addr_t
768 DigitalPort::_PortRegister()
769 {
770 	switch (PortIndex()) {
771 		case INTEL_PORT_A:
772 			return INTEL_DIGITAL_PORT_A;
773 		case INTEL_PORT_B:
774 			return INTEL_DIGITAL_PORT_B;
775 		case INTEL_PORT_C:
776 			return INTEL_DIGITAL_PORT_C;
777 		default:
778 			return 0;
779 	}
780 	return 0;
781 }
782 
783 
784 status_t
785 DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
786 {
787 	CALLED();
788 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
789 		target->virtual_height);
790 
791 	if (fPipe == NULL) {
792 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
793 		return B_ERROR;
794 	}
795 
796 	// Setup PanelFitter and Train FDI if it exists
797 	PanelFitter* fitter = fPipe->PFT();
798 	if (fitter != NULL)
799 		fitter->Enable(*target);
800 	FDILink* link = fPipe->FDI();
801 	if (link != NULL)
802 		link->Train(target);
803 
804 	pll_divisors divisors;
805 	compute_pll_divisors(target, &divisors, false);
806 
807 	uint32 extraPLLFlags = 0;
808 	if (gInfo->shared_info->device_type.Generation() >= 3)
809 		extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
810 
811 	// Program general pipe config
812 	fPipe->Configure(target);
813 
814 	// Program pipe PLL's
815 	fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
816 
817 	// Program target display mode
818 	fPipe->ConfigureTimings(target);
819 
820 	// Set fCurrentMode to our set display mode
821 	memcpy(&fCurrentMode, target, sizeof(display_mode));
822 
823 	return B_OK;
824 }
825 
826 
827 // #pragma mark - LVDS Panel
828 // #pragma mark - HDMI
829 
830 
831 HDMIPort::HDMIPort(port_index index)
832 	:
833 	DigitalPort(index, "HDMI")
834 {
835 }
836 
837 
838 bool
839 HDMIPort::IsConnected()
840 {
841 	if (!gInfo->shared_info->device_type.SupportsHDMI())
842 		return false;
843 
844 	addr_t portRegister = _PortRegister();
845 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
846 		portRegister);
847 
848 	if (portRegister == 0)
849 		return false;
850 
851 	//Notes:
852 	//- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is
853 	//  connected to the port *if* you have the AUX channel stuff under power. It does not
854 	//  tell you which -type- of digital display is connected.
855 	//- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :)
856 	//  Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit
857 	//  for DPMS as well. So we should better buffer our findings here for i.e. possible
858 	//  accelerant clones starting up. For DPMS there's currently no problem as this bit
859 	//  is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI.
860 	//
861 	//if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0)
862 	if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0)
863 		return false;
864 
865 	return HasEDID();
866 }
867 
868 
869 addr_t
870 HDMIPort::_PortRegister()
871 {
872 	// on PCH there's an additional port sandwiched in
873 	bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE);
874 	bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV);
875 
876 	switch (PortIndex()) {
877 		case INTEL_PORT_B:
878 			if (fourthGen)
879 				return GEN4_HDMI_PORT_B;
880 			return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B;
881 		case INTEL_PORT_C:
882 			if (fourthGen)
883 				return GEN4_HDMI_PORT_C;
884 			return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C;
885 		case INTEL_PORT_D:
886 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV))
887 				return CHV_HDMI_PORT_D;
888 			return hasPCH ? PCH_HDMI_PORT_D : 0;
889 		default:
890 			return 0;
891 		}
892 
893 	return 0;
894 }
895 
896 
897 // #pragma mark - DisplayPort
898 
899 
900 DisplayPort::DisplayPort(port_index index, const char* baseName)
901 	:
902 	Port(index, baseName)
903 {
904 }
905 
906 
907 pipe_index
908 DisplayPort::PipePreference()
909 {
910 	CALLED();
911 	if (gInfo->shared_info->device_type.Generation() <= 4)
912 		return INTEL_PIPE_ANY;
913 
914 	// Notes:
915 	// - The BIOSes seen sofar do not use PIPE C by default.
916 	// - Looks like BIOS selected Transcoder (A,B,C) is not always same as selected Pipe (A,B,C)
917 	//   so these should probably be handled seperately. For now this is OK as we don't touch
918 	//   the pipe for DisplayPort, only the transcoder..
919 	uint32 TranscoderPort = INTEL_TRANS_DP_PORT_NONE;
920 	switch (PortIndex()) {
921 		case INTEL_PORT_A:
922 			return INTEL_PIPE_ANY;
923 		case INTEL_PORT_B:
924 			TranscoderPort = INTEL_TRANS_DP_PORT_B;
925 			break;
926 		case INTEL_PORT_C:
927 			TranscoderPort = INTEL_TRANS_DP_PORT_C;
928 			break;
929 		case INTEL_PORT_D:
930 			TranscoderPort = INTEL_TRANS_DP_PORT_D;
931 			break;
932 		default:
933 			return INTEL_PIPE_ANY;
934 	}
935 
936 	for (uint32 Transcoder = 0; Transcoder < 3; Transcoder++) {
937 		if ((read32(INTEL_TRANSCODER_A_DP_CTL + (Transcoder << 12)) & INTEL_TRANS_DP_PORT_MASK) ==
938 			INTEL_TRANS_DP_PORT(TranscoderPort)) {
939 			switch (Transcoder) {
940 				case 0:
941 					return INTEL_PIPE_A;
942 				case 1:
943 					return INTEL_PIPE_B;
944 				case 2:
945 					return INTEL_PIPE_C;
946 			}
947 		}
948 	}
949 
950 	return INTEL_PIPE_ANY;
951 }
952 
953 
954 bool
955 DisplayPort::IsConnected()
956 {
957 	addr_t portRegister = _PortRegister();
958 
959 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
960 		portRegister);
961 
962 	if (portRegister == 0)
963 		return false;
964 
965 	//Notes:
966 	//- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is
967 	//  connected to the port *if* you have the AUX channel stuff under power. It does not
968 	//  tell you which -type- of digital display is connected.
969 	//- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :)
970 	//  Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit
971 	//  for DPMS as well. So we should better buffer our findings here for i.e. possible
972 	//  accelerant clones starting up. For DPMS there's currently no problem as this bit
973 	//  is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI.
974 	//
975 	//if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) {
976 	if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0) {
977 		TRACE("%s: %s link not detected\n", __func__, PortName());
978 		return false;
979 	}
980 
981 	//since EDID is not correctly implemented yet for this connection type we'll do without it for now
982 	//return HasEDID();
983 	TRACE("%s: %s link detected\n", __func__, PortName());
984 	return true;
985 }
986 
987 
988 addr_t
989 DisplayPort::_DDCRegister()
990 {
991 	// TODO: Do VLV + CHV use the VLV_DP_AUX_CTL_B + VLV_DP_AUX_CTL_C?
992 	switch (PortIndex()) {
993 		case INTEL_PORT_A:
994 			return INTEL_DP_AUX_CTL_A;
995 		case INTEL_PORT_B:
996 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
997 				return VLV_DP_AUX_CTL_B;
998 			return INTEL_DP_AUX_CTL_B;
999 		case INTEL_PORT_C:
1000 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1001 				return VLV_DP_AUX_CTL_C;
1002 			return INTEL_DP_AUX_CTL_C;
1003 		case INTEL_PORT_D:
1004 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV))
1005 				return CHV_DP_AUX_CTL_D;
1006 			else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1007 				return 0;
1008 			return INTEL_DP_AUX_CTL_D;
1009 		default:
1010 			return 0;
1011 	}
1012 
1013 	return 0;
1014 }
1015 
1016 
1017 addr_t
1018 DisplayPort::_PortRegister()
1019 {
1020 	// There are 6000 lines of intel linux code probing DP registers
1021 	// to properly detect DP vs eDP to then in-turn properly figure out
1022 	// what is DP and what is HDMI. It only takes 3 lines to
1023 	// ignore DisplayPort on ValleyView / CherryView
1024 
1025 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)
1026 		|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) {
1027 		ERROR("TODO: DisplayPort on ValleyView / CherryView");
1028 		return 0;
1029 	}
1030 
1031 	// Intel, are humans even involved anymore?
1032 	// This is a lot more complex than this code makes it look. (see defines)
1033 	// INTEL_DISPLAY_PORT_X moves around a lot based on PCH
1034 	// except on ValleyView and CherryView.
1035 	switch (PortIndex()) {
1036 		case INTEL_PORT_A:
1037 			return INTEL_DISPLAY_PORT_A;
1038 		case INTEL_PORT_B:
1039 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1040 				return VLV_DISPLAY_PORT_B;
1041 			return INTEL_DISPLAY_PORT_B;
1042 		case INTEL_PORT_C:
1043 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1044 				return VLV_DISPLAY_PORT_C;
1045 			return INTEL_DISPLAY_PORT_C;
1046 		case INTEL_PORT_D:
1047 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV))
1048 				return CHV_DISPLAY_PORT_D;
1049 			else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1050 				return 0;
1051 			return INTEL_DISPLAY_PORT_D;
1052 		default:
1053 			return 0;
1054 	}
1055 
1056 	return 0;
1057 }
1058 
1059 
1060 status_t
1061 DisplayPort::_SetPortLinkGen4(display_mode* target)
1062 {
1063 	// Khz / 10. ( each output octet encoded as 10 bits.
1064 	//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz
1065 	//fixme: always so?
1066 	uint32 linkBandwidth = 270000; //khz
1067 	uint32 fPipeOffset = 0;
1068 	if (fPipe->Index() == INTEL_PIPE_B)
1069 		fPipeOffset = 0x1000;
1070 
1071 	TRACE("%s: DP M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset));
1072 	TRACE("%s: DP N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset));
1073 	TRACE("%s: DP M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset));
1074 	TRACE("%s: DP N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset));
1075 
1076 	uint32 bitsPerPixel = 24;	//fixme: always so?
1077 	uint32 lanes = 4;			//fixme: always so?
1078 
1079 	//Setup Data M/N
1080 	uint64 linkspeed = lanes * linkBandwidth * 8;
1081 	uint64 ret_n = 1;
1082 	while(ret_n < linkspeed) {
1083 		ret_n *= 2;
1084 	}
1085 	if (ret_n > 0x800000) {
1086 		ret_n = 0x800000;
1087 	}
1088 	uint64 ret_m = target->timing.pixel_clock * ret_n * bitsPerPixel / linkspeed;
1089 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
1090 		ret_m >>= 1;
1091 		ret_n >>= 1;
1092 	}
1093 	//Set TU size bits (to default, max) before link training so that error detection works
1094 	write32(INTEL_PIPE_A_DATA_M + fPipeOffset, ret_m | FDI_PIPE_MN_TU_SIZE_MASK);
1095 	write32(INTEL_PIPE_A_DATA_N + fPipeOffset, ret_n);
1096 
1097 	//Setup Link M/N
1098 	linkspeed = linkBandwidth;
1099 	ret_n = 1;
1100 	while(ret_n < linkspeed) {
1101 		ret_n *= 2;
1102 	}
1103 	if (ret_n > 0x800000) {
1104 		ret_n = 0x800000;
1105 	}
1106 	ret_m = target->timing.pixel_clock * ret_n / linkspeed;
1107 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
1108 		ret_m >>= 1;
1109 		ret_n >>= 1;
1110 	}
1111 	write32(INTEL_PIPE_A_LINK_M + fPipeOffset, ret_m);
1112 	//Writing Link N triggers all four registers to be activated also (on next VBlank)
1113 	write32(INTEL_PIPE_A_LINK_N + fPipeOffset, ret_n);
1114 
1115 	TRACE("%s: DP M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset));
1116 	TRACE("%s: DP N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset));
1117 	TRACE("%s: DP M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset));
1118 	TRACE("%s: DP N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset));
1119 
1120 	return B_OK;
1121 }
1122 
1123 
1124 status_t
1125 DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
1126 {
1127 	CALLED();
1128 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
1129 		target->virtual_height);
1130 
1131 	if (fPipe == NULL) {
1132 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
1133 		return B_ERROR;
1134 	}
1135 
1136 	status_t result = B_OK;
1137 	if (gInfo->shared_info->device_type.Generation() <= 4) {
1138 		fPipe->ConfigureTimings(target);
1139 		result = _SetPortLinkGen4(target);
1140 	} else {
1141 		//fixme: doesn't work yet. For now just scale to native mode.
1142 #if 0
1143 		// Setup PanelFitter and Train FDI if it exists
1144 		PanelFitter* fitter = fPipe->PFT();
1145 		if (fitter != NULL)
1146 			fitter->Enable(*target);
1147 		FDILink* link = fPipe->FDI();
1148 		if (link != NULL)
1149 			link->Train(target);
1150 
1151 		pll_divisors divisors;
1152 		compute_pll_divisors(target, &divisors, false);
1153 
1154 		uint32 extraPLLFlags = 0;
1155 		if (gInfo->shared_info->device_type.Generation() >= 3)
1156 			extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
1157 
1158 		// Program general pipe config
1159 		fPipe->Configure(target);
1160 
1161 		// Program pipe PLL's
1162 		fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
1163 
1164 		// Program target display mode
1165 		fPipe->ConfigureTimings(target);
1166 #endif
1167 
1168 		// Keep monitor at native mode and scale image to that
1169 		fPipe->ConfigureScalePos(target);
1170 	}
1171 
1172 	// Set fCurrentMode to our set display mode
1173 	memcpy(&fCurrentMode, target, sizeof(display_mode));
1174 
1175 	return result;
1176 }
1177 
1178 
1179 // #pragma mark - Embedded DisplayPort
1180 
1181 
1182 EmbeddedDisplayPort::EmbeddedDisplayPort()
1183 	:
1184 	DisplayPort(INTEL_PORT_A, "Embedded DisplayPort")
1185 {
1186 }
1187 
1188 
1189 bool
1190 EmbeddedDisplayPort::IsConnected()
1191 {
1192 	addr_t portRegister = _PortRegister();
1193 
1194 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
1195 		portRegister);
1196 
1197 	if (!gInfo->shared_info->device_type.IsMobile()) {
1198 		TRACE("%s: skipping eDP on non-mobile GPU\n", __func__);
1199 		return false;
1200 	}
1201 
1202 	if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) {
1203 		TRACE("%s: %s link not detected\n", __func__, PortName());
1204 		return false;
1205 	}
1206 
1207 	HasEDID();
1208 
1209 	// If eDP has EDID, awesome. We use it.
1210 	// No EDID? The modesetting code falls back to VBIOS panel_mode
1211 	return true;
1212 }
1213 
1214 
1215 // #pragma mark - Digital Display Port
1216 
1217 
1218 DigitalDisplayInterface::DigitalDisplayInterface(port_index index,
1219 		const char* baseName)
1220 	:
1221 	Port(index, baseName)
1222 {
1223 	// As of Haswell, Intel decided to change eDP ports to a "DDI" bus...
1224 	// on a dare because the hardware engineers were drunk one night.
1225 }
1226 
1227 
1228 addr_t
1229 DigitalDisplayInterface::_PortRegister()
1230 {
1231 	// TODO: Linux does a DDI_BUF_CTL(INTEL_PORT_A) which is cleaner
1232 	// (but we have to ensure the offsets + region base is correct)
1233 	switch (PortIndex()) {
1234 		case INTEL_PORT_A:
1235 			return DDI_BUF_CTL_A;
1236 		case INTEL_PORT_B:
1237 			return DDI_BUF_CTL_B;
1238 		case INTEL_PORT_C:
1239 			return DDI_BUF_CTL_C;
1240 		case INTEL_PORT_D:
1241 			return DDI_BUF_CTL_D;
1242 		case INTEL_PORT_E:
1243 			return DDI_BUF_CTL_E;
1244 		default:
1245 			return 0;
1246 	}
1247 	return 0;
1248 }
1249 
1250 
1251 addr_t
1252 DigitalDisplayInterface::_DDCRegister()
1253 {
1254 	// TODO: No idea, does DDI have DDC?
1255 	return 0;
1256 }
1257 
1258 
1259 status_t
1260 DigitalDisplayInterface::Power(bool enabled)
1261 {
1262 	TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(),
1263 		enabled ? "true" : "false");
1264 
1265 	fPipe->Enable(enabled);
1266 
1267 	addr_t portRegister = _PortRegister();
1268 	uint32 state = read32(portRegister);
1269 	write32(portRegister,
1270 		enabled ? (state | DDI_BUF_CTL_ENABLE) : (state & ~DDI_BUF_CTL_ENABLE));
1271 	read32(portRegister);
1272 
1273 	return B_OK;
1274 }
1275 
1276 
1277 bool
1278 DigitalDisplayInterface::IsConnected()
1279 {
1280 	addr_t portRegister = _PortRegister();
1281 
1282 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
1283 		portRegister);
1284 
1285 	if (portRegister == 0)
1286 		return false;
1287 
1288 	if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) {
1289 		TRACE("%s: %s link not detected\n", __func__, PortName());
1290 		return false;
1291 	}
1292 
1293 	// Probe a little port info.
1294 	if ((read32(DDI_BUF_CTL_A) & DDI_A_4_LANES) != 0) {
1295 		switch (PortIndex()) {
1296 			case INTEL_PORT_A:
1297 				fMaxLanes = 4;
1298 				break;
1299 			case INTEL_PORT_E:
1300 				fMaxLanes = 0;
1301 				break;
1302 			default:
1303 				fMaxLanes = 4;
1304 				break;
1305 		}
1306 	} else {
1307 		switch (PortIndex()) {
1308 			case INTEL_PORT_A:
1309 				fMaxLanes = 2;
1310 				break;
1311 			case INTEL_PORT_E:
1312 				fMaxLanes = 2;
1313 				break;
1314 			default:
1315 				fMaxLanes = 4;
1316 				break;
1317 		}
1318 	}
1319 
1320 	TRACE("%s: %s Maximum Lanes: %" B_PRId8 "\n", __func__,
1321 		PortName(), fMaxLanes);
1322 
1323 	//since EDID is not correctly implemented yet for this connection type we'll do without it for now
1324 	//return HasEDID();
1325 	TRACE("%s: %s link detected\n", __func__, PortName());
1326 	return true;
1327 }
1328 
1329 
1330 status_t
1331 DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
1332 {
1333 	CALLED();
1334 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
1335 		target->virtual_height);
1336 
1337 	if (fPipe == NULL) {
1338 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
1339 		return B_ERROR;
1340 	}
1341 
1342 	// Setup PanelFitter and Train FDI if it exists
1343 	PanelFitter* fitter = fPipe->PFT();
1344 	if (fitter != NULL)
1345 		fitter->Enable(*target);
1346 	// Skip FDI if we have a CPU connected display
1347 	if (PortIndex() != INTEL_PORT_A) {
1348 		FDILink* link = fPipe->FDI();
1349 		if (link != NULL)
1350 			link->Train(target);
1351 	}
1352 
1353 	pll_divisors divisors;
1354 	compute_pll_divisors(target, &divisors, false);
1355 
1356 	uint32 extraPLLFlags = 0;
1357 	if (gInfo->shared_info->device_type.Generation() >= 3)
1358 		extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
1359 
1360 	// Program general pipe config
1361 	fPipe->Configure(target);
1362 
1363 	// Program pipe PLL's
1364 	fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
1365 
1366 	// Program target display mode
1367 	fPipe->ConfigureTimings(target);
1368 
1369 	// Set fCurrentMode to our set display mode
1370 	memcpy(&fCurrentMode, target, sizeof(display_mode));
1371 
1372 	return B_OK;
1373 }
1374