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