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