intel_extreme: First work at programming FDI

This commit is contained in:
Alexander von Gluck IV 2015-11-17 23:28:09 -06:00
parent 32807945aa
commit 00e0982f68
10 changed files with 116 additions and 51 deletions

View File

@ -263,6 +263,12 @@ struct intel_shared_info {
bool has_vesa_edid_info; bool has_vesa_edid_info;
}; };
enum pipe_index {
INTEL_PIPE_ANY,
INTEL_PIPE_A,
INTEL_PIPE_B
};
//----------------- ioctl() interface ---------------- //----------------- ioctl() interface ----------------
// magic code for ioctls // magic code for ioctls
@ -710,12 +716,17 @@ struct intel_free_graphics_memory {
// FDI receiver A is hooked up to transcoder A, FDI receiver B is hooked up to // FDI receiver A is hooked up to transcoder A, FDI receiver B is hooked up to
// transcoder B, so we have the same mapping as with the display pipes. // transcoder B, so we have the same mapping as with the display pipes.
#define PCH_FDI_RX_BASE_REGISTER 0xf0000 #define PCH_FDI_RX_BASE_REGISTER 0xf0000
#define PCH_FDI_TX_BASE_REGISTER 0x60000
#define PCH_FDI_RX_PIPE_OFFSET 0x01000 #define PCH_FDI_RX_PIPE_OFFSET 0x01000
#define PCH_FDI_TX_PIPE_OFFSET 0x01000
#define PCH_FDI_RX_CONTROL 0x0c #define PCH_FDI_RX_CONTROL 0x00c
#define PCH_FDI_TX_CONTROL 0x100
#define FDI_RX_CLOCK_MASK (1 << 4) #define FDI_RX_CLOCK_MASK (1 << 4)
#define FDI_RX_CLOCK_RAW (0 << 4) #define FDI_RX_CLOCK_RAW (0 << 4)
#define FDI_RX_CLOCK_PCD (1 << 4) #define FDI_RX_CLOCK_PCD (1 << 4)
#define FDI_TX_PLL_ENABLED (1 << 14)
#define FDI_RX_PLL_ENABLED (1 << 13)
#define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30 #define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30
#define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38 #define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38

View File

@ -6,8 +6,6 @@
* Michael Lotz, mmlr@mlotz.ch * Michael Lotz, mmlr@mlotz.ch
* Alexander von Gluck IV, kallisti5@unixzen.com * Alexander von Gluck IV, kallisti5@unixzen.com
*/ */
#include "DisplayPipe.h" #include "DisplayPipe.h"
#include "accelerant.h" #include "accelerant.h"
@ -17,6 +15,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <new>
#define TRACE_PIPE #define TRACE_PIPE
#ifdef TRACE_PIPE #ifdef TRACE_PIPE
@ -29,6 +29,7 @@ extern "C" void _sPrintf(const char* format, ...);
#define ERROR(x...) _sPrintf("intel_extreme: " x) #define ERROR(x...) _sPrintf("intel_extreme: " x)
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
// PIPE: 6 // PIPE: 6
// PLANE: 7 // PLANE: 7
@ -50,7 +51,7 @@ program_pipe_color_modes(uint32 colorMode)
DisplayPipe::DisplayPipe(pipe_index pipeIndex) DisplayPipe::DisplayPipe(pipe_index pipeIndex)
: :
// fFDILink(NULL), fFDILink(NULL),
// fPanelFitter(NULL), // fPanelFitter(NULL),
fPipeIndex(pipeIndex), fPipeIndex(pipeIndex),
fPipeBase(REGS_NORTH_PIPE_AND_PORT), fPipeBase(REGS_NORTH_PIPE_AND_PORT),
@ -61,6 +62,12 @@ DisplayPipe::DisplayPipe(pipe_index pipeIndex)
fPlaneBase += INTEL_PLANE_OFFSET; fPlaneBase += INTEL_PLANE_OFFSET;
} }
// Program FDILink if PCH
if (gInfo->shared_info->device_type.HasPlatformControlHub()) {
if (fFDILink == NULL)
fFDILink = new(std::nothrow) FDILink(pipeIndex);
}
TRACE("DisplayPipe %s. Pipe Base: 0x%" B_PRIxADDR TRACE("DisplayPipe %s. Pipe Base: 0x%" B_PRIxADDR
" Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A) " Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A)
? "A" : "B", fPipeBase, fPlaneBase); ? "A" : "B", fPipeBase, fPlaneBase);

