intel_extreme: gen4 displayport now sets modes, dualhead clone works.
This commit is contained in:
parent
977a873ab2
commit
3334d6fba1
@ -558,6 +558,16 @@ struct intel_free_graphics_memory {
|
||||
#define INTEL_DISPLAY_A_PIPE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT)
|
||||
#define INTEL_DISPLAY_B_PIPE_SIZE (0x101c | REGS_NORTH_PIPE_AND_PORT)
|
||||
|
||||
//G45 displayport link
|
||||
#define INTEL_PIPE_A_DATA_M (0x0050 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_B_DATA_M (0x1050 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_A_DATA_N (0x0054 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_B_DATA_N (0x1054 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_A_LINK_M (0x0060 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_B_LINK_M (0x1060 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_A_LINK_N (0x0064 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define INTEL_PIPE_B_LINK_N (0x1064 | REGS_NORTH_PLANE_CONTROL)
|
||||
|
||||
// on PCH we also have to set the transcoder
|
||||
#define INTEL_TRANSCODER_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
#define INTEL_TRANSCODER_A_HBLANK (0x0004 | REGS_SOUTH_TRANSCODER_PORT)
|
||||
|
@ -1057,6 +1057,70 @@ DisplayPort::_PortRegister()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DisplayPort::_SetPortLinkGen4(display_mode* target)
|
||||
{
|
||||
// Khz / 10. ( each output octet encoded as 10 bits.
|
||||
//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz
|
||||
//fixme: always so?
|
||||
uint32 linkBandwidth = 270000; //khz
|
||||
uint32 fPipeOffset = 0;
|
||||
if (fPipe->Index() == INTEL_PIPE_B)
|
||||
fPipeOffset = 0x1000;
|
||||
|
||||
TRACE("%s: DP M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset));
|
||||
TRACE("%s: DP N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset));
|
||||
TRACE("%s: DP M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset));
|
||||
TRACE("%s: DP N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset));
|
||||
|
||||
uint32 bitsPerPixel = 24; //fixme: always so?
|
||||
uint32 lanes = 4; //fixme: always so?
|
||||
|
||||
//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(INTEL_PIPE_A_DATA_M + fPipeOffset, ret_m | FDI_PIPE_MN_TU_SIZE_MASK);
|
||||
write32(INTEL_PIPE_A_DATA_N + fPipeOffset, 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(INTEL_PIPE_A_LINK_M + fPipeOffset, ret_m);
|
||||
//Writing Link N triggers all four registers to be activated also (on next VBlank)
|
||||
write32(INTEL_PIPE_A_LINK_N + fPipeOffset, ret_n);
|
||||
|
||||
TRACE("%s: DP M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset));
|
||||
TRACE("%s: DP N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset));
|
||||
TRACE("%s: DP M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset));
|
||||
TRACE("%s: DP N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
{
|
||||
@ -1069,40 +1133,46 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
//fixme: doesn't work yet. For now just scale to native mode.
|
||||
status_t result = B_OK;
|
||||
if (gInfo->shared_info->device_type.Generation() <= 4) {
|
||||
fPipe->ConfigureTimings(target);
|
||||
result = _SetPortLinkGen4(target);
|
||||
} else {
|
||||
//fixme: doesn't work yet. For now just scale to native mode.
|
||||
#if 0
|
||||
// Setup PanelFitter and Train FDI if it exists
|
||||
PanelFitter* fitter = fPipe->PFT();
|
||||
if (fitter != NULL)
|
||||
fitter->Enable(*target);
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
link->Train(target);
|
||||
// Setup PanelFitter and Train FDI if it exists
|
||||
PanelFitter* fitter = fPipe->PFT();
|
||||
if (fitter != NULL)
|
||||
fitter->Enable(*target);
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
link->Train(target);
|
||||
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, &divisors, false);
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, &divisors, false);
|
||||
|
||||
uint32 extraPLLFlags = 0;
|
||||
if (gInfo->shared_info->device_type.Generation() >= 3)
|
||||
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
|
||||
uint32 extraPLLFlags = 0;
|
||||
if (gInfo->shared_info->device_type.Generation() >= 3)
|
||||
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
|
||||
|
||||
// Program general pipe config
|
||||
fPipe->Configure(target);
|
||||
// Program general pipe config
|
||||
fPipe->Configure(target);
|
||||
|
||||
// Program pipe PLL's
|
||||
fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
|
||||
// Program pipe PLL's
|
||||
fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
|
||||
|
||||
// Program target display mode
|
||||
fPipe->ConfigureTimings(target);
|
||||
// Program target display mode
|
||||
fPipe->ConfigureTimings(target);
|
||||
#endif
|
||||
|
||||
// Keep monitor at native mode and scale image to that
|
||||
fPipe->ConfigureScalePos(target);
|
||||
// Keep monitor at native mode and scale image to that
|
||||
fPipe->ConfigureScalePos(target);
|
||||
}
|
||||
|
||||
// Set fCurrentMode to our set display mode
|
||||
memcpy(&fCurrentMode, target, sizeof(display_mode));
|
||||
|
||||
return B_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -188,6 +188,9 @@ virtual pipe_index PipePreference();
|
||||
protected:
|
||||
virtual addr_t _DDCRegister();
|
||||
virtual addr_t _PortRegister();
|
||||
|
||||
private:
|
||||
status_t _SetPortLinkGen4(display_mode* target);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user