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