xref: /haiku/src/add-ons/accelerants/intel_extreme/Ports.cpp (revision ab3c8bea07449c2305e9b9ad10421e316ce1d453)
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  *		Rudolf Cornelissen, ruud@highsand-juicylake.nl
10  */
11 
12 
13 #include "Ports.h"
14 
15 #include <ddc.h>
16 #include <dp_raw.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <Debug.h>
20 #include <KernelExport.h>
21 
22 #include "accelerant.h"
23 #include "accelerant_protos.h"
24 #include "FlexibleDisplayInterface.h"
25 #include "intel_extreme.h"
26 #include "PanelFitter.h"
27 
28 #include <new>
29 
30 
31 #undef TRACE
32 #define TRACE_PORTS
33 #ifdef TRACE_PORTS
34 #   define TRACE(x...) _sPrintf("intel_extreme: " x)
35 #else
36 #   define TRACE(x...)
37 #endif
38 
39 #define ERROR(x...) _sPrintf("intel_extreme: " x)
40 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
41 
42 
43 static bool
44 wait_for_set(addr_t address, uint32 mask, uint32 timeout)
45 {
46 	int interval = 50;
47 	uint32 i = 0;
48 	for(i = 0; i <= timeout; i += interval) {
49 		spin(interval);
50 		if ((read32(address) & mask) != 0)
51 			return true;
52 	}
53 	return false;
54 }
55 
56 
57 static bool
58 wait_for_clear(addr_t address, uint32 mask, uint32 timeout)
59 {
60 	int interval = 50;
61 	uint32 i = 0;
62 	for(i = 0; i <= timeout; i += interval) {
63 		spin(interval);
64 		if ((read32(address) & mask) == 0)
65 			return true;
66 	}
67 	return false;
68 }
69 
70 
71 static uint32
72 wait_for_clear_status(addr_t address, uint32 mask, uint32 timeout)
73 {
74 	int interval = 50;
75 	uint32 i = 0;
76 	uint32 status = 0;
77 	for(i = 0; i <= timeout; i += interval) {
78 		spin(interval);
79 		status = read32(address);
80 		if ((status & mask) == 0)
81 			return status;
82 	}
83 	return status;
84 }
85 
86 
87 Port::Port(port_index index, const char* baseName)
88 	:
89 	fPipe(NULL),
90 	fEDIDState(B_NO_INIT),
91 	fPortIndex(index),
92 	fPortName(NULL)
93 {
94 	char portID[2];
95 	portID[0] = 'A' + index - INTEL_PORT_A;
96 	portID[1] = 0;
97 
98 	char buffer[32];
99 	buffer[0] = 0;
100 
101 	strlcat(buffer, baseName, sizeof(buffer));
102 	strlcat(buffer, " ", sizeof(buffer));
103 	strlcat(buffer, portID, sizeof(buffer));
104 	fPortName = strdup(buffer);
105 }
106 
107 
108 Port::~Port()
109 {
110 	free(fPortName);
111 }
112 
113 
114 bool
115 Port::HasEDID()
116 {
117 	if (fEDIDState == B_NO_INIT)
118 		GetEDID(NULL);
119 
120 	return fEDIDState == B_OK;
121 }
122 
123 
124 status_t
125 Port::SetPipe(Pipe* pipe)
126 {
127 	CALLED();
128 
129 	if (pipe == NULL) {
130 		ERROR("%s: Invalid pipe provided!\n", __func__);
131 		return B_ERROR;
132 	}
133 
134 	uint32 portRegister = _PortRegister();
135 	if (portRegister == 0) {
136 		ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__,
137 			portRegister, PortName());
138 		return B_ERROR;
139 	}
140 
141 	// TODO: UnAssignPipe?  This likely needs reworked a little
142 	if (fPipe != NULL) {
143 		ERROR("%s: Can't reassign display pipe (yet)\n", __func__);
144 		return B_ERROR;
145 	}
146 
147 	switch (pipe->Index()) {
148 		case INTEL_PIPE_B:
149 			TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe B\n", __func__,
150 				PortName(), portRegister);
151 			break;
152 		case INTEL_PIPE_C:
153 			TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe C\n", __func__,
154 				PortName(), portRegister);
155 			break;
156 		case INTEL_PIPE_D:
157 			TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe D\n", __func__,
158 				PortName(), portRegister);
159 			break;
160 		default:
161 			TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe A\n", __func__,
162 				PortName(), portRegister);
163 			break;
164 	}
165 
166 	uint32 portState = read32(portRegister);
167 
168 	// generation 6 gfx SandyBridge/SNB non-DP use the same 2 bits on all ports (eDP = 1 bit).
169 	// generation 7 gfx IvyBridge/IVB non-DP use the same 2 bits on all ports (eDP = 2 bits).
170 	// DP ports/all DDI ports: Pipe selections works differently, via own SetPipe() implementation.
171 	if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
172 		portState &= ~PORT_TRANS_SEL_MASK;
173 		switch (pipe->Index()) {
174 			case INTEL_PIPE_B:
175 				write32(portRegister, portState | PORT_TRANS_B_SEL_CPT);
176 				break;
177 			case INTEL_PIPE_C:
178 				write32(portRegister, portState | PORT_TRANS_C_SEL_CPT);
179 				break;
180 			default:
181 				write32(portRegister, portState | PORT_TRANS_A_SEL_CPT);
182 				break;
183 		}
184 	} else {
185 		// generation 3/4/5 gfx uses the same single bit on all ports
186 		if (pipe->Index() == INTEL_PIPE_A)
187 			write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B);
188 		else
189 			write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B);
190 	}
191 	fPipe = pipe;
192 
193 	if (fPipe == NULL)
194 		return B_NO_MEMORY;
195 
196 	// Disable display pipe until modesetting enables it
197 	if (fPipe->IsEnabled())
198 		fPipe->Enable(false);
199 
200 	read32(portRegister);
201 
202 	return B_OK;
203 }
204 
205 
206 status_t
207 Port::Power(bool enabled)
208 {
209 	if (fPipe == NULL) {
210 		ERROR("%s: Setting power mode without assigned pipe!\n", __func__);
211 		return B_ERROR;
212 	}
213 
214 	fPipe->Enable(enabled);
215 
216 	return B_OK;
217 }
218 
219 
220 status_t
221 Port::GetEDID(edid1_info* edid, bool forceRead)
222 {
223 	CALLED();
224 
225 	if (fEDIDState == B_NO_INIT || forceRead) {
226 		TRACE("%s: trying to read EDID\n", PortName());
227 
228 		i2c_bus bus;
229 		if (SetupI2c(&bus) != B_OK)
230 			return fEDIDState;
231 
232 		fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL);
233 
234 		if (fEDIDState == B_OK) {
235 			TRACE("%s: found EDID information!\n", PortName());
236 			edid_dump(&fEDIDInfo);
237 		}
238 	}
239 
240 	if (fEDIDState != B_OK) {
241 		TRACE("%s: no EDID information found.\n", PortName());
242 		return fEDIDState;
243 	}
244 
245 	if (edid != NULL)
246 		memcpy(edid, &fEDIDInfo, sizeof(edid1_info));
247 
248 	return B_OK;
249 }
250 
251 
252 status_t
253 Port::SetupI2c(i2c_bus *bus)
254 {
255 	addr_t ddcRegister = _DDCRegister();
256 	if (ddcRegister == 0) {
257 		TRACE("%s: no DDC register found\n", PortName());
258 		fEDIDState = B_ERROR;
259 		return fEDIDState;
260 	}
261 
262 	TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister);
263 
264 	ddc2_init_timing(bus);
265 	bus->cookie = (void*)ddcRegister;
266 	bus->set_signals = &_SetI2CSignals;
267 	bus->get_signals = &_GetI2CSignals;
268 
269 	return B_OK;
270 }
271 
272 
273 status_t
274 Port::GetPLLLimits(pll_limits& limits)
275 {
276 	return B_ERROR;
277 }
278 
279 
280 pipe_index
281 Port::PipePreference()
282 {
283 	CALLED();
284 	// Ideally we could just return INTEL_PIPE_ANY for all devices by default, but
285 	// this doesn't quite work yet. We need to use the BIOS presetup pipes for now.
286 	if (gInfo->shared_info->device_type.Generation() < 4)
287 		return INTEL_PIPE_ANY;
288 
289 	// Notes:
290 	// - The BIOSes seen sofar do not use PIPE C by default.
291 	// - The BIOSes seen sofar program transcoder A to PIPE A, etc.
292 	// - Later devices add a pipe C alongside the added transcoder C.
293 
294 	if ((gInfo->shared_info->device_type.Generation() <= 7) &&
295 		(!gInfo->shared_info->device_type.HasDDI())) {
296 		uint32 portState = read32(_PortRegister());
297 		if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
298 			portState &= PORT_TRANS_SEL_MASK;
299 			if (portState == PORT_TRANS_B_SEL_CPT)
300 				return INTEL_PIPE_B;
301 			else
302 				return INTEL_PIPE_A;
303 		} else {
304 			if (portState & DISPLAY_MONITOR_PIPE_B)
305 				return INTEL_PIPE_B;
306 			else
307 				return INTEL_PIPE_A;
308 		}
309 	}
310 
311 	if (gInfo->shared_info->device_type.HasDDI()) {
312 		// scan all our pipes to find the one connected to the current port
313 		uint32 pipeState = 0;
314 		for (uint32 pipeCnt = 0; pipeCnt < 4; pipeCnt++) {
315 			switch (pipeCnt) {
316 				case 0:
317 					pipeState = read32(PIPE_DDI_FUNC_CTL_A);
318 					break;
319 				case 1:
320 					pipeState = read32(PIPE_DDI_FUNC_CTL_B);
321 					break;
322 				case 2:
323 					pipeState = read32(PIPE_DDI_FUNC_CTL_C);
324 					break;
325 				default:
326 					pipeState = read32(PIPE_DDI_FUNC_CTL_EDP);
327 					break;
328 			}
329 
330 			if ((((pipeState & PIPE_DDI_SELECT_MASK) >> PIPE_DDI_SELECT_SHIFT) + 1)
331 				== (uint32)PortIndex()) {
332 				switch (pipeCnt) {
333 					case 0:
334 						return INTEL_PIPE_A;
335 					case 1:
336 						return INTEL_PIPE_B;
337 					case 2:
338 						return INTEL_PIPE_C;
339 					default:
340 						return INTEL_PIPE_D;
341 				}
342 			}
343 		}
344 	}
345 
346 	return INTEL_PIPE_ANY;
347 }
348 
349 
350 status_t
351 Port::_GetI2CSignals(void* cookie, int* _clock, int* _data)
352 {
353 	addr_t ioRegister = (addr_t)cookie;
354 	uint32 value = read32(ioRegister);
355 
356 	*_clock = (value & I2C_CLOCK_VALUE_IN) != 0;
357 	*_data = (value & I2C_DATA_VALUE_IN) != 0;
358 
359 	return B_OK;
360 }
361 
362 
363 status_t
364 Port::_SetI2CSignals(void* cookie, int clock, int data)
365 {
366 	addr_t ioRegister = (addr_t)cookie;
367 	uint32 value;
368 
369 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_83x)) {
370 		// on these chips, the reserved values are fixed
371 		value = 0;
372 	} else {
373 		// on all others, we have to preserve them manually
374 		value = read32(ioRegister) & I2C_RESERVED;
375 	}
376 
377 	// if we send clk or data, we always send low logic level;
378 	// if we want to send high level, we actually receive and let the
379 	// external pullup resistors create the high level on the bus.
380 	value |= I2C_DATA_VALUE_MASK;  //sets data = 0, always latch
381 	value |= I2C_CLOCK_VALUE_MASK; //sets clock = 0, always latch
382 
383 	if (data != 0)
384 		value |= I2C_DATA_DIRECTION_MASK;
385 	else {
386 		value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT;
387 	}
388 
389 	if (clock != 0)
390 		value |= I2C_CLOCK_DIRECTION_MASK;
391 	else {
392 		value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT;
393 	}
394 
395 	write32(ioRegister, value);
396 	read32(ioRegister);
397 		// make sure the PCI bus has flushed the write
398 
399 	return B_OK;
400 }
401 
402 
403 // #pragma mark - Analog Port
404 
405 
406 AnalogPort::AnalogPort()
407 	:
408 	Port(INTEL_PORT_A, "Analog")
409 {
410 }
411 
412 
413 bool
414 AnalogPort::IsConnected()
415 {
416 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
417 		_PortRegister());
418 	return HasEDID();
419 }
420 
421 
422 addr_t
423 AnalogPort::_DDCRegister()
424 {
425 	// always fixed
426 	return INTEL_I2C_IO_A;
427 }
428 
429 
430 addr_t
431 AnalogPort::_PortRegister()
432 {
433 	// always fixed
434 	return INTEL_ANALOG_PORT;
435 }
436 
437 
438 status_t
439 AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
440 {
441 	CALLED();
442 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display,
443 		target->timing.v_display);
444 
445 	if (fPipe == NULL) {
446 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
447 		return B_ERROR;
448 	}
449 
450 	// Setup PanelFitter and Train FDI if it exists
451 	PanelFitter* fitter = fPipe->PFT();
452 	if (fitter != NULL)
453 		fitter->Enable(target->timing);
454 	FDILink* link = fPipe->FDI();
455 	if (link != NULL) {
456 		uint32 lanes = 0;
457 		uint32 linkBandwidth = 0;
458 		uint32 bitsPerPixel = 0;
459 		link->PreTrain(&target->timing, &linkBandwidth, &lanes, &bitsPerPixel);
460 		fPipe->SetFDILink(target->timing, linkBandwidth, lanes, bitsPerPixel);
461 		link->Train(&target->timing, lanes);
462 	}
463 	pll_divisors divisors;
464 	compute_pll_divisors(&target->timing, &divisors, false);
465 
466 	uint32 extraPLLFlags = 0;
467 	if (gInfo->shared_info->device_type.Generation() >= 3)
468 		extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
469 
470 	// Program general pipe config
471 	fPipe->Configure(target);
472 
473 	// Program pipe PLL's
474 	fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
475 
476 	write32(_PortRegister(), (read32(_PortRegister())
477 		& ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY))
478 		| ((target->timing.flags & B_POSITIVE_HSYNC) != 0
479 			? DISPLAY_MONITOR_POSITIVE_HSYNC : 0)
480 		| ((target->timing.flags & B_POSITIVE_VSYNC) != 0
481 			? DISPLAY_MONITOR_POSITIVE_VSYNC : 0));
482 
483 	// Program target display mode
484 	fPipe->ConfigureTimings(target);
485 
486 	// Set fCurrentMode to our set display mode
487 	memcpy(&fCurrentMode, target, sizeof(display_mode));
488 
489 	return B_OK;
490 }
491 
492 
493 // #pragma mark - LVDS Panel
494 
495 
496 LVDSPort::LVDSPort()
497 	:
498 	Port(INTEL_PORT_C, "LVDS")
499 {
500 	// Always unlock LVDS port as soon as we start messing with it.
501 	uint32 panelControl = INTEL_PANEL_CONTROL;
502 	if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
503 		// FIXME writing there results in black screen on SandyBridge
504 		return;
505 		// panelControl = PCH_PANEL_CONTROL;
506 	}
507 	write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK);
508 }
509 
510 
511 pipe_index
512 LVDSPort::PipePreference()
513 {
514 	CALLED();
515 	// Older devices have hardcoded pipe/port mappings, so just use that
516 	if (gInfo->shared_info->device_type.Generation() < 4)
517 		return INTEL_PIPE_B;
518 
519 	// Ideally we could just return INTEL_PIPE_ANY for the newer devices, but
520 	// this doesn't quite work yet.
521 
522 	// On SandyBridge and later, there is a transcoder C. On SandyBridge at least
523 	// that can't be used by the LVDS port (but A and B would be fine).
524 	// On Ibex Point, SandyBridge and IvyBridge (tested) changing pipes does not
525 	// work yet.
526 	// Notes:
527 	// - Switching Pipes only works reliably when a 'full modeswitch' is executed
528 	//   (FDI training) so we have to reuse the BIOS preset setup always for now.
529 	// - The BIOSes seen sofar do not use PIPE C by default.
530 	// - The BIOSes seen sofar program transcoder A to PIPE A, etc.
531 	// - Later devices add a pipe C alongside the added transcoder C.
532 
533 	// FIXME How's this setup in newer gens? Currently return Pipe B fixed there..
534 	if (gInfo->shared_info->device_type.Generation() <= 7) {
535 		uint32 portState = read32(_PortRegister());
536 		if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
537 			portState &= PORT_TRANS_SEL_MASK;
538 			if (portState == PORT_TRANS_B_SEL_CPT)
539 				return INTEL_PIPE_B;
540 			else
541 				return INTEL_PIPE_A;
542 		} else {
543 			if (portState & DISPLAY_MONITOR_PIPE_B)
544 				return INTEL_PIPE_B;
545 			else
546 				return INTEL_PIPE_A;
547 		}
548 	}
549 
550 	return INTEL_PIPE_B;
551 }
552 
553 
554 bool
555 LVDSPort::IsConnected()
556 {
557 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
558 		_PortRegister());
559 
560 	if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
561 		uint32 registerValue = read32(_PortRegister());
562 		// there's a detection bit we can use
563 		if ((registerValue & PCH_LVDS_DETECTED) == 0) {
564 			TRACE("LVDS: Not detected\n");
565 			return false;
566 		}
567 		// TODO: Skip if eDP support
568 	} else if (gInfo->shared_info->device_type.Generation() <= 4) {
569 		// Older generations don't have LVDS detection. If not mobile skip.
570 		if (!gInfo->shared_info->device_type.IsMobile()) {
571 			TRACE("LVDS: Skipping LVDS detection due to gen and not mobile\n");
572 			return false;
573 		}
574 		// If mobile, try to grab EDID
575 		// Linux seems to look at lid status for LVDS port detection
576 		// If we don't get EDID, we can use vbios native mode or vesa?
577 		if (!HasEDID()) {
578 			if (gInfo->shared_info->has_vesa_edid_info) {
579 				TRACE("LVDS: Using VESA edid info\n");
580 				memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
581 					sizeof(edid1_info));
582 				if (fEDIDState != B_OK) {
583 					fEDIDState = B_OK;
584 					// HasEDID now true
585 					edid_dump(&fEDIDInfo);
586 				}
587 			} else if (gInfo->shared_info->got_vbt) {
588 				TRACE("LVDS: No EDID, but force enabled as we have a VBT\n");
589 				return true;
590 			} else {
591 				TRACE("LVDS: Couldn't find any valid EDID!\n");
592 				return false;
593 			}
594 		}
595 	}
596 
597 	// Try getting EDID, as the LVDS port doesn't overlap with anything else,
598 	// we don't run the risk of getting someone else's data.
599 	return HasEDID();
600 }
601 
602 
603 addr_t
604 LVDSPort::_DDCRegister()
605 {
606 	// always fixed
607 	return INTEL_I2C_IO_C;
608 }
609 
610 
611 addr_t
612 LVDSPort::_PortRegister()
613 {
614 	// always fixed
615 	return INTEL_DIGITAL_LVDS_PORT;
616 }
617 
618 
619 status_t
620 LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
621 {
622 	CALLED();
623 	if (target == NULL) {
624 		ERROR("%s: Invalid target mode passed!\n", __func__);
625 		return B_ERROR;
626 	}
627 
628 	TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(),
629 		target->timing.h_display, target->timing.v_display);
630 
631 	if (fPipe == NULL) {
632 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
633 		return B_ERROR;
634 	}
635 
636 	addr_t panelControl = INTEL_PANEL_CONTROL;
637 	addr_t panelStatus = INTEL_PANEL_STATUS;
638 	if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
639 		panelControl = PCH_PANEL_CONTROL;
640 		panelStatus = PCH_PANEL_STATUS;
641 	}
642 
643 	if (gInfo->shared_info->device_type.Generation() != 4) {
644 		// TODO not needed on any generation if we are using the panel fitter
645 		// Power off Panel
646 		write32(panelControl,
647 			read32(panelControl) & ~PANEL_CONTROL_POWER_TARGET_ON);
648 		read32(panelControl);
649 
650 		if (!wait_for_clear(panelStatus, PANEL_STATUS_POWER_ON, 1000)) {
651 			ERROR("%s: %s didn't power off within 1000ms!\n", __func__,
652 				PortName());
653 		}
654 	}
655 
656 	// For LVDS panels, we may need to set the timings according to the panel
657 	// native video mode, and let the panel fitter do the scaling. But the
658 	// place where the scaling happens varies accross generations of devices.
659 	display_timing hardwareTarget;
660 	bool needsScaling = false;
661 
662 	// TODO figure out how it's done (or if we need to configure something at
663 	// all) for other generations
664 	if (gInfo->shared_info->device_type.Generation() <= 6
665 		&& gInfo->shared_info->device_type.Generation() >= 3
666 		&& gInfo->shared_info->got_vbt) {
667 		// Set vbios hardware panel mode as base
668 		hardwareTarget = gInfo->shared_info->panel_timing;
669 
670 		if (hardwareTarget.h_display == target->timing.h_display
671 				&& hardwareTarget.v_display == target->timing.v_display) {
672 			// We are setting the native video mode, nothing special to do
673 			// Note: this means refresh and timing might vary according to requested mode.
674 			hardwareTarget = target->timing;
675 			TRACE("%s: Setting LVDS to native resolution at %" B_PRIu32 "Hz\n", __func__,
676 				hardwareTarget.pixel_clock * 1000 / (hardwareTarget.h_total * hardwareTarget.v_total));
677 		} else {
678 			// We need to enable the panel fitter
679 			TRACE("%s: Hardware mode will actually be %dx%d at %" B_PRIu32 "Hz\n", __func__,
680 				hardwareTarget.h_display, hardwareTarget.v_display,
681 				hardwareTarget.pixel_clock * 1000 / (hardwareTarget.h_total * hardwareTarget.v_total));
682 
683 			// FIXME we should also get the refresh frequency from the target
684 			// mode, and then "sanitize" the resulting mode we made up.
685 			needsScaling = true;
686 		}
687 	} else {
688 		TRACE("Setting LVDS mode without VBT info or on unhandled hardware "
689 			"generation, scaling may not work\n");
690 		// We don't have VBT data, try to set the requested mode directly
691 		// and hope for the best
692 		hardwareTarget = target->timing;
693 	}
694 
695 	// Setup PanelFitter and Train FDI if it exists
696 	PanelFitter* fitter = fPipe->PFT();
697 	if (fitter != NULL)
698 		fitter->Enable(hardwareTarget);
699 	FDILink* link = fPipe->FDI();
700 	if (link != NULL) {
701 		uint32 lanes = 0;
702 		uint32 linkBandwidth = 0;
703 		uint32 bitsPerPixel = 0;
704 		link->PreTrain(&hardwareTarget, &linkBandwidth, &lanes, &bitsPerPixel);
705 		fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel);
706 		link->Train(&hardwareTarget, lanes);
707 	}
708 
709 	pll_divisors divisors;
710 	compute_pll_divisors(&hardwareTarget, &divisors, true);
711 
712 	uint32 lvds = read32(_PortRegister())
713 		| LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
714 
715 	if (gInfo->shared_info->device_type.Generation() == 4) {
716 		// LVDS_A3_POWER_UP == 24bpp
717 		// otherwise, 18bpp
718 		if ((lvds & LVDS_A3_POWER_MASK) != LVDS_A3_POWER_UP)
719 			lvds |= LVDS_18BIT_DITHER;
720 	}
721 
722 	// LVDS on PCH needs set before display enable
723 	if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
724 		lvds &= ~PORT_TRANS_SEL_MASK;
725 		if (fPipe->Index() == INTEL_PIPE_A)
726 			lvds |= PORT_TRANS_A_SEL_CPT;
727 		else
728 			lvds |= PORT_TRANS_B_SEL_CPT;
729 	}
730 
731 	// Set the B0-B3 data pairs corresponding to whether we're going to
732 	// set the DPLLs for dual-channel mode or not.
733 	if (divisors.p2 == 5 || divisors.p2 == 7) {
734 		TRACE("LVDS: dual channel\n");
735 		lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
736 	} else {
737 		TRACE("LVDS: single channel\n");
738 		lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
739 	}
740 
741 	// LVDS port control moves polarity bits because Intel hates you.
742 	// Set LVDS sync polarity
743 	lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
744 
745 	// set on - polarity.
746 	if ((target->timing.flags & B_POSITIVE_HSYNC) == 0)
747 		lvds |= LVDS_HSYNC_POLARITY;
748 	if ((target->timing.flags & B_POSITIVE_VSYNC) == 0)
749 		lvds |= LVDS_VSYNC_POLARITY;
750 
751 	TRACE("%s: LVDS Write: 0x%" B_PRIx32 "\n", __func__, lvds);
752 	write32(_PortRegister(), lvds);
753 	read32(_PortRegister());
754 
755 	uint32 extraPLLFlags = 0;
756 
757 	// DPLL mode LVDS for i915+
758 	if (gInfo->shared_info->device_type.Generation() >= 3)
759 		extraPLLFlags |= DISPLAY_PLL_MODE_LVDS | DISPLAY_PLL_2X_CLOCK;
760 
761 	// Program general pipe config
762 	fPipe->Configure(target);
763 
764 	// Program pipe PLL's (using the hardware mode timings, since that's what
765 	// the PLL is used for)
766 	fPipe->ConfigureClocks(divisors, hardwareTarget.pixel_clock,
767 		extraPLLFlags);
768 
769 	if (gInfo->shared_info->device_type.Generation() != 4) {
770 		// G45: no need to power the panel off
771 		// Power on Panel
772 		write32(panelControl,
773 			read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON);
774 		read32(panelControl);
775 
776 		if (!wait_for_set(panelStatus, PANEL_STATUS_POWER_ON, 1000)) {
777 			ERROR("%s: %s didn't power on within 1000us!\n", __func__,
778 				PortName());
779 		}
780 	}
781 
782 	// Program target display mode
783 	fPipe->ConfigureTimings(target, !needsScaling);
784 
785 	if (needsScaling) {
786 		if (gInfo->shared_info->device_type.Generation() <= 4) {
787 			// Enable panel fitter in automatic mode. It will figure out
788 			// the scaling ratios automatically.
789 			uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL);
790 			panelFitterControl |= PANEL_FITTER_ENABLED;
791 			panelFitterControl &= ~(PANEL_FITTER_SCALING_MODE_MASK
792 				| PANEL_FITTER_PIPE_MASK);
793 			panelFitterControl |= PANEL_FITTER_PIPE_B;
794 			// LVDS is always on pipe B.
795 			write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl);
796 		}
797 		// TODO do we need to do anything on later generations?
798 	} else {
799 		if (gInfo->shared_info->device_type.Generation() == 4
800 			|| gInfo->shared_info->device_type.Generation() == 3) {
801 			// Bypass the panel fitter
802 			uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL);
803 			panelFitterControl &= ~PANEL_FITTER_ENABLED;
804 			write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl);
805 		} else {
806 			// We don't need to do anything more for later generations, the
807 			// scaling is handled at the transcoder level. We may want to
808 			// configure dithering, but the code below ignores the previous
809 			// value in the register and may mess things up so we should do
810 			// this in a safeer way. For now, assume the BIOS did the right
811 			// thing.
812 #if 0
813 			// Disable panel fitting, but enable 8 to 6-bit dithering
814 			write32(INTEL_PANEL_FIT_CONTROL, 0x4);
815 				// TODO: do not do this if the connected panel is 24-bit
816 				// (I don't know how to detect that)
817 #endif
818 		}
819 	}
820 
821 	// Set fCurrentMode to our set display mode
822 	memcpy(&fCurrentMode, target, sizeof(display_mode));
823 
824 	return B_OK;
825 }
826 
827 
828 // #pragma mark - DVI/SDVO/generic
829 
830 
831 DigitalPort::DigitalPort(port_index index, const char* baseName)
832 	:
833 	Port(index, baseName)
834 {
835 }
836 
837 
838 bool
839 DigitalPort::IsConnected()
840 {
841 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
842 		_PortRegister());
843 
844 	// As this port overlaps with pretty much everything, this must be called
845 	// after having ruled out all other port types.
846 	return HasEDID();
847 }
848 
849 
850 addr_t
851 DigitalPort::_DDCRegister()
852 {
853 	//TODO: IS BROXTON, B = B, C = C, D = NIL
854 	switch (PortIndex()) {
855 		case INTEL_PORT_B:
856 			return INTEL_I2C_IO_E;
857 		case INTEL_PORT_C:
858 			return INTEL_I2C_IO_D;
859 		case INTEL_PORT_D:
860 			return INTEL_I2C_IO_F;
861 		default:
862 			return 0;
863 	}
864 
865 	return 0;
866 }
867 
868 
869 addr_t
870 DigitalPort::_PortRegister()
871 {
872 	switch (PortIndex()) {
873 		case INTEL_PORT_A:
874 			return INTEL_DIGITAL_PORT_A;
875 		case INTEL_PORT_B:
876 			return INTEL_DIGITAL_PORT_B;
877 		case INTEL_PORT_C:
878 			return INTEL_DIGITAL_PORT_C;
879 		default:
880 			return 0;
881 	}
882 	return 0;
883 }
884 
885 
886 status_t
887 DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
888 {
889 	CALLED();
890 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display,
891 		target->timing.v_display);
892 
893 	if (fPipe == NULL) {
894 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
895 		return B_ERROR;
896 	}
897 
898 	// Setup PanelFitter and Train FDI if it exists
899 	PanelFitter* fitter = fPipe->PFT();
900 	if (fitter != NULL)
901 		fitter->Enable(target->timing);
902 	FDILink* link = fPipe->FDI();
903 	if (link != NULL) {
904 		uint32 lanes = 0;
905 		uint32 linkBandwidth = 0;
906 		uint32 bitsPerPixel = 0;
907 		link->PreTrain(&target->timing, &linkBandwidth, &lanes, &bitsPerPixel);
908 		fPipe->SetFDILink(target->timing, linkBandwidth, lanes, bitsPerPixel);
909 		link->Train(&target->timing, lanes);
910 	}
911 
912 	pll_divisors divisors;
913 	compute_pll_divisors(&target->timing, &divisors, false);
914 
915 	uint32 extraPLLFlags = 0;
916 	if (gInfo->shared_info->device_type.Generation() >= 3)
917 		extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
918 
919 	// Program general pipe config
920 	fPipe->Configure(target);
921 
922 	// Program pipe PLL's
923 	fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
924 
925 	// Program target display mode
926 	fPipe->ConfigureTimings(target);
927 
928 	// Set fCurrentMode to our set display mode
929 	memcpy(&fCurrentMode, target, sizeof(display_mode));
930 
931 	return B_OK;
932 }
933 
934 
935 // #pragma mark - LVDS Panel
936 // #pragma mark - HDMI
937 
938 
939 HDMIPort::HDMIPort(port_index index)
940 	:
941 	DigitalPort(index, "HDMI")
942 {
943 }
944 
945 
946 bool
947 HDMIPort::IsConnected()
948 {
949 	if (!gInfo->shared_info->device_type.SupportsHDMI())
950 		return false;
951 
952 	addr_t portRegister = _PortRegister();
953 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
954 		portRegister);
955 
956 	if (portRegister == 0)
957 		return false;
958 
959 	//Notes:
960 	//- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is
961 	//  connected to the port *if* you have the AUX channel stuff under power. It does not
962 	//  tell you which -type- of digital display is connected.
963 	//- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :)
964 	//  Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit
965 	//  for DPMS as well. So we should better buffer our findings here for i.e. possible
966 	//  accelerant clones starting up. For DPMS there's currently no problem as this bit
967 	//  is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI.
968 	//
969 	//if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0)
970 	if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0)
971 		return false;
972 
973 	return HasEDID();
974 }
975 
976 
977 addr_t
978 HDMIPort::_PortRegister()
979 {
980 	// on PCH there's an additional port sandwiched in
981 	bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE);
982 	bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV);
983 
984 	switch (PortIndex()) {
985 		case INTEL_PORT_B:
986 			if (fourthGen)
987 				return GEN4_HDMI_PORT_B;
988 			return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B;
989 		case INTEL_PORT_C:
990 			if (fourthGen)
991 				return GEN4_HDMI_PORT_C;
992 			return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C;
993 		case INTEL_PORT_D:
994 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV))
995 				return CHV_HDMI_PORT_D;
996 			return hasPCH ? PCH_HDMI_PORT_D : 0;
997 		default:
998 			return 0;
999 		}
1000 
1001 	return 0;
1002 }
1003 
1004 
1005 // #pragma mark - DisplayPort
1006 
1007 
1008 DisplayPort::DisplayPort(port_index index, const char* baseName)
1009 	:
1010 	Port(index, baseName)
1011 {
1012 }
1013 
1014 
1015 pipe_index
1016 DisplayPort::PipePreference()
1017 {
1018 	CALLED();
1019 	if (gInfo->shared_info->device_type.Generation() <= 4)
1020 		return INTEL_PIPE_ANY;
1021 
1022 	// Notes:
1023 	// - The BIOSes seen sofar do not use PIPE C by default.
1024 	// - Looks like BIOS selected Transcoder (A,B,C) is not always same as selected Pipe (A,B,C)
1025 	//   so these should probably be handled seperately. For now this is OK as we don't touch
1026 	//   the pipe for DisplayPort, only the transcoder..
1027 	uint32 TranscoderPort = INTEL_TRANS_DP_PORT_NONE;
1028 	switch (PortIndex()) {
1029 		case INTEL_PORT_A:
1030 			if (gInfo->shared_info->device_type.Generation() == 6) {
1031 				if (((read32(INTEL_DISPLAY_PORT_A) & INTEL_DISP_PORTA_SNB_PIPE_MASK)
1032 					>> INTEL_DISP_PORTA_SNB_PIPE_SHIFT) == INTEL_DISP_PORTA_SNB_PIPE_A) {
1033 					return INTEL_PIPE_A;
1034 				} else {
1035 					return INTEL_PIPE_B;
1036 				}
1037 			}
1038 			if (gInfo->shared_info->device_type.Generation() == 7) {
1039 				uint32 Pipe = (read32(INTEL_DISPLAY_PORT_A) & INTEL_DISP_PORTA_IVB_PIPE_MASK)
1040 					>> INTEL_DISP_PORTA_IVB_PIPE_SHIFT;
1041 				switch (Pipe) {
1042 					case INTEL_DISP_PORTA_IVB_PIPE_A:
1043 						return INTEL_PIPE_A;
1044 					case INTEL_DISP_PORTA_IVB_PIPE_B:
1045 						return INTEL_PIPE_B;
1046 					case INTEL_DISP_PORTA_IVB_PIPE_C:
1047 						return INTEL_PIPE_C;
1048 					default:
1049 						return INTEL_PIPE_ANY;
1050 				}
1051 			}
1052 			return INTEL_PIPE_ANY;
1053 		case INTEL_PORT_B:
1054 			TranscoderPort = INTEL_TRANS_DP_PORT_B;
1055 			break;
1056 		case INTEL_PORT_C:
1057 			TranscoderPort = INTEL_TRANS_DP_PORT_C;
1058 			break;
1059 		case INTEL_PORT_D:
1060 			TranscoderPort = INTEL_TRANS_DP_PORT_D;
1061 			break;
1062 		default:
1063 			return INTEL_PIPE_ANY;
1064 	}
1065 
1066 	for (uint32 Transcoder = 0; Transcoder < 3; Transcoder++) {
1067 		if ((read32(INTEL_TRANSCODER_A_DP_CTL + (Transcoder << 12)) & INTEL_TRANS_DP_PORT_MASK) ==
1068 			INTEL_TRANS_DP_PORT(TranscoderPort)) {
1069 			switch (Transcoder) {
1070 				case 0:
1071 					return INTEL_PIPE_A;
1072 				case 1:
1073 					return INTEL_PIPE_B;
1074 				case 2:
1075 					return INTEL_PIPE_C;
1076 			}
1077 		}
1078 	}
1079 
1080 	return INTEL_PIPE_ANY;
1081 }
1082 
1083 
1084 status_t
1085 DisplayPort::SetPipe(Pipe* pipe)
1086 {
1087 	CALLED();
1088 
1089 	if (pipe == NULL) {
1090 		ERROR("%s: Invalid pipe provided!\n", __func__);
1091 		return B_ERROR;
1092 	}
1093 
1094 	// TODO: UnAssignPipe?  This likely needs reworked a little
1095 	if (fPipe != NULL) {
1096 		ERROR("%s: Can't reassign display pipe (yet)\n", __func__);
1097 		return B_ERROR;
1098 	}
1099 
1100 	// generation 3/4/5 gfx have no eDP ports.
1101 	// generation 6 gfx SandyBridge/SNB uses one bit (b30) on the eDP port.
1102 	// generation 7 gfx IvyBridge/IVB uses 2 bits (b29-30) on the eDP port.
1103 	// on all other DP ports pipe selections works differently (indirect).
1104 	// fixme: implement..
1105 	TRACE("%s: Assuming pipe is assigned by BIOS (fixme)\n", __func__);
1106 
1107 	fPipe = pipe;
1108 
1109 	if (fPipe == NULL)
1110 		return B_NO_MEMORY;
1111 
1112 	// Disable display pipe until modesetting enables it
1113 	if (fPipe->IsEnabled())
1114 		fPipe->Enable(false);
1115 
1116 	return B_OK;
1117 }
1118 
1119 
1120 bool
1121 DisplayPort::IsConnected()
1122 {
1123 	addr_t portRegister = _PortRegister();
1124 
1125 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
1126 		portRegister);
1127 
1128 	if (portRegister == 0)
1129 		return false;
1130 
1131 	//Notes:
1132 	//- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is
1133 	//  connected to the port *if* you have the AUX channel stuff under power. It does not
1134 	//  tell you which -type- of digital display is connected.
1135 	//- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :)
1136 	//  Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit
1137 	//  for DPMS as well. So we should better buffer our findings here for i.e. possible
1138 	//  accelerant clones starting up. For DPMS there's currently no problem as this bit
1139 	//  is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI.
1140 	//
1141 	//if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) {
1142 	if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0) {
1143 		TRACE("%s: %s link not detected\n", __func__, PortName());
1144 		return false;
1145 	}
1146 
1147 	TRACE("%s: %s link detected\n", __func__, PortName());
1148 
1149 	// On laptops we always have an internal panel.. (this is on the eDP port)
1150 	if (gInfo->shared_info->device_type.IsMobile() && (PortIndex() == INTEL_PORT_A)) {
1151 		if (gInfo->shared_info->has_vesa_edid_info) {
1152 			TRACE("%s: Laptop. Using VESA edid info\n", __func__);
1153 			memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
1154 				sizeof(edid1_info));
1155 			if (fEDIDState != B_OK) {
1156 				fEDIDState = B_OK;
1157 				// HasEDID now true
1158 				edid_dump(&fEDIDInfo);
1159 			}
1160 			return true;
1161 		} else if (gInfo->shared_info->got_vbt) {
1162 			TRACE("%s: Laptop. No EDID, but force enabled as we have a VBT\n", __func__);
1163 			return true;
1164 		}
1165 	}
1166 
1167 	//since EDID is not correctly implemented yet for this connection type we'll do without it for now
1168 	//return HasEDID();
1169 	return true;
1170 }
1171 
1172 
1173 addr_t
1174 DisplayPort::_DDCRegister()
1175 {
1176 	return 0;
1177 }
1178 
1179 
1180 status_t
1181 DigitalDisplayInterface::SetupI2c(i2c_bus *bus)
1182 {
1183 	CALLED();
1184 	ddc2_init_timing(bus);
1185 	bus->cookie = this;
1186 	bus->send_receive = &_DpAuxSendReceiveHook;
1187 
1188 	if (gInfo->shared_info->device_type.Generation() >= 11) {
1189 		uint32 value = read32(ICL_PWR_WELL_CTL_AUX2);
1190 		if ((value & HSW_PWR_WELL_CTL_STATE(0)) != 0)
1191 			return B_OK;
1192 
1193 		write32(ICL_PWR_WELL_CTL_AUX2, value | HSW_PWR_WELL_CTL_REQ(0));
1194 		if (!wait_for_set(ICL_PWR_WELL_CTL_AUX2, HSW_PWR_WELL_CTL_STATE(0), 1000))
1195 			ERROR("%s: %s AUX didn't power on within 1000us!\n", __func__, PortName());
1196 	}
1197 	return B_OK;
1198 }
1199 
1200 
1201 
1202 status_t
1203 DigitalDisplayInterface::_DpAuxSendReceive(uint32 slaveAddress,
1204 	const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
1205 {
1206 	size_t transferLength = 16;
1207 
1208 	dp_aux_msg message;
1209 	memset(&message, 0, sizeof(message));
1210 
1211 	if (writeBuffer != NULL) {
1212 		message.address = slaveAddress;
1213 		message.buffer = NULL;
1214 		message.request = DP_AUX_I2C_WRITE;
1215 		message.size = 0;
1216 		ssize_t result = _DpAuxTransfer(&message);
1217 		if (result < 0)
1218 			return result;
1219 
1220 		for (size_t i = 0; i < writeLength;) {
1221 			message.buffer = (void*)(writeBuffer + i);
1222 			message.size = min_c(transferLength, writeLength - i);
1223 			// Middle-Of-Transmission on final transaction
1224 			if (writeLength - i > transferLength)
1225 				message.request |= DP_AUX_I2C_MOT;
1226 			else
1227 				message.request &= ~DP_AUX_I2C_MOT;
1228 
1229 			for (int attempt = 0; attempt < 7; attempt++) {
1230 				ssize_t result = _DpAuxTransfer(&message);
1231 				if (result < 0) {
1232 					ERROR("%s: aux_ch transaction failed!\n", __func__);
1233 					return result;
1234 				}
1235 
1236 				switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
1237 					case DP_AUX_I2C_REPLY_ACK:
1238 						goto nextWrite;
1239 					case DP_AUX_I2C_REPLY_NACK:
1240 						TRACE("%s: aux i2c nack\n", __func__);
1241 						return B_IO_ERROR;
1242 					case DP_AUX_I2C_REPLY_DEFER:
1243 						TRACE("%s: aux i2c defer\n", __func__);
1244 						snooze(400);
1245 						break;
1246 					default:
1247 						TRACE("%s: aux invalid I2C reply: 0x%02x\n",
1248 							__func__, message.reply);
1249 						return B_ERROR;
1250 				}
1251 			}
1252 nextWrite:
1253 			if (result < 0)
1254 				return result;
1255 			i += message.size;
1256 		}
1257 	}
1258 
1259 
1260 	if (readBuffer != NULL) {
1261 		message.address = slaveAddress;
1262 		message.buffer = NULL;
1263 		message.request = DP_AUX_I2C_READ;
1264 		message.size = 0;
1265 		ssize_t result = _DpAuxTransfer(&message);
1266 		if (result < 0)
1267 			return result;
1268 
1269 		for (size_t i = 0; i < readLength;) {
1270 			message.buffer = readBuffer + i;
1271 			message.size = min_c(transferLength, readLength - i);
1272 			// Middle-Of-Transmission on final transaction
1273 			if (readLength - i > transferLength)
1274 				message.request |= DP_AUX_I2C_MOT;
1275 			else
1276 				message.request &= ~DP_AUX_I2C_MOT;
1277 
1278 			for (int attempt = 0; attempt < 7; attempt++) {
1279 				result = _DpAuxTransfer(&message);
1280 				if (result < 0) {
1281 					ERROR("%s: aux_ch transaction failed!\n", __func__);
1282 					return result;
1283 				}
1284 
1285 				switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
1286 					case DP_AUX_I2C_REPLY_ACK:
1287 						goto nextRead;
1288 					case DP_AUX_I2C_REPLY_NACK:
1289 						TRACE("%s: aux i2c nack\n", __func__);
1290 						return B_IO_ERROR;
1291 					case DP_AUX_I2C_REPLY_DEFER:
1292 						TRACE("%s: aux i2c defer\n", __func__);
1293 						snooze(400);
1294 						break;
1295 					default:
1296 						TRACE("%s: aux invalid I2C reply: 0x%02x\n",
1297 							__func__, message.reply);
1298 						return B_ERROR;
1299 				}
1300 			}
1301 nextRead:
1302 			if (result < 0)
1303 				return result;
1304 			if (result == 0)
1305 				i += message.size;
1306 		}
1307 	}
1308 
1309 	return B_OK;
1310 }
1311 
1312 
1313 status_t
1314 DigitalDisplayInterface::_DpAuxSendReceiveHook(const struct i2c_bus *bus, uint32 slaveAddress,
1315 	const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
1316 {
1317 	CALLED();
1318 	DigitalDisplayInterface* port = (DigitalDisplayInterface*)bus->cookie;
1319 	return port->_DpAuxSendReceive(slaveAddress, writeBuffer, writeLength, readBuffer, readLength);
1320 }
1321 
1322 
1323 ssize_t
1324 DigitalDisplayInterface::_DpAuxTransfer(dp_aux_msg* message)
1325 {
1326 	CALLED();
1327 	if (message == NULL) {
1328 		ERROR("%s: DP message is invalid!\n", __func__);
1329 		return B_ERROR;
1330 	}
1331 
1332 	if (message->size > 16) {
1333 		ERROR("%s: Too many bytes! (%" B_PRIuSIZE ")\n", __func__,
1334 			message->size);
1335 		return B_ERROR;
1336 	}
1337 
1338 	uint8 transmitSize = message->size > 0 ? 4 : 3;
1339 	uint8 receiveSize;
1340 
1341 	switch(message->request & ~DP_AUX_I2C_MOT) {
1342 		case DP_AUX_NATIVE_WRITE:
1343 		case DP_AUX_I2C_WRITE:
1344 		case DP_AUX_I2C_WRITE_STATUS_UPDATE:
1345 			transmitSize += message->size;
1346 			break;
1347 	}
1348 
1349 	// If not bare address, check for buffer
1350 	if (message->size > 0 && message->buffer == NULL) {
1351 		ERROR("%s: DP message uninitalized buffer!\n", __func__);
1352 		return B_ERROR;
1353 	}
1354 
1355 	uint8 receiveBuffer[20];
1356 	uint8 transmitBuffer[20];
1357 	transmitBuffer[0] = (message->request << 4) | ((message->address >> 16) & 0xf);
1358 	transmitBuffer[1] = (message->address >> 8) & 0xff;
1359 	transmitBuffer[2] = message->address & 0xff;
1360 	transmitBuffer[3] = message->size != 0 ? (message->size - 1) : 0;
1361 
1362 	uint8 retry;
1363 	for (retry = 0; retry < 7; retry++) {
1364 		ssize_t result = B_ERROR;
1365 		switch(message->request & ~DP_AUX_I2C_MOT) {
1366 			case DP_AUX_NATIVE_WRITE:
1367 			case DP_AUX_I2C_WRITE:
1368 			case DP_AUX_I2C_WRITE_STATUS_UPDATE:
1369 				receiveSize = 2;
1370 				if (message->buffer != NULL)
1371 					memcpy(transmitBuffer + 4, message->buffer, message->size);
1372 				result = _DpAuxTransfer(transmitBuffer,
1373 					transmitSize, receiveBuffer, receiveSize);
1374 				if (result > 0) {
1375 					message->reply = receiveBuffer[0] >> 4;
1376 					if (result > 1)
1377 						result = min_c(receiveBuffer[1], message->size);
1378 					else
1379 						result = message->size;
1380 				}
1381 				break;
1382 			case DP_AUX_NATIVE_READ:
1383 			case DP_AUX_I2C_READ:
1384 				receiveSize = message->size + 1;
1385 				result = _DpAuxTransfer(transmitBuffer,
1386 					transmitSize, receiveBuffer, receiveSize);
1387 				if (result > 0) {
1388 					message->reply = receiveBuffer[0] >> 4;
1389 					result--;
1390 					memcpy(message->buffer, receiveBuffer + 1, result);
1391 				}
1392 				break;
1393 			default:
1394 				ERROR("%s: Unknown dp_aux_msg request!\n", __func__);
1395 				return B_ERROR;
1396 		}
1397 
1398 		if (result == B_BUSY)
1399 			continue;
1400 		else if (result < B_OK)
1401 			return result;
1402 
1403 		switch(message->reply & DP_AUX_NATIVE_REPLY_MASK) {
1404 			case DP_AUX_NATIVE_REPLY_ACK:
1405 				return B_OK;
1406 			case DP_AUX_NATIVE_REPLY_DEFER:
1407 				TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
1408 				snooze(400);
1409 				break;
1410 			default:
1411 				TRACE("%s: aux invalid native reply: 0x%02x\n", __func__,
1412 					message->reply);
1413 				return B_IO_ERROR;
1414 		}
1415 	}
1416 
1417 	ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry);
1418 	return B_IO_ERROR;
1419 }
1420 
1421 
1422 ssize_t
1423 DigitalDisplayInterface::_DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSize,
1424 	uint8* receiveBuffer, uint8 receiveSize)
1425 {
1426 	addr_t channelControl;
1427 	addr_t channelData[5];
1428 	if (gInfo->shared_info->device_type.Generation() >= 9) {
1429 		// assume AUX channel 0
1430 		channelControl = DP_AUX_CH_CTL(0);
1431 		for (int i = 0; i < 5; i++)
1432 			channelData[i] = DP_AUX_CH_DATA(0, i);
1433 	} else {
1434 		ERROR("DigitalDisplayInterface::_DpAuxTransfer() unknown register config\n");
1435 		return B_BUSY;
1436 	}
1437 	if (transmitSize > 20 || receiveSize > 20)
1438 		return E2BIG;
1439 
1440 	int tries = 0;
1441 	while ((read32(channelControl) & INTEL_DP_AUX_CTL_BUSY) != 0) {
1442 		if (tries++ == 3) {
1443 			ERROR("%s: %s AUX channel is busy!\n", __func__, PortName());
1444 			return B_BUSY;
1445 		}
1446 		snooze(1000);
1447 	}
1448 
1449 	uint32 sendControl = 0;
1450 	if (gInfo->shared_info->device_type.Generation() >= 9) {
1451 		sendControl = INTEL_DP_AUX_CTL_BUSY | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_INTERRUPT
1452 			| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | INTEL_DP_AUX_CTL_TIMEOUT_1600us | INTEL_DP_AUX_CTL_RECEIVE_ERROR
1453 			| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | INTEL_DP_AUX_CTL_FW_SYNC_PULSE_SKL(32)
1454 			| INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(32);
1455 	}
1456 
1457 	uint8 retry;
1458 	uint32 status = 0;
1459 	for (retry = 0; retry < 5; retry++) {
1460 		for (uint8 i = 0; i < transmitSize;) {
1461 			uint8 index = i / 4;
1462 			uint32 data = ((uint32)transmitBuffer[i++]) << 24;
1463 			if (i < transmitSize)
1464 				data |= ((uint32)transmitBuffer[i++]) << 16;
1465 			if (i < transmitSize)
1466 				data |= ((uint32)transmitBuffer[i++]) << 8;
1467 			if (i < transmitSize)
1468 				data |= transmitBuffer[i++];
1469 			write32(channelData[index], data);
1470 		}
1471 		write32(channelControl, sendControl);
1472 
1473 		// wait 10 ms reading channelControl until INTEL_DP_AUX_CTL_BUSY
1474 		status = wait_for_clear_status(channelControl, INTEL_DP_AUX_CTL_BUSY, 10000);
1475 		if ((status & INTEL_DP_AUX_CTL_BUSY) != 0) {
1476 			ERROR("%s: %s AUX channel stayed busy for 10000us!\n", __func__, PortName());
1477 		}
1478 
1479 		write32(channelControl, status | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_TIMEOUT_ERROR
1480 			| INTEL_DP_AUX_CTL_RECEIVE_ERROR);
1481 		if ((status & INTEL_DP_AUX_CTL_TIMEOUT_ERROR) != 0)
1482 			continue;
1483 		if ((status & INTEL_DP_AUX_CTL_RECEIVE_ERROR) != 0) {
1484 			snooze(400);
1485 			continue;
1486 		}
1487 		if ((status & INTEL_DP_AUX_CTL_DONE) != 0)
1488 			goto done;
1489 	}
1490 
1491 	if ((status & INTEL_DP_AUX_CTL_DONE) == 0) {
1492 		ERROR("%s: Busy Error. %" B_PRIu8 " attempts\n", __func__, retry);
1493 		return B_BUSY;
1494 	}
1495 done:
1496 	if ((status & INTEL_DP_AUX_CTL_RECEIVE_ERROR) != 0)
1497 		return B_IO_ERROR;
1498 	if ((status & INTEL_DP_AUX_CTL_TIMEOUT_ERROR) != 0)
1499 		return B_TIMEOUT;
1500 
1501 	uint8 bytes = (status & INTEL_DP_AUX_CTL_MSG_SIZE_MASK) >> INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT;
1502 	if (bytes == 0 || bytes > 20) {
1503 		ERROR("%s: Status byte count incorrect %u\n", __func__, bytes);
1504 		return B_BUSY;
1505 	}
1506 	if (bytes > receiveSize)
1507 		bytes = receiveSize;
1508 	for (uint8 i = 0; i < bytes;) {
1509 		uint32 data = read32(channelData[i / 4]);
1510 		receiveBuffer[i++] = data >> 24;
1511 		if (i < bytes)
1512 			receiveBuffer[i++] = data >> 16;
1513 		if (i < bytes)
1514 			receiveBuffer[i++] = data >> 8;
1515 		if (i < bytes)
1516 			receiveBuffer[i++] = data;
1517 	}
1518 
1519 	return bytes;
1520 }
1521 
1522 
1523 addr_t
1524 DisplayPort::_PortRegister()
1525 {
1526 	// There are 6000 lines of intel linux code probing DP registers
1527 	// to properly detect DP vs eDP to then in-turn properly figure out
1528 	// what is DP and what is HDMI. It only takes 3 lines to
1529 	// ignore DisplayPort on ValleyView / CherryView
1530 
1531 	if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)
1532 		|| gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) {
1533 		ERROR("TODO: DisplayPort on ValleyView / CherryView");
1534 		return 0;
1535 	}
1536 
1537 	// Intel, are humans even involved anymore?
1538 	// This is a lot more complex than this code makes it look. (see defines)
1539 	// INTEL_DISPLAY_PORT_X moves around a lot based on PCH
1540 	// except on ValleyView and CherryView.
1541 	switch (PortIndex()) {
1542 		case INTEL_PORT_A:
1543 			return INTEL_DISPLAY_PORT_A;
1544 		case INTEL_PORT_B:
1545 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1546 				return VLV_DISPLAY_PORT_B;
1547 			return INTEL_DISPLAY_PORT_B;
1548 		case INTEL_PORT_C:
1549 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1550 				return VLV_DISPLAY_PORT_C;
1551 			return INTEL_DISPLAY_PORT_C;
1552 		case INTEL_PORT_D:
1553 			if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV))
1554 				return CHV_DISPLAY_PORT_D;
1555 			else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV))
1556 				return 0;
1557 			return INTEL_DISPLAY_PORT_D;
1558 		default:
1559 			return 0;
1560 	}
1561 
1562 	return 0;
1563 }
1564 
1565 
1566 status_t
1567 DisplayPort::_SetPortLinkGen4(const display_timing& timing)
1568 {
1569 	// Khz / 10. ( each output octet encoded as 10 bits.
1570 	//fixme: always so?
1571 	uint32 linkBandwidth = 270000; //khz
1572 	uint32 fPipeOffset = 0;
1573 	if (fPipe->Index() == INTEL_PIPE_B)
1574 		fPipeOffset = 0x1000;
1575 
1576 	TRACE("%s: DP M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset));
1577 	TRACE("%s: DP N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset));
1578 	TRACE("%s: DP M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset));
1579 	TRACE("%s: DP N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset));
1580 
1581 	uint32 bitsPerPixel = 24;	//fixme: always so?
1582 	uint32 lanes = 4;			//fixme: always so?
1583 
1584 	//Setup Data M/N
1585 	uint64 linkspeed = lanes * linkBandwidth * 8;
1586 	uint64 ret_n = 1;
1587 	while(ret_n < linkspeed) {
1588 		ret_n *= 2;
1589 	}
1590 	if (ret_n > 0x800000) {
1591 		ret_n = 0x800000;
1592 	}
1593 	uint64 ret_m = timing.pixel_clock * ret_n * bitsPerPixel / linkspeed;
1594 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
1595 		ret_m >>= 1;
1596 		ret_n >>= 1;
1597 	}
1598 	//Set TU size bits (to default, max) before link training so that error detection works
1599 	write32(INTEL_PIPE_A_DATA_M + fPipeOffset, ret_m | FDI_PIPE_MN_TU_SIZE_MASK);
1600 	write32(INTEL_PIPE_A_DATA_N + fPipeOffset, ret_n);
1601 
1602 	//Setup Link M/N
1603 	linkspeed = linkBandwidth;
1604 	ret_n = 1;
1605 	while(ret_n < linkspeed) {
1606 		ret_n *= 2;
1607 	}
1608 	if (ret_n > 0x800000) {
1609 		ret_n = 0x800000;
1610 	}
1611 	ret_m = timing.pixel_clock * ret_n / linkspeed;
1612 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
1613 		ret_m >>= 1;
1614 		ret_n >>= 1;
1615 	}
1616 	write32(INTEL_PIPE_A_LINK_M + fPipeOffset, ret_m);
1617 	//Writing Link N triggers all four registers to be activated also (on next VBlank)
1618 	write32(INTEL_PIPE_A_LINK_N + fPipeOffset, ret_n);
1619 
1620 	TRACE("%s: DP M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset));
1621 	TRACE("%s: DP N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset));
1622 	TRACE("%s: DP M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset));
1623 	TRACE("%s: DP N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset));
1624 
1625 	return B_OK;
1626 }
1627 
1628 
1629 status_t
1630 DisplayPort::_SetPortLinkGen6(const display_timing& timing)
1631 {
1632 	// Khz / 10. ( each output octet encoded as 10 bits.
1633 	//note: (fixme) eDP is fixed option 162 or 270Mc, other DPs go via DPLL programming to one of the same vals.
1634 	uint32 linkBandwidth = 270000; //khz
1635 	TRACE("%s: DP link reference clock is %gMhz\n", __func__, linkBandwidth / 1000.0f);
1636 
1637 	uint32 fPipeOffset = 0;
1638 	switch (fPipe->Index()) {
1639 		case INTEL_PIPE_B:
1640 			fPipeOffset = 0x1000;
1641 			break;
1642 		case INTEL_PIPE_C:
1643 			fPipeOffset = 0x2000;
1644 			break;
1645 		default:
1646 			break;
1647 	}
1648 
1649 	TRACE("%s: DP M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_DATA_M1 + fPipeOffset));
1650 	TRACE("%s: DP N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_DATA_N1 + fPipeOffset));
1651 	TRACE("%s: DP M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_LINK_M1 + fPipeOffset));
1652 	TRACE("%s: DP N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_LINK_N1 + fPipeOffset));
1653 
1654 	uint32 bitsPerPixel =
1655 		(read32(INTEL_TRANSCODER_A_DP_CTL + fPipeOffset) & INTEL_TRANS_DP_BPC_MASK) >> INTEL_TRANS_DP_COLOR_SHIFT;
1656 	switch (bitsPerPixel) {
1657 		case PIPE_DDI_8BPC:
1658 			bitsPerPixel = 24;
1659 			break;
1660 		case PIPE_DDI_10BPC:
1661 			bitsPerPixel = 30;
1662 			break;
1663 		case PIPE_DDI_6BPC:
1664 			bitsPerPixel = 18;
1665 			break;
1666 		case PIPE_DDI_12BPC:
1667 			bitsPerPixel = 36;
1668 			break;
1669 		default:
1670 			ERROR("%s: DP illegal link colordepth set.\n", __func__);
1671 			return B_ERROR;
1672 	}
1673 	TRACE("%s: DP link colordepth: %" B_PRIu32 "\n", __func__, bitsPerPixel);
1674 
1675 	uint32 lanes = ((read32(_PortRegister()) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT) + 1;
1676 	if (lanes > 4) {
1677 		ERROR("%s: DP illegal number of lanes set.\n", __func__);
1678 		return B_ERROR;
1679 	}
1680 	TRACE("%s: DP mode with %" B_PRIx32 " lane(s) in use\n", __func__, lanes);
1681 
1682 	//Reserving 5% bandwidth for possible spread spectrum clock use
1683 	uint32 bps = timing.pixel_clock * bitsPerPixel * 21 / 20;
1684 	//use DIV_ROUND_UP:
1685 	uint32 required_lanes = (bps + (linkBandwidth * 8) - 1) / (linkBandwidth * 8);
1686 	TRACE("%s: DP mode needs %" B_PRIx32 " lane(s) in use\n", __func__, required_lanes);
1687 	if (required_lanes > lanes) {
1688 		//Note that we *must* abort as otherwise the PIPE/DP-link hangs forever (without retraining!).
1689 		ERROR("%s: DP not enough lanes active for requested mode.\n", __func__);
1690 		return B_ERROR;
1691 	}
1692 
1693 	//Setup Data M/N
1694 	uint64 linkspeed = lanes * linkBandwidth * 8;
1695 	uint64 ret_n = 1;
1696 	while(ret_n < linkspeed) {
1697 		ret_n *= 2;
1698 	}
1699 	if (ret_n > 0x800000) {
1700 		ret_n = 0x800000;
1701 	}
1702 	uint64 ret_m = timing.pixel_clock * ret_n * bitsPerPixel / linkspeed;
1703 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
1704 		ret_m >>= 1;
1705 		ret_n >>= 1;
1706 	}
1707 	//Set TU size bits (to default, max) before link training so that error detection works
1708 	write32(INTEL_TRANSCODER_A_DATA_M1 + fPipeOffset, ret_m | INTEL_TRANSCODER_MN_TU_SIZE_MASK);
1709 	write32(INTEL_TRANSCODER_A_DATA_N1 + fPipeOffset, ret_n);
1710 
1711 	//Setup Link M/N
1712 	linkspeed = linkBandwidth;
1713 	ret_n = 1;
1714 	while(ret_n < linkspeed) {
1715 		ret_n *= 2;
1716 	}
1717 	if (ret_n > 0x800000) {
1718 		ret_n = 0x800000;
1719 	}
1720 	ret_m = timing.pixel_clock * ret_n / linkspeed;
1721 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
1722 		ret_m >>= 1;
1723 		ret_n >>= 1;
1724 	}
1725 	write32(INTEL_TRANSCODER_A_LINK_M1 + fPipeOffset, ret_m);
1726 	//Writing Link N triggers all four registers to be activated also (on next VBlank)
1727 	write32(INTEL_TRANSCODER_A_LINK_N1 + fPipeOffset, ret_n);
1728 
1729 	TRACE("%s: DP M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_DATA_M1 + fPipeOffset));
1730 	TRACE("%s: DP N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_DATA_N1 + fPipeOffset));
1731 	TRACE("%s: DP M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_LINK_M1 + fPipeOffset));
1732 	TRACE("%s: DP N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_TRANSCODER_A_LINK_N1 + fPipeOffset));
1733 
1734 	return B_OK;
1735 }
1736 
1737 
1738 status_t
1739 DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
1740 {
1741 	CALLED();
1742 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display,
1743 		target->timing.v_display);
1744 
1745 	if (fPipe == NULL) {
1746 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
1747 		return B_ERROR;
1748 	}
1749 
1750 	status_t result = B_OK;
1751 	if (gInfo->shared_info->device_type.Generation() <= 4) {
1752 		fPipe->ConfigureTimings(target);
1753 		result = _SetPortLinkGen4(target->timing);
1754 	} else {
1755 		display_timing hardwareTarget = target->timing;
1756 		bool needsScaling = false;
1757 		if ((PortIndex() == INTEL_PORT_A) && gInfo->shared_info->device_type.IsMobile()) {
1758 			// For internal panels, we may need to set the timings according to the panel
1759 			// native video mode, and let the panel fitter do the scaling.
1760 			// note: upto/including generation 5 laptop panels are still LVDS types, handled elsewhere.
1761 
1762 			if (gInfo->shared_info->got_vbt) {
1763 				// Set vbios hardware panel mode as base
1764 				hardwareTarget = gInfo->shared_info->panel_timing;
1765 
1766 				if (hardwareTarget.h_display == target->timing.h_display
1767 						&& hardwareTarget.v_display == target->timing.v_display) {
1768 					// We are feeding the native video mode, nothing to do: disable scaling
1769 					TRACE("%s: Requested mode is panel's native resolution: disabling scaling\n", __func__);
1770 				} else {
1771 					// We need to enable the panel fitter
1772 					TRACE("%s: Requested mode is not panel's native resolution: enabling scaling\n", __func__);
1773 					needsScaling = true;
1774 				}
1775 			} else {
1776 				//fixme: We should now first try for EDID info detailed timing, highest res in list: that's the
1777 				//native mode as well. If we also have no EDID, then fallback to setting mode directly as below.
1778 
1779 				TRACE("%s: Setting internal panel mode without VBT info generation, scaling may not work\n",
1780 					__func__);
1781 				// We don't have VBT data, try to set the requested mode directly
1782 				// and hope for the best
1783 				hardwareTarget = target->timing;
1784 			}
1785 		}
1786 
1787 		result = B_OK;
1788 		if (PortIndex() != INTEL_PORT_A)
1789 			result = _SetPortLinkGen6(hardwareTarget);
1790 
1791 		if (result == B_OK) {
1792 			// Setup PanelFitter and Train FDI if it exists
1793 			PanelFitter* fitter = fPipe->PFT();
1794 			if (fitter != NULL)
1795 				fitter->Enable(hardwareTarget);
1796 
1797 			uint32 lanes = 0;
1798 			uint32 linkBandwidth = 0;
1799 			uint32 bitsPerPixel = 0;
1800 			if (PortIndex() != INTEL_PORT_A) {
1801 				FDILink* link = fPipe->FDI();
1802 				if (link != NULL) {
1803 					link->PreTrain(&hardwareTarget, &linkBandwidth, &lanes, &bitsPerPixel);
1804 					fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel);
1805 					link->Train(&hardwareTarget, lanes);
1806 				}
1807 			} else {
1808 				// 'local' eDP port is in use
1809 				linkBandwidth =
1810 					(read32(INTEL_DISPLAY_PORT_A) & INTEL_DISP_EDP_PLL_FREQ_MASK) >> INTEL_DISP_EDP_PLL_FREQ_SHIFT;
1811 				switch (linkBandwidth) {
1812 					case INTEL_DISP_EDP_PLL_FREQ_270:
1813 						linkBandwidth = 270000; //khz
1814 						break;
1815 					case INTEL_DISP_EDP_PLL_FREQ_162:
1816 						linkBandwidth = 162000; //khz
1817 						break;
1818 					default:
1819 						TRACE("%s: eDP illegal reference clock ID set, assuming 270Mhz.\n", __func__);
1820 						linkBandwidth = 270000; //khz
1821 				}
1822 
1823 				bitsPerPixel =
1824 					(read32(INTEL_DISPLAY_A_PIPE_CONTROL) & INTEL_PIPE_BPC_MASK) >> INTEL_PIPE_COLOR_SHIFT;
1825 				switch (bitsPerPixel) {
1826 					case INTEL_PIPE_8BPC:
1827 						bitsPerPixel = 24;
1828 						break;
1829 					case INTEL_PIPE_10BPC:
1830 						bitsPerPixel = 30;
1831 						break;
1832 					case INTEL_PIPE_6BPC:
1833 						bitsPerPixel = 18;
1834 						break;
1835 					case INTEL_PIPE_12BPC:
1836 						bitsPerPixel = 36;
1837 						break;
1838 					default:
1839 						bitsPerPixel = 0;
1840 				}
1841 
1842 				lanes =
1843 					((read32(INTEL_DISPLAY_PORT_A) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT) + 1;
1844 
1845 				fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel);
1846 			}
1847 
1848 			// Program general pipe config
1849 			fPipe->Configure(target);
1850 
1851 			// Pll programming is not needed for (e)DP..
1852 
1853 			// Program target display mode
1854 			fPipe->ConfigureTimings(target, !needsScaling, PortIndex());
1855 		} else {
1856 			TRACE("%s: Setting display mode via fallback: using scaling!\n", __func__);
1857 			// Keep monitor at native mode and scale image to that
1858 			fPipe->ConfigureScalePos(target);
1859 		}
1860 	}
1861 
1862 	// Set fCurrentMode to our set display mode
1863 	memcpy(&fCurrentMode, target, sizeof(display_mode));
1864 
1865 	return result;
1866 }
1867 
1868 
1869 // #pragma mark - Embedded DisplayPort
1870 
1871 
1872 EmbeddedDisplayPort::EmbeddedDisplayPort()
1873 	:
1874 	DisplayPort(INTEL_PORT_A, "Embedded DisplayPort")
1875 {
1876 }
1877 
1878 
1879 bool
1880 EmbeddedDisplayPort::IsConnected()
1881 {
1882 	addr_t portRegister = _PortRegister();
1883 
1884 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
1885 		portRegister);
1886 
1887 	if (!gInfo->shared_info->device_type.IsMobile()) {
1888 		TRACE("%s: skipping eDP on non-mobile GPU\n", __func__);
1889 		return false;
1890 	}
1891 
1892 	if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) {
1893 		TRACE("%s: %s link not detected\n", __func__, PortName());
1894 		return false;
1895 	}
1896 
1897 	HasEDID();
1898 
1899 	// If eDP has EDID, awesome. We use it.
1900 	// No EDID? The modesetting code falls back to VBIOS panel_mode
1901 	return true;
1902 }
1903 
1904 
1905 // #pragma mark - Digital Display Port
1906 
1907 
1908 DigitalDisplayInterface::DigitalDisplayInterface(port_index index,
1909 		const char* baseName)
1910 	:
1911 	Port(index, baseName)
1912 {
1913 	// As of Haswell, Intel decided to change eDP ports to a "DDI" bus...
1914 	// on a dare because the hardware engineers were drunk one night.
1915 }
1916 
1917 
1918 addr_t
1919 DigitalDisplayInterface::_PortRegister()
1920 {
1921 	// TODO: Linux does a DDI_BUF_CTL(INTEL_PORT_A) which is cleaner
1922 	// (but we have to ensure the offsets + region base is correct)
1923 	switch (PortIndex()) {
1924 		case INTEL_PORT_A:
1925 			return DDI_BUF_CTL_A;
1926 		case INTEL_PORT_B:
1927 			return DDI_BUF_CTL_B;
1928 		case INTEL_PORT_C:
1929 			return DDI_BUF_CTL_C;
1930 		case INTEL_PORT_D:
1931 			return DDI_BUF_CTL_D;
1932 		case INTEL_PORT_E:
1933 			return DDI_BUF_CTL_E;
1934 		case INTEL_PORT_F:
1935 			if ((gInfo->shared_info->device_type.Generation() > 8) &&
1936 				!gInfo->shared_info->device_type.InGroup(INTEL_GROUP_SKY))
1937 				return DDI_BUF_CTL_F;
1938 			return 0;
1939 		default:
1940 			return 0;
1941 	}
1942 	return 0;
1943 }
1944 
1945 
1946 addr_t
1947 DigitalDisplayInterface::_DDCRegister()
1948 {
1949 	switch (PortIndex()) {
1950 		case INTEL_PORT_B:
1951 			return INTEL_I2C_IO_E;
1952 		case INTEL_PORT_C:
1953 			return INTEL_I2C_IO_D;
1954 		case INTEL_PORT_D:
1955 			return INTEL_I2C_IO_F;
1956 		default:
1957 			return 0;
1958 	}
1959 
1960 	return 0;
1961 }
1962 
1963 
1964 status_t
1965 DigitalDisplayInterface::Power(bool enabled)
1966 {
1967 	if (fPipe == NULL) {
1968 		ERROR("%s: Setting power without assigned pipe!\n", __func__);
1969 		return B_ERROR;
1970 	}
1971 	TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(),
1972 		enabled ? "true" : "false");
1973 
1974 	fPipe->Enable(enabled);
1975 
1976 	//nogo currently.. (kills output forever)
1977 #if 0
1978 	addr_t portRegister = _PortRegister();
1979 	uint32 state = read32(portRegister);
1980 	write32(portRegister,
1981 		enabled ? (state | DDI_BUF_CTL_ENABLE) : (state & ~DDI_BUF_CTL_ENABLE));
1982 	read32(portRegister);
1983 #endif
1984 
1985 	return B_OK;
1986 }
1987 
1988 
1989 status_t
1990 DigitalDisplayInterface::SetPipe(Pipe* pipe)
1991 {
1992 	CALLED();
1993 
1994 	if (pipe == NULL) {
1995 		ERROR("%s: Invalid pipe provided!\n", __func__);
1996 		return B_ERROR;
1997 	}
1998 
1999 	// TODO: UnAssignPipe?  This likely needs reworked a little
2000 	if (fPipe != NULL) {
2001 		ERROR("%s: Can't reassign display pipe (yet)\n", __func__);
2002 		return B_ERROR;
2003 	}
2004 
2005 	// all DDI ports pipe selections works differently than on the old port types (indirect).
2006 	// fixme: implement..
2007 	TRACE("%s: Assuming pipe is assigned by BIOS (fixme)\n", __func__);
2008 
2009 	fPipe = pipe;
2010 
2011 	if (fPipe == NULL)
2012 		return B_NO_MEMORY;
2013 
2014 	// Disable display pipe until modesetting enables it
2015 	if (fPipe->IsEnabled())
2016 		fPipe->Enable(false);
2017 
2018 	return B_OK;
2019 }
2020 
2021 
2022 bool
2023 DigitalDisplayInterface::IsConnected()
2024 {
2025 	addr_t portRegister = _PortRegister();
2026 
2027 	TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
2028 		portRegister);
2029 
2030 	// Please note: Skylake and up (Desktop) might use eDP for a seperate active VGA converter chip.
2031 	if (portRegister == 0) {
2032 		TRACE("%s: Port not implemented\n", __func__);
2033 		return false;
2034 	}
2035 
2036 	// newer chipsets support 4 lanes on all ports
2037 	fMaxLanes = 4;
2038 	if ((gInfo->shared_info->device_type.Generation() < 9) ||
2039 		gInfo->shared_info->device_type.InGroup(INTEL_GROUP_SKY)) {
2040 		// Probe a little port info.
2041 		if ((read32(DDI_BUF_CTL_A) & DDI_A_4_LANES) != 0) {
2042 			switch (PortIndex()) {
2043 				case INTEL_PORT_A:
2044 					fMaxLanes = 4;
2045 					break;
2046 				case INTEL_PORT_E:
2047 					fMaxLanes = 0;
2048 					break;
2049 				default:
2050 					fMaxLanes = 4;
2051 					break;
2052 			}
2053 		} else {
2054 			switch (PortIndex()) {
2055 				case INTEL_PORT_A:
2056 					fMaxLanes = 2;
2057 					break;
2058 				case INTEL_PORT_E:
2059 					fMaxLanes = 2;
2060 					break;
2061 				default:
2062 					fMaxLanes = 4;
2063 					break;
2064 			}
2065 		}
2066 	}
2067 
2068 	TRACE("%s: %s Maximum Lanes: %" B_PRId8 "\n", __func__,
2069 		PortName(), fMaxLanes);
2070 
2071 	// fetch EDID but determine 'in use' later (below) so we also catch screens that fail EDID
2072 	bool edidDetected = HasEDID();
2073 
2074 	// On laptops we always have an internal panel.. (on the eDP port on DDI systems, fixed on eDP pipe)
2075 	uint32 pipeState = 0;
2076 	if (gInfo->shared_info->device_type.IsMobile() && (PortIndex() == INTEL_PORT_E)) {
2077 		pipeState = read32(PIPE_DDI_FUNC_CTL_EDP);
2078 		TRACE("%s: PIPE_DDI_FUNC_CTL_EDP: 0x%" B_PRIx32 "\n", __func__, pipeState);
2079 		if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
2080 			TRACE("%s: Laptop, but eDP port down: enabling port on pipe EDP\n", __func__);
2081 			//fixme: turn on port and power
2082 			write32(PIPE_DDI_FUNC_CTL_EDP, pipeState | PIPE_DDI_FUNC_CTL_ENABLE);
2083 			TRACE("%s: PIPE_DDI_FUNC_CTL_EDP after: 0x%" B_PRIx32 "\n", __func__,
2084 				read32(PIPE_DDI_FUNC_CTL_EDP));
2085 		}
2086 
2087 		if (gInfo->shared_info->has_vesa_edid_info) {
2088 			TRACE("%s: Laptop. Using VESA edid info\n", __func__);
2089 			memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,	sizeof(edid1_info));
2090 			if (fEDIDState != B_OK) {
2091 				fEDIDState = B_OK;
2092 				// HasEDID now true
2093 				edid_dump(&fEDIDInfo);
2094 			}
2095 			return true;
2096 		} else if (gInfo->shared_info->got_vbt) {
2097 			TRACE("%s: Laptop. No EDID, but force enabled as we have a VBT\n", __func__);
2098 			return true;
2099 		}
2100 		//should not happen:
2101 		TRACE("%s: No (panel) type info found, assuming not connected\n", __func__);
2102 		return false;
2103 	}
2104 
2105 	// scan all our non-eDP pipes to find the one connected to the current port and check it's enabled
2106 	for (uint32 pipeCnt = 0; pipeCnt < 3; pipeCnt++) {
2107 		switch (pipeCnt) {
2108 			case 1:
2109 				pipeState = read32(PIPE_DDI_FUNC_CTL_B);
2110 				break;
2111 			case 2:
2112 				pipeState = read32(PIPE_DDI_FUNC_CTL_C);
2113 				break;
2114 			default:
2115 				pipeState = read32(PIPE_DDI_FUNC_CTL_A);
2116 				break;
2117 		}
2118 		if ((((pipeState & PIPE_DDI_SELECT_MASK) >> PIPE_DDI_SELECT_SHIFT) + 1) == (uint32)PortIndex()) {
2119 			TRACE("%s: PIPE_DDI_FUNC_CTL nr %" B_PRIx32 ": 0x%" B_PRIx32 "\n", __func__, pipeCnt + 1, pipeState);
2120 			// See if the BIOS enabled our output as it indicates it's in use
2121 			if (pipeState & PIPE_DDI_FUNC_CTL_ENABLE) {
2122 				TRACE("%s: Connected\n", __func__);
2123 				return true;
2124 			}
2125 		}
2126 	}
2127 
2128 	if (edidDetected) {
2129 		for (uint32 pipeCnt = 0; pipeCnt < 3; pipeCnt++) {
2130 			uint32 pipeReg = 0;
2131 			switch (pipeCnt) {
2132 				case 1:
2133 					pipeReg = PIPE_DDI_FUNC_CTL_B;
2134 					break;
2135 				case 2:
2136 					pipeReg = PIPE_DDI_FUNC_CTL_C;
2137 					break;
2138 				default:
2139 					pipeReg = PIPE_DDI_FUNC_CTL_A;
2140 					break;
2141 			}
2142 			pipeState = read32(pipeReg);
2143 			if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
2144 				TRACE("%s: Connected but port down: enabling port on pipe nr %" B_PRIx32 "\n", __func__, pipeCnt + 1);
2145 				//fixme: turn on port and power
2146 				pipeState |= PIPE_DDI_FUNC_CTL_ENABLE;
2147 				pipeState &= ~PIPE_DDI_SELECT_MASK;
2148 				pipeState |= (((uint32)PortIndex()) - 1) << PIPE_DDI_SELECT_SHIFT;
2149 				//fixme: set mode to DVI mode for now (b26..24 = %001)
2150 				write32(pipeReg, pipeState);
2151 				TRACE("%s: PIPE_DDI_FUNC_CTL after: 0x%" B_PRIx32 "\n", __func__, read32(pipeReg));
2152 				return true;
2153 			}
2154 		}
2155 		TRACE("%s: No pipe available, ignoring connected screen\n", __func__);
2156 	}
2157 
2158 	TRACE("%s: Not connected\n", __func__);
2159 	return false;
2160 }
2161 
2162 status_t
2163 DigitalDisplayInterface::_SetPortLinkGen8(const display_timing& timing, uint32 pllSel)
2164 {
2165 	//fixme: always so on pre gen 9?
2166 	uint32 linkBandwidth = 270000; //khz
2167 
2168 	if (gInfo->shared_info->device_type.Generation() >= 9) {
2169 		if (pllSel != 0xff) {
2170 			linkBandwidth = (read32(SKL_DPLL_CTRL1) >> (1 + 6 * pllSel)) & SKL_DPLL_DP_LINKRATE_MASK;
2171 			switch (linkBandwidth) {
2172 				case SKL_DPLL_CTRL1_2700:
2173 					linkBandwidth = 2700000 / 5;
2174 					break;
2175 				case SKL_DPLL_CTRL1_1350:
2176 					linkBandwidth = 1350000 / 5;
2177 					break;
2178 				case SKL_DPLL_CTRL1_810:
2179 					linkBandwidth =  810000 / 5;
2180 					break;
2181 				case SKL_DPLL_CTRL1_1620:
2182 					linkBandwidth = 1620000 / 5;
2183 					break;
2184 				case SKL_DPLL_CTRL1_1080:
2185 					linkBandwidth = 1080000 / 5;
2186 					break;
2187 				case SKL_DPLL_CTRL1_2160:
2188 					linkBandwidth = 2160000 / 5;
2189 					break;
2190 				default:
2191 					linkBandwidth = 270000;
2192 					ERROR("%s: DDI No known DP-link reference clock selected, assuming default\n", __func__);
2193 					break;
2194 			}
2195 		} else {
2196 			ERROR("%s: DDI No known PLL selected, assuming default DP-link reference\n", __func__);
2197 		}
2198 	}
2199 	TRACE("%s: DDI DP-link reference clock is %gMhz\n", __func__, linkBandwidth / 1000.0f);
2200 
2201 	uint32 fPipeOffset = 0;
2202 	switch (fPipe->Index()) {
2203 		case INTEL_PIPE_B:
2204 			fPipeOffset = 0x1000;
2205 			break;
2206 		case INTEL_PIPE_C:
2207 			fPipeOffset = 0x2000;
2208 			break;
2209 		case INTEL_PIPE_D:
2210 			fPipeOffset = 0xf000;
2211 			break;
2212 		default:
2213 			break;
2214 	}
2215 
2216 	TRACE("%s: DDI M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_DATA_M + fPipeOffset));
2217 	TRACE("%s: DDI N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_DATA_N + fPipeOffset));
2218 	TRACE("%s: DDI M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_LINK_M + fPipeOffset));
2219 	TRACE("%s: DDI N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_LINK_N + fPipeOffset));
2220 
2221 	uint32 pipeFunc = read32(PIPE_DDI_FUNC_CTL_A + fPipeOffset);
2222 	uint32 bitsPerPixel = (pipeFunc & PIPE_DDI_BPC_MASK) >> PIPE_DDI_COLOR_SHIFT;
2223 	switch (bitsPerPixel) {
2224 		case PIPE_DDI_8BPC:
2225 			bitsPerPixel = 24;
2226 			break;
2227 		case PIPE_DDI_10BPC:
2228 			bitsPerPixel = 30;
2229 			break;
2230 		case PIPE_DDI_6BPC:
2231 			bitsPerPixel = 18;
2232 			break;
2233 		case PIPE_DDI_12BPC:
2234 			bitsPerPixel = 36;
2235 			break;
2236 		default:
2237 			ERROR("%s: DDI illegal link colordepth set.\n", __func__);
2238 			return B_ERROR;
2239 	}
2240 	TRACE("%s: DDI Link Colordepth: %" B_PRIu32 "\n", __func__, bitsPerPixel);
2241 
2242 	uint32 lanes = 4;
2243 	// Only DP modes supports less than 4 lanes: read current config
2244 	if (((pipeFunc & PIPE_DDI_MODESEL_MASK) >> PIPE_DDI_MODESEL_SHIFT) >= PIPE_DDI_MODE_DP_SST) {
2245 		// On gen 9.5 IceLake 3x mode exists (DSI only), earlier models: reserved value.
2246 		lanes = ((pipeFunc & PIPE_DDI_DP_WIDTH_MASK) >> PIPE_DDI_DP_WIDTH_SHIFT) + 1;
2247 		TRACE("%s: DDI in DP mode with %" B_PRIx32 " lane(s) in use\n", __func__, lanes);
2248 	} else {
2249 		TRACE("%s: DDI in non-DP mode with %" B_PRIx32 " lane(s) in use\n", __func__, lanes);
2250 	}
2251 
2252 	//Setup Data M/N
2253 	uint64 linkspeed = lanes * linkBandwidth * 8;
2254 	uint64 ret_n = 1;
2255 	while(ret_n < linkspeed) {
2256 		ret_n *= 2;
2257 	}
2258 	if (ret_n > 0x800000) {
2259 		ret_n = 0x800000;
2260 	}
2261 	uint64 ret_m = timing.pixel_clock * ret_n * bitsPerPixel / linkspeed;
2262 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
2263 		ret_m >>= 1;
2264 		ret_n >>= 1;
2265 	}
2266 	//Set TU size bits (to default, max) before link training so that error detection works
2267 	write32(INTEL_DDI_PIPE_A_DATA_M + fPipeOffset, ret_m | FDI_PIPE_MN_TU_SIZE_MASK);
2268 	write32(INTEL_DDI_PIPE_A_DATA_N + fPipeOffset, ret_n);
2269 
2270 	//Setup Link M/N
2271 	linkspeed = linkBandwidth;
2272 	ret_n = 1;
2273 	while(ret_n < linkspeed) {
2274 		ret_n *= 2;
2275 	}
2276 	if (ret_n > 0x800000) {
2277 		ret_n = 0x800000;
2278 	}
2279 	ret_m = timing.pixel_clock * ret_n / linkspeed;
2280 	while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
2281 		ret_m >>= 1;
2282 		ret_n >>= 1;
2283 	}
2284 	write32(INTEL_DDI_PIPE_A_LINK_M + fPipeOffset, ret_m);
2285 	//Writing Link N triggers all four registers to be activated also (on next VBlank)
2286 	write32(INTEL_DDI_PIPE_A_LINK_N + fPipeOffset, ret_n);
2287 
2288 	TRACE("%s: DDI M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_DATA_M + fPipeOffset));
2289 	TRACE("%s: DDI N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_DATA_N + fPipeOffset));
2290 	TRACE("%s: DDI M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_LINK_M + fPipeOffset));
2291 	TRACE("%s: DDI N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_DDI_PIPE_A_LINK_N + fPipeOffset));
2292 
2293 	return B_OK;
2294 }
2295 
2296 status_t
2297 DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
2298 {
2299 	CALLED();
2300 	TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display,
2301 		target->timing.v_display);
2302 
2303 	if (fPipe == NULL) {
2304 		ERROR("%s: Setting display mode without assigned pipe!\n", __func__);
2305 		return B_ERROR;
2306 	}
2307 
2308 	display_timing hardwareTarget = target->timing;
2309 	bool needsScaling = false;
2310 	if ((PortIndex() == INTEL_PORT_E) && gInfo->shared_info->device_type.IsMobile()) {
2311 		// For internal panels, we may need to set the timings according to the panel
2312 		// native video mode, and let the panel fitter do the scaling.
2313 
2314 		if (gInfo->shared_info->got_vbt) {
2315 			// Set vbios hardware panel mode as base
2316 			hardwareTarget = gInfo->shared_info->panel_timing;
2317 
2318 			if (hardwareTarget.h_display == target->timing.h_display
2319 					&& hardwareTarget.v_display == target->timing.v_display) {
2320 				// We are setting the native video mode, nothing special to do
2321 				// Note: this means refresh and timing might vary according to requested mode.
2322 				hardwareTarget = target->timing;
2323 				TRACE("%s: Setting internal panel to native resolution at %" B_PRIu32 "Hz\n", __func__,
2324 					hardwareTarget.pixel_clock * 1000 / (hardwareTarget.h_total * hardwareTarget.v_total));
2325 			} else {
2326 				// We need to enable the panel fitter
2327 				TRACE("%s: Hardware mode will actually be %dx%d at %" B_PRIu32 "Hz\n", __func__,
2328 					hardwareTarget.h_display, hardwareTarget.v_display,
2329 					hardwareTarget.pixel_clock * 1000 / (hardwareTarget.h_total * hardwareTarget.v_total));
2330 
2331 				// FIXME we should also get the refresh frequency from the target
2332 				// mode, and then "sanitize" the resulting mode we made up.
2333 				needsScaling = true;
2334 			}
2335 		} else {
2336 			TRACE("%s: Setting internal panel mode without VBT info generation, scaling may not work\n",
2337 				__func__);
2338 			// We don't have VBT data, try to set the requested mode directly
2339 			// and hope for the best
2340 			hardwareTarget = target->timing;
2341 		}
2342 	}
2343 
2344 	// Setup PanelFitter
2345 	PanelFitter* fitter = fPipe->PFT();
2346 	if (fitter != NULL)
2347 		fitter->Enable(hardwareTarget);
2348 
2349 	// skip FDI as it never applies to DDI (on gen7 and 8 only for the real analog VGA port)
2350 
2351 	// Program general pipe config
2352 	fPipe->Configure(target);
2353 
2354 	uint32 pllSel = 0xff; // no PLL selected
2355 	if (gInfo->shared_info->device_type.Generation() <= 8) {
2356 		unsigned int r2_out, n2_out, p_out;
2357 		hsw_ddi_calculate_wrpll(
2358 			hardwareTarget.pixel_clock * 1000 /* in Hz */,
2359 			&r2_out, &n2_out, &p_out);
2360 	} else {
2361 		skl_wrpll_params wrpll_params;
2362 		skl_ddi_calculate_wrpll(
2363 			hardwareTarget.pixel_clock * 1000 /* in Hz */,
2364 			gInfo->shared_info->pll_info.reference_frequency,
2365 			&wrpll_params);
2366 		fPipe->ConfigureClocksSKL(wrpll_params,
2367 			hardwareTarget.pixel_clock,
2368 			PortIndex(),
2369 			&pllSel);
2370 	}
2371 
2372 	// Program target display mode
2373 	fPipe->ConfigureTimings(target, !needsScaling);
2374 	_SetPortLinkGen8(hardwareTarget, pllSel);
2375 
2376 	// Set fCurrentMode to our set display mode
2377 	memcpy(&fCurrentMode, target, sizeof(display_mode));
2378 
2379 	return B_OK;
2380 }
2381