View File

@ -13,14 +13,9 @@
#include <edid.h> #include <edid.h>
#include "intel_extreme.h" #include "intel_extreme.h"
#include "pll.h" #include "pll.h"
#include "FlexibleDisplayInterface.h"
enum pipe_index {
INTEL_PIPE_ANY,
INTEL_PIPE_A,
INTEL_PIPE_B
};
void program_pipe_color_modes(uint32 colorMode); void program_pipe_color_modes(uint32 colorMode);
@ -47,15 +42,15 @@ public:
uint32 extraFlags); uint32 extraFlags);
// access to the various parts of the pipe // access to the various parts of the pipe
// ::FDILink* FDILink() ::FDILink* FDI()
// { return fFDILink; } { return fFDILink; }
// ::PanelFitter* PanelFitter() // ::PanelFitter* PanelFitter()
// { return fPanelFitter; } // { return fPanelFitter; }
private: private:
void _Enable(bool enable); void _Enable(bool enable);
// FDILink* fFDILink; FDILink* fFDILink;
// PanelFitter* fPanelFitter; // PanelFitter* fPanelFitter;
pipe_index fPipeIndex; pipe_index fPipeIndex;

View File

@ -9,11 +9,12 @@
#include "FlexibleDisplayInterface.h" #include "FlexibleDisplayInterface.h"
#include "accelerant.h"
#include "intel_extreme.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <KernelExport.h>
#include "accelerant.h"
#include "intel_extreme.h"
#define TRACE_FDI #define TRACE_FDI
@ -28,9 +29,16 @@ extern "C" void _sPrintf(const char* format, ...);
// #pragma mark - FDITransmitter // #pragma mark - FDITransmitter
FDITransmitter::FDITransmitter(int32 pipeIndex) FDITransmitter::FDITransmitter(pipe_index pipeIndex)
: :
fBaseRegister(PCH_FDI_TX_BASE_REGISTER + pipeIndex * PCH_FDI_TX_PIPE_OFFSET) fRegisterBase(PCH_FDI_TX_BASE_REGISTER)
{
if (pipeIndex == INTEL_PIPE_B)
fRegisterBase += PCH_FDI_TX_PIPE_OFFSET * 1;
}
FDITransmitter::~FDITransmitter()
{ {
} }
@ -38,7 +46,7 @@ FDITransmitter::FDITransmitter(int32 pipeIndex)
bool bool
FDITransmitter::IsPLLEnabled() FDITransmitter::IsPLLEnabled()
{ {
return (read32(fBaseRegister + PCH_FDI_TX_CONTROL) & PCH_FDI_TX_PLL_ENABLED) return (read32(fRegisterBase + PCH_FDI_TX_CONTROL) & FDI_TX_PLL_ENABLED)
!= 0; != 0;
} }
@ -46,14 +54,14 @@ FDITransmitter::IsPLLEnabled()
void void
FDITransmitter::EnablePLL() FDITransmitter::EnablePLL()
{ {
uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL; uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
uint32 value = read32(targetRegister); uint32 value = read32(targetRegister);
if ((value & PCH_FDI_TX_PLL_ENABLED) != 0) { if ((value & FDI_TX_PLL_ENABLED) != 0) {
// already enabled, possibly IronLake where it always is // already enabled, possibly IronLake where it always is
return; return;
} }
write32(targetRegister, value | PCH_FDI_TX_PLL_ENABLED); write32(targetRegister, value | FDI_TX_PLL_ENABLED);
read32(targetRegister); read32(targetRegister);
spin(100); // warmup 10us + dmi delay 20us, be generous spin(100); // warmup 10us + dmi delay 20us, be generous
} }
@ -62,13 +70,13 @@ FDITransmitter::EnablePLL()
void void
FDITransmitter::DisablePLL() FDITransmitter::DisablePLL()
{ {
if (gInfo->shared_info->device_type.IsGroup(INTEL_GROUP_ILK)) { if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK)) {
// on IronLake the FDI PLL is alaways enabled, so no point in trying... // on IronLake the FDI PLL is alaways enabled, so no point in trying...
return; return;
} }
uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL; uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
write32(targetRegister, read32(targetRegister) & ~PCH_FDI_TX_PLL_ENABLED); write32(targetRegister, read32(targetRegister) & ~FDI_TX_PLL_ENABLED);
read32(targetRegister); read32(targetRegister);
spin(100); spin(100);
} }
@ -77,9 +85,16 @@ FDITransmitter::DisablePLL()
// #pragma mark - FDIReceiver // #pragma mark - FDIReceiver
FDIReceiver::FDIReceiver(int32 pipeIndex) FDIReceiver::FDIReceiver(pipe_index pipeIndex)
: :
fBaseRegister(PCH_FDI_RX_BASE_REGISTER + pipeIndex * PCH_FDI_RX_PIPE_OFFSET) fRegisterBase(PCH_FDI_RX_BASE_REGISTER)
{
if (pipeIndex == INTEL_PIPE_B)
fRegisterBase += PCH_FDI_RX_PIPE_OFFSET * 1;
}
FDIReceiver::~FDIReceiver()
{ {
} }
@ -87,7 +102,7 @@ FDIReceiver::FDIReceiver(int32 pipeIndex)
bool bool
FDIReceiver::IsPLLEnabled() FDIReceiver::IsPLLEnabled()
{ {
return (read32(fBaseRegister + PCH_FDI_RX_CONTROL) & PCH_FDI_RX_PLL_ENABLED) return (read32(fRegisterBase + PCH_FDI_RX_CONTROL) & FDI_RX_PLL_ENABLED)
!= 0; != 0;
} }
@ -95,12 +110,12 @@ FDIReceiver::IsPLLEnabled()
void void
FDIReceiver::EnablePLL() FDIReceiver::EnablePLL()
{ {
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
uint32 value = read32(targetRegister); uint32 value = read32(targetRegister);
if ((value & PCH_FDI_RX_PLL_ENABLED) != 0) if ((value & FDI_RX_PLL_ENABLED) != 0)
return; return;
write32(targetRegister, value | PCH_FDI_RX_PLL_ENABLED); write32(targetRegister, value | FDI_RX_PLL_ENABLED);
read32(targetRegister); read32(targetRegister);
spin(200); // warmup 10us + dmi delay 20us, be generous spin(200); // warmup 10us + dmi delay 20us, be generous
} }
@ -109,19 +124,19 @@ FDIReceiver::EnablePLL()
void void
FDIReceiver::DisablePLL() FDIReceiver::DisablePLL()
{ {
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
write32(targetRegister, read32(targetRegister) & ~PCH_FDI_RX_PLL_ENABLED); write32(targetRegister, read32(targetRegister) & ~FDI_RX_PLL_ENABLED);
read32(targetRegister); read32(targetRegister);
spin(100); spin(100);
} }
void void
FDIReceiver::SwtichClock(bool toPCDClock) FDIReceiver::SwitchClock(bool toPCDClock)
{ {
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
write32(targetRegister, (read32(targetRegister) & ~PCH_FDI_RX_CLOCK_MASK) write32(targetRegister, (read32(targetRegister) & ~FDI_RX_CLOCK_MASK)
| (toPCDClock ? PCH_FDI_RX_CLOCK_PCD : PCH_FDI_RX_CLOCK_RAW)); | (toPCDClock ? FDI_RX_CLOCK_PCD : FDI_RX_CLOCK_RAW));
read32(targetRegister); read32(targetRegister);
spin(200); spin(200);
} }
@ -130,9 +145,14 @@ FDIReceiver::SwtichClock(bool toPCDClock)
// #pragma mark - FDILink // #pragma mark - FDILink
FDILink::FDILink(int32 pipeIndex) FDILink::FDILink(pipe_index pipeIndex)
: :
fTransmitter(pipeIndex), fTransmitter(pipeIndex),
fReceiver(pipeIndex) fReceiver(pipeIndex)
{ {
} }
FDILink::~FDILink()
{
}

