Serenity Operating System
at master 110 lines 6.2 kB view raw
1/* 2 * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <Kernel/Arch/Delay.h> 8#include <Kernel/Graphics/Intel/Transcoder/DisplayTranscoder.h> 9#include <Kernel/PhysicalAddress.h> 10 11namespace Kernel { 12 13IntelDisplayTranscoder::IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile> registers_mapping, Memory::TypedMapping<PipeRegisters volatile> pipe_registers_mapping) 14 : m_transcoder_registers(move(registers_mapping)) 15 , m_pipe_registers(move(pipe_registers_mapping)) 16{ 17} 18 19IntelDisplayTranscoder::ShadowRegisters IntelDisplayTranscoder::current_registers_state() const 20{ 21 SpinlockLocker locker(m_access_lock); 22 return m_shadow_registers; 23} 24 25ErrorOr<void> IntelDisplayTranscoder::set_mode_setting_timings(Badge<IntelDisplayConnectorGroup>, DisplayConnector::ModeSetting const& mode_setting) 26{ 27 SpinlockLocker locker(m_access_lock); 28 29 dbgln_if(INTEL_GRAPHICS_DEBUG, "htotal - {}, {}", (mode_setting.horizontal_active - 1), (mode_setting.horizontal_total() - 1)); 30 m_shadow_registers.horizontal_total = ((mode_setting.horizontal_active - 1) | (mode_setting.horizontal_total() - 1) << 16); 31 m_transcoder_registers->horizontal_total = ((mode_setting.horizontal_active - 1) | (mode_setting.horizontal_total() - 1) << 16); 32 33 dbgln_if(INTEL_GRAPHICS_DEBUG, "hblank - {}, {}", (mode_setting.horizontal_blanking_start() - 1), (mode_setting.horizontal_blanking_start() + mode_setting.horizontal_blank_pixels - 1)); 34 m_shadow_registers.horizontal_blank = ((mode_setting.horizontal_blanking_start() - 1) | (mode_setting.horizontal_blanking_start() + mode_setting.horizontal_blank_pixels - 1) << 16); 35 m_transcoder_registers->horizontal_blank = ((mode_setting.horizontal_blanking_start() - 1) | (mode_setting.horizontal_blanking_start() + mode_setting.horizontal_blank_pixels - 1) << 16); 36 37 dbgln_if(INTEL_GRAPHICS_DEBUG, "hsync - {}, {}", (mode_setting.horizontal_sync_start() - 1), (mode_setting.horizontal_sync_end() - 1)); 38 m_shadow_registers.horizontal_sync = ((mode_setting.horizontal_sync_start() - 1) | (mode_setting.horizontal_sync_end() - 1) << 16); 39 m_transcoder_registers->horizontal_sync = ((mode_setting.horizontal_sync_start() - 1) | (mode_setting.horizontal_sync_end() - 1) << 16); 40 41 dbgln_if(INTEL_GRAPHICS_DEBUG, "vtotal - {}, {}", (mode_setting.vertical_active - 1), (mode_setting.vertical_blanking_start() + mode_setting.vertical_blank_lines - 1)); 42 m_shadow_registers.vertical_total = ((mode_setting.vertical_active - 1) | (mode_setting.vertical_blanking_start() + mode_setting.vertical_blank_lines - 1) << 16); 43 m_transcoder_registers->vertical_total = ((mode_setting.vertical_active - 1) | (mode_setting.vertical_blanking_start() + mode_setting.vertical_blank_lines - 1) << 16); 44 45 dbgln_if(INTEL_GRAPHICS_DEBUG, "vblank - {}, {}", (mode_setting.vertical_blanking_start() - 1), (mode_setting.vertical_blanking_start() + mode_setting.vertical_blank_lines - 1)); 46 m_shadow_registers.vertical_blank = ((mode_setting.vertical_blanking_start() - 1) | (mode_setting.vertical_blanking_start() + mode_setting.vertical_blank_lines - 1) << 16); 47 m_transcoder_registers->vertical_blank = ((mode_setting.vertical_blanking_start() - 1) | (mode_setting.vertical_blanking_start() + mode_setting.vertical_blank_lines - 1) << 16); 48 49 dbgln_if(INTEL_GRAPHICS_DEBUG, "vsync - {}, {}", (mode_setting.vertical_sync_start() - 1), (mode_setting.vertical_sync_end() - 1)); 50 m_shadow_registers.vertical_sync = ((mode_setting.vertical_sync_start() - 1) | (mode_setting.vertical_sync_end() - 1) << 16); 51 m_transcoder_registers->vertical_sync = ((mode_setting.vertical_sync_start() - 1) | (mode_setting.vertical_sync_end() - 1) << 16); 52 53 dbgln_if(INTEL_GRAPHICS_DEBUG, "sourceSize - {}, {}", (mode_setting.vertical_active - 1), (mode_setting.horizontal_active - 1)); 54 m_shadow_registers.pipe_source = ((mode_setting.vertical_active - 1) | (mode_setting.horizontal_active - 1) << 16); 55 m_transcoder_registers->pipe_source = ((mode_setting.vertical_active - 1) | (mode_setting.horizontal_active - 1) << 16); 56 return {}; 57} 58 59ErrorOr<void> IntelDisplayTranscoder::disable_pipe(Badge<IntelDisplayConnectorGroup>) 60{ 61 SpinlockLocker locker(m_access_lock); 62 m_pipe_registers->pipe_configuration = 0; 63 m_shadow_registers.pipe_conf = 0; 64 dbgln_if(INTEL_GRAPHICS_DEBUG, "Disabling Pipe"); 65 size_t milliseconds_elapsed = 0; 66 while (milliseconds_elapsed < 100) { 67 u32 value = m_pipe_registers->pipe_configuration; 68 if (!(value & (1 << 30))) 69 return {}; 70 microseconds_delay(1000); 71 milliseconds_elapsed++; 72 } 73 return Error::from_errno(EBUSY); 74} 75 76ErrorOr<void> IntelDisplayTranscoder::enable_pipe(Badge<IntelDisplayConnectorGroup>) 77{ 78 SpinlockLocker locker(m_access_lock); 79 u32 value = m_pipe_registers->pipe_configuration; 80 // Note: Just verify these are not already enabled... 81 if ((value & (1 << 30)) && (value & (1 << 31))) 82 return {}; 83 84 // Note: Set the pipe configuration register with these bits: 85 // 1. Bit 31 - to enable the Pipe 86 // 2. Bit 24 - to enable Gamma Unit Mode to 10 bit Gamma mode. 87 // 3. Bits 21-23 are set to zero to indicate Progressive mode (non Interlaced mode) 88 // 4. Bits 18 and 19 are set to zero to indicate Normal operations of assigned 89 // Cursor and Display planes. 90 m_pipe_registers->pipe_configuration = (1 << 31) | (1 << 24); 91 m_shadow_registers.pipe_conf = (1 << 31) | (1 << 24); 92 dbgln_if(INTEL_GRAPHICS_DEBUG, "Enabling Pipe"); 93 size_t milliseconds_elapsed = 0; 94 while (milliseconds_elapsed < 100) { 95 u32 value = m_pipe_registers->pipe_configuration; 96 if ((value & (1 << 30))) 97 return {}; 98 microseconds_delay(1000); 99 milliseconds_elapsed++; 100 } 101 // FIXME: Seems like my video card is buggy and doesn't set the enabled bit (bit 30)!! 102 return {}; 103} 104bool IntelDisplayTranscoder::pipe_enabled(Badge<IntelDisplayConnectorGroup>) const 105{ 106 SpinlockLocker locker(m_access_lock); 107 u32 value = m_pipe_registers->pipe_configuration; 108 return (value & (1 << 30)); 109} 110}