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