intel_extreme: gen4 displayport now sets modes, dualhead clone works.
This commit is contained in:
@@ -558,6 +558,16 @@ struct intel_free_graphics_memory {
|
|||||||
#define INTEL_DISPLAY_A_PIPE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT)
|
#define INTEL_DISPLAY_A_PIPE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT)
|
||||||
#define INTEL_DISPLAY_B_PIPE_SIZE (0x101c | 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
|
// on PCH we also have to set the transcoder
|
||||||
#define INTEL_TRANSCODER_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT)
|
#define INTEL_TRANSCODER_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT)
|
||||||
#define INTEL_TRANSCODER_A_HBLANK (0x0004 | 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
|
status_t
|
||||||
DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||||
{
|
{
|
||||||
@@ -1069,40 +1133,46 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
return B_ERROR;
|
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
|
#if 0
|
||||||
// Setup PanelFitter and Train FDI if it exists
|
// Setup PanelFitter and Train FDI if it exists
|
||||||
PanelFitter* fitter = fPipe->PFT();
|
PanelFitter* fitter = fPipe->PFT();
|
||||||
if (fitter != NULL)
|
if (fitter != NULL)
|
||||||
fitter->Enable(*target);
|
fitter->Enable(*target);
|
||||||
FDILink* link = fPipe->FDI();
|
FDILink* link = fPipe->FDI();
|
||||||
if (link != NULL)
|
if (link != NULL)
|
||||||
link->Train(target);
|
link->Train(target);
|
||||||
|
|
||||||
pll_divisors divisors;
|
pll_divisors divisors;
|
||||||
compute_pll_divisors(target, &divisors, false);
|
compute_pll_divisors(target, &divisors, false);
|
||||||
|
|
||||||
uint32 extraPLLFlags = 0;
|
uint32 extraPLLFlags = 0;
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 3)
|
if (gInfo->shared_info->device_type.Generation() >= 3)
|
||||||
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
|
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
|
||||||
|
|
||||||
// Program general pipe config
|
// Program general pipe config
|
||||||
fPipe->Configure(target);
|
fPipe->Configure(target);
|
||||||
|
|
||||||
// Program pipe PLL's
|
// Program pipe PLL's
|
||||||
fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
|
fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
|
||||||
|
|
||||||
// Program target display mode
|
// Program target display mode
|
||||||
fPipe->ConfigureTimings(target);
|
fPipe->ConfigureTimings(target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Keep monitor at native mode and scale image to that
|
// Keep monitor at native mode and scale image to that
|
||||||
fPipe->ConfigureScalePos(target);
|
fPipe->ConfigureScalePos(target);
|
||||||
|
}
|
||||||
|
|
||||||
// Set fCurrentMode to our set display mode
|
// Set fCurrentMode to our set display mode
|
||||||
memcpy(&fCurrentMode, target, sizeof(display_mode));
|
memcpy(&fCurrentMode, target, sizeof(display_mode));
|
||||||
|
|
||||||
return B_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,9 @@ virtual pipe_index PipePreference();
|
|||||||
protected:
|
protected:
|
||||||
virtual addr_t _DDCRegister();
|
virtual addr_t _DDCRegister();
|
||||||
virtual addr_t _PortRegister();
|
virtual addr_t _PortRegister();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _SetPortLinkGen4(display_mode* target);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user