View File

@ -9,10 +9,13 @@
#define INTEL_FDI_H #define INTEL_FDI_H
#include "intel_extreme.h"
class FDITransmitter { class FDITransmitter {
public: public:
FDITransmitter(int32 pipeIndex); FDITransmitter(pipe_index pipeIndex);
virtual ~FDITransmitter(); ~FDITransmitter();
bool IsPLLEnabled(); bool IsPLLEnabled();
void EnablePLL(); void EnablePLL();
@ -25,7 +28,8 @@ private:
class FDIReceiver { class FDIReceiver {
public: public:
FDIReceiver(int32 pipeIndex); FDIReceiver(pipe_index pipeIndex);
~FDIReceiver();
bool IsPLLEnabled(); bool IsPLLEnabled();
void EnablePLL(); void EnablePLL();
@ -40,14 +44,18 @@ protected:
class FDILink { class FDILink {
public: public:
FDILink(int32 pipeIndex); FDILink(pipe_index pipeIndex);
~FDILink();
FDITransmitter& Transmitter(); FDITransmitter& Transmitter()
FDIReceiver& Receiver(); { return fTransmitter; };
FDIReceiver& Receiver()
{ return fReceiver; };
private: private:
FDITransmitter fTransmitter; FDITransmitter fTransmitter;
FDIReceiver fReceiver; FDIReceiver fReceiver;
}; };
#endif // INTEL_FDI_H #endif // INTEL_FDI_H

View File

@ -19,7 +19,7 @@ Addon intel_extreme.accelerant :
pll.cpp pll.cpp
# classes # classes
DisplayPipe.cpp DisplayPipe.cpp
# FlexibleDisplayInterface.cpp FlexibleDisplayInterface.cpp
# PanelFitter.cpp # PanelFitter.cpp
Ports.cpp Ports.cpp
: be $(TARGET_LIBSTDC++) libaccelerantscommon.a : be $(TARGET_LIBSTDC++) libaccelerantscommon.a

View File

@ -19,6 +19,7 @@
#include "accelerant.h" #include "accelerant.h"
#include "accelerant_protos.h" #include "accelerant_protos.h"
#include "FlexibleDisplayInterface.h"
#include "intel_extreme.h" #include "intel_extreme.h"
#include <new> #include <new>
@ -85,6 +86,12 @@ Port::AssignPipe(pipe_index pipeIndex)
return B_ERROR; return B_ERROR;
} }
// TODO: UnAssignPipe? This likely needs reworked a little
if (fDisplayPipe != NULL) {
ERROR("%s: Can't reassign DisplayPipe (yet)\n", __func__);
return B_ERROR;
}
TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__,
PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B"); PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B");
@ -253,6 +260,14 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
return B_ERROR; return B_ERROR;
} }
// Train FDI if it exists
FDILink* link = fDisplayPipe->FDI();
if (link != NULL) {
link->Receiver().EnablePLL();
link->Receiver().SwitchClock(true);
link->Transmitter().EnablePLL();
}
pll_divisors divisors; pll_divisors divisors;
compute_pll_divisors(target, &divisors, false); compute_pll_divisors(target, &divisors, false);
@ -660,6 +675,14 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
return B_ERROR; return B_ERROR;
} }
// Train FDI if it exists
FDILink* link = fDisplayPipe->FDI();
if (link != NULL) {
link->Receiver().EnablePLL();
link->Receiver().SwitchClock(true);
link->Transmitter().EnablePLL();
}
pll_divisors divisors; pll_divisors divisors;
compute_pll_divisors(target, &divisors, false); compute_pll_divisors(target, &divisors, false);

