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(display_mode * mode,display_mode * low,display_mode * high)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
GetSetting(BScreen * screen,uint16 code,uint32 * setting)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
SetSetting(BScreen * screen,uint16 code,uint32 value)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
GetNthSupportedSetting(BScreen * screen,uint16 code,int32 idx,uint32 * setting)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
GetSwapDisplays(BScreen * screen,bool * swap)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
SetSwapDisplays(BScreen * screen,bool swap)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
GetUseLaptopPanel(BScreen * screen,bool * use)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
SetUseLaptopPanel(BScreen * screen,bool use)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
GetNthSupportedTVStandard(BScreen * screen,int idx,uint32 * standard)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
GetTVStandard(BScreen * screen,uint32 * standard)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
SetTVStandard(BScreen * screen,uint32 standard)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
TestMultiMonSupport(BScreen * screen)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