diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 63226436c2..03ab34d207 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -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. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ @@ -11,6 +12,7 @@ #include "accelerant.h" #include "intel_extreme.h" +#include #include #include @@ -25,14 +27,28 @@ extern "C" void _sPrintf(const char* format, ...); #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 -DisplayPipe::DisplayPipe(int32 pipeIndex) +DisplayPipe::DisplayPipe(pipe_index pipeIndex) : - fFDILink(NULL), - fPanelFitter(NULL), - fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_PIPE_OFFSET) +// fFDILink(NULL), +// fPanelFitter(NULL), + fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_OFFSET), + fPipeIndex(pipeIndex) { } @@ -40,7 +56,8 @@ DisplayPipe::DisplayPipe(int32 pipeIndex) bool 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) { _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); spin(150); + #if 0 // update timing parameters write32(INTEL_DISPLAY_A_HTOTAL, ((uint32)(target.timing.h_total - 1) << 16) @@ -149,27 +169,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors) ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); - - // 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); - } - + #endif } @@ -177,7 +177,7 @@ void DisplayPipe::_Enable(bool enable) { uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL; - write32(targetRegister, read32(targetRegister) & ~PIPE_ENABLED - | (enable ? PIPE_ENABLED | 0)); + write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED) + | (enable ? INTEL_PIPE_ENABLED : 0)); read32(targetRegister); } diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index 7273288c49..c402de7cff 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -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. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ #ifndef INTEL_PIPE_H #define INTEL_PIPE_H -class FDILink; -class PanelFitter; +#include -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 { public: - DisplayPipe(int32 pipeIndex); + DisplayPipe(pipe_index pipeIndex); virtual ~DisplayPipe(); + pipe_index Index() + { return fPipeIndex; } + bool IsEnabled(); void Enable(const display_mode& mode); void Disable(); @@ -27,18 +43,20 @@ virtual ~DisplayPipe(); const pll_divisors& divisors); // access to the various parts of the pipe - ::FDILink* FDILink() - { return fFDILink; } - ::PanelFitter* PanelFitter() - { return fPanelFitter; } + // ::FDILink* FDILink() + // { return fFDILink; } + // ::PanelFitter* PanelFitter() + // { return fPanelFitter; } private: void _Enable(bool enable); - FDILink* fFDILink; - PanelFitter* fPanelFitter; + // FDILink* fFDILink; + // PanelFitter* fPanelFitter; - uint32 fRegisterBase; + addr_t fBaseRegister; + pipe_index fPipeIndex; }; + #endif // INTEL_PIPE_H diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 5d2ea96c66..59307e59c4 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -18,7 +18,7 @@ Addon intel_extreme.accelerant : # overlay_3d_i965.cpp pll.cpp # classes -# DisplayPipe.cpp + DisplayPipe.cpp # FlexibleDisplayInterface.cpp # PanelFitter.cpp Ports.cpp diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index dea72a59e0..2c841c04ee 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -21,6 +21,8 @@ #include "accelerant_protos.h" #include "intel_extreme.h" +#include + #undef TRACE #define TRACE_PORTS @@ -38,7 +40,7 @@ Port::Port(port_index index, const char* baseName) : fPortIndex(index), fPortName(NULL), - fPipeIndex(INTEL_PIPE_ANY), + fDisplayPipe(NULL), fEDIDState(B_NO_INIT) { char portID[2]; @@ -71,8 +73,8 @@ Port::HasEDID() } -void -Port::PipeSelect(pipe_index pipeIndex) +status_t +Port::AssignPipe(pipe_index pipeIndex) { CALLED(); @@ -80,7 +82,7 @@ Port::PipeSelect(pipe_index pipeIndex) if (portRegister == 0) { ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, portRegister, PortName()); - return; + return B_ERROR; } TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, @@ -93,8 +95,14 @@ Port::PipeSelect(pipe_index pipeIndex) else write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); - fPipeIndex = pipeIndex; + fDisplayPipe = new(std::nothrow) DisplayPipe(pipeIndex); + + if (fDisplayPipe == NULL) + return B_NO_MEMORY; + read32(portRegister); + + return B_OK; } @@ -730,7 +738,7 @@ HDMIPort::IsConnected() return false; addr_t portRegister = _PortRegister(); - TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), portRegister); if (portRegister == 0) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 31bcc6f777..3a1b3d4663 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -12,6 +12,7 @@ #include +#include "DisplayPipe.h" #include "intel_extreme.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 { public: Port(port_index index, @@ -60,12 +53,9 @@ virtual uint32 Type() const = 0; port_index PortIndex() const { return fPortIndex; } - pipe_index PipeIndex() const - { return fPipeIndex; } - virtual bool IsConnected() = 0; - void PipeSelect(pipe_index pipeIndex); + status_t AssignPipe(pipe_index pipeIndex); bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, @@ -93,7 +83,7 @@ virtual addr_t _PortRegister() = 0; port_index fPortIndex; char* fPortName; - pipe_index fPipeIndex; + DisplayPipe* fDisplayPipe; status_t fEDIDState; edid1_info fEDIDInfo; @@ -179,7 +169,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: -virtual uint32 _PortRegister(); +virtual addr_t _PortRegister(); }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index fde449df3d..4f60beae56 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -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 @@ -350,6 +381,11 @@ intel_init_accelerant(int device) if (status != B_OK) 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(); if (status != B_OK) { uninit_common(); diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index aa5cc07f50..34994669ac 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -615,9 +615,6 @@ if (first) { if (!gInfo->ports[i]->IsConnected()) 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); if (status != B_OK) ERROR("%s: Unable to set display mode!\n", __func__); @@ -717,6 +714,9 @@ if (first) { // 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) set_display_power_mode(sharedInfo.dpms_mode);