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