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