intel_extreme: Begin using new DisplayPipe class

This commit is contained in:
Alexander von Gluck IV
2015-11-08 11:58:49 -06:00
parent 37b903fbc8
commit 6e1ff82f45
7 changed files with 117 additions and 65 deletions
@@ -1,9 +1,10 @@
/* /*
* Copyright 2011, Haiku, Inc. All Rights Reserved. * Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Michael Lotz, [email protected] * Michael Lotz, [email protected]
* Alexander von Gluck IV, [email protected]
*/ */
@@ -11,6 +12,7 @@
#include "accelerant.h" #include "accelerant.h"
#include "intel_extreme.h" #include "intel_extreme.h"
#include <KernelExport.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -25,14 +27,28 @@ extern "C" void _sPrintf(const char* format, ...);
#endif #endif
void
program_pipe_color_modes(uint32 colorMode)
{
// All pipes get the same color mode
write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL)
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
| colorMode);
write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL)
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
| colorMode);
}
// #pragma mark - DisplayPipe // #pragma mark - DisplayPipe
DisplayPipe::DisplayPipe(int32 pipeIndex) DisplayPipe::DisplayPipe(pipe_index pipeIndex)
: :
fFDILink(NULL), // fFDILink(NULL),
fPanelFitter(NULL), // fPanelFitter(NULL),
fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_PIPE_OFFSET) fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_OFFSET),
fPipeIndex(pipeIndex)
{ {
} }
@@ -40,7 +56,8 @@ DisplayPipe::DisplayPipe(int32 pipeIndex)
bool bool
DisplayPipe::IsEnabled() DisplayPipe::IsEnabled()
{ {
return (read32(fBaseRegister + INTEL_PIPE_CONTROL) & PIPE_ENABLED) != 0; return (read32(fBaseRegister + INTEL_PIPE_CONTROL)
& INTEL_PIPE_ENABLED) != 0;
} }
@@ -48,6 +65,8 @@ void
DisplayPipe::Enable(const display_mode& mode) DisplayPipe::Enable(const display_mode& mode)
{ {
_Enable(true); _Enable(true);
write32(INTEL_DISPLAY_B_IMAGE_SIZE, ((uint32)(mode.virtual_width - 1) << 16)
| (uint32)(mode.virtual_height - 1));
} }
@@ -117,6 +136,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors)
read32(INTEL_DISPLAY_A_PLL); read32(INTEL_DISPLAY_A_PLL);
spin(150); spin(150);
#if 0
// update timing parameters // update timing parameters
write32(INTEL_DISPLAY_A_HTOTAL, write32(INTEL_DISPLAY_A_HTOTAL,
((uint32)(target.timing.h_total - 1) << 16) ((uint32)(target.timing.h_total - 1) << 16)
@@ -149,27 +169,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors)
? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0)
| ((target.timing.flags & B_POSITIVE_VSYNC) != 0 | ((target.timing.flags & B_POSITIVE_VSYNC) != 0
? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0));
#endif
// TODO: verify the two comments below: the X driver doesn't seem to
// care about both of them!
// These two have to be set for display B, too - this obviously means
// that the second head always must adopt the color space of the first
// head.
write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL)
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
| colorMode);
if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) {
write32(INTEL_DISPLAY_B_IMAGE_SIZE,
((uint32)(target.virtual_width - 1) << 16)
| ((uint32)target.virtual_height - 1));
write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL)
& ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA))
| colorMode);
}
} }
@@ -177,7 +177,7 @@ void
DisplayPipe::_Enable(bool enable) DisplayPipe::_Enable(bool enable)
{ {
uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL; uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL;
write32(targetRegister, read32(targetRegister) & ~PIPE_ENABLED write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED)
| (enable ? PIPE_ENABLED | 0)); | (enable ? INTEL_PIPE_ENABLED : 0));
read32(targetRegister); read32(targetRegister);
} }
@@ -1,24 +1,40 @@
/* /*
* Copyright 2011, Haiku, Inc. All Rights Reserved. * Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Michael Lotz, [email protected] * Michael Lotz, [email protected]
* Alexander von Gluck IV, [email protected]
*/ */
#ifndef INTEL_PIPE_H #ifndef INTEL_PIPE_H
#define INTEL_PIPE_H #define INTEL_PIPE_H
class FDILink; #include <edid.h>
class PanelFitter;
struct pll_divisors; #include "intel_extreme.h"
#include "pll.h"
enum pipe_index {
INTEL_PIPE_A,
INTEL_PIPE_B
};
void program_pipe_color_modes(uint32 colorMode);
//class FDILink;
//class PanelFitter;
class DisplayPipe { class DisplayPipe {
public: public:
DisplayPipe(int32 pipeIndex); DisplayPipe(pipe_index pipeIndex);
virtual ~DisplayPipe(); virtual ~DisplayPipe();
pipe_index Index()
{ return fPipeIndex; }
bool IsEnabled(); bool IsEnabled();
void Enable(const display_mode& mode); void Enable(const display_mode& mode);
void Disable(); void Disable();
@@ -27,18 +43,20 @@ virtual ~DisplayPipe();
const pll_divisors& divisors); const pll_divisors& divisors);
// access to the various parts of the pipe // access to the various parts of the pipe
::FDILink* FDILink() // ::FDILink* FDILink()
{ 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;
uint32 fRegisterBase; addr_t fBaseRegister;
pipe_index fPipeIndex;
}; };
#endif // INTEL_PIPE_H #endif // INTEL_PIPE_H
@@ -18,7 +18,7 @@ Addon intel_extreme.accelerant :
# overlay_3d_i965.cpp # overlay_3d_i965.cpp
pll.cpp pll.cpp
# classes # classes
# DisplayPipe.cpp DisplayPipe.cpp
# FlexibleDisplayInterface.cpp # FlexibleDisplayInterface.cpp
# PanelFitter.cpp # PanelFitter.cpp
Ports.cpp Ports.cpp
@@ -21,6 +21,8 @@
#include "accelerant_protos.h" #include "accelerant_protos.h"
#include "intel_extreme.h" #include "intel_extreme.h"
#include <new>
#undef TRACE #undef TRACE
#define TRACE_PORTS #define TRACE_PORTS
@@ -38,7 +40,7 @@ Port::Port(port_index index, const char* baseName)
: :
fPortIndex(index), fPortIndex(index),
fPortName(NULL), fPortName(NULL),
fPipeIndex(INTEL_PIPE_ANY), fDisplayPipe(NULL),
fEDIDState(B_NO_INIT) fEDIDState(B_NO_INIT)
{ {
char portID[2]; char portID[2];
@@ -71,8 +73,8 @@ Port::HasEDID()
} }
void status_t
Port::PipeSelect(pipe_index pipeIndex) Port::AssignPipe(pipe_index pipeIndex)
{ {
CALLED(); CALLED();
@@ -80,7 +82,7 @@ Port::PipeSelect(pipe_index pipeIndex)
if (portRegister == 0) { if (portRegister == 0) {
ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__,
portRegister, PortName()); portRegister, PortName());
return; 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__,
@@ -93,8 +95,14 @@ Port::PipeSelect(pipe_index pipeIndex)
else else
write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B);
fPipeIndex = pipeIndex; fDisplayPipe = new(std::nothrow) DisplayPipe(pipeIndex);
if (fDisplayPipe == NULL)
return B_NO_MEMORY;
read32(portRegister); read32(portRegister);
return B_OK;
} }
@@ -730,7 +738,7 @@ HDMIPort::IsConnected()
return false; return false;
addr_t portRegister = _PortRegister(); addr_t portRegister = _PortRegister();
TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
portRegister); portRegister);
if (portRegister == 0) if (portRegister == 0)
+4 -14
View File
@@ -12,6 +12,7 @@
#include <edid.h> #include <edid.h>
#include "DisplayPipe.h"
#include "intel_extreme.h" #include "intel_extreme.h"
#include "pll.h" #include "pll.h"
@@ -39,14 +40,6 @@ enum port_index {
}; };
// TODO: This likely should go in some pipe header
enum pipe_index {
INTEL_PIPE_ANY,
INTEL_PIPE_A,
INTEL_PIPE_B
};
class Port { class Port {
public: public:
Port(port_index index, Port(port_index index,
@@ -60,12 +53,9 @@ virtual uint32 Type() const = 0;
port_index PortIndex() const port_index PortIndex() const
{ return fPortIndex; } { return fPortIndex; }
pipe_index PipeIndex() const
{ return fPipeIndex; }
virtual bool IsConnected() = 0; virtual bool IsConnected() = 0;
void PipeSelect(pipe_index pipeIndex); status_t AssignPipe(pipe_index pipeIndex);
bool HasEDID(); bool HasEDID();
virtual status_t GetEDID(edid1_info* edid, virtual status_t GetEDID(edid1_info* edid,
@@ -93,7 +83,7 @@ virtual addr_t _PortRegister() = 0;
port_index fPortIndex; port_index fPortIndex;
char* fPortName; char* fPortName;
pipe_index fPipeIndex; DisplayPipe* fDisplayPipe;
status_t fEDIDState; status_t fEDIDState;
edid1_info fEDIDInfo; edid1_info fEDIDInfo;
@@ -179,7 +169,7 @@ virtual uint32 Type() const
virtual bool IsConnected(); virtual bool IsConnected();
protected: protected:
virtual uint32 _PortRegister(); virtual addr_t _PortRegister();
}; };
@@ -318,6 +318,37 @@ probe_ports()
} }
static status_t
assign_pipes()
{
uint32 assigned = 0;
// TODO: At some point we should "group" ports to pipes with the same mode.
// You can drive multiple ports from a single pipe as long as the mode is
// the same.
for (uint32 i = 0; i < gInfo->port_count; i++) {
if (gInfo->ports[i] == NULL)
continue;
if (gInfo->ports[i]->IsConnected()) {
pipe_index currentPipe = INTEL_PIPE_A;
if (assigned == 1)
currentPipe = INTEL_PIPE_B;
else if (assigned > 2) {
ERROR("%s: No pipes left to assign to port %s!\n", __func__,
gInfo->ports[i]->PortName());
continue;
}
gInfo->ports[i]->AssignPipe(currentPipe);
assigned++;
}
}
return B_OK;
}
// #pragma mark - public accelerant functions // #pragma mark - public accelerant functions
@@ -350,6 +381,11 @@ intel_init_accelerant(int device)
if (status != B_OK) if (status != B_OK)
ERROR("Warning: zero active displays were found!\n"); ERROR("Warning: zero active displays were found!\n");
status = assign_pipes();
if (status != B_OK)
ERROR("Warning: error while assigning pipes!\n");
status = create_mode_list(); status = create_mode_list();
if (status != B_OK) { if (status != B_OK) {
uninit_common(); uninit_common();
@@ -615,9 +615,6 @@ if (first) {
if (!gInfo->ports[i]->IsConnected()) if (!gInfo->ports[i]->IsConnected())
continue; continue;
// XXX: For now we force everything on PIPE A
gInfo->ports[i]->PipeSelect(INTEL_PIPE_A);
status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode); status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode);
if (status != B_OK) if (status != B_OK)
ERROR("%s: Unable to set display mode!\n", __func__); ERROR("%s: Unable to set display mode!\n", __func__);
@@ -717,6 +714,9 @@ if (first) {
// RIP ANALOG // RIP ANALOG
// We set the same color mode across all pipes
program_pipe_color_modes(colorMode);
// TODO: This may not be neccesary (see DPMS OFF at top) // TODO: This may not be neccesary (see DPMS OFF at top)
set_display_power_mode(sharedInfo.dpms_mode); set_display_power_mode(sharedInfo.dpms_mode);