1 /* 2 * Copyright 2005-2011, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include <compute_display_timing.h> 11 #include <create_display_modes.h> 12 13 #include "accelerant_protos.h" 14 #include "accelerant.h" 15 #include "utility.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 static uint32 28 get_color_space_for_depth(uint32 depth) 29 { 30 switch (depth) { 31 case 4: 32 return B_GRAY8; 33 // the app_server is smart enough to translate this to VGA mode 34 case 8: 35 return B_CMAP8; 36 case 15: 37 return B_RGB15; 38 case 16: 39 return B_RGB16; 40 case 24: 41 return B_RGB24; 42 case 32: 43 return B_RGB32; 44 } 45 46 return 0; 47 } 48 49 50 /*! Checks if the specified \a mode can be set using VESA. */ 51 static bool 52 is_mode_supported(display_mode* mode) 53 { 54 vesa_mode* modes = gInfo->vesa_modes; 55 56 for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) { 57 // search mode in VESA mode list 58 // TODO: list is ordered, we could use binary search 59 if (modes[i].width == mode->virtual_width 60 && modes[i].height == mode->virtual_height 61 && get_color_space_for_depth(modes[i].bits_per_pixel) 62 == mode->space) 63 return true; 64 } 65 66 return false; 67 } 68 69 70 /*! Creates the initial mode list of the primary accelerant. 71 It's called from vesa_init_accelerant(). 72 */ 73 status_t 74 create_mode_list(void) 75 { 76 const color_space kVesaSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 77 B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 78 79 // Create the initial list from the support mode list - but only if we don't 80 // have EDID info available, as that should be good enough. 81 display_mode* initialModes = NULL; 82 uint32 initialModesCount = 0; 83 if (!gInfo->shared_info->has_edid) { 84 initialModes = (display_mode*)malloc( 85 sizeof(display_mode) * gInfo->shared_info->vesa_mode_count); 86 if (initialModes != NULL) { 87 initialModesCount = gInfo->shared_info->vesa_mode_count; 88 vesa_mode* vesaModes = gInfo->vesa_modes; 89 90 for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) { 91 compute_display_timing(vesaModes[i].width, vesaModes[i].height, 92 60, false, &initialModes[i].timing); 93 fill_display_mode(vesaModes[i].width, vesaModes[i].height, 94 &initialModes[i]); 95 } 96 } 97 } 98 99 gInfo->mode_list_area = create_display_modes("vesa modes", 100 gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL, 101 initialModes, initialModesCount, 102 kVesaSpaces, sizeof(kVesaSpaces) / sizeof(kVesaSpaces[0]), 103 is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 104 105 free(initialModes); 106 107 if (gInfo->mode_list_area < 0) 108 return gInfo->mode_list_area; 109 110 gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 111 return B_OK; 112 } 113 114 115 // #pragma mark - 116 117 118 uint32 119 vesa_accelerant_mode_count(void) 120 { 121 TRACE(("vesa_accelerant_mode_count()\n")); 122 return gInfo->shared_info->mode_count; 123 } 124 125 126 status_t 127 vesa_get_mode_list(display_mode* modeList) 128 { 129 TRACE(("vesa_get_mode_info()\n")); 130 memcpy(modeList, gInfo->mode_list, 131 gInfo->shared_info->mode_count * sizeof(display_mode)); 132 return B_OK; 133 } 134 135 136 status_t 137 vesa_propose_display_mode(display_mode* target, const display_mode* low, 138 const display_mode* high) 139 { 140 TRACE(("vesa_propose_display_mode()\n")); 141 142 // just search for the specified mode in the list 143 144 for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { 145 display_mode* current = &gInfo->mode_list[i]; 146 147 if (target->virtual_width != current->virtual_width 148 || target->virtual_height != current->virtual_height 149 || target->space != current->space) 150 continue; 151 152 *target = *current; 153 return B_OK; 154 } 155 return B_BAD_VALUE; 156 } 157 158 159 status_t 160 vesa_set_display_mode(display_mode* _mode) 161 { 162 TRACE(("vesa_set_display_mode()\n")); 163 164 display_mode mode = *_mode; 165 if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK) 166 return B_BAD_VALUE; 167 168 vesa_mode* modes = gInfo->vesa_modes; 169 for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) { 170 // search mode in VESA mode list 171 // TODO: list is ordered, we could use binary search 172 if (modes[i].width == mode.virtual_width 173 && modes[i].height == mode.virtual_height 174 && get_color_space_for_depth(modes[i].bits_per_pixel) 175 == mode.space) 176 return ioctl(gInfo->device, VESA_SET_DISPLAY_MODE, &i, sizeof(i)); 177 } 178 179 return B_UNSUPPORTED; 180 } 181 182 183 status_t 184 vesa_get_display_mode(display_mode* _currentMode) 185 { 186 TRACE(("vesa_get_display_mode()\n")); 187 *_currentMode = gInfo->shared_info->current_mode; 188 return B_OK; 189 } 190 191 192 status_t 193 vesa_get_edid_info(void* info, size_t size, uint32* _version) 194 { 195 TRACE(("intel_get_edid_info()\n")); 196 197 if (!gInfo->shared_info->has_edid) 198 return B_ERROR; 199 if (size < sizeof(struct edid1_info)) 200 return B_BUFFER_OVERFLOW; 201 202 memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 203 *_version = EDID_VERSION_1; 204 return B_OK; 205 } 206 207 208 status_t 209 vesa_get_frame_buffer_config(frame_buffer_config* config) 210 { 211 TRACE(("vesa_get_frame_buffer_config()\n")); 212 213 config->frame_buffer = gInfo->shared_info->frame_buffer; 214 config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; 215 config->bytes_per_row = gInfo->shared_info->bytes_per_row; 216 217 return B_OK; 218 } 219 220 221 status_t 222 vesa_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high) 223 { 224 TRACE(("vesa_get_pixel_clock_limits()\n")); 225 226 // TODO: do some real stuff here (taken from radeon driver) 227 uint32 totalPixel = (uint32)mode->timing.h_total 228 * (uint32)mode->timing.v_total; 229 uint32 clockLimit = 2000000; 230 231 // lower limit of about 48Hz vertical refresh 232 *_low = totalPixel * 48L / 1000L; 233 if (*_low > clockLimit) 234 return B_ERROR; 235 236 *_high = clockLimit; 237 return B_OK; 238 } 239 240 241 status_t 242 vesa_move_display(uint16 h_display_start, uint16 v_display_start) 243 { 244 TRACE(("vesa_move_display()\n")); 245 return B_ERROR; 246 } 247 248 249 status_t 250 vesa_get_timing_constraints(display_timing_constraints* constraints) 251 { 252 TRACE(("vesa_get_timing_constraints()\n")); 253 return B_ERROR; 254 } 255 256 257 void 258 vesa_set_indexed_colors(uint count, uint8 first, uint8* colors, uint32 flags) 259 { 260 TRACE(("vesa_set_indexed_colors()\n")); 261 262 vesa_set_indexed_colors_args args; 263 args.first = first; 264 args.count = count; 265 args.colors = colors; 266 ioctl(gInfo->device, VESA_SET_INDEXED_COLORS, &args, sizeof(args)); 267 } 268 269