xref: /haiku/src/add-ons/accelerants/vesa/mode.cpp (revision 82a8a20999118b748396cf16a33c47c3b0c0222d)
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", NULL, NULL, 0,
78 		kVesaSpaces, sizeof(kVesaSpaces) / sizeof(kVesaSpaces[0]),
79 		is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count);
80 	if (gInfo->mode_list_area < B_OK)
81 		return gInfo->mode_list_area;
82 
83 	gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
84 	return B_OK;
85 }
86 
87 
88 //	#pragma mark -
89 
90 
91 uint32
92 vesa_accelerant_mode_count(void)
93 {
94 	TRACE(("vesa_accelerant_mode_count()\n"));
95 	return gInfo->shared_info->mode_count;
96 }
97 
98 
99 status_t
100 vesa_get_mode_list(display_mode* modeList)
101 {
102 	TRACE(("vesa_get_mode_info()\n"));
103 	memcpy(modeList, gInfo->mode_list,
104 		gInfo->shared_info->mode_count * sizeof(display_mode));
105 	return B_OK;
106 }
107 
108 
109 status_t
110 vesa_propose_display_mode(display_mode* target, const display_mode* low,
111 	const display_mode* high)
112 {
113 	TRACE(("vesa_propose_display_mode()\n"));
114 
115 	// just search for the specified mode in the list
116 
117 	for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) {
118 		display_mode* current = &gInfo->mode_list[i];
119 
120 		if (target->virtual_width != current->virtual_width
121 			|| target->virtual_height != current->virtual_height
122 			|| target->space != current->space)
123 			continue;
124 
125 		*target = *current;
126 		return B_OK;
127 	}
128 	return B_BAD_VALUE;
129 }
130 
131 
132 status_t
133 vesa_set_display_mode(display_mode* _mode)
134 {
135 	TRACE(("vesa_set_display_mode()\n"));
136 
137 	display_mode mode = *_mode;
138 	if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK)
139 		return B_BAD_VALUE;
140 
141 	vesa_mode* modes = gInfo->vesa_modes;
142 	for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
143 		// search mode in VESA mode list
144 		// TODO: list is ordered, we could use binary search
145 		if (modes[i].width == mode.virtual_width
146 			&& modes[i].height == mode.virtual_height
147 			&& get_color_space_for_depth(modes[i].bits_per_pixel)
148 				== mode.space)
149 			return ioctl(gInfo->device, VESA_SET_DISPLAY_MODE, &i, sizeof(i));
150 	}
151 
152 	return B_UNSUPPORTED;
153 }
154 
155 
156 status_t
157 vesa_get_display_mode(display_mode* _currentMode)
158 {
159 	TRACE(("vesa_get_display_mode()\n"));
160 	*_currentMode = gInfo->shared_info->current_mode;
161 	return B_OK;
162 }
163 
164 
165 status_t
166 vesa_get_edid_info(void* info, size_t size, uint32* _version)
167 {
168 	TRACE(("intel_get_edid_info()\n"));
169 
170 	if (!gInfo->shared_info->has_edid)
171 		return B_ERROR;
172 	if (size < sizeof(struct edid1_info))
173 		return B_BUFFER_OVERFLOW;
174 
175 	memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
176 	*_version = EDID_VERSION_1;
177 	return B_OK;
178 }
179 
180 
181 status_t
182 vesa_get_frame_buffer_config(frame_buffer_config* config)
183 {
184 	TRACE(("vesa_get_frame_buffer_config()\n"));
185 
186 	config->frame_buffer = gInfo->shared_info->frame_buffer;
187 	config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
188 	config->bytes_per_row = gInfo->shared_info->bytes_per_row;
189 
190 	return B_OK;
191 }
192 
193 
194 status_t
195 vesa_get_pixel_clock_limits(display_mode* mode, uint32* low, uint32* high)
196 {
197 	TRACE(("vesa_get_pixel_clock_limits()\n"));
198 
199 	// TODO: do some real stuff here (taken from radeon driver)
200 	uint32 totalPixel = (uint32)mode->timing.h_total
201 		* (uint32)mode->timing.v_total;
202 	uint32 clockLimit = 2000000;
203 
204 	// lower limit of about 48Hz vertical refresh
205 	*low = totalPixel * 48L / 1000L;
206 	if (*low > clockLimit)
207 		return B_ERROR;
208 
209 	*high = clockLimit;
210 	return B_OK;
211 }
212 
213 
214 status_t
215 vesa_move_display(uint16 h_display_start, uint16 v_display_start)
216 {
217 	TRACE(("vesa_move_display()\n"));
218 	return B_ERROR;
219 }
220 
221 
222 status_t
223 vesa_get_timing_constraints(display_timing_constraints* constraints)
224 {
225 	TRACE(("vesa_get_timing_constraints()\n"));
226 	return B_ERROR;
227 }
228 
229 
230 void
231 vesa_set_indexed_colors(uint count, uint8 first, uint8* colors, uint32 flags)
232 {
233 	TRACE(("vesa_set_indexed_colors()\n"));
234 	vga_set_indexed_colors_args args;
235 	args.first = first;
236 	args.count = count;
237 	args.colors = colors;
238 	ioctl(gInfo->device, VGA_SET_INDEXED_COLORS, &args, sizeof(args));
239 }
240 
241