Serenity Operating System
1/*
2 * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/RefPtr.h>
10#include <AK/Try.h>
11#include <AK/Types.h>
12#include <Kernel/Graphics/DisplayConnector.h>
13#include <Kernel/Graphics/Intel/Definitions.h>
14#include <Kernel/Locking/Spinlock.h>
15#include <Kernel/Memory/TypedMapping.h>
16
17namespace Kernel {
18
19class IntelDisplayConnectorGroup;
20class IntelDisplayTranscoder {
21public:
22 // Note: This is used to "cache" all the registers we wrote to, because
23 // we might not be able to read them directly from hardware later.
24 struct ShadowRegisters {
25 u32 horizontal_total;
26 u32 horizontal_blank;
27 u32 horizontal_sync;
28 u32 vertical_total;
29 u32 vertical_blank;
30 u32 vertical_sync;
31 u32 exit_line;
32 u32 pipe_source;
33 u32 pipe_border_color_pattern;
34 u32 reserved;
35 u32 vsync_shift;
36 u32 pipe_mult;
37 u32 dpll_reserved_dac_multiplier;
38 u32 dpll_raw_dac_multiplier;
39 u32 dpll_divisor_a0;
40 u32 dpll_divisor_a1;
41 u32 dpll_p1;
42 u32 dpll_control;
43 u32 m1_value;
44 u32 n1_value;
45 u32 m2_value;
46 u32 n2_value;
47 u32 m1_link;
48 u32 n1_link;
49 u32 m2_link;
50 u32 n2_link;
51 u32 pipe_conf;
52 };
53
54 ErrorOr<void> set_mode_setting_timings(Badge<IntelDisplayConnectorGroup>, DisplayConnector::ModeSetting const&);
55 virtual ErrorOr<void> set_dpll_settings(Badge<IntelDisplayConnectorGroup>, IntelGraphics::PLLSettings const& settings, size_t dac_multiplier) = 0;
56 virtual ErrorOr<void> enable_dpll_without_vga(Badge<IntelDisplayConnectorGroup>) = 0;
57 virtual ErrorOr<void> disable_dpll(Badge<IntelDisplayConnectorGroup>) = 0;
58
59 ErrorOr<void> disable_pipe(Badge<IntelDisplayConnectorGroup>);
60 ErrorOr<void> enable_pipe(Badge<IntelDisplayConnectorGroup>);
61 bool pipe_enabled(Badge<IntelDisplayConnectorGroup>) const;
62
63 ShadowRegisters current_registers_state() const;
64
65 virtual ~IntelDisplayTranscoder() = default;
66
67protected:
68 struct [[gnu::packed]] TranscoderRegisters {
69 u32 horizontal_total;
70 u32 horizontal_blank;
71 u32 horizontal_sync;
72 u32 vertical_total;
73 u32 vertical_blank;
74 u32 vertical_sync;
75 u32 exit_line;
76 u32 pipe_source;
77 u32 pipe_border_color_pattern;
78 u32 reserved;
79 u32 vsync_shift;
80 u32 pipe_mult;
81 u32 m1_value;
82 u32 n1_value;
83 u32 m2_value;
84 u32 n2_value;
85 u32 m1_link;
86 u32 n1_link;
87 u32 m2_link;
88 u32 n2_link;
89 };
90
91 struct [[gnu::packed]] PipeRegisters {
92 u32 pipe_display_scan_line;
93 u32 pipe_display_scan_line_count_range_compare;
94 u32 pipe_configuration;
95 u32 reserved;
96 u32 pipe_gamma_correction_max_red;
97 u32 pipe_gamma_correction_max_green;
98 u32 pipe_gamma_correction_max_blue;
99 u32 reserved2[2];
100 u32 pipe_display_status;
101 u32 reserved3[2];
102 u32 display_arbitration_control;
103 u32 display_fifo_watermark_control1;
104 u32 display_fifo_watermark_control2;
105 u32 display_fifo_watermark_control3;
106 u32 pipe_frame_count_high;
107 // Note: The specification calls this "Pipe Frame Count Low and Pixel Count"
108 u32 pipe_frame_count_low;
109 };
110
111 IntelDisplayTranscoder(Memory::TypedMapping<TranscoderRegisters volatile>, Memory::TypedMapping<PipeRegisters volatile>);
112 mutable Spinlock<LockRank::None> m_access_lock;
113
114 ShadowRegisters m_shadow_registers {};
115 Memory::TypedMapping<TranscoderRegisters volatile> m_transcoder_registers;
116 Memory::TypedMapping<PipeRegisters volatile> m_pipe_registers;
117};
118}