View File

@ -12,8 +12,9 @@
#include <edid.h> #include <edid.h>
#include "DisplayPipe.h"
#include "intel_extreme.h" #include "intel_extreme.h"
#include "DisplayPipe.h"
#include "pll.h" #include "pll.h"
@ -69,6 +70,9 @@ virtual status_t SetDisplayMode(display_mode* mode,
virtual pipe_index PipePreference() virtual pipe_index PipePreference()
{ return INTEL_PIPE_ANY; }; { return INTEL_PIPE_ANY; };
::DisplayPipe* Pipe()
{ return fDisplayPipe; };
protected: protected:
void _SetName(const char* name); void _SetName(const char* name);

View File

@ -350,6 +350,7 @@ assign_pipes()
} }
gInfo->ports[i]->AssignPipe(currentPipe); gInfo->ports[i]->AssignPipe(currentPipe);
assigned++; assigned++;
} }
} }

View File

@ -23,10 +23,6 @@
#include "accelerant_protos.h" #include "accelerant_protos.h"
#include "accelerant.h" #include "accelerant.h"
#if 0
#include "DisplayPipe.h"
#include "FlexibleDisplayInterface.h"
#endif
#include "pll.h" #include "pll.h"
#include "Ports.h" #include "Ports.h"
#include "utility.h" #include "utility.h"