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