EDID.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * Copyright (c) 2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/ByteReader.h>
  9. #include <AK/Endian.h>
  10. #include <AK/Error.h>
  11. #include <AK/FixedPoint.h>
  12. #include <AK/Forward.h>
  13. #include <AK/Span.h>
  14. #include <AK/Vector.h>
  15. #include <LibEDID/DMT.h>
  16. #include <LibEDID/VIC.h>
  17. #ifdef KERNEL
  18. # include <Kernel/KString.h>
  19. #else
  20. # include <AK/String.h>
  21. #endif
  22. namespace EDID {
  23. namespace Definitions {
  24. struct EDID;
  25. struct DetailedTiming;
  26. struct DisplayDescriptor;
  27. struct ExtensionBlock;
  28. }
  29. class Parser final {
  30. friend class CEA861ExtensionBlock;
  31. public:
  32. static constexpr size_t BufferSize = 128;
  33. using RawBytes = unsigned char[BufferSize];
  34. protected:
  35. class DisplayFeatures {
  36. public:
  37. bool supports_standby() const { return (m_features & (1 << 7)) != 0; }
  38. bool supports_suspend() const { return (m_features & (1 << 6)) != 0; }
  39. bool supports_off() const { return (m_features & (1 << 5)) != 0; }
  40. bool preferred_timing_mode_includes_pixel_format_and_refresh_rate() const
  41. {
  42. if (m_edid_revision < 4)
  43. return true; // Bit 1 must be set to 1
  44. return (m_features & (1 << 1)) != 0;
  45. }
  46. bool srgb_is_default_color_space() const { return (m_features & (1 << 2)) != 0; }
  47. enum class Frequency : u8 {
  48. Continuous,
  49. NonContinuous,
  50. DefaultGTF,
  51. VESA_DMT
  52. };
  53. Frequency frequency() const
  54. {
  55. if (m_edid_revision < 4)
  56. return ((m_features & 1) != 0) ? Frequency::DefaultGTF : Frequency::VESA_DMT;
  57. return ((m_features & 1) != 0) ? Frequency::Continuous : Frequency::NonContinuous;
  58. }
  59. protected:
  60. DisplayFeatures(u8 features, u8 edid_revision)
  61. : m_features(features)
  62. , m_edid_revision(edid_revision)
  63. {
  64. }
  65. u8 m_features { 0 };
  66. u8 m_edid_revision { 0 };
  67. };
  68. public:
  69. static ErrorOr<Parser> from_bytes(ReadonlyBytes);
  70. static ErrorOr<Parser> from_bytes(ByteBuffer&&);
  71. #ifndef KERNEL
  72. static ErrorOr<Parser> from_framebuffer_device(int, size_t);
  73. static ErrorOr<Parser> from_framebuffer_device(String const&, size_t);
  74. #endif
  75. StringView legacy_manufacturer_id() const;
  76. #ifndef KERNEL
  77. String manufacturer_name() const;
  78. #endif
  79. u16 product_code() const;
  80. u32 serial_number() const;
  81. class DigitalDisplayFeatures final : public DisplayFeatures {
  82. friend class Parser;
  83. public:
  84. enum class SupportedColorEncodings : u8 {
  85. RGB444,
  86. RGB444_YCrCb444,
  87. RGB444_YCrCb422,
  88. RGB444_YCrCb444_YCrCb422
  89. };
  90. SupportedColorEncodings supported_color_encodings() const { return (SupportedColorEncodings)((m_features >> 3) & 3); }
  91. private:
  92. DigitalDisplayFeatures(u8 features, u8 edid_revision)
  93. : DisplayFeatures(features, edid_revision)
  94. {
  95. }
  96. };
  97. class AnalogDisplayFeatures final : public DisplayFeatures {
  98. friend class Parser;
  99. public:
  100. enum class DisplayColorType : u8 {
  101. MonochromeOrGrayscale,
  102. RGB,
  103. NonRGB,
  104. Undefined
  105. };
  106. DisplayColorType display_color_type() const { return (DisplayColorType)((m_features >> 3) & 3); }
  107. private:
  108. AnalogDisplayFeatures(u8 features, u8 edid_revision)
  109. : DisplayFeatures(features, edid_revision)
  110. {
  111. }
  112. };
  113. class DigitalDisplay final {
  114. friend class Parser;
  115. public:
  116. enum class ColorBitDepth : u8 {
  117. Undefined = 0,
  118. BPP_6,
  119. BPP_8,
  120. BPP_10,
  121. BPP_12,
  122. BPP_14,
  123. BPP_16,
  124. Reserved
  125. };
  126. enum class SupportedInterface : u8 {
  127. Undefined = 0,
  128. DVI,
  129. HDMI_A,
  130. HDMI_B,
  131. MDDI,
  132. DisplayPort,
  133. Reserved
  134. };
  135. ColorBitDepth color_bit_depth() const { return (ColorBitDepth)((m_video_input_definition >> 4) & 7); }
  136. SupportedInterface supported_interface() const { return ((m_video_input_definition & 0xf) <= 5) ? (SupportedInterface)(m_video_input_definition & 0xf) : SupportedInterface::Reserved; }
  137. DigitalDisplayFeatures const& features() { return m_features; }
  138. private:
  139. DigitalDisplay(u8 video_input_definition, u8 features, u8 edid_revision)
  140. : m_video_input_definition(video_input_definition)
  141. , m_features(features, edid_revision)
  142. {
  143. }
  144. u8 m_video_input_definition { 0 };
  145. DigitalDisplayFeatures m_features;
  146. };
  147. Optional<DigitalDisplay> digital_display() const;
  148. class AnalogDisplay final {
  149. friend class Parser;
  150. public:
  151. bool separate_sync_h_and_v_supported() const { return (m_video_input_definition & (1 << 3)) != 0; }
  152. private:
  153. AnalogDisplay(u8 video_input_definition, u8 features, u8 edid_revision)
  154. : m_video_input_definition(video_input_definition)
  155. , m_features(features, edid_revision)
  156. {
  157. }
  158. u8 m_video_input_definition { 0 };
  159. AnalogDisplayFeatures m_features;
  160. };
  161. Optional<AnalogDisplay> analog_display() const;
  162. class ScreenSize final {
  163. friend class Parser;
  164. public:
  165. unsigned horizontal_cm() const { return m_horizontal_cm; }
  166. unsigned vertical_cm() const { return m_vertical_cm; }
  167. private:
  168. ScreenSize(u8 horizontal_cm, u8 vertical_cm)
  169. : m_horizontal_cm(horizontal_cm)
  170. , m_vertical_cm(vertical_cm)
  171. {
  172. }
  173. u8 m_horizontal_cm { 0 };
  174. u8 m_vertical_cm { 0 };
  175. };
  176. Optional<ScreenSize> screen_size() const;
  177. class ScreenAspectRatio final {
  178. friend class Parser;
  179. public:
  180. enum class Orientation {
  181. Landscape,
  182. Portrait
  183. };
  184. Orientation orientation() const { return m_orientation; }
  185. auto ratio() const { return m_ratio; }
  186. private:
  187. ScreenAspectRatio(Orientation orientation, FixedPoint<16> ratio)
  188. : m_orientation(orientation)
  189. , m_ratio(ratio)
  190. {
  191. }
  192. Orientation m_orientation { Orientation::Landscape };
  193. FixedPoint<16> m_ratio {};
  194. };
  195. Optional<ScreenAspectRatio> aspect_ratio() const;
  196. Optional<FixedPoint<16>> gamma() const;
  197. class EstablishedTiming final {
  198. friend class Parser;
  199. public:
  200. enum class Source {
  201. IBM,
  202. Apple,
  203. VESA,
  204. Manufacturer
  205. };
  206. ALWAYS_INLINE Source source() const { return m_source; }
  207. ALWAYS_INLINE unsigned width() const { return m_width; };
  208. ALWAYS_INLINE unsigned height() const { return m_height; }
  209. ALWAYS_INLINE unsigned refresh_rate() const
  210. {
  211. if (m_source == Source::Manufacturer)
  212. return 0;
  213. return m_refresh_rate_or_manufacturer_specific;
  214. }
  215. ALWAYS_INLINE u8 manufacturer_specific() const
  216. {
  217. VERIFY(m_source == Source::Manufacturer);
  218. return m_refresh_rate_or_manufacturer_specific;
  219. }
  220. ALWAYS_INLINE u8 dmt_id() const { return m_dmt_id; }
  221. private:
  222. constexpr EstablishedTiming(Source source, u16 width, u16 height, u8 refresh_rate_or_manufacturer_specific, u8 dmt_id = 0)
  223. : m_source(source)
  224. , m_width(width)
  225. , m_height(height)
  226. , m_refresh_rate_or_manufacturer_specific(refresh_rate_or_manufacturer_specific)
  227. , m_dmt_id(dmt_id)
  228. {
  229. }
  230. Source m_source { Source::IBM };
  231. u16 m_width { 0 };
  232. u16 m_height { 0 };
  233. u8 m_refresh_rate_or_manufacturer_specific { 0 };
  234. u8 m_dmt_id { 0 };
  235. };
  236. ErrorOr<IterationDecision> for_each_established_timing(Function<IterationDecision(EstablishedTiming const&)>) const;
  237. class StandardTiming final {
  238. friend class Parser;
  239. public:
  240. enum class AspectRatio {
  241. AR_16_10,
  242. AR_4_3,
  243. AR_5_4,
  244. AR_16_9
  245. };
  246. unsigned width() const { return m_width; }
  247. unsigned height() const { return m_height; }
  248. unsigned refresh_rate() const { return m_refresh_rate; }
  249. AspectRatio aspect_ratio() const { return m_aspect_ratio; }
  250. u8 dmt_id() const { return m_dmt_id; }
  251. private:
  252. constexpr StandardTiming(u16 width, u16 height, u8 refresh_rate, AspectRatio aspect_ratio, u8 dmt_id)
  253. : m_width(width)
  254. , m_height(height)
  255. , m_refresh_rate(refresh_rate)
  256. , m_aspect_ratio(aspect_ratio)
  257. , m_dmt_id(dmt_id)
  258. {
  259. }
  260. u16 m_width { 0 };
  261. u16 m_height { 0 };
  262. u8 m_refresh_rate { 0 };
  263. AspectRatio m_aspect_ratio { AspectRatio::AR_16_10 };
  264. u8 m_dmt_id { 0 };
  265. };
  266. ErrorOr<IterationDecision> for_each_standard_timing(Function<IterationDecision(StandardTiming const&)>) const;
  267. class DetailedTiming final {
  268. friend class Parser;
  269. friend class CEA861ExtensionBlock;
  270. public:
  271. u32 pixel_clock_khz() const;
  272. u16 horizontal_addressable_pixels() const;
  273. u16 horizontal_blanking_pixels() const;
  274. u16 vertical_addressable_lines() const;
  275. u16 vertical_blanking_lines() const;
  276. u16 horizontal_front_porch_pixels() const;
  277. ALWAYS_INLINE u16 horizontal_back_porch_pixels() const { return horizontal_blanking_pixels() - horizontal_sync_pulse_width_pixels() - horizontal_front_porch_pixels(); }
  278. u16 horizontal_sync_pulse_width_pixels() const;
  279. u16 vertical_front_porch_lines() const;
  280. ALWAYS_INLINE u16 vertical_back_porch_lines() const { return vertical_blanking_lines() - vertical_sync_pulse_width_lines() - vertical_front_porch_lines(); }
  281. u16 vertical_sync_pulse_width_lines() const;
  282. u16 horizontal_image_size_mm() const;
  283. u16 vertical_image_size_mm() const;
  284. u8 horizontal_right_or_left_border_pixels() const;
  285. u8 vertical_top_or_bottom_border_lines() const;
  286. bool is_interlaced() const;
  287. FixedPoint<16, u32> refresh_rate() const;
  288. private:
  289. DetailedTiming(Parser const& edid, Definitions::DetailedTiming const* detailed_timings)
  290. : m_edid(edid)
  291. , m_detailed_timings(*detailed_timings)
  292. {
  293. }
  294. u16 vertical_addressable_lines_raw() const;
  295. Parser const& m_edid;
  296. Definitions::DetailedTiming const& m_detailed_timings;
  297. };
  298. ErrorOr<IterationDecision> for_each_detailed_timing(Function<IterationDecision(DetailedTiming const&, unsigned)>) const;
  299. Optional<DetailedTiming> detailed_timing(size_t) const;
  300. #ifndef KERNEL
  301. String display_product_name() const;
  302. String display_product_serial_number() const;
  303. #endif
  304. ErrorOr<IterationDecision> for_each_short_video_descriptor(Function<IterationDecision(unsigned, bool, VIC::Details const&)>) const;
  305. class CoordinatedVideoTiming final {
  306. friend class Parser;
  307. public:
  308. enum class AspectRatio : u8 {
  309. AR_4_3 = 0,
  310. AR_16_9 = 1,
  311. AR_16_10 = 2,
  312. AR_15_9 = 3
  313. };
  314. u16 horizontal_addressable_pixels() const;
  315. u16 vertical_addressable_lines() const;
  316. AspectRatio aspect_ratio() const;
  317. u16 preferred_refresh_rate();
  318. ALWAYS_INLINE DMT::CVT cvt_code() const { return m_cvt; }
  319. private:
  320. CoordinatedVideoTiming(DMT::CVT const& cvt)
  321. : m_cvt(cvt)
  322. {
  323. }
  324. DMT::CVT m_cvt;
  325. };
  326. ErrorOr<IterationDecision> for_each_coordinated_video_timing(Function<IterationDecision(CoordinatedVideoTiming const&)>) const;
  327. ErrorOr<IterationDecision> for_each_extension_block(Function<IterationDecision(unsigned, u8, u8, ReadonlyBytes)>) const;
  328. struct SupportedResolution {
  329. unsigned width { 0 };
  330. unsigned height { 0 };
  331. struct RefreshRate {
  332. FixedPoint<16, u32> rate;
  333. bool preferred { false };
  334. bool operator<(RefreshRate const& rhs) const { return rate < rhs.rate; }
  335. };
  336. Vector<RefreshRate, 4> refresh_rates;
  337. };
  338. ErrorOr<Vector<SupportedResolution>> supported_resolutions() const;
  339. Parser() = default;
  340. Parser(Parser&&) = default;
  341. Parser(Parser const&);
  342. Parser& operator=(Parser&&);
  343. Parser& operator=(Parser const&);
  344. bool operator==(Parser const& other) const;
  345. StringView version() const;
  346. auto bytes() const { return m_bytes; }
  347. private:
  348. Parser(ReadonlyBytes);
  349. Parser(ByteBuffer&&);
  350. ErrorOr<void> parse();
  351. template<typename T>
  352. T read_host(T const*) const;
  353. template<typename T>
  354. requires(IsIntegral<T> && sizeof(T) > 1) T read_le(T const*)
  355. const;
  356. template<typename T>
  357. requires(IsIntegral<T> && sizeof(T) > 1) T read_be(T const*)
  358. const;
  359. Definitions::EDID const& raw_edid() const;
  360. ErrorOr<IterationDecision> for_each_display_descriptor(Function<IterationDecision(u8, Definitions::DisplayDescriptor const&)>) const;
  361. ByteBuffer m_bytes_buffer;
  362. ReadonlyBytes m_bytes;
  363. u8 m_revision { 0 };
  364. #ifdef KERNEL
  365. OwnPtr<Kernel::KString> m_version;
  366. #else
  367. String m_version;
  368. #endif
  369. char m_legacy_manufacturer_id[4] {};
  370. };
  371. }