Kernel/IntelGraphics: Move pipe management to the Transcoder class

It became apparent to me that future generations of the Intel graphics
chipset utilize the same register set as part of the Transcoder register
set. Therefore, it should be included now in the Transcoder class.
This commit is contained in:
Liav A 2022-04-01 12:52:49 +03:00 committed by Andrew Kaster
parent 2def16a3d2
commit 8042ae43c3
Notes: sideshowbarker 2024-07-17 10:54:57 +09:00
7 changed files with 95 additions and 122 deletions

View file

@ -11,17 +11,18 @@
namespace Kernel {
ErrorOr<NonnullOwnPtr<IntelAnalogDisplayTranscoder>> IntelAnalogDisplayTranscoder::create_with_physical_addresses(PhysicalAddress transcoder_registers_start_address,
PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_multiplier_register_start_address)
PhysicalAddress pipe_registers_start_address, PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_multiplier_register_start_address)
{
auto transcoder_registers_mapping = TRY(Memory::map_typed<TranscoderRegisters volatile>(transcoder_registers_start_address, sizeof(IntelDisplayTranscoder::TranscoderRegisters), Memory::Region::Access::ReadWrite));
auto pipe_registers_mapping = TRY(Memory::map_typed<PipeRegisters volatile>(pipe_registers_start_address, sizeof(IntelDisplayTranscoder::PipeRegisters), Memory::Region::Access::ReadWrite));
auto dpll_registers_mapping = TRY(Memory::map_typed<DPLLRegisters volatile>(dpll_registers_start_address, sizeof(DPLLRegisters), Memory::Region::Access::ReadWrite));
auto dpll_control_mapping = TRY(Memory::map_typed<DPLLControlRegisters volatile>(dpll_multiplier_register_start_address, sizeof(DPLLControlRegisters), Memory::Region::Access::ReadWrite));
return adopt_nonnull_own_or_enomem(new (nothrow) IntelAnalogDisplayTranscoder(move(transcoder_registers_mapping), move(dpll_registers_mapping), move(dpll_control_mapping)));
return adopt_nonnull_own_or_enomem(new (nothrow) IntelAnalogDisplayTranscoder(move(transcoder_registers_mapping), move(pipe_registers_mapping), move(dpll_registers_mapping), move(dpll_control_mapping)));
}
IntelAnalogDisplayTranscoder::IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> transcoder_registers_mapping,
Memory::TypedMapping<DPLLRegisters volatile> dpll_registers_mapping, Memory::TypedMapping<DPLLControlRegisters volatile> dpll_control_registers)
: IntelDisplayTranscoder(move(transcoder_registers_mapping))
Memory::TypedMapping<PipeRegisters volatile> pipe_registers_mapping, Memory::TypedMapping<DPLLRegisters volatile> dpll_registers_mapping, Memory::TypedMapping<DPLLControlRegisters volatile> dpll_control_registers)
: IntelDisplayTranscoder(move(transcoder_registers_mapping), move(pipe_registers_mapping))
, m_dpll_registers(move(dpll_registers_mapping))
, m_dpll_control_registers(move(dpll_control_registers))
{

View file

@ -17,7 +17,7 @@ class IntelDisplayConnectorGroup;
class IntelAnalogDisplayTranscoder final : public IntelDisplayTranscoder {
public:
static ErrorOr<NonnullOwnPtr<IntelAnalogDisplayTranscoder>> create_with_physical_addresses(PhysicalAddress transcoder_registers_start_address,
PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_control_registers_start_address);
PhysicalAddress pipe_registers_start_address, PhysicalAddress dpll_registers_start_address, PhysicalAddress dpll_control_registers_start_address);
virtual ErrorOr<void> set_dpll_settings(Badge<IntelDisplayConnectorGroup>, IntelGraphics::PLLSettings const& settings, size_t dac_multiplier) override;
virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) override;
@ -35,7 +35,7 @@ private:
u32 multiplier;
};
IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<DPLLRegisters volatile>, Memory::TypedMapping<DPLLControlRegisters volatile>);
IntelAnalogDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<PipeRegisters volatile>, Memory::TypedMapping<DPLLRegisters volatile>, Memory::TypedMapping<DPLLControlRegisters volatile>);
Memory::TypedMapping<DPLLRegisters volatile> m_dpll_registers;
Memory::TypedMapping<DPLLControlRegisters volatile> m_dpll_control_registers;
};

View file

