xref: /haiku/src/preferences/screen/multimon.cpp (revision 4f2fd49bdc6078128b1391191e4edac647044c3d)
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 PrepareTunnel(
22 	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 GetSetting(
40 	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 SetSetting(
66 	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 GetNthSupportedSetting(
87 	BScreen *screen, uint16 code, int32 idx, uint32 *setting )
88 {
89 	display_mode mode, low, high;
90 	status_t result;
91 
92 	result = TestMultiMonSupport( screen );
93 	if( result != B_OK )
94 		return result;
95 
96 	PrepareTunnel( &mode, &low, &high );
97 
98 	mode.h_display_start = code;
99 	mode.v_display_start = 2;
100 	mode.timing.flags = idx;
101 
102 	result = screen->ProposeMode( &mode, &low, &high );
103 	if( result != B_OK )
104 		return result;
105 
106 	*setting = mode.timing.flags;
107 
108 	return B_OK;
109 }
110 
111 
112 // get current Swap Displays settings
113 status_t GetSwapDisplays(
114 	BScreen *screen, bool *swap )
115 {
116 	status_t result;
117 	uint32 tmp;
118 
119 	result = GetSetting( screen, ms_swap, &tmp );
120 	if( result != B_OK )
121 		return result;
122 
123 	*swap = tmp != 0;
124 
125 	return B_OK;
126 }
127 
128 
129 // set "Swap Displays"
130 status_t SetSwapDisplays(
131 	BScreen *screen, bool swap )
132 {
133 	return SetSetting( screen, ms_swap, swap );
134 }
135 
136 
137 // get current "Use Laptop Panel" settings
138 status_t GetUseLaptopPanel(
139 	BScreen *screen, bool *use )
140 {
141 	status_t result;
142 	uint32 tmp;
143 
144 	result = GetSetting( screen, ms_use_laptop_panel, &tmp );
145 	if( result != B_OK )
146 		return result;
147 
148 	*use = tmp != 0;
149 	return B_OK;
150 }
151 
152 
153 // set "Use Laptop Panel"
154 status_t SetUseLaptopPanel(
155 	BScreen *screen, bool use )
156 {
157 	return SetSetting( screen, ms_use_laptop_panel, use );
158 }
159 
160 
161 // get n-th supported TV standard
162 status_t GetNthSupportedTVStandard( BScreen *screen, int idx, uint32 *standard )
163 {
164 	return GetNthSupportedSetting(
165 		screen, ms_tv_standard, (int32)idx, standard );
166 }
167 
168 
169 // get current TV Standard settings
170 status_t GetTVStandard( BScreen *screen, uint32 *standard )
171 {
172 	return GetSetting( screen, ms_tv_standard, standard );
173 }
174 
175 
176 // set TV Standard
177 status_t SetTVStandard( BScreen *screen, uint32 standard )
178 {
179 	return SetSetting( screen, ms_tv_standard, standard );
180 }
181 
182 
183 // Verify existence of Multi-Monitor Settings Tunnel
184 status_t
185 TestMultiMonSupport(BScreen *screen)
186 {
187 	display_mode *modeList = NULL;
188 	display_mode low, high;
189 	uint32 count;
190 	status_t result;
191 
192 	// take any valid mode
193 	result = screen->GetModeList(&modeList, &count);
194 	if (result != B_OK)
195 		return result;
196 
197 	if (count < 1)
198 		return B_ERROR;
199 
200 	// set request bits
201 	modeList[0].timing.flags |= RADEON_MODE_MULTIMON_REQUEST;
202 	modeList[0].timing.flags &= ~RADEON_MODE_MULTIMON_REPLY;
203 	low = high = modeList[0];
204 
205 	result = screen->ProposeMode(&modeList[0], &low, &high);
206 	if (result != B_OK)
207 		goto out;
208 
209 	// check reply bits
210 	if ((modeList[0].timing.flags & RADEON_MODE_MULTIMON_REQUEST) == 0
211 		&& (modeList[0].timing.flags & RADEON_MODE_MULTIMON_REPLY) != 0)
212 		result = B_OK;
213 	else
214 		result = B_ERROR;
215 
216 out:
217 	free(modeList);
218 	return result;
219 }
220