diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 66c35888bf..aa5e636562 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -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) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index d73d68a7b1..b666e9bcc1 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -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; } diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index e926f4897c..d3ae0532eb 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -188,6 +188,9 @@ virtual pipe_index PipePreference(); protected: virtual addr_t _DDCRegister(); virtual addr_t _PortRegister(); + +private: + status_t _SetPortLinkGen4(display_mode* target); };