xref: /haiku/src/add-ons/accelerants/vesa/mode.cpp (revision 3be9edf8da228afd9fec0390f408c964766122aa)
1 /*
2  * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <string.h>
8 
9 #include <create_display_modes.h>
10 
11 #include "accelerant_protos.h"
12 #include "accelerant.h"
13 #include "utility.h"
14 
15 
16 //#define TRACE_MODE
17 #ifdef TRACE_MODE
18 extern "C" void _sPrintf(const char* format, ...);
19 #	define TRACE(x) _sPrintf x
20 #else
21 #	define TRACE(x) ;
22 #endif
23 
24 
25 static uint32
26 get_color_space_for_depth(uint32 depth)
27 {
28 	switch (depth) {
29 		case 4:
30 			return B_GRAY8;
31 				// the app_server is smart enough to translate this to VGA mode
32 		case 8:
33 			return B_CMAP8;
34 		case 15:
35 			return B_RGB15;
36 		case 16:
37 			return B_RGB16;
38 		case 24:
39 			return B_RGB24;
40 		case 32:
41 			return B_RGB32;
42 	}
43 
44 	return 0;
45 }
46 
47 
48 /*!	Checks if the specified \a mode can be set using VESA. */
49 static bool
50 is_mode_supported(display_mode* mode)
51 {
52 	vesa_mode* modes = gInfo->vesa_modes;
53 
54 	for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
55 		// search mode in VESA mode list
56 		// TODO: list is ordered, we could use binary search
57 		if (modes[i].width == mode->virtual_width
58 			&& modes[i].height == mode->virtual_height
59 			&& get_color_space_for_depth(modes[i].bits_per_pixel)
60 				== mode->space)
61 			return true;
62 	}
63 
64 	return false;
65 }
66 
67 
68 /*!	Creates the initial mode list of the primary accelerant.
69 	It's called from vesa_init_accelerant().
70 */
71 status_t
72 create_mode_list(void)
73 {
74 	const color_space kVesaSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE,
75 		B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
76 
77 	gInfo->mode_list_area = create_display_modes("vesa modes",
78 		gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL,
79 		NULL, 0, kVesaSpaces, sizeof(kVesaSpaces) / sizeof(kVesaSpaces[0]),
80 		is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count);
81 	if (gInfo->mode_list_area < B_OK)
82 		return gInfo->mode_list_area;
83 
84 	gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
85 	return B_OK;
86 }
87 
88 
89 //	#pragma mark -
90 
91 
92 uint32
93 vesa_accelerant_mode_count(void)
94 {
95 	TRACE(("vesa_accelerant_mode_count()\n"));
96 	return gInfo->shared_info->mode_count;
97 }
98 
99 
100 status_t
101 vesa_get_mode_list(display_mode* modeList)
102 {
103 	TRACE(("vesa_get_mode_info()\n"));
104 	memcpy(modeList, gInfo->mode_list,
105 		gInfo->shared_info->mode_count * sizeof(display_mode));
106 	return B_OK;
107 }
108 
109 
110 status_t
111 vesa_propose_display_mode(display_mode* target, const display_mode* low,
112 	const display_mode* high)
113 {
114 	TRACE(("vesa_propose_display_mode()\n"));
115 
116 	// just search for the specified mode in the list
117 
118 	for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) {
119 		display_mode* current = &gInfo->mode_list[i];
120 
121 		if (target->virtual_width != current->virtual_width
122 			|| target->virtual_height != current->virtual_height
123 			|| target->space != current->space)
124 			continue;
125 
126 		*target = *current;
127 		return B_OK;
128 	}
129 	return B_BAD_VALUE;
130 }
131 
132 
133 status_t
134 vesa_set_display_mode(display_mode* _mode)
135 {
136 	TRACE(("vesa_set_display_mode()\n"));
137 
138 	display_mode mode = *_mode;
139 	if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK)
140 		return B_BAD_VALUE;
141 
142 	vesa_mode* modes = gInfo->vesa_modes;
143 	for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
144 		// search mode in VESA mode list
145 		// TODO: list is ordered, we could use binary search
146 		if (modes[i].width == mode.virtual_width
147 			&& modes[i].height == mode.virtual_height
148 			&& get_color_space_for_depth(modes[i].bits_per_pixel)
149 				== mode.space)
150 			return ioctl(gInfo->device, VESA_SET_DISPLAY_MODE, &i, sizeof(i));
151 	}
152 
153 	return B_UNSUPPORTED;
154 }
155 
156 
157 status_t
158 vesa_get_display_mode(display_mode* _currentMode)
159 {
160 	TRACE(("vesa_get_display_mode()\n"));
161 	*_currentMode = gInfo->shared_info->current_mode;
162 	return B_OK;
163 }
164 
165 
166 status_t
167 vesa_get_edid_info(void* info, size_t size, uint32* _version)
168 {
169 	TRACE(("intel_get_edid_info()\n"));
170 
171 	if (!gInfo->shared_info->has_edid)
172 		return B_ERROR;
173 	if (size < sizeof(struct edid1_info))
174 		return B_BUFFER_OVERFLOW;
175 
176 	memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
177 	*_version = EDID_VERSION_1;
178 	return B_OK;
179 }
180 
181 
182 status_t
183 vesa_get_frame_buffer_config(frame_buffer_config* config)
184 {
185 	TRACE(("vesa_get_frame_buffer_config()\n"));
186 
187 	config->frame_buffer = gInfo->shared_info->frame_buffer;
188 	config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
189 	config->bytes_per_row = gInfo->shared_info->bytes_per_row;
190 
191 	return B_OK;
192 }
193 
194 
195 status_t
196 vesa_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high)
197 {
198 	TRACE(("vesa_get_pixel_clock_limits()\n"));
199 
200 	// TODO: do some real stuff here (taken from radeon driver)
201 	uint32 totalPixel = (uint32)mode->timing.h_total
202 		* (uint32)mode->timing.v_total;
203 	uint32 clockLimit = 2000000;
204 
205 	// lower limit of about 48Hz vertical refresh
206 	*_low = totalPixel * 48L / 1000L;
207 	if (*_low > clockLimit)
208 		return B_ERROR;
209 
210 	*_high = clockLimit;
211 	return B_OK;
212 }
213 
214 
215 status_t
216 vesa_move_display(uint16 h_display_start, uint16 v_display_start)
217 {
218 	TRACE(("vesa_move_display()\n"));
219 	return B_ERROR;
220 }
221 
222 
223 status_t
224 vesa_get_timing_constraints(display_timing_constraints* constraints)
225 {
226 	TRACE(("vesa_get_timing_constraints()\n"));
227 	return B_ERROR;
228 }
229 
230 
231 void
232 vesa_set_indexed_colors(uint count, uint8 first, uint8* colors, uint32 flags)
233 {
234 	TRACE(("vesa_set_indexed_colors()\n"));
235 
236 	vesa_set_indexed_colors_args args;
237 	args.first = first;
238 	args.count = count;
239 	args.colors = colors;
240 	ioctl(gInfo->device, VESA_SET_INDEXED_COLORS, &args, sizeof(args));
241 }
242 
243