1 /*
2 * Copyright 2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Michael Lotz, mmlr@mlotz.ch
7 */
8
9
10 #include "PanelFitter.h"
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <Debug.h>
15
16 #include "accelerant.h"
17 #include "intel_extreme.h"
18
19
20 #undef TRACE
21 #define TRACE_FITTER
22 #ifdef TRACE_FITTER
23 # define TRACE(x...) _sPrintf("intel_extreme: " x)
24 #else
25 # define TRACE(x...)
26 #endif
27
28 #define ERROR(x...) _sPrintf("intel_extreme: " x)
29 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
30
31
32 // #pragma mark - PanelFitter
33
34
PanelFitter(pipe_index pipeIndex)35 PanelFitter::PanelFitter(pipe_index pipeIndex)
36 :
37 fRegisterBase(PCH_PANEL_FITTER_BASE_REGISTER)
38 {
39 // SkyLake has a newer type of panelfitter, called panelscaler (PS) there
40 if (gInfo->shared_info->device_type.Generation() >= 9) {
41 fRegisterBase += 0x100;
42 }
43 if (pipeIndex == INTEL_PIPE_B) {
44 fRegisterBase += PCH_PANEL_FITTER_PIPE_OFFSET;
45 }
46 if (pipeIndex == INTEL_PIPE_C) {
47 fRegisterBase += 2 * PCH_PANEL_FITTER_PIPE_OFFSET;
48 }
49 TRACE("%s: requested fitter #%d\n", __func__, (int)pipeIndex);
50
51 uint32 fitCtl = read32(fRegisterBase + PCH_PANEL_FITTER_CONTROL);
52 if (fitCtl & PANEL_FITTER_ENABLED) {
53 if (gInfo->shared_info->device_type.Generation() <= 8) {
54 TRACE("%s: this fitter is connected to pipe #%" B_PRIx32 "\n", __func__,
55 ((fitCtl & PANEL_FITTER_PIPE_MASK) >> 29) + 1);
56 } else {
57 TRACE("%s: this fitter is enabled by the BIOS\n", __func__);
58 }
59 } else {
60 TRACE("%s: this fitter is not setup by the BIOS: Enabling.\n", __func__);
61 fitCtl |= PANEL_FITTER_ENABLED;
62 write32(fRegisterBase + PCH_PANEL_FITTER_CONTROL, fitCtl);
63 }
64 }
65
66
~PanelFitter()67 PanelFitter::~PanelFitter()
68 {
69 }
70
71
72 bool
IsEnabled()73 PanelFitter::IsEnabled()
74 {
75 return (read32(fRegisterBase + PCH_PANEL_FITTER_CONTROL)
76 & PANEL_FITTER_ENABLED) != 0;
77 }
78
79
80 void
Enable(const display_timing & timing)81 PanelFitter::Enable(const display_timing& timing)
82 {
83 _Enable(true);
84
85 // TODO: program the window position based on the mode, setup/select filter
86 // Note: for now assuming fitter was setup by BIOS and pipeA has fitterA, etc.
87 TRACE("%s: PCH_PANEL_FITTER_CONTROL, 0x%" B_PRIx32 "\n", __func__, read32(fRegisterBase + PCH_PANEL_FITTER_CONTROL));
88 TRACE("%s: PCH_PANEL_FITTER_WINDOW_POS, 0x%" B_PRIx32 "\n", __func__, read32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_POS));
89
90 // Window size _must_ be the last register programmed as it 'arms'/unlocks all the other ones..
91 write32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_SIZE, (timing.h_display << 16) | timing.v_display);
92 }
93
94
95 void
Disable()96 PanelFitter::Disable()
97 {
98 _Enable(false);
99
100 // Window size _must_ be the last register programmed as it 'arms'/unlocks all the other ones..
101 write32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_SIZE, 0);
102 }
103
104
105 void
_Enable(bool enable)106 PanelFitter::_Enable(bool enable)
107 {
108 uint32 targetRegister = fRegisterBase + PCH_PANEL_FITTER_CONTROL;
109 write32(targetRegister, (read32(targetRegister) & ~PANEL_FITTER_ENABLED)
110 | (enable ? PANEL_FITTER_ENABLED : 0));
111 read32(targetRegister);
112 }
113