@ -4,13 +4,15 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Arch/Delay.h>
#include <Kernel/Graphics/Intel/Transcoder/DisplayTranscoder.h>
#include <Kernel/PhysicalAddress.h>
namespace Kernel {
IntelDisplayTranscoder::IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> registers_mapping)
IntelDisplayTranscoder::IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> registers_mapping, Memory::TypedMapping<PipeRegisters volatile> pipe_registers_mapping)
: m_transcoder_registers(move(registers_mapping))
, m_pipe_registers(move(pipe_registers_mapping))
{
}
@ -54,4 +56,55 @@ ErrorOr<void> IntelDisplayTranscoder::set_mode_setting_timings(Badge<IntelDispla
return {};
}
ErrorOr<void> IntelDisplayTranscoder::disable_pipe(Badge<IntelDisplayConnectorGroup>)
{
SpinlockLocker locker(m_access_lock);
m_pipe_registers->pipe_configuration = 0;
m_shadow_registers.pipe_conf = 0;
dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe");
size_t milliseconds_elapsed = 0;
while (milliseconds_elapsed < 100) {
u32 value = m_pipe_registers->pipe_configuration;
if (!(value & (1 << 30)))
return {};
microseconds_delay(1000);
milliseconds_elapsed++;
}
return Error::from_errno(EBUSY);
}
ErrorOr<void> IntelDisplayTranscoder::enable_pipe(Badge<IntelDisplayConnectorGroup>)
{
SpinlockLocker locker(m_access_lock);
u32 value = m_pipe_registers->pipe_configuration;
// Note: Just verify these are not already enabled...
if ((value & (1 << 30)) && (value & (1 << 31)))
return {};
// Note: Set the pipe configuration register with these bits:
// 1. Bit 31 - to enable the Pipe
// 2. Bit 24 - to enable Gamma Unit Mode to 10 bit Gamma mode.
// 3. Bits 21-23 are set to zero to indicate Progressive mode (non Interlaced mode)
// 4. Bits 18 and 19 are set to zero to indicate Normal operations of assigned
// Cursor and Display planes.
m_pipe_registers->pipe_configuration = (1 << 31) | (1 << 24);
m_shadow_registers.pipe_conf = (1 << 31) | (1 << 24);
dbgln_if(INTEL_GRAPHICS_DEBUG, "Enabling Pipe");
size_t milliseconds_elapsed = 0;
while (milliseconds_elapsed < 100) {
u32 value = m_pipe_registers->pipe_configuration;
if ((value & (1 << 30)))
return {};
microseconds_delay(1000);
milliseconds_elapsed++;
}
// FIXME: Seems like my video card is buggy and doesn't set the enabled bit (bit 30)!!
return {};
}
bool IntelDisplayTranscoder::pipe_enabled(Badge<IntelDisplayConnectorGroup>) const
{
SpinlockLocker locker(m_access_lock);
u32 value = m_pipe_registers->pipe_configuration;
return (value & (1 << 30));
}
}

View file

@ -48,6 +48,7 @@ public:
u32 n1_link;
u32 m2_link;
u32 n2_link;
u32 pipe_conf;
};
ErrorOr<void> set_mode_setting_timings(Badge<IntelDisplayConnectorGroup>, DisplayConnector::ModeSetting const&);
@ -55,6 +56,10 @@ public:
virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) = 0;
virtual ErrorOr<void> disable_dpll(Badge<IntelDisplayConnectorGroup>) = 0;
ErrorOr<void> disable_pipe(Badge<IntelDisplayConnectorGroup>);
ErrorOr<void> enable_pipe(Badge<IntelDisplayConnectorGroup>);
bool pipe_enabled(Badge<IntelDisplayConnectorGroup>) const;
ShadowRegisters current_registers_state() const;
virtual ~IntelDisplayTranscoder() = default;
@ -83,9 +88,31 @@ protected:
u32 n2_link;
};
explicit IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>);
struct [[gnu::packed]] PipeRegisters {
u32 pipe_display_scan_line;
u32 pipe_display_scan_line_count_range_compare;
u32 pipe_configuration;
u32 reserved;
u32 pipe_gamma_correction_max_red;
u32 pipe_gamma_correction_max_green;
u32 pipe_gamma_correction_max_blue;
u32 reserved2[2];
u32 pipe_display_status;
u32 reserved3[2];
u32 display_arbitration_control;
u32 display_fifo_watermark_control1;
u32 display_fifo_watermark_control2;
u32 display_fifo_watermark_control3;
u32 pipe_frame_count_high;
// Note: The specification calls this "Pipe Frame Count Low and Pixel Count"
u32 pipe_frame_count_low;
};
IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<PipeRegisters volatile>);
mutable Spinlock<LockRank::None> m_access_lock;
ShadowRegisters m_shadow_registers {};
Memory::TypedMapping<TranscoderRegisters volatile> m_transcoder_registers;
Memory::TypedMapping<PipeRegisters volatile> m_pipe_registers;
};
}