xref: /haiku/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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 
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\n", __func__);
61 	}
62 }
63 
64 
65 PanelFitter::~PanelFitter()
66 {
67 }
68 
69 
70 bool
71 PanelFitter::IsEnabled()
72 {
73 	return (read32(fRegisterBase + PCH_PANEL_FITTER_CONTROL)
74 		& PANEL_FITTER_ENABLED) != 0;
75 }
76 
77 
78 void
79 PanelFitter::Enable(const display_timing& timing)
80 {
81 	_Enable(true);
82 
83 	// TODO: program the window position based on the mode, setup/select filter
84 	// Note: for now assuming fitter was setup by BIOS and pipeA has fitterA, etc.
85 	TRACE("%s: PCH_PANEL_FITTER_CONTROL, 0x%" B_PRIx32 "\n", __func__, read32(fRegisterBase + PCH_PANEL_FITTER_CONTROL));
86 	TRACE("%s: PCH_PANEL_FITTER_WINDOW_POS, 0x%" B_PRIx32 "\n", __func__, read32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_POS));
87 
88 	// Window size _must_ be the last register programmed as it 'arms'/unlocks all the other ones..
89 	write32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_SIZE, (timing.h_display << 16) | timing.v_display);
90 }
91 
92 
93 void
94 PanelFitter::Disable()
95 {
96 	_Enable(false);
97 
98 	// Window size _must_ be the last register programmed as it 'arms'/unlocks all the other ones..
99 	write32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_SIZE, 0);
100 }
101 
102 
103 void
104 PanelFitter::_Enable(bool enable)
105 {
106 	uint32 targetRegister = fRegisterBase + PCH_PANEL_FITTER_CONTROL;
107 	write32(targetRegister, (read32(targetRegister) & ~PANEL_FITTER_ENABLED)
108 		| (enable ? PANEL_FITTER_ENABLED : 0));
109 	read32(targetRegister);
110 }
111