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 20extern "C" void _sPrintf(const char* format, ...); 21# define TRACE(x) _sPrintf x 22#else 23# define TRACE(x) ; 24#endif 25 26 27bool 28operator==(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. */ 39static bool 40is_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*/ 49status_t 50create_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 84uint32 85virtio_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 93status_t 94virtio_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 103status_t 104virtio_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 113status_t 114virtio_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 125status_t 126virtio_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 134status_t 135virtio_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 151status_t 152virtio_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 166status_t 167virtio_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