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", NULL, NULL, 0, 78 kVesaSpaces, sizeof(kVesaSpaces) / sizeof(kVesaSpaces[0]), 79 is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 80 if (gInfo->mode_list_area < B_OK) 81 return gInfo->mode_list_area; 82 83 gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 84 return B_OK; 85 } 86 87 88 // #pragma mark - 89 90 91 uint32 92 vesa_accelerant_mode_count(void) 93 { 94 TRACE(("vesa_accelerant_mode_count()\n")); 95 return gInfo->shared_info->mode_count; 96 } 97 98 99 status_t 100 vesa_get_mode_list(display_mode* modeList) 101 { 102 TRACE(("vesa_get_mode_info()\n")); 103 memcpy(modeList, gInfo->mode_list, 104 gInfo->shared_info->mode_count * sizeof(display_mode)); 105 return B_OK; 106 } 107 108 109 status_t 110 vesa_propose_display_mode(display_mode* target, const display_mode* low, 111 const display_mode* high) 112 { 113 TRACE(("vesa_propose_display_mode()\n")); 114 115 // just search for the specified mode in the list 116 117 for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { 118 display_mode* current = &gInfo->mode_list[i]; 119 120 if (target->virtual_width != current->virtual_width 121 || target->virtual_height != current->virtual_height 122 || target->space != current->space) 123 continue; 124 125 *target = *current; 126 return B_OK; 127 } 128 return B_BAD_VALUE; 129 } 130 131 132 status_t 133 vesa_set_display_mode(display_mode* _mode) 134 { 135 TRACE(("vesa_set_display_mode()\n")); 136 137 display_mode mode = *_mode; 138 if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK) 139 return B_BAD_VALUE; 140 141 vesa_mode* modes = gInfo->vesa_modes; 142 for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) { 143 // search mode in VESA mode list 144 // TODO: list is ordered, we could use binary search 145 if (modes[i].width == mode.virtual_width 146 && modes[i].height == mode.virtual_height 147 && get_color_space_for_depth(modes[i].bits_per_pixel) 148 == mode.space) 149 return ioctl(gInfo->device, VESA_SET_DISPLAY_MODE, &i, sizeof(i)); 150 } 151 152 return B_UNSUPPORTED; 153 } 154 155 156 status_t 157 vesa_get_display_mode(display_mode* _currentMode) 158 { 159 TRACE(("vesa_get_display_mode()\n")); 160 *_currentMode = gInfo->shared_info->current_mode; 161 return B_OK; 162 } 163 164 165 status_t 166 vesa_get_edid_info(void* info, size_t size, uint32* _version) 167 { 168 TRACE(("intel_get_edid_info()\n")); 169 170 if (!gInfo->shared_info->has_edid) 171 return B_ERROR; 172 if (size < sizeof(struct edid1_info)) 173 return B_BUFFER_OVERFLOW; 174 175 memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 176 *_version = EDID_VERSION_1; 177 return B_OK; 178 } 179 180 181 status_t 182 vesa_get_frame_buffer_config(frame_buffer_config* config) 183 { 184 TRACE(("vesa_get_frame_buffer_config()\n")); 185 186 config->frame_buffer = gInfo->shared_info->frame_buffer; 187 config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; 188 config->bytes_per_row = gInfo->shared_info->bytes_per_row; 189 190 return B_OK; 191 } 192 193 194 status_t 195 vesa_get_pixel_clock_limits(display_mode* mode, uint32* low, uint32* high) 196 { 197 TRACE(("vesa_get_pixel_clock_limits()\n")); 198 199 // TODO: do some real stuff here (taken from radeon driver) 200 uint32 totalPixel = (uint32)mode->timing.h_total 201 * (uint32)mode->timing.v_total; 202 uint32 clockLimit = 2000000; 203 204 // lower limit of about 48Hz vertical refresh 205 *low = totalPixel * 48L / 1000L; 206 if (*low > clockLimit) 207 return B_ERROR; 208 209 *high = clockLimit; 210 return B_OK; 211 } 212 213 214 status_t 215 vesa_move_display(uint16 h_display_start, uint16 v_display_start) 216 { 217 TRACE(("vesa_move_display()\n")); 218 return B_ERROR; 219 } 220 221 222 status_t 223 vesa_get_timing_constraints(display_timing_constraints* constraints) 224 { 225 TRACE(("vesa_get_timing_constraints()\n")); 226 return B_ERROR; 227 } 228 229 230 void 231 vesa_set_indexed_colors(uint count, uint8 first, uint8* colors, uint32 flags) 232 { 233 TRACE(("vesa_set_indexed_colors()\n")); 234 vga_set_indexed_colors_args args; 235 args.first = first; 236 args.count = count; 237 args.colors = colors; 238 ioctl(gInfo->device, VGA_SET_INDEXED_COLORS, &args, sizeof(args)); 239 } 240 241