xref: /haiku/src/add-ons/accelerants/virtio/mode.cpp (revision 7eab6b486ebadb54ca3c306601f4b04dd92359fa)
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 
17 
18 #define TRACE_MODE
19 #ifdef TRACE_MODE
20 extern "C" void _sPrintf(const char* format, ...);
21 #	define TRACE(x) _sPrintf x
22 #else
23 #	define TRACE(x) ;
24 #endif
25 
26 
27 bool
28 operator==(const display_mode &lhs, const display_mode &rhs)
29 {
30 	return lhs.space == rhs.space
31 		&& lhs.virtual_width == rhs.virtual_width
32 		&& lhs.virtual_height == rhs.virtual_height
33 		&& lhs.h_display_start == rhs.h_display_start
34 		&& lhs.v_display_start == rhs.v_display_start;
35 }
36 
37 
38 /*!	Checks if the specified \a mode can be set using VESA. */
39 static bool
40 is_mode_supported(display_mode* mode)
41 {
42 	return (mode != NULL) && (*mode == gInfo->shared_info->current_mode);
43 }
44 
45 
46 /*!	Creates the initial mode list of the primary accelerant.
47 	It's called from vesa_init_accelerant().
48 */
49 status_t
50 create_mode_list(void)
51 {
52 	const color_space colorspace[] = {
53 		(color_space)gInfo->shared_info->current_mode.space
54 	};
55 
56 	if (!gInfo->shared_info->has_edid) {
57 		display_mode mode = gInfo->shared_info->current_mode;
58 
59 		compute_display_timing(mode.virtual_width, mode.virtual_height, 60, false,
60 			&mode.timing);
61 		fill_display_mode(mode.virtual_width, mode.virtual_height, &mode);
62 
63 		gInfo->mode_list_area = create_display_modes("virtio_gpu modes",
64 			NULL, &mode, 1, colorspace, 1, is_mode_supported, &gInfo->mode_list,
65 			&gInfo->shared_info->mode_count);
66 	} else {
67 		edid1_info edidInfo;
68 		edid_decode(&edidInfo, &gInfo->shared_info->edid_raw);
69 		gInfo->mode_list_area = create_display_modes("virtio_gpu modes",
70 			&edidInfo, NULL, 0, colorspace, 1, NULL, &gInfo->mode_list,
71 			&gInfo->shared_info->mode_count);
72 	}
73 	if (gInfo->mode_list_area < 0)
74 		return gInfo->mode_list_area;
75 
76 	gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
77 	return B_OK;
78 }
79 
80 
81 //	#pragma mark -
82 
83 
84 uint32
85 virtio_gpu_accelerant_mode_count(void)
86 {
87 	TRACE(("virtio_gpu_accelerant_mode_count() = %d\n",
88 		gInfo->shared_info->mode_count));
89 	return gInfo->shared_info->mode_count;
90 }
91 
92 
93 status_t
94 virtio_gpu_get_mode_list(display_mode* modeList)
95 {
96 	TRACE(("virtio_gpu_get_mode_info()\n"));
97 	memcpy(modeList, gInfo->mode_list,
98 		gInfo->shared_info->mode_count * sizeof(display_mode));
99 	return B_OK;
100 }
101 
102 
103 status_t
104 virtio_gpu_get_preferred_mode(display_mode* _mode)
105 {
106 	TRACE(("virtio_gpu_get_preferred_mode()\n"));
107 	*_mode = gInfo->shared_info->current_mode;
108 
109 	return B_OK;
110 }
111 
112 
113 status_t
114 virtio_gpu_set_display_mode(display_mode* _mode)
115 {
116 	TRACE(("virtio_gpu_set_display_mode()\n"));
117 	if (_mode != NULL && *_mode == gInfo->shared_info->current_mode)
118 		return B_OK;
119 
120 	return ioctl(gInfo->device, VIRTIO_GPU_SET_DISPLAY_MODE,
121 		_mode, sizeof(display_mode));
122 }
123 
124 
125 status_t
126 virtio_gpu_get_display_mode(display_mode* _currentMode)
127 {
128 	TRACE(("virtio_gpu_get_display_mode()\n"));
129 	*_currentMode = gInfo->shared_info->current_mode;
130 	return B_OK;
131 }
132 
133 
134 status_t
135 virtio_gpu_get_edid_info(void* info, size_t size, uint32* _version)
136 {
137 	TRACE(("virtio_gpu_get_edid_info()\n"));
138 
139 	if (!gInfo->shared_info->has_edid)
140 		return B_ERROR;
141 	if (size < sizeof(struct edid1_info))
142 		return B_BUFFER_OVERFLOW;
143 
144 	edid_decode((edid1_info*)info, &gInfo->shared_info->edid_raw);
145 	*_version = EDID_VERSION_1;
146 	edid_dump((edid1_info*)info);
147 	return B_OK;
148 }
149 
150 
151 status_t
152 virtio_gpu_get_frame_buffer_config(frame_buffer_config* config)
153 {
154 	TRACE(("virtio_gpu_get_frame_buffer_config()\n"));
155 
156 	config->frame_buffer = gInfo->shared_info->frame_buffer;
157 	TRACE(("virtio_gpu_get_frame_buffer_config() = %" B_PRIxADDR "\n",
158 		config->frame_buffer));
159 	//config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
160 	config->bytes_per_row = gInfo->shared_info->bytes_per_row;
161 	TRACE(("virtio_gpu_get_frame_buffer_config() %p\n", config->frame_buffer));
162 	return B_OK;
163 }
164 
165 
166 status_t
167 virtio_gpu_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high)
168 {
169 	TRACE(("virtio_gpu_get_pixel_clock_limits()\n"));
170 
171 	// TODO: do some real stuff here (taken from radeon driver)
172 	uint32 totalPixel = (uint32)mode->timing.h_total
173 		* (uint32)mode->timing.v_total;
174 	uint32 clockLimit = 2000000;
175 
176 	// lower limit of about 48Hz vertical refresh
177 	*_low = totalPixel * 48L / 1000L;
178 	if (*_low > clockLimit)
179 		return B_ERROR;
180 
181 	*_high = clockLimit;
182 	return B_OK;
183 }
184 
185