diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ab4e025659..bf1ac03f88 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -89,8 +89,8 @@ #define INTEL_PCH_PPT_DEVICE_ID 0x1e00 #define INTEL_PCH_LPT_DEVICE_ID 0x8c00 #define INTEL_PCH_LPT_LP_DEVICE_ID 0x9c00 -#define INTEL_PCH_SPT_DEVICE_ID 0xA100 -#define INTEL_PCH_SPT_LP_DEVICE_ID 0x9D00 +#define INTEL_PCH_SPT_DEVICE_ID 0xa100 +#define INTEL_PCH_SPT_LP_DEVICE_ID 0x9d00 #define INTEL_PCH_P2X_DEVICE_ID 0x7100 #define INTEL_PCH_P3X_DEVICE_ID 0x7000 @@ -543,21 +543,21 @@ struct intel_free_graphics_memory { #define PORT_TRANS_SEL_MASK (3<<29) // 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) -#define INTEL_TRANSCODER_A_HSYNC (0x0008 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_A_VTOTAL (0x000c | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_A_VBLANK (0x0010 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_A_VSYNC (0x0014 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_HTOTAL (0x1000 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_HBLANK (0x1004 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_HSYNC (0x1008 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_VTOTAL (0x100c | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_VBLANK (0x1010 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_VSYNC (0x1014 | 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_HSYNC (0x0008 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_VTOTAL (0x000c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_VBLANK (0x0010 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_VSYNC (0x0014 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_HTOTAL (0x1000 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_HBLANK (0x1004 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_HSYNC (0x1008 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_VTOTAL (0x100c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_VBLANK (0x1010 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_VSYNC (0x1014 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_A_IMAGE_SIZE (0x001c | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_TRANSCODER_B_IMAGE_SIZE (0x101c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_IMAGE_SIZE (0x001c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_IMAGE_SIZE (0x101c | REGS_SOUTH_TRANSCODER_PORT) // TODO: Is there consolidation that could happen here with digital ports? @@ -855,9 +855,26 @@ struct intel_free_graphics_memory { #define PCH_FDI_RX_BASE_REGISTER 0xf0000 #define PCH_FDI_RX_PIPE_OFFSET 0x01000 #define PCH_FDI_RX_CONTROL 0x00c +#define PCH_FDI_RX_IIR 0x014 +#define PCH_FDI_RX_IMR 0x018 + #define FDI_RX_ENABLE (1 << 31) #define FDI_RX_PLL_ENABLED (1 << 13) + +// FDI_tX interrupt register +#define FDI_RX_INTER_LANE_ALIGN (1 << 10) +#define FDI_RX_SYMBOL_LOCK (1 << 9) +#define FDI_RX_BIT_LOCK (1 << 8) +#define FDI_RX_TRAIN_PATTERN_2_FAIL (1 << 7) +#define FDI_RX_FS_CODE_ERR (1 << 6) +#define FDI_RX_FE_CODE_ERR (1 << 5) +#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1 << 4) +#define FDI_RX_HDCP_LINK_FAIL (1 << 3) +#define FDI_RX_PIXEL_FIFO_OVERFLOW (1 << 2) +#define FDI_RX_CROSS_CLOCK_OVERFLOW (1 << 1) +#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1 << 0) + #define FDI_FS_ERRC_ENABLE (1 << 27) #define FDI_FE_ERRC_ENABLE (1 << 26) @@ -871,12 +888,37 @@ struct intel_free_graphics_memory { #define FDI_RX_CLOCK_RAW (0 << 4) #define FDI_RX_CLOCK_PCD (1 << 4) -#define PCH_FDI_TX_BASE_REGISTER 0x60000 -#define PCH_FDI_TX_PIPE_OFFSET 0x01000 -#define PCH_FDI_TX_CONTROL 0x100 -#define FDI_TX_ENABLE (1 << 31) -#define FDI_TX_ENHANCE_FRAME_ENABLE (1 << 18) -#define FDI_TX_PLL_ENABLED (1 << 14) +#define PCH_FDI_TX_BASE_REGISTER 0x60000 +#define PCH_FDI_TX_PIPE_OFFSET 0x01000 +#define PCH_FDI_TX_CONTROL 0x100 +#define FDI_TX_ENABLE (1 << 31) +#define FDI_LINK_TRAIN_PATTERN_1 (0 << 28) +#define FDI_LINK_TRAIN_PATTERN_2 (1 << 28) +#define FDI_LINK_TRAIN_PATTERN_IDLE (2 << 28) +#define FDI_LINK_TRAIN_NONE (3 << 28) +#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3 << 25) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22) + +// SNB A stepping +#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) +#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22) +#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22) +#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x00 << 22) + +// SNB B stepping +#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x00 << 22) +#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a << 22) +#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39 << 22) +#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38 << 22) +#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f << 22) +#define FDI_TX_ENHANCE_FRAME_ENABLE (1 << 18) +#define FDI_TX_PLL_ENABLED (1 << 14) #define FDI_DP_PORT_WIDTH_SHIFT 19 #define FDI_DP_PORT_WIDTH_MASK (7 << FDI_DP_PORT_WIDTH_SHIFT) @@ -887,35 +929,9 @@ struct intel_free_graphics_memory { #define FDI_PLL_BIOS_1 0x46004 #define FDI_PLL_BIOS_2 0x46008 -#define FDI_LINK_TRAIN_PATTERN_1 (0 << 28) -#define FDI_LINK_TRAIN_PATTERN_2 (1 << 28) -#define FDI_LINK_TRAIN_PATTERN_IDLE (2 << 28) -#define FDI_LINK_TRAIN_NONE (3 << 28) -#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0 << 25) -#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1 << 25) -#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2 << 25) -#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3 << 25) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22) -#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22) - #define FDI_AUTO_TRAINING (1 << 10) #define FDI_AUTO_TRAIN_DONE (1 << 1) -// SNB A-stepping -#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) -#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22) -#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22) -#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x00 << 22) - -// SNB B-stepping -#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x00 << 22) -#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a << 22) -#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39 << 22) -#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38 << 22) -#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f << 22) - #define FDI_LINK_TRAIN_PATTERN_1_CPT (0 << 8) #define FDI_LINK_TRAIN_PATTERN_2_CPT (1 << 8) #define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2 << 8) @@ -928,6 +944,11 @@ struct intel_free_graphics_memory { #define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2 << 8) #define FDI_LINK_TRAIN_NONE_IVB (3 << 8) +#define PCH_FDI_RXA_CHICKEN (0x200c | REGS_SOUTH_SHARED) +#define PCH_FDI_RXB_CHICKEN (0x2010 | REGS_SOUTH_SHARED) +#define FDI_RX_PHASE_SYNC_POINTER_EN (1 << 0) +#define FDI_RX_PHASE_SYNC_POINTER_OVR (1 << 1) + // CPU Panel Fitters - These are for IronLake and up and are the CPU internal // panel fitters. #define PCH_PANEL_FITTER_BASE_REGISTER 0x68000 diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index f9d3ac067f..1ed0b915db 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -220,7 +220,8 @@ FDIReceiver::SwitchClock(bool toPCDClock) FDILink::FDILink(pipe_index pipeIndex) : fTransmitter(pipeIndex), - fReceiver(pipeIndex) + fReceiver(pipeIndex), + fPipeIndex(pipeIndex) { } @@ -262,17 +263,172 @@ FDILink::Train(display_mode* target) status_t result = B_ERROR; - // Over IVB supports AutoTraining of FDI - if (gInfo->shared_info->device_type.Generation() >= 7) { + // TODO: Only _AutoTrain on IVYB Stepping B or later + // otherwise, _ManualTrain + if (gInfo->shared_info->device_type.Generation() >= 7) result = _AutoTrain(lanes); - if (result != B_OK) { - ERROR("%s: FDI auto-training fault. Attempting manual train.\n", - __func__); - return _ManualTrain(lanes); - } - return B_OK; + else if (gInfo->shared_info->device_type.Generation() == 6) + result = _SnbTrain(lanes); + else if (gInfo->shared_info->device_type.Generation() == 5) + result = _IlkTrain(lanes); + else + result = _NormalTrain(lanes); + + if (result != B_OK) { + ERROR("%s: FDI training fault.\n", __func__); } - return _ManualTrain(lanes); + + return result; +} + + +status_t +FDILink::_NormalTrain(uint32 lanes) +{ + CALLED(); + uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL; + uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL; + + // Enable normal link training + uint32 tmp = read32(txControl); + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) { + tmp &= ~FDI_LINK_TRAIN_NONE_IVB; + tmp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; + } else { + tmp &= ~FDI_LINK_TRAIN_NONE; + tmp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; + } + write32(txControl, tmp); + + tmp = read32(rxControl); + if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { + tmp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + tmp |= FDI_LINK_TRAIN_NORMAL_CPT; + } else { + tmp &= ~FDI_LINK_TRAIN_NONE; + tmp |= FDI_LINK_TRAIN_NONE; + } + write32(rxControl, tmp | FDI_RX_ENHANCE_FRAME_ENABLE); + + // Wait 1x idle pattern + read32(rxControl); + spin(1000); + + // Enable ecc on IVB + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) { + write32(rxControl, read32(rxControl) + | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE); + read32(rxControl); + } + + return B_OK; +} + + +status_t +FDILink::_IlkTrain(uint32 lanes) +{ + CALLED(); + uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL; + uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL; + + // Train 1: unmask FDI RX Interrupt symbol_lock and bit_lock + uint32 tmp = read32(Receiver().Base() + PCH_FDI_RX_IMR); + tmp &= ~FDI_RX_SYMBOL_LOCK; + tmp &= ~FDI_RX_BIT_LOCK; + write32(Receiver().Base() + PCH_FDI_RX_IMR, tmp); + spin(150); + + // Enable CPU FDI TX and RX + tmp = read32(txControl); + tmp &= ~FDI_DP_PORT_WIDTH_MASK; + tmp |= FDI_DP_PORT_WIDTH(lanes); + tmp &= ~FDI_LINK_TRAIN_NONE; + tmp |= FDI_LINK_TRAIN_PATTERN_1; + write32(txControl, tmp); + Transmitter().Enable(); + + tmp = read32(rxControl); + tmp &= ~FDI_LINK_TRAIN_NONE; + tmp |= FDI_LINK_TRAIN_PATTERN_1; + write32(rxControl, tmp); + Receiver().Enable(); + + // ILK Workaround, enable clk after FDI enable + if (fPipeIndex == INTEL_PIPE_B) { + write32(PCH_FDI_RXB_CHICKEN, FDI_RX_PHASE_SYNC_POINTER_OVR); + write32(PCH_FDI_RXB_CHICKEN, FDI_RX_PHASE_SYNC_POINTER_OVR + | FDI_RX_PHASE_SYNC_POINTER_EN); + } else { + write32(PCH_FDI_RXA_CHICKEN, FDI_RX_PHASE_SYNC_POINTER_OVR); + write32(PCH_FDI_RXA_CHICKEN, FDI_RX_PHASE_SYNC_POINTER_OVR + | FDI_RX_PHASE_SYNC_POINTER_EN); + } + + uint32 iirControl = Receiver().Base() + PCH_FDI_RX_IIR; + TRACE("%s: FDI RX IIR Control @ 0x%x\n", __func__, iirControl); + + int tries = 0; + for (tries = 0; tries < 5; tries++) { + tmp = read32(iirControl); + TRACE("%s: FDI RX IIR 0x%x\n", __func__, tmp); + + if ((tmp & FDI_RX_BIT_LOCK)) { + TRACE("%s: FDI train 1 done\n", __func__); + write32(iirControl, tmp | FDI_RX_BIT_LOCK); + break; + } + } + + if (tries == 5) { + ERROR("%s: FDI train 1 failure!\n", __func__); + return B_ERROR; + } + + // Train 2 + tmp = read32(txControl); + tmp &= ~FDI_LINK_TRAIN_NONE; + tmp |= FDI_LINK_TRAIN_PATTERN_2; + write32(txControl, tmp); + + tmp = read32(rxControl); + tmp &= ~FDI_LINK_TRAIN_NONE; + tmp |= FDI_LINK_TRAIN_PATTERN_2; + write32(rxControl, tmp); + + read32(rxControl); + spin(150); + + for (tries = 0; tries < 5; tries++) { + tmp = read32(iirControl); + TRACE("%s: FDI RX IIR 0x%x\n", __func__, tmp); + + if (tmp & FDI_RX_SYMBOL_LOCK) { + TRACE("%s: FDI train 2 done\n", __func__); + write32(iirControl, tmp | FDI_RX_SYMBOL_LOCK); + break; + } + } + + if (tries == 5) { + ERROR("%s: FDI train 2 failure!\n", __func__); + return B_ERROR; + } + + return B_OK; +} + + +status_t +FDILink::_SnbTrain(uint32 lanes) +{ + CALLED(); + //uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL; + //uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL; + + ERROR("%s: TODO\n", __func__); + + return B_ERROR; } @@ -280,14 +436,12 @@ status_t FDILink::_ManualTrain(uint32 lanes) { CALLED(); + //uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL; + //uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL; - // This needs completed - ERROR("TODO: Manual FDI Link Training\n"); + ERROR("%s: TODO\n", __func__); - // Enable pipes - Transmitter().Enable(); - Receiver().Enable(); - return B_OK; + return B_ERROR; } diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h index 8f6156f2b2..d6220ca6f2 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h @@ -68,11 +68,16 @@ public: status_t Train(display_mode* target); private: + status_t _NormalTrain(uint32 lanes); + status_t _IlkTrain(uint32 lanes); + status_t _SnbTrain(uint32 lanes); status_t _ManualTrain(uint32 lanes); status_t _AutoTrain(uint32 lanes); FDITransmitter fTransmitter; FDIReceiver fReceiver; + + pipe_index fPipeIndex; }; diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 0014837f55..a93636ecb8 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -74,8 +74,7 @@ Pipe::Pipe(pipe_index pipeIndex) fHasTranscoder = true; // Program FDILink if PCH - if (fFDILink == NULL) - fFDILink = new(std::nothrow) FDILink(pipeIndex); + fFDILink = new(std::nothrow) FDILink(pipeIndex); } TRACE("Pipe %s. Pipe Base: 0x%" B_PRIxADDR diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 60e9e8c97d..4663a3dd1b 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -471,6 +471,11 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (!wait_for_clear(panelStatus, PANEL_STATUS_POWER_ON, 1000)) ERROR("%s: %s didn't power off within 1000ms!\n", __func__, PortName()); + // Train FDI if it exists + FDILink* link = fPipe->FDI(); + if (link != NULL) + link->Train(target); + #if 0 // Disable PanelFitter for now addr_t panelFitterControl = PCH_PANEL_FITTER_BASE_REGISTER