mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 03:02:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/String.h>
 | |
| #include <AK/Types.h>
 | |
| #include <Kernel/Bus/PCI/DeviceController.h>
 | |
| #include <Kernel/Graphics/Definitions.h>
 | |
| #include <Kernel/Graphics/FramebufferDevice.h>
 | |
| #include <Kernel/Graphics/VGACompatibleAdapter.h>
 | |
| #include <Kernel/PhysicalAddress.h>
 | |
| 
 | |
| namespace Kernel {
 | |
| 
 | |
| namespace IntelGraphics {
 | |
| 
 | |
| enum RegisterIndex {
 | |
|     PipeAConf = 0x70008,
 | |
|     PipeBConf = 0x71008,
 | |
|     GMBusData = 0x510C,
 | |
|     GMBusStatus = 0x5108,
 | |
|     GMBusCommand = 0x5104,
 | |
|     GMBusClock = 0x5100,
 | |
|     DisplayPlaneAControl = 0x70180,
 | |
|     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,
 | |
| };
 | |
| }
 | |
| 
 | |
| class IntelNativeGraphicsAdapter final
 | |
|     : public VGACompatibleAdapter {
 | |
|     AK_MAKE_ETERNAL
 | |
| public:
 | |
|     struct PLLSettings {
 | |
|         bool is_valid() const { return (n != 0 && m1 != 0 && m2 != 0 && p1 != 0 && p2 != 0); }
 | |
|         u64 compute_dot_clock(u64 refclock) const
 | |
|         {
 | |
|             return (refclock * (5 * (m1) + (m2)) / (n)) / (p1 * p2);
 | |
|         }
 | |
| 
 | |
|         u64 compute_vco(u64 refclock) const
 | |
|         {
 | |
|             return refclock * (5 * (m1) + (m2)) / n;
 | |
|         }
 | |
| 
 | |
|         u64 compute_m() const
 | |
|         {
 | |
|             return 5 * (m1) + (m2);
 | |
|         }
 | |
| 
 | |
|         u64 compute_p() const
 | |
|         {
 | |
|             return p1 * p2;
 | |
|         }
 | |
|         u64 n { 0 };
 | |
|         u64 m1 { 0 };
 | |
|         u64 m2 { 0 };
 | |
|         u64 p1 { 0 };
 | |
|         u64 p2 { 0 };
 | |
|     };
 | |
|     struct PLLParameterLimit {
 | |
|         size_t min, max;
 | |
|     };
 | |
|     struct PLLMaxSettings {
 | |
|         PLLParameterLimit dot_clock, vco, n, m, m1, m2, p, p1, p2;
 | |
|     };
 | |
| 
 | |
| private:
 | |
|     enum GMBusPinPair : u8 {
 | |
|         None = 0,
 | |
|         DedicatedControl = 1,
 | |
|         DedicatedAnalog = 0b10,
 | |
|         IntegratedDigital = 0b11,
 | |
|         sDVO = 0b101,
 | |
|         Dconnector = 0b111,
 | |
|     };
 | |
| 
 | |
|     enum class GMBusStatus {
 | |
|         TransactionCompletion,
 | |
|         HardwareReady
 | |
|     };
 | |
| 
 | |
|     enum GMBusCycle {
 | |
|         Wait = 1,
 | |
|         Stop = 4,
 | |
|     };
 | |
| 
 | |
| public:
 | |
|     static RefPtr<IntelNativeGraphicsAdapter> initialize(PCI::Address);
 | |
| 
 | |
| private:
 | |
|     explicit IntelNativeGraphicsAdapter(PCI::Address);
 | |
| 
 | |
|     void write_to_register(IntelGraphics::RegisterIndex, u32 value) const;
 | |
|     u32 read_from_register(IntelGraphics::RegisterIndex) const;
 | |
| 
 | |
|     // ^GraphicsDevice
 | |
|     virtual void initialize_framebuffer_devices() override;
 | |
|     virtual Type type() const override { return Type::VGACompatible; }
 | |
| 
 | |
|     bool pipe_a_enabled() const;
 | |
|     bool pipe_b_enabled() const;
 | |
| 
 | |
|     bool is_resolution_valid(size_t width, size_t height);
 | |
| 
 | |
|     bool set_crt_resolution(size_t width, size_t height);
 | |
| 
 | |
|     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(const PLLSettings&);
 | |
| 
 | |
|     void enable_dpll_without_vga(const PLLSettings&, size_t dac_multiplier);
 | |
|     void set_display_timings(const Graphics::Modesetting&);
 | |
|     void enable_pipe_a();
 | |
|     void set_framebuffer_parameters(size_t, size_t);
 | |
|     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 set_gmbus_default_rate();
 | |
|     void set_gmbus_pin_pair(GMBusPinPair pin_pair);
 | |
| 
 | |
|     // FIXME: It would be better if we generalize the I2C access later on
 | |
|     void gmbus_read_edid();
 | |
|     void gmbus_write(unsigned address, u32 byte);
 | |
|     void gmbus_read(unsigned address, u8* buf, size_t length);
 | |
|     bool gmbus_wait_for(GMBusStatus desired_status, Optional<size_t> milliseconds_timeout);
 | |
| 
 | |
|     Optional<PLLSettings> create_pll_settings(u64 target_frequency, u64 reference_clock, const PLLMaxSettings&);
 | |
| 
 | |
|     SpinLock<u8> m_control_lock;
 | |
|     SpinLock<u8> m_modeset_lock;
 | |
|     mutable SpinLock<u8> m_registers_lock;
 | |
| 
 | |
|     Graphics::VideoInfoBlock m_crt_edid;
 | |
|     const PhysicalAddress m_registers;
 | |
|     const PhysicalAddress m_framebuffer_addr;
 | |
|     OwnPtr<Region> m_registers_region;
 | |
| };
 | |
| 
 | |
| }
 | 
