DisplayTranscoder.cpp 6.0 KB

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