mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 15:48:12 +00:00
Kernel/Graphics: Introduce the IntelDisplayConnectorGroup class
In the real world, graphics hardware tend to have multiple display connectors. However, usually the connectors share one register space but still keeping different PLL timings and display lanes. This new class should represent a group of multiple display connectors working together in the same Intel graphics adapter. This opens an opportunity to abstract the interface so we could support future Intel iGPU generations. This is also a preparation before the driver can support newer devices and utilize their capabilities. The mentioned preparation is applied in a these aspects: 1. The code is splitted into more classes to adjust to future expansion. 2 classes are introduced: IntelDisplayPlane and IntelDisplayTranscoder, so the IntelDisplayPlane controls the plane registers and second class controls the pipeline (transcoder, encoder) registers. On gen4 it's not really useful because there are probably one plane and one encoder to care about, but in future generations, there are likely to be multiple transcoders and planes to accommodate multi head support. 2. The set_edid_bytes method in the DisplayConnector class can now be told to not assume the provided EDID bytes are always invalid. Therefore it can refrain from printing error messages if this flag parameter is true. This is useful for supporting real hardware situation when on boot not all ports are connected to a monitor, which can result in floating bus condition (essentially all the bytes we read are 0xFF). 3. An IntelNativeDisplayConnector could now be set to flag other types of connections such as eDP (embedded DisplayPort), Analog output, etc. This is important because on the Intel gen4 graphics we could assume to have one analog output connector, but on future generations this is very likely to not be the case, as there might be no VGA outputs, but rather only an eDP connector which is converted to VGA by a design choice of the motherboard manufacturer. 4. Add ConnectorIndex to IntelNativeDisplayConnector class - Currently this is used to verify we always handle the correct connector when doing modesetting. Later, it will be used to locate special settings needed when handling connector requests. 5. Prepare to support more types of display planes. For example, the Intel Skylake register set for display planes is a bit different, so let's ensure we can properly support it in the near future.
This commit is contained in:
parent
e2dde64628
commit
2def16a3d2
19 changed files with 1211 additions and 689 deletions
|
@ -16,54 +16,42 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
namespace IntelGraphics {
|
||||
|
||||
enum class RegisterIndex {
|
||||
PipeAConf = 0x70008,
|
||||
PipeBConf = 0x71008,
|
||||
GMBusData = 0x510C,
|
||||
GMBusStatus = 0x5108,
|
||||
GMBusCommand = 0x5104,
|
||||
GMBusClock = 0x5100,
|
||||
DisplayPlaneAControl = 0x70180,
|
||||
DisplayPlaneBControl = 0x71180,
|
||||
DisplayPlaneALinearOffset = 0x70184,
|
||||
DisplayPlaneAStride = 0x70188,
|
||||
DisplayPlaneASurface = 0x7019C,
|
||||
DPLLDivisorA0 = 0x6040,
|
||||
DPLLDivisorA1 = 0x6044,
|
||||
DPLLControlA = 0x6014,
|
||||
DPLLControlB = 0x6018,
|
||||
DPLLMultiplierA = 0x601C,
|
||||
HTotalA = 0x60000,
|
||||
HBlankA = 0x60004,
|
||||
HSyncA = 0x60008,
|
||||
VTotalA = 0x6000C,
|
||||
VBlankA = 0x60010,
|
||||
VSyncA = 0x60014,
|
||||
PipeASource = 0x6001C,
|
||||
AnalogDisplayPort = 0x61100,
|
||||
VGADisplayPlaneControl = 0x71400,
|
||||
};
|
||||
|
||||
struct PLLSettings;
|
||||
|
||||
struct PLLParameterLimit {
|
||||
size_t min, max;
|
||||
};
|
||||
|
||||
struct PLLMaxSettings {
|
||||
PLLParameterLimit dot_clock, vco, n, m, m1, m2, p, p1, p2;
|
||||
};
|
||||
}
|
||||
|
||||
class IntelDisplayConnectorGroup;
|
||||
class IntelNativeDisplayConnector final
|
||||
: public DisplayConnector {
|
||||
friend class IntelNativeGraphicsAdapter;
|
||||
friend class IntelDisplayConnectorGroup;
|
||||
friend class DeviceManagement;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<IntelNativeDisplayConnector>> try_create(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, PhysicalAddress registers_region_address, size_t registers_region_length);
|
||||
enum class Type {
|
||||
Invalid,
|
||||
Analog,
|
||||
DVO,
|
||||
LVDS,
|
||||
TVOut,
|
||||
HDMI,
|
||||
DisplayPort,
|
||||
EmbeddedDisplayPort,
|
||||
};
|
||||
|
||||
enum class ConnectorIndex : size_t {
|
||||
PortA = 0,
|
||||
PortB = 1,
|
||||
PortC = 2,
|
||||
PortD = 3,
|
||||
PortE = 4,
|
||||
PortF = 5,
|
||||
PortH = 6,
|
||||
PortG = 7,
|
||||
PortI = 8,
|
||||
};
|
||||
|
||||
static ErrorOr<NonnullLockRefPtr<IntelNativeDisplayConnector>> try_create_with_display_connector_group(IntelDisplayConnectorGroup const&, ConnectorIndex, Type, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size);
|
||||
|
||||
void set_edid_bytes(Badge<IntelDisplayConnectorGroup>, Array<u8, 128> const& edid_bytes);
|
||||
ErrorOr<void> create_attached_framebuffer_console(Badge<IntelDisplayConnectorGroup>);
|
||||
|
||||
ConnectorIndex connector_index() const { return m_connector_index; }
|
||||
|
||||
private:
|
||||
// ^DisplayConnector
|
||||
|
@ -83,55 +71,10 @@ private:
|
|||
// Note: Paravirtualized hardware doesn't require a defined refresh rate for modesetting.
|
||||
virtual bool refresh_rate_support() const override { return true; }
|
||||
|
||||
IntelNativeDisplayConnector(PhysicalAddress framebuffer_address, size_t framebuffer_resource_size, NonnullOwnPtr<GMBusConnector>, NonnullOwnPtr<Memory::Region> registers_region);
|
||||
|
||||
ErrorOr<void> create_attached_framebuffer_console();
|
||||
ErrorOr<void> initialize_gmbus_settings_and_read_edid();
|
||||
|
||||
void write_to_register(IntelGraphics::RegisterIndex, u32 value) const;
|
||||
u32 read_from_register(IntelGraphics::RegisterIndex) const;
|
||||
|
||||
bool pipe_a_enabled() const;
|
||||
bool pipe_b_enabled() const;
|
||||
|
||||
bool is_resolution_valid(size_t width, size_t height);
|
||||
|
||||
bool set_safe_crt_resolution();
|
||||
|
||||
void disable_output();
|
||||
void enable_output(PhysicalAddress fb_address, size_t width);
|
||||
|
||||
void disable_vga_emulation();
|
||||
void enable_vga_plane();
|
||||
|
||||
void disable_dac_output();
|
||||
void enable_dac_output();
|
||||
|
||||
void disable_all_planes();
|
||||
void disable_pipe_a();
|
||||
void disable_pipe_b();
|
||||
void disable_dpll();
|
||||
|
||||
void set_dpll_registers(IntelGraphics::PLLSettings const&);
|
||||
|
||||
void enable_dpll_without_vga(IntelGraphics::PLLSettings const&, size_t dac_multiplier);
|
||||
void set_display_timings(Graphics::Modesetting const&);
|
||||
void enable_pipe_a();
|
||||
void enable_primary_plane(PhysicalAddress fb_address, size_t stride);
|
||||
|
||||
bool wait_for_enabled_pipe_a(size_t milliseconds_timeout) const;
|
||||
bool wait_for_disabled_pipe_a(size_t milliseconds_timeout) const;
|
||||
bool wait_for_disabled_pipe_b(size_t milliseconds_timeout) const;
|
||||
|
||||
void gmbus_read_edid();
|
||||
|
||||
Optional<IntelGraphics::PLLSettings> create_pll_settings(u64 target_frequency, u64 reference_clock, IntelGraphics::PLLMaxSettings const&);
|
||||
|
||||
mutable Spinlock<LockRank::None> m_registers_lock {};
|
||||
IntelNativeDisplayConnector(IntelDisplayConnectorGroup const&, ConnectorIndex connector_index, Type, PhysicalAddress framebuffer_address, size_t framebuffer_resource_size);
|
||||
Type const m_type { Type::Analog };
|
||||
ConnectorIndex const m_connector_index { 0 };
|
||||
NonnullLockRefPtr<IntelDisplayConnectorGroup> m_parent_connector_group;
|
||||
LockRefPtr<Graphics::GenericFramebufferConsole> m_framebuffer_console;
|
||||
|
||||
const PhysicalAddress m_registers;
|
||||
NonnullOwnPtr<Memory::Region> m_registers_region;
|
||||
NonnullOwnPtr<GMBusConnector> m_gmbus_connector;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue