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;
};
enum pipe_index {
INTEL_PIPE_ANY,
INTEL_PIPE_A,
INTEL_PIPE_B
};
//----------------- ioctl() interface ----------------
// 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
// transcoder B, so we have the same mapping as with the display pipes.
#define PCH_FDI_RX_BASE_REGISTER 0xf0000
#define PCH_FDI_TX_BASE_REGISTER 0x60000
#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_RAW (0 << 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_2 0x38

View File

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

View File

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

View File

@ -9,11 +9,12 @@
#include "FlexibleDisplayInterface.h"
#include "accelerant.h"
#include "intel_extreme.h"
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
#include "accelerant.h"
#include "intel_extreme.h"
#define TRACE_FDI
@ -28,9 +29,16 @@ extern "C" void _sPrintf(const char* format, ...);
// #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
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;
}
@ -46,14 +54,14 @@ FDITransmitter::IsPLLEnabled()
void
FDITransmitter::EnablePLL()
{
uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL;
uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
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
return;
}
write32(targetRegister, value | PCH_FDI_TX_PLL_ENABLED);
write32(targetRegister, value | FDI_TX_PLL_ENABLED);
read32(targetRegister);
spin(100); // warmup 10us + dmi delay 20us, be generous
}
@ -62,13 +70,13 @@ FDITransmitter::EnablePLL()
void
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...
return;
}
uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL;
write32(targetRegister, read32(targetRegister) & ~PCH_FDI_TX_PLL_ENABLED);
uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL;
write32(targetRegister, read32(targetRegister) & ~FDI_TX_PLL_ENABLED);
read32(targetRegister);
spin(100);
}
@ -77,9 +85,16 @@ FDITransmitter::DisablePLL()
// #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
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;
}
@ -95,12 +110,12 @@ FDIReceiver::IsPLLEnabled()
void
FDIReceiver::EnablePLL()
{
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL;
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
uint32 value = read32(targetRegister);
if ((value & PCH_FDI_RX_PLL_ENABLED) != 0)
if ((value & FDI_RX_PLL_ENABLED) != 0)
return;
write32(targetRegister, value | PCH_FDI_RX_PLL_ENABLED);
write32(targetRegister, value | FDI_RX_PLL_ENABLED);
read32(targetRegister);
spin(200); // warmup 10us + dmi delay 20us, be generous
}
@ -109,19 +124,19 @@ FDIReceiver::EnablePLL()
void
FDIReceiver::DisablePLL()
{
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL;
write32(targetRegister, read32(targetRegister) & ~PCH_FDI_RX_PLL_ENABLED);
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
write32(targetRegister, read32(targetRegister) & ~FDI_RX_PLL_ENABLED);
read32(targetRegister);
spin(100);
}
void
FDIReceiver::SwtichClock(bool toPCDClock)
FDIReceiver::SwitchClock(bool toPCDClock)
{
uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL;
write32(targetRegister, (read32(targetRegister) & ~PCH_FDI_RX_CLOCK_MASK)
| (toPCDClock ? PCH_FDI_RX_CLOCK_PCD : PCH_FDI_RX_CLOCK_RAW));
uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL;
write32(targetRegister, (read32(targetRegister) & ~FDI_RX_CLOCK_MASK)
| (toPCDClock ? FDI_RX_CLOCK_PCD : FDI_RX_CLOCK_RAW));
read32(targetRegister);
spin(200);
}
@ -130,9 +145,14 @@ FDIReceiver::SwtichClock(bool toPCDClock)
// #pragma mark - FDILink
FDILink::FDILink(int32 pipeIndex)
FDILink::FDILink(pipe_index pipeIndex)
:
fTransmitter(pipeIndex),
fReceiver(pipeIndex)
{
}
FDILink::~FDILink()
{
}

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include "accelerant.h"
#include "accelerant_protos.h"
#include "FlexibleDisplayInterface.h"
#include "intel_extreme.h"
#include <new>
@ -85,6 +86,12 @@ Port::AssignPipe(pipe_index pipeIndex)
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__,
PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B");
@ -253,6 +260,14 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
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;
compute_pll_divisors(target, &divisors, false);
@ -660,6 +675,14 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
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;
compute_pll_divisors(target, &divisors, false);

View File

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

View File

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

View File

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