1a90ebd77SClemens Zeidler /* 2d5c3acacSAlexander von Gluck IV * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. 3a90ebd77SClemens Zeidler * Distributed under the terms of the MIT License. 4a90ebd77SClemens Zeidler * 5a90ebd77SClemens Zeidler * Support for i915 chipset and up based on the X driver, 6a90ebd77SClemens Zeidler * Copyright 2006-2007 Intel Corporation. 7a90ebd77SClemens Zeidler * 8a90ebd77SClemens Zeidler * Authors: 9a90ebd77SClemens Zeidler * Axel Dörfler, axeld@pinc-software.de 10d5c3acacSAlexander von Gluck IV * Alexander von Gluck, kallisti5@unixzen.com 11a90ebd77SClemens Zeidler */ 12a90ebd77SClemens Zeidler 13a90ebd77SClemens Zeidler 14d5c3acacSAlexander von Gluck IV #include "mode.h" 15a90ebd77SClemens Zeidler 1661cf7133SAlexander von Gluck IV #include <create_display_modes.h> 17a90ebd77SClemens Zeidler #include <stdio.h> 18a90ebd77SClemens Zeidler #include <string.h> 19a90ebd77SClemens Zeidler #include <math.h> 20a90ebd77SClemens Zeidler 2161cf7133SAlexander von Gluck IV #include "accelerant.h" 2261cf7133SAlexander von Gluck IV #include "accelerant_protos.h" 2361cf7133SAlexander von Gluck IV #include "bios.h" 24c8677fb1SAlexander von Gluck IV #include "connector.h" 2561cf7133SAlexander von Gluck IV #include "display.h" 26c8677fb1SAlexander von Gluck IV #include "displayport.h" 2761cf7133SAlexander von Gluck IV #include "encoder.h" 2861cf7133SAlexander von Gluck IV #include "pll.h" 2961cf7133SAlexander von Gluck IV #include "utility.h" 30192781ddSAlexander von Gluck IV 31a90ebd77SClemens Zeidler 32a90ebd77SClemens Zeidler #define TRACE_MODE 33a90ebd77SClemens Zeidler #ifdef TRACE_MODE 34a90ebd77SClemens Zeidler extern "C" void _sPrintf(const char* format, ...); 35d5c3acacSAlexander von Gluck IV # define TRACE(x...) _sPrintf("radeon_hd: " x) 36a90ebd77SClemens Zeidler #else 37d5c3acacSAlexander von Gluck IV # define TRACE(x...) ; 38a90ebd77SClemens Zeidler #endif 39a90ebd77SClemens Zeidler 4009aaa658SAlexander von Gluck IV #define ERROR(x...) _sPrintf("radeon_hd: " x) 41a90ebd77SClemens Zeidler 42a90ebd77SClemens Zeidler status_t 43a90ebd77SClemens Zeidler create_mode_list(void) 44a90ebd77SClemens Zeidler { 45f35af704SAlexander von Gluck IV // TODO: multi-monitor? for now we use VESA and not gDisplay edid 46f35af704SAlexander von Gluck IV 47192781ddSAlexander von Gluck IV const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 48192781ddSAlexander von Gluck IV B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 49a90ebd77SClemens Zeidler 50192781ddSAlexander von Gluck IV gInfo->mode_list_area = create_display_modes("radeon HD modes", 512613175eSAlexander von Gluck IV gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL, 522613175eSAlexander von Gluck IV NULL, 0, kRadeonHDSpaces, 53192781ddSAlexander von Gluck IV sizeof(kRadeonHDSpaces) / sizeof(kRadeonHDSpaces[0]), 54192781ddSAlexander von Gluck IV is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 55192781ddSAlexander von Gluck IV if (gInfo->mode_list_area < B_OK) 56192781ddSAlexander von Gluck IV return gInfo->mode_list_area; 57a90ebd77SClemens Zeidler 58192781ddSAlexander von Gluck IV gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 59d5c3acacSAlexander von Gluck IV 60a90ebd77SClemens Zeidler return B_OK; 61a90ebd77SClemens Zeidler } 62a90ebd77SClemens Zeidler 63a90ebd77SClemens Zeidler 64a90ebd77SClemens Zeidler // #pragma mark - 65a90ebd77SClemens Zeidler 66a90ebd77SClemens Zeidler 67a90ebd77SClemens Zeidler uint32 68a90ebd77SClemens Zeidler radeon_accelerant_mode_count(void) 69a90ebd77SClemens Zeidler { 70333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 71a90ebd77SClemens Zeidler 72a90ebd77SClemens Zeidler return gInfo->shared_info->mode_count; 73a90ebd77SClemens Zeidler } 74a90ebd77SClemens Zeidler 75a90ebd77SClemens Zeidler 76a90ebd77SClemens Zeidler status_t 77a90ebd77SClemens Zeidler radeon_get_mode_list(display_mode* modeList) 78a90ebd77SClemens Zeidler { 79333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 80a90ebd77SClemens Zeidler memcpy(modeList, gInfo->mode_list, 81a90ebd77SClemens Zeidler gInfo->shared_info->mode_count * sizeof(display_mode)); 82a90ebd77SClemens Zeidler return B_OK; 83a90ebd77SClemens Zeidler } 84a90ebd77SClemens Zeidler 85a90ebd77SClemens Zeidler 8688bfef92SAlexander von Gluck IV status_t 8788bfef92SAlexander von Gluck IV radeon_get_edid_info(void* info, size_t size, uint32* edid_version) 8888bfef92SAlexander von Gluck IV { 8907a90a63SAlexander von Gluck IV // TODO: multi-monitor? for now we use VESA edid 90f35af704SAlexander von Gluck IV 9188bfef92SAlexander von Gluck IV TRACE("%s\n", __func__); 9288bfef92SAlexander von Gluck IV if (!gInfo->shared_info->has_edid) 9388bfef92SAlexander von Gluck IV return B_ERROR; 9488bfef92SAlexander von Gluck IV if (size < sizeof(struct edid1_info)) 9588bfef92SAlexander von Gluck IV return B_BUFFER_OVERFLOW; 9688bfef92SAlexander von Gluck IV 9788bfef92SAlexander von Gluck IV memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 9807a90a63SAlexander von Gluck IV // VESA 9907a90a63SAlexander von Gluck IV //memcpy(info, &gDisplay[0]->edid_info, sizeof(struct edid1_info)); 10007a90a63SAlexander von Gluck IV // BitBanged display 0 10107a90a63SAlexander von Gluck IV 10288bfef92SAlexander von Gluck IV *edid_version = EDID_VERSION_1; 10388bfef92SAlexander von Gluck IV 10488bfef92SAlexander von Gluck IV return B_OK; 10588bfef92SAlexander von Gluck IV } 10688bfef92SAlexander von Gluck IV 10788bfef92SAlexander von Gluck IV 1087934da0fSAlexander von Gluck IV uint32 1097934da0fSAlexander von Gluck IV radeon_dpms_capabilities(void) 1107934da0fSAlexander von Gluck IV { 1117934da0fSAlexander von Gluck IV // These should be pretty universally supported on Radeon HD cards 1127934da0fSAlexander von Gluck IV return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; 1137934da0fSAlexander von Gluck IV } 1147934da0fSAlexander von Gluck IV 1157934da0fSAlexander von Gluck IV 1167934da0fSAlexander von Gluck IV uint32 1177934da0fSAlexander von Gluck IV radeon_dpms_mode(void) 1187934da0fSAlexander von Gluck IV { 1197934da0fSAlexander von Gluck IV // TODO: this really isn't a good long-term solution 1207934da0fSAlexander von Gluck IV // we may need to look at the encoder dpms scratch registers 1217934da0fSAlexander von Gluck IV return gInfo->dpms_mode; 1227934da0fSAlexander von Gluck IV } 1237934da0fSAlexander von Gluck IV 1247934da0fSAlexander von Gluck IV 125b54c8119SAlexander von Gluck IV void 126b54c8119SAlexander von Gluck IV radeon_dpms_set(int mode) 127b54c8119SAlexander von Gluck IV { 128f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 129f089aa52SAlexander von Gluck IV 130b54c8119SAlexander von Gluck IV switch (mode) { 131b54c8119SAlexander von Gluck IV case B_DPMS_ON: 132936aec74SAlexander von Gluck IV TRACE("%s: ON\n", __func__); 133b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 134b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 135b54c8119SAlexander von Gluck IV continue; 136*4e9e0295SAlexander von Gluck IV encoder_dpms_set(id, mode); 137936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 138b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 139f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 140b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 1416c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 142936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 143b54c8119SAlexander von Gluck IV } 144b54c8119SAlexander von Gluck IV break; 145b54c8119SAlexander von Gluck IV case B_DPMS_STAND_BY: 146b54c8119SAlexander von Gluck IV case B_DPMS_SUSPEND: 147b54c8119SAlexander von Gluck IV case B_DPMS_OFF: 148936aec74SAlexander von Gluck IV TRACE("%s: OFF\n", __func__); 149b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 150b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 151b54c8119SAlexander von Gluck IV continue; 152936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1536c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 154f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 155b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 156b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 157936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 158*4e9e0295SAlexander von Gluck IV encoder_dpms_set(id, mode); 159b54c8119SAlexander von Gluck IV } 160b54c8119SAlexander von Gluck IV break; 161b54c8119SAlexander von Gluck IV } 1627934da0fSAlexander von Gluck IV gInfo->dpms_mode = mode; 163b54c8119SAlexander von Gluck IV } 164b54c8119SAlexander von Gluck IV 165b54c8119SAlexander von Gluck IV 166a90ebd77SClemens Zeidler status_t 167a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode* mode) 168a90ebd77SClemens Zeidler { 169f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 170f089aa52SAlexander von Gluck IV 1716ab8261bSAlexander von Gluck IV // Set mode on each display 1726ab8261bSAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 173b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 1746ab8261bSAlexander von Gluck IV continue; 175f2fe29a0SAlexander von Gluck IV 1766b0b621bSAlexander von Gluck IV uint16 connectorIndex = gDisplay[id]->connectorIndex; 17717b66d82SAlexander von Gluck IV 17809aaa658SAlexander von Gluck IV // Determine DP lanes if DP 17909aaa658SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) 18009aaa658SAlexander von Gluck IV gDPInfo[connectorIndex]->laneCount 18109aaa658SAlexander von Gluck IV = dp_get_lane_count(connectorIndex, mode); 18209aaa658SAlexander von Gluck IV 183b54c8119SAlexander von Gluck IV // *** encoder prep 184b54c8119SAlexander von Gluck IV encoder_output_lock(true); 18545e71a9eSAlexander von Gluck IV encoder_dpms_set(id, B_DPMS_OFF); 18617b66d82SAlexander von Gluck IV encoder_assign_crtc(id); 187e53d6375SAlexander von Gluck IV 188b54c8119SAlexander von Gluck IV // *** CRT controler prep 189b54c8119SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1906c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 191f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 192936aec74SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 193936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 194f35af704SAlexander von Gluck IV 195b54c8119SAlexander von Gluck IV // *** CRT controler mode set 19617b66d82SAlexander von Gluck IV // TODO: program SS 197e7d0abaeSAlexander von Gluck IV pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id); 198e7d0abaeSAlexander von Gluck IV // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so 1996da3f7d4SAlexander von Gluck IV display_crtc_set_dtd(id, mode); 200b54c8119SAlexander von Gluck IV 201afbd52f1SAlexander von Gluck IV display_crtc_fb_set(id, mode); 202b54c8119SAlexander von Gluck IV // atombios_overscan_setup 2036da3f7d4SAlexander von Gluck IV display_crtc_scale(id, mode); 2046ab8261bSAlexander von Gluck IV 205b54c8119SAlexander von Gluck IV // *** encoder mode set 206b54c8119SAlexander von Gluck IV encoder_mode_set(id, mode->timing.pixel_clock); 207b54c8119SAlexander von Gluck IV 208b54c8119SAlexander von Gluck IV // *** CRT controler commit 209936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 210f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 211245fe001SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 2126c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 2136da3f7d4SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 214b54c8119SAlexander von Gluck IV 215b54c8119SAlexander von Gluck IV // *** encoder commit 216c8677fb1SAlexander von Gluck IV 217c8677fb1SAlexander von Gluck IV // handle DisplayPort link training 218c8677fb1SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) { 219c8677fb1SAlexander von Gluck IV if (info.dceMajor >= 4) 220c8677fb1SAlexander von Gluck IV encoder_dig_setup(connectorIndex, 221c8677fb1SAlexander von Gluck IV ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 222c8677fb1SAlexander von Gluck IV 223c8677fb1SAlexander von Gluck IV dp_link_train(id, mode); 224c8677fb1SAlexander von Gluck IV 225c8677fb1SAlexander von Gluck IV if (info.dceMajor >= 4) 226c8677fb1SAlexander von Gluck IV encoder_dig_setup(connectorIndex, 227c8677fb1SAlexander von Gluck IV ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 228c8677fb1SAlexander von Gluck IV } 229c8677fb1SAlexander von Gluck IV 23045e71a9eSAlexander von Gluck IV encoder_dpms_set(id, B_DPMS_ON); 231b54c8119SAlexander von Gluck IV encoder_output_lock(false); 2326ab8261bSAlexander von Gluck IV } 2336604b1b6SAlexander von Gluck IV 234245fe001SAlexander von Gluck IV // for debugging 235245fe001SAlexander von Gluck IV TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, D1CRTC_STATUS)); 236245fe001SAlexander von Gluck IV TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, D2CRTC_STATUS)); 237245fe001SAlexander von Gluck IV TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D1CRTC_CONTROL)); 238245fe001SAlexander von Gluck IV TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D2CRTC_CONTROL)); 239025d4eedSAlexander von Gluck IV TRACE("D1GRPH_ENABLE Value: 0x%X\n", 240025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1GRPH_ENABLE)); 241025d4eedSAlexander von Gluck IV TRACE("D2GRPH_ENABLE Value: 0x%X\n", 242025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2GRPH_ENABLE)); 243025d4eedSAlexander von Gluck IV TRACE("D1SCL_ENABLE Value: 0x%X\n", 244025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); 245025d4eedSAlexander von Gluck IV TRACE("D2SCL_ENABLE Value: 0x%X\n", 246025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); 24746af8165SAlexander von Gluck IV TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", 248025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 24946af8165SAlexander von Gluck IV TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", 250025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 2513be5e036SAlexander von Gluck IV 252a90ebd77SClemens Zeidler return B_OK; 253a90ebd77SClemens Zeidler } 254a90ebd77SClemens Zeidler 255a90ebd77SClemens Zeidler 256a90ebd77SClemens Zeidler status_t 257a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode* _currentMode) 258a90ebd77SClemens Zeidler { 259d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 260a90ebd77SClemens Zeidler 261192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 262a90ebd77SClemens Zeidler return B_OK; 263a90ebd77SClemens Zeidler } 264a90ebd77SClemens Zeidler 265a90ebd77SClemens Zeidler 266a90ebd77SClemens Zeidler status_t 267a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config* config) 268a90ebd77SClemens Zeidler { 269d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 270a90ebd77SClemens Zeidler 2713be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 2723be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8*)gInfo->shared_info->frame_buffer_phys; 27351a43d0fSAlexander von Gluck IV 274a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 275a90ebd77SClemens Zeidler 276a90ebd77SClemens Zeidler return B_OK; 277a90ebd77SClemens Zeidler } 278a90ebd77SClemens Zeidler 279a90ebd77SClemens Zeidler 280a90ebd77SClemens Zeidler status_t 281a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high) 282a90ebd77SClemens Zeidler { 283d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 284e7e76b29SAlexander von Gluck IV 285a90ebd77SClemens Zeidler if (_low != NULL) { 286a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 2875f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 2885f6744a8SAlexander von Gluck IV * (uint32)mode->timing.v_total; 289a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 290e7e76b29SAlexander von Gluck IV 291d3e8b642SAlexander von Gluck IV if (low < PLL_MIN_DEFAULT) 292d3e8b642SAlexander von Gluck IV low = PLL_MIN_DEFAULT; 293d3e8b642SAlexander von Gluck IV else if (low > PLL_MAX_DEFAULT) 294a90ebd77SClemens Zeidler return B_ERROR; 295a90ebd77SClemens Zeidler 296a90ebd77SClemens Zeidler *_low = low; 297a90ebd77SClemens Zeidler } 298a90ebd77SClemens Zeidler 299a90ebd77SClemens Zeidler if (_high != NULL) 300d3e8b642SAlexander von Gluck IV *_high = PLL_MAX_DEFAULT; 301e7e76b29SAlexander von Gluck IV 302e7e76b29SAlexander von Gluck IV //*_low = 48L; 303e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 304a90ebd77SClemens Zeidler return B_OK; 305a90ebd77SClemens Zeidler } 306a90ebd77SClemens Zeidler 307a90ebd77SClemens Zeidler 308192781ddSAlexander von Gluck IV bool 309192781ddSAlexander von Gluck IV is_mode_supported(display_mode* mode) 310192781ddSAlexander von Gluck IV { 311f52ca69cSAlexander von Gluck IV bool sane = true; 312d1d65a79SAlexander von Gluck IV 3131dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 314192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 315f52ca69cSAlexander von Gluck IV sane = false; 316192781ddSAlexander von Gluck IV 31795e1d7e8SAlexander von Gluck IV // TODO: is_mode_supported on *which* display? 318d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 3191dac4469SAlexander von Gluck IV 320d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 321e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 322e1b9d6e6SAlexander von Gluck IV && gDisplay[crtid]->found_ranges) { 3231dac4469SAlexander von Gluck IV 324f52ca69cSAlexander von Gluck IV // validate horizontal frequency range 325d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 32695e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 32795e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 328f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of hfreq range!\n"); 329f52ca69cSAlexander von Gluck IV sane = false; 330d1d65a79SAlexander von Gluck IV } 331d1d65a79SAlexander von Gluck IV 332f52ca69cSAlexander von Gluck IV // validate vertical frequency range 333d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 334d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 33595e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 33695e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 337f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of vfreq range!\n"); 338f52ca69cSAlexander von Gluck IV sane = false; 339d1d65a79SAlexander von Gluck IV } 340e1b9d6e6SAlexander von Gluck IV } 341e1b9d6e6SAlexander von Gluck IV 342f52ca69cSAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d is %s\n", 343f52ca69cSAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 344f52ca69cSAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 345f52ca69cSAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 346f52ca69cSAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 347f52ca69cSAlexander von Gluck IV mode->timing.v_total, 348f52ca69cSAlexander von Gluck IV sane ? "OK." : "BAD, out of range!"); 349192781ddSAlexander von Gluck IV 350f52ca69cSAlexander von Gluck IV return sane; 351192781ddSAlexander von Gluck IV } 352192781ddSAlexander von Gluck IV 353192781ddSAlexander von Gluck IV 354d5c3acacSAlexander von Gluck IV /* 355d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 356d5c3acacSAlexander von Gluck IV */ 357d5c3acacSAlexander von Gluck IV status_t 358192781ddSAlexander von Gluck IV is_mode_sane(display_mode* mode) 359d5c3acacSAlexander von Gluck IV { 360333bd770SAlexander von Gluck IV // horizontal timing 361333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 362333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 36391235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 36491235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 365333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 366333bd770SAlexander von Gluck IV return B_ERROR; 367333bd770SAlexander von Gluck IV } 368333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 369333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 37091235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 37191235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 372333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 373d5c3acacSAlexander von Gluck IV return B_ERROR; 374d5c3acacSAlexander von Gluck IV } 375d5c3acacSAlexander von Gluck IV 376333bd770SAlexander von Gluck IV // vertical timing 377333bd770SAlexander von Gluck IV // validate v_start is less then v_end 378333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 37991235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 38091235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\n", 381333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 382d5c3acacSAlexander von Gluck IV return B_ERROR; 383d5c3acacSAlexander von Gluck IV } 384333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 385333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 38691235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 38791235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 388333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 389d5c3acacSAlexander von Gluck IV return B_ERROR; 390d5c3acacSAlexander von Gluck IV } 391d5c3acacSAlexander von Gluck IV 39291235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 39391235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 39491235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 39591235829SAlexander von Gluck IV 39691235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 39791235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 39891235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 39991235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 40091235829SAlexander von Gluck IV return B_ERROR; 40191235829SAlexander von Gluck IV } 40291235829SAlexander von Gluck IV 403d5c3acacSAlexander von Gluck IV return B_OK; 404d5c3acacSAlexander von Gluck IV } 405d5c3acacSAlexander von Gluck IV 406d1d65a79SAlexander von Gluck IV 40709aaa658SAlexander von Gluck IV uint32 40809aaa658SAlexander von Gluck IV get_mode_bpp(display_mode* mode) 40909aaa658SAlexander von Gluck IV { 41009aaa658SAlexander von Gluck IV // Get bitsPerPixel for given mode 41109aaa658SAlexander von Gluck IV 41209aaa658SAlexander von Gluck IV switch (mode->space) { 41309aaa658SAlexander von Gluck IV case B_CMAP8: 41409aaa658SAlexander von Gluck IV return 8; 41509aaa658SAlexander von Gluck IV case B_RGB15_LITTLE: 41609aaa658SAlexander von Gluck IV return 15; 41709aaa658SAlexander von Gluck IV case B_RGB16_LITTLE: 41809aaa658SAlexander von Gluck IV return 16; 41909aaa658SAlexander von Gluck IV case B_RGB24_LITTLE: 42009aaa658SAlexander von Gluck IV case B_RGB32_LITTLE: 42109aaa658SAlexander von Gluck IV return 32; 42209aaa658SAlexander von Gluck IV } 42309aaa658SAlexander von Gluck IV ERROR("%s: Unknown colorspace for mode, guessing 32 bits per pixel\n", 42409aaa658SAlexander von Gluck IV __func__); 42509aaa658SAlexander von Gluck IV return 32; 42609aaa658SAlexander von Gluck IV } 427