xref: /haiku/src/preferences/screen/multimon.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 	Part of Radeon driver
5 	Multi-Monitor Settings interface
6 */
7 
8 
9 #include "multimon.h"
10 #include "accelerant_ext.h"
11 
12 #include <OS.h>
13 #include <Screen.h>
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 
20 // prepare parameters so they recognized as tunneled settings
21 static void
22 PrepareTunnel(display_mode *mode, display_mode *low, display_mode *high)
23 {
24 	memset(mode, 0, sizeof(*mode));
25 
26 	// mark modes as settings tunnel
27 	mode->space = low->space = high->space = 0;
28 	low->virtual_width = 0xffff;
29 	low->virtual_height = 0xffff;
30 	high->virtual_width = 0;
31 	high->virtual_height = 0;
32 	mode->timing.pixel_clock = 0;
33 	low->timing.pixel_clock = 'TKTK';
34 	high->timing.pixel_clock = 'KTKT';
35 }
36 
37 
38 // retrieve value of setting "code"
39 static status_t
40 GetSetting(BScreen *screen, uint16 code, uint32 *setting)
41 {
42 	display_mode mode, low, high;
43 	status_t result;
44 
45 	result = TestMultiMonSupport(screen);
46 	if (result != B_OK)
47 		return result;
48 
49 	PrepareTunnel(&mode, &low, &high);
50 
51 	mode.h_display_start = code;
52 	mode.v_display_start = 0;
53 
54 	result = screen->ProposeMode(&mode, &low, &high);
55 	if (result != B_OK)
56 		return result;
57 
58 	*setting = mode.timing.flags;
59 
60 	return B_OK;
61 }
62 
63 
64 // set setting "code" to "value"
65 static status_t
66 SetSetting(BScreen *screen, uint16 code, uint32 value)
67 {
68 	display_mode mode, low, high;
69 	status_t result;
70 
71 	result = TestMultiMonSupport(screen);
72 	if (result != B_OK)
73 		return result;
74 
75 	PrepareTunnel(&mode, &low, &high);
76 
77 	mode.h_display_start = code;
78 	mode.v_display_start = 1;
79 	mode.timing.flags = value;
80 
81 	return screen->ProposeMode(&mode, &low, &high);
82 }
83 
84 
85 // retrieve n-th supported value of setting "code"
86 static status_t
87 GetNthSupportedSetting(BScreen *screen, uint16 code, int32 idx,
88 	uint32 *setting)
89 {
90 	display_mode mode, low, high;
91 	status_t result;
92 
93 	result = TestMultiMonSupport(screen);
94 	if (result != B_OK)
95 		return result;
96 
97 	PrepareTunnel(&mode, &low, &high);
98 
99 	mode.h_display_start = code;
100 	mode.v_display_start = 2;
101 	mode.timing.flags = idx;
102 
103 	result = screen->ProposeMode(&mode, &low, &high);
104 	if (result != B_OK)
105 		return result;
106 
107 	*setting = mode.timing.flags;
108 
109 	return B_OK;
110 }
111 
112 
113 // get current Swap Displays settings
114 status_t
115 GetSwapDisplays(BScreen *screen, bool *swap)
116 {
117 	status_t result;
118 	uint32 tmp;
119 
120 	result = GetSetting(screen, ms_swap, &tmp);
121 	if (result != B_OK)
122 		return result;
123 
124 	*swap = tmp != 0;
125 
126 	return B_OK;
127 }
128 
129 
130 // set "Swap Displays"
131 status_t
132 SetSwapDisplays(BScreen *screen, bool swap)
133 {
134 	return SetSetting(screen, ms_swap, swap);
135 }
136 
137 
138 // get current "Use Laptop Panel" settings
139 status_t
140 GetUseLaptopPanel(BScreen *screen, bool *use)
141 {
142 	status_t result;
143 	uint32 tmp;
144 
145 	result = GetSetting(screen, ms_use_laptop_panel, &tmp);
146 	if (result != B_OK)
147 		return result;
148 
149 	*use = tmp != 0;
150 	return B_OK;
151 }
152 
153 
154 // set "Use Laptop Panel"
155 status_t
156 SetUseLaptopPanel(BScreen *screen, bool use)
157 {
158 	return SetSetting(screen, ms_use_laptop_panel, use);
159 }
160 
161 
162 // get n-th supported TV standard
163 status_t
164 GetNthSupportedTVStandard(BScreen *screen, int idx, uint32 *standard)
165 {
166 	return GetNthSupportedSetting(
167 		screen, ms_tv_standard, (int32)idx, standard);
168 }
169 
170 
171 // get current TV Standard settings
172 status_t
173 GetTVStandard(BScreen *screen, uint32 *standard)
174 {
175 	return GetSetting(screen, ms_tv_standard, standard);
176 }
177 
178 
179 // set TV Standard
180 status_t
181 SetTVStandard(BScreen *screen, uint32 standard)
182 {
183 	return SetSetting(screen, ms_tv_standard, standard);
184 }
185 
186 
187 // Verify existence of Multi-Monitor Settings Tunnel
188 status_t
189 TestMultiMonSupport(BScreen *screen)
190 {
191 	display_mode *modeList = NULL;
192 	display_mode low, high;
193 	uint32 count;
194 	status_t result;
195 
196 	// take any valid mode
197 	result = screen->GetModeList(&modeList, &count);
198 	if (result != B_OK)
199 		return result;
200 
201 	if (count < 1)
202 		return B_ERROR;
203 
204 	// set request bits
205 	modeList[0].timing.flags |= RADEON_MODE_MULTIMON_REQUEST;
206 	modeList[0].timing.flags &= ~RADEON_MODE_MULTIMON_REPLY;
207 	low = high = modeList[0];
208 
209 	result = screen->ProposeMode(&modeList[0], &low, &high);
210 	if (result != B_OK)
211 		goto out;
212 
213 	// check reply bits
214 	if ((modeList[0].timing.flags & RADEON_MODE_MULTIMON_REQUEST) == 0
215 		&& (modeList[0].timing.flags & RADEON_MODE_MULTIMON_REPLY) != 0)
216 		result = B_OK;
217 	else
218 		result = B_ERROR;
219 
220 out:
221 	free(modeList);
222 	return result;
223 }
224