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