xref: /haiku/src/add-ons/accelerants/framebuffer/mode.cpp (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
1 /*
2  * Copyright 2005-2015, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <compute_display_timing.h>
12 #include <create_display_modes.h>
13 
14 #include "accelerant_protos.h"
15 #include "accelerant.h"
16 #include "utility.h"
17 
18 
19 //#define TRACE_MODE
20 #ifdef TRACE_MODE
21 extern "C" void _sPrintf(const char* format, ...);
22 #	define TRACE(x) _sPrintf x
23 #else
24 #	define TRACE(x) ;
25 #endif
26 
27 
28 bool
29 operator==(const display_mode &lhs, const display_mode &rhs)
30 {
31 	return lhs.space == rhs.space
32 		&& lhs.virtual_width == rhs.virtual_width
33 		&& lhs.virtual_height == rhs.virtual_height
34 		&& lhs.h_display_start == rhs.h_display_start
35 		&& lhs.v_display_start == rhs.v_display_start;
36 }
37 
38 
39 /*!	Checks if the specified \a mode can be set using VESA. */
40 static bool
41 is_mode_supported(display_mode* mode)
42 {
43 	return (mode != NULL) && (*mode == gInfo->shared_info->current_mode);
44 }
45 
46 
47 /*!	Creates the initial mode list of the primary accelerant.
48 	It's called from vesa_init_accelerant().
49 */
50 status_t
51 create_mode_list(void)
52 {
53 	const color_space colorspace[] = {
54 		(color_space)gInfo->shared_info->current_mode.space
55 	};
56 	display_mode mode = gInfo->shared_info->current_mode;
57 
58 	compute_display_timing(mode.virtual_width, mode.virtual_height, 60, false,
59 		&mode.timing);
60 	fill_display_mode(mode.virtual_width, mode.virtual_height, &mode);
61 
62 	gInfo->mode_list_area = create_display_modes("framebuffer modes",
63 		NULL, &mode, 1, colorspace, 1, is_mode_supported, &gInfo->mode_list,
64 		&gInfo->shared_info->mode_count);
65 
66 	if (gInfo->mode_list_area < 0)
67 		return gInfo->mode_list_area;
68 
69 	gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
70 	return B_OK;
71 }
72 
73 
74 //	#pragma mark -
75 
76 
77 uint32
78 framebuffer_accelerant_mode_count(void)
79 {
80 	TRACE(("framebuffer_accelerant_mode_count() = %d\n",
81 		gInfo->shared_info->mode_count));
82 	return gInfo->shared_info->mode_count;
83 }
84 
85 
86 status_t
87 framebuffer_get_mode_list(display_mode* modeList)
88 {
89 	TRACE(("framebuffer_get_mode_info()\n"));
90 	memcpy(modeList, gInfo->mode_list,
91 		gInfo->shared_info->mode_count * sizeof(display_mode));
92 	return B_OK;
93 }
94 
95 
96 status_t
97 framebuffer_set_display_mode(display_mode* _mode)
98 {
99 	TRACE(("framebuffer_set_display_mode()\n"));
100 	if (_mode != NULL && *_mode == gInfo->shared_info->current_mode)
101 		return B_OK;
102 
103 	return B_UNSUPPORTED;
104 }
105 
106 
107 status_t
108 framebuffer_get_display_mode(display_mode* _currentMode)
109 {
110 	TRACE(("framebuffer_get_display_mode()\n"));
111 	*_currentMode = gInfo->shared_info->current_mode;
112 	return B_OK;
113 }
114 
115 
116 status_t
117 framebuffer_get_edid_info(void* info, size_t size, uint32* _version)
118 {
119 	TRACE(("framebuffer_get_edid_info()\n"));
120 
121 	if (!gInfo->shared_info->has_edid)
122 		return B_ERROR;
123 	if (size < sizeof(struct edid1_info))
124 		return B_BUFFER_OVERFLOW;
125 
126 	memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
127 	*_version = EDID_VERSION_1;
128 	return B_OK;
129 }
130 
131 
132 status_t
133 framebuffer_get_frame_buffer_config(frame_buffer_config* config)
134 {
135 	TRACE(("framebuffer_get_frame_buffer_config()\n"));
136 
137 	config->frame_buffer = gInfo->shared_info->frame_buffer;
138 	config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
139 	config->bytes_per_row = gInfo->shared_info->bytes_per_row;
140 
141 	return B_OK;
142 }
143 
144 
145 status_t
146 framebuffer_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high)
147 {
148 	TRACE(("framebuffer_get_pixel_clock_limits()\n"));
149 
150 	// TODO: do some real stuff here (taken from radeon driver)
151 	uint32 totalPixel = (uint32)mode->timing.h_total
152 		* (uint32)mode->timing.v_total;
153 	uint32 clockLimit = 2000000;
154 
155 	// lower limit of about 48Hz vertical refresh
156 	*_low = totalPixel * 48L / 1000L;
157 	if (*_low > clockLimit)
158 		return B_ERROR;
159 
160 	*_high = clockLimit;
161 	return B_OK;
162 }
163 
164