mirror of
https://review.haiku-os.org/haiku
synced 2024-11-23 15:28:58 +01:00
Intel_extreme: fixed hrev55115 regression and added FDI data/link M/N programming.
This commit is contained in:
parent
1a5fe94b7a
commit
aca9888e37
@ -727,10 +727,13 @@ struct intel_free_graphics_memory {
|
||||
#define INTEL_PIPE_DITHER_TYPE_ST2 (2 << 2)
|
||||
#define INTEL_PIPE_DITHER_TYPE_TEMP (3 << 2)
|
||||
#define INTEL_PIPE_DITHER_EN (1 << 4)
|
||||
#define INTEL_PIPE_8BPC (0 << 5)
|
||||
#define INTEL_PIPE_10BPC (1 << 5)
|
||||
#define INTEL_PIPE_6BPC (2 << 5)
|
||||
#define INTEL_PIPE_12BPC (3 << 5)
|
||||
#define INTEL_PIPE_COLOR_SHIFT 5
|
||||
#define INTEL_PIPE_BPC(x) ((x) << INTEL_PIPE_COLOR_SHIFT)
|
||||
#define INTEL_PIPE_BPC_MASK (7 << INTEL_PIPE_COLOR_SHIFT)
|
||||
#define INTEL_PIPE_8BPC 0
|
||||
#define INTEL_PIPE_10BPC 1
|
||||
#define INTEL_PIPE_6BPC 2
|
||||
#define INTEL_PIPE_12BPC 3
|
||||
#define INTEL_PIPE_PROGRESSIVE (0 << 21)
|
||||
|
||||
// cursors
|
||||
@ -917,6 +920,10 @@ struct intel_free_graphics_memory {
|
||||
#define FDI_RX_ENABLE (1 << 31)
|
||||
#define FDI_RX_PLL_ENABLED (1 << 13)
|
||||
|
||||
#define FDI_RX_LINK_COLOR_SHIFT 16
|
||||
#define FDI_RX_LINK_BPC(x) ((x) << FDI_RX_LINK_COLOR_SHIFT)
|
||||
#define FDI_RX_LINK_BPC_MASK (7 << FDI_RX_LINK_COLOR_SHIFT)
|
||||
|
||||
// Transcoder - same base as FDI_RX
|
||||
#define PCH_TRANS_CONF_A 0x0008
|
||||
#define PCH_TRANS_CONF_B 0x1008
|
||||
|
@ -103,6 +103,13 @@ FDITransmitter::EnablePLL(uint32 lanes)
|
||||
return;
|
||||
}
|
||||
|
||||
value &= ~FDI_DP_PORT_WIDTH_MASK;
|
||||
value |= FDI_DP_PORT_WIDTH(lanes);
|
||||
|
||||
//first update config, -then- enable PLL to be sure config is indeed updated
|
||||
write32(targetRegister, value);
|
||||
read32(targetRegister);
|
||||
|
||||
write32(targetRegister, value | FDI_TX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(100); // warmup 10us + dmi delay 20us, be generous
|
||||
@ -189,9 +196,17 @@ FDIReceiver::EnablePLL(uint32 lanes)
|
||||
return;
|
||||
}
|
||||
|
||||
value &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));
|
||||
//Link bit depth: this should be globally known per FDI link (i.e. laptop panel 3x6, rest 3x8)
|
||||
//currently using BIOS preconfigured setup
|
||||
//value &= ~FDI_DP_PORT_WIDTH_MASK;
|
||||
//value |= FDI_RX_LINK_BPC(INTEL_PIPE_8BPC);
|
||||
|
||||
value &= ~FDI_DP_PORT_WIDTH_MASK;
|
||||
value |= FDI_DP_PORT_WIDTH(lanes);
|
||||
//value |= (read32(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
|
||||
|
||||
//first update config, -then- enable PLL to be sure config is indeed updated
|
||||
write32(targetRegister, value);
|
||||
read32(targetRegister);
|
||||
|
||||
write32(targetRegister, value | FDI_RX_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
@ -239,38 +254,132 @@ FDILink::Train(display_mode* target)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
uint32 bitsPerPixel;
|
||||
switch (target->space) {
|
||||
case B_RGB32_LITTLE:
|
||||
bitsPerPixel = 32;
|
||||
status_t result = B_OK;
|
||||
|
||||
uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL;
|
||||
uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL;
|
||||
|
||||
//Link bit depth: this should be globally known per FDI link (i.e. laptop panel 3x6, rest 3x8)
|
||||
uint32 bitsPerPixel = ((read32(rxControl) & FDI_RX_LINK_BPC_MASK) >> FDI_RX_LINK_COLOR_SHIFT);
|
||||
switch (bitsPerPixel) {
|
||||
case INTEL_PIPE_8BPC:
|
||||
bitsPerPixel = 24;
|
||||
break;
|
||||
case B_RGB16_LITTLE:
|
||||
bitsPerPixel = 16;
|
||||
case INTEL_PIPE_10BPC:
|
||||
bitsPerPixel = 30;
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
bitsPerPixel = 15;
|
||||
case INTEL_PIPE_6BPC:
|
||||
bitsPerPixel = 18;
|
||||
break;
|
||||
case INTEL_PIPE_12BPC:
|
||||
bitsPerPixel = 36;
|
||||
break;
|
||||
case B_CMAP8:
|
||||
default:
|
||||
bitsPerPixel = 8;
|
||||
break;
|
||||
ERROR("%s: FDI illegal link colordepth set.\n", __func__);
|
||||
return B_ERROR;
|
||||
}
|
||||
TRACE("%s: FDI Link Colordepth: %" B_PRIu32 "\n", __func__, bitsPerPixel);
|
||||
|
||||
// Khz / 10. ( each output octet encoded as 10 bits.
|
||||
uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10;
|
||||
//Reserving 5% bandwidth for possible spread spectrum clock use
|
||||
uint32 bps = target->timing.pixel_clock * bitsPerPixel * 21 / 20;
|
||||
|
||||
uint32 lanes = bps / (linkBandwidth * 8);
|
||||
//use DIV_ROUND_UP:
|
||||
uint32 lanes = (bps + (linkBandwidth * 8) - 1) / (linkBandwidth * 8);
|
||||
//remove below line when link training is to be done
|
||||
lanes = ((read32(txControl) & FDI_DP_PORT_WIDTH_MASK) >> FDI_DP_PORT_WIDTH_SHIFT) + 1;
|
||||
|
||||
TRACE("%s: FDI Link Lanes: %" B_PRIu32 "\n", __func__, lanes);
|
||||
//assuming we'll only use link A and B (not C)
|
||||
if (lanes > 4) {
|
||||
result = B_ERROR;
|
||||
}
|
||||
if (result != B_OK) {
|
||||
ERROR("%s: FDI not enough lanes in hardware.\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
TRACE("%s: FDI TX ctrl: 0x%" B_PRIx32 "\n", __func__, read32(txControl));
|
||||
TRACE("%s: FDI RX ctrl: 0x%" B_PRIx32 "\n", __func__, read32(rxControl));
|
||||
|
||||
#if 0
|
||||
//when link training is to be done re-enable this code
|
||||
|
||||
//The order of handling things is important here..
|
||||
write32(txControl, read32(txControl) & ~FDI_TX_ENABLE);
|
||||
read32(txControl);
|
||||
write32(rxControl, read32(rxControl) & ~FDI_RX_ENABLE);
|
||||
read32(rxControl);
|
||||
|
||||
write32(txControl, (read32(txControl) & ~FDI_LINK_TRAIN_NONE) | FDI_LINK_TRAIN_PATTERN_1);
|
||||
read32(txControl);
|
||||
if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
|
||||
write32(rxControl, (read32(rxControl) & ~FDI_LINK_TRAIN_PATTERN_MASK_CPT) | FDI_LINK_TRAIN_PATTERN_1_CPT);
|
||||
} else {
|
||||
write32(rxControl, (read32(rxControl) & ~FDI_LINK_TRAIN_NONE) | FDI_LINK_TRAIN_PATTERN_1);
|
||||
}
|
||||
read32(rxControl);
|
||||
spin(100);
|
||||
|
||||
// Disable FDI clocks
|
||||
Receiver().SwitchClock(false);
|
||||
Transmitter().DisablePLL();
|
||||
Receiver().DisablePLL();
|
||||
#endif
|
||||
|
||||
//Setup Data M/N
|
||||
uint64 linkspeed = lanes * linkBandwidth * 8;
|
||||
uint64 ret_n = 1;
|
||||
while(ret_n < linkspeed) {
|
||||
ret_n *= 2;
|
||||
}
|
||||
if (ret_n > 0x800000) {
|
||||
ret_n = 0x800000;
|
||||
}
|
||||
uint64 ret_m = target->timing.pixel_clock * ret_n * bitsPerPixel / linkspeed;
|
||||
while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
|
||||
ret_m >>= 1;
|
||||
ret_n >>= 1;
|
||||
}
|
||||
//Set TU size bits (to default, max) before link training so that error detection works
|
||||
write32(Transmitter().Base() + PCH_FDI_PIPE_A_DATA_M1, ret_m | FDI_PIPE_MN_TU_SIZE_MASK);
|
||||
write32(Transmitter().Base() + PCH_FDI_PIPE_A_DATA_N1, ret_n);
|
||||
|
||||
//Setup Link M/N
|
||||
linkspeed = linkBandwidth;
|
||||
ret_n = 1;
|
||||
while(ret_n < linkspeed) {
|
||||
ret_n *= 2;
|
||||
}
|
||||
if (ret_n > 0x800000) {
|
||||
ret_n = 0x800000;
|
||||
}
|
||||
ret_m = target->timing.pixel_clock * ret_n / linkspeed;
|
||||
while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) {
|
||||
ret_m >>= 1;
|
||||
ret_n >>= 1;
|
||||
}
|
||||
write32(Transmitter().Base() + PCH_FDI_PIPE_A_LINK_M1, ret_m);
|
||||
//Writing Link N triggers all four registers to be activated also (on next VBlank)
|
||||
write32(Transmitter().Base() + PCH_FDI_PIPE_A_LINK_N1, ret_n);
|
||||
|
||||
TRACE("%s: FDI data M1: 0x%" B_PRIx32 "\n", __func__, read32(Transmitter().Base() + PCH_FDI_PIPE_A_DATA_M1));
|
||||
TRACE("%s: FDI data N1: 0x%" B_PRIx32 "\n", __func__, read32(Transmitter().Base() + PCH_FDI_PIPE_A_DATA_N1));
|
||||
TRACE("%s: FDI link M1: 0x%" B_PRIx32 "\n", __func__, read32(Transmitter().Base() + PCH_FDI_PIPE_A_LINK_M1));
|
||||
TRACE("%s: FDI link N1: 0x%" B_PRIx32 "\n", __func__, read32(Transmitter().Base() + PCH_FDI_PIPE_A_LINK_N1));
|
||||
|
||||
//Set receiving end TU size bits to match sending end's setting
|
||||
write32(Receiver().Base() + PCH_FDI_RX_TRANS_UNIT_SIZE_1, FDI_RX_TRANS_UNIT_MASK);
|
||||
write32(Receiver().Base() + PCH_FDI_RX_TRANS_UNIT_SIZE_2, FDI_RX_TRANS_UNIT_MASK);
|
||||
|
||||
#if 0
|
||||
//when link training is to be done re-enable this code
|
||||
// Enable FDI clocks
|
||||
Receiver().EnablePLL(lanes);
|
||||
Receiver().SwitchClock(true);
|
||||
Transmitter().EnablePLL(lanes);
|
||||
|
||||
status_t result = B_ERROR;
|
||||
|
||||
// TODO: Only _AutoTrain on IVYB Stepping B or later
|
||||
// otherwise, _ManualTrain
|
||||
if (gInfo->shared_info->device_type.Generation() >= 7)
|
||||
@ -281,6 +390,7 @@ FDILink::Train(display_mode* target)
|
||||
result = _IlkTrain(lanes);
|
||||
else
|
||||
result = _NormalTrain(lanes);
|
||||
#endif
|
||||
|
||||
if (result != B_OK) {
|
||||
ERROR("%s: FDI training fault.\n", __func__);
|
||||
@ -580,6 +690,7 @@ FDILink::_AutoTrain(uint32 lanes)
|
||||
uint32 buffer = read32(txControl);
|
||||
|
||||
// Clear port width selection and set number of lanes
|
||||
// fixme: does not belong in the train routines (?), (now) sits in FDI EnablePLL() routines
|
||||
buffer &= ~(7 << 19);
|
||||
buffer |= (lanes - 1) << 19;
|
||||
|
||||
@ -589,6 +700,9 @@ FDILink::_AutoTrain(uint32 lanes)
|
||||
buffer &= ~FDI_LINK_TRAIN_NONE;
|
||||
write32(txControl, buffer);
|
||||
|
||||
write32(Receiver().Base() + PCH_FDI_RX_MISC,
|
||||
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
|
||||
|
||||
bool trained = false;
|
||||
|
||||
for (uint32 i = 0; i < (sizeof(gSnbBFDITrainParam)
|
||||
@ -599,10 +713,11 @@ FDILink::_AutoTrain(uint32 lanes)
|
||||
buffer &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
||||
buffer |= gSnbBFDITrainParam[i];
|
||||
write32(txControl, buffer | FDI_TX_ENABLE);
|
||||
|
||||
read32(txControl);
|
||||
write32(rxControl, read32(rxControl) | FDI_RX_ENABLE);
|
||||
read32(rxControl);
|
||||
|
||||
spin(5);
|
||||
spin(50);//looks like datasheet specified 5uS is not enough..?
|
||||
|
||||
buffer = read32(txControl);
|
||||
if ((buffer & FDI_AUTO_TRAIN_DONE) != 0) {
|
||||
@ -612,6 +727,7 @@ FDILink::_AutoTrain(uint32 lanes)
|
||||
}
|
||||
|
||||
write32(txControl, read32(txControl) & ~FDI_TX_ENABLE);
|
||||
read32(txControl);
|
||||
write32(rxControl, read32(rxControl) & ~FDI_RX_ENABLE);
|
||||
read32(rxControl);
|
||||
|
||||
@ -628,11 +744,14 @@ FDILink::_AutoTrain(uint32 lanes)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// Enable ecc on IVB
|
||||
// Enable ecc on IVB (and disable test pattern at sending and receiving end)
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) {
|
||||
write32(rxControl, read32(rxControl)
|
||||
| FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE);
|
||||
read32(rxControl);
|
||||
//enable normal pixels (kill testpattern)
|
||||
write32(txControl, read32(txControl) | (0x3 << 8));
|
||||
read32(txControl);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
@ -107,8 +107,10 @@ Pipe::Configure(display_mode* mode)
|
||||
//if (gInfo->shared_info->device_type.Generation() >= 4) {
|
||||
// pipeControl |= (INTEL_PIPE_DITHER_EN | INTEL_PIPE_DITHER_TYPE_SP);
|
||||
|
||||
//Link bit depth, which is currently hardcoded to 8-bits per color
|
||||
pipeControl = (pipeControl & ~(0x7 << 5)) | INTEL_PIPE_8BPC;
|
||||
//Link bit depth: this should be globally known per FDI link (i.e. laptop panel 3x6, rest 3x8)
|
||||
//currently using BIOS preconfigured setup
|
||||
//pipeControl = (pipeControl & ~INTEL_PIPE_BPC_MASK) | INTEL_PIPE_BPC(INTEL_PIPE_8BPC);
|
||||
|
||||
// TODO: CxSR downclocking?
|
||||
|
||||
// TODO: Interlaced modes
|
||||
@ -356,7 +358,7 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
|
||||
// register which routes the PLL output to the transcoder that we need
|
||||
// to configure
|
||||
uint32 pllSel = read32(SNB_DPLL_SEL);
|
||||
TRACE("Old PLL selection: %x\n", pllSel);
|
||||
TRACE("Old PLL selection: 0x%" B_PRIx32 "\n", pllSel);
|
||||
uint32 shift = 0;
|
||||
uint32 pllIndex = 0;
|
||||
|
||||
@ -381,7 +383,7 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
|
||||
// Set up the new configuration for this transcoder and enable it
|
||||
pllSel |= (8 | pllIndex) << shift;
|
||||
|
||||
TRACE("New PLL selection: %x\n", pllSel);
|
||||
TRACE("New PLL selection: 0x%" B_PRIx32 "\n", pllSel);
|
||||
write32(SNB_DPLL_SEL, pllSel);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "accelerant_protos.h"
|
||||
#include "FlexibleDisplayInterface.h"
|
||||
#include "intel_extreme.h"
|
||||
#include "PanelFitter.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
@ -133,7 +134,7 @@ Port::SetPipe(Pipe* pipe)
|
||||
// FIXME is the use of PORT_TRANS_* constants correct for Sandy Bridge /
|
||||
// Cougar Point? Or is it only for Ivy Bridge / Panther point onwards?
|
||||
if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) {
|
||||
portState &= ~PORT_TRANS_SEL_MASK;
|
||||
portState &= ~PORT_TRANS_SEL_MASK; //fixme should be done sooner, not here!
|
||||
if (pipe->Index() == INTEL_PIPE_A)
|
||||
write32(portRegister, portState | PORT_TRANS_A_SEL_CPT);
|
||||
else
|
||||
@ -144,7 +145,6 @@ Port::SetPipe(Pipe* pipe)
|
||||
else
|
||||
write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B);
|
||||
}
|
||||
|
||||
fPipe = pipe;
|
||||
|
||||
if (fPipe == NULL)
|
||||
@ -306,6 +306,7 @@ AnalogPort::_PortRegister()
|
||||
status_t
|
||||
AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
{
|
||||
CALLED();
|
||||
TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
|
||||
target->virtual_height);
|
||||
|
||||
@ -314,14 +315,13 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Disabled for now as our code doesn't work. Let's hope VESA/EFI has
|
||||
// already set things up for us during boot.
|
||||
// Train FDI if it exists
|
||||
// Setup PanelFitter and Train FDI if it exists
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
if (link != NULL) {
|
||||
// fixme insert fitter setup here
|
||||
|
||||
link->Train(target);
|
||||
#endif
|
||||
}
|
||||
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, &divisors, false);
|
||||
@ -500,14 +500,13 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Disabled for now as our code doesn't work. Let's hope VESA/EFI has
|
||||
// already set things up for us during boot.
|
||||
// Train FDI if it exists
|
||||
// Setup PanelFitter and Train FDI if it exists
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
if (link != NULL) {
|
||||
// fixme insert fitter setup here
|
||||
|
||||
link->Train(target);
|
||||
#endif
|
||||
}
|
||||
|
||||
// For LVDS panels, we may need to set the timings according to the panel
|
||||
// native video mode, and let the panel fitter do the scaling. But the
|
||||
@ -727,6 +726,7 @@ DigitalPort::_PortRegister()
|
||||
status_t
|
||||
DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
{
|
||||
CALLED();
|
||||
TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
|
||||
target->virtual_height);
|
||||
|
||||
@ -735,14 +735,13 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Disabled for now as our code doesn't work. Let's hope VESA/EFI has
|
||||
// already set things up for us during boot.
|
||||
// Train FDI if it exists
|
||||
// Setup PanelFitter and Train FDI if it exists
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
if (link != NULL) {
|
||||
// fixme insert fitter setup here
|
||||
|
||||
link->Train(target);
|
||||
#endif
|
||||
}
|
||||
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, &divisors, false);
|
||||
@ -934,6 +933,7 @@ DisplayPort::_PortRegister()
|
||||
status_t
|
||||
DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
{
|
||||
CALLED();
|
||||
TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
|
||||
target->virtual_height);
|
||||
|
||||
@ -1095,6 +1095,7 @@ DigitalDisplayInterface::IsConnected()
|
||||
status_t
|
||||
DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
{
|
||||
CALLED();
|
||||
TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width,
|
||||
target->virtual_height);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user