1a90ebd77SClemens Zeidler /* 200bc40adSAlexander von Gluck IV * Copyright 2006-2013, 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 42d2a69507SAlexander von Gluck IV 43a90ebd77SClemens Zeidler status_t 44a90ebd77SClemens Zeidler create_mode_list(void) 45a90ebd77SClemens Zeidler { 46f35af704SAlexander von Gluck IV // TODO: multi-monitor? for now we use VESA and not gDisplay edid 47878a8d3fSAlexander von Gluck IV uint8 crtcID = 0; 48f35af704SAlexander von Gluck IV 49192781ddSAlexander von Gluck IV const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 50192781ddSAlexander von Gluck IV B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 51a90ebd77SClemens Zeidler 52192781ddSAlexander von Gluck IV gInfo->mode_list_area = create_display_modes("radeon HD modes", 53878a8d3fSAlexander von Gluck IV &gDisplay[crtcID]->edidData, NULL, 0, kRadeonHDSpaces, 54192781ddSAlexander von Gluck IV sizeof(kRadeonHDSpaces) / sizeof(kRadeonHDSpaces[0]), 55192781ddSAlexander von Gluck IV is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 56192781ddSAlexander von Gluck IV if (gInfo->mode_list_area < B_OK) 57192781ddSAlexander von Gluck IV return gInfo->mode_list_area; 58a90ebd77SClemens Zeidler 59192781ddSAlexander von Gluck IV gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 60d5c3acacSAlexander von Gluck IV 61a90ebd77SClemens Zeidler return B_OK; 62a90ebd77SClemens Zeidler } 63a90ebd77SClemens Zeidler 64a90ebd77SClemens Zeidler 65a90ebd77SClemens Zeidler // #pragma mark - 66a90ebd77SClemens Zeidler 67a90ebd77SClemens Zeidler 68a90ebd77SClemens Zeidler uint32 69a90ebd77SClemens Zeidler radeon_accelerant_mode_count(void) 70a90ebd77SClemens Zeidler { 71333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 7200bc40adSAlexander von Gluck IV // TODO: multi-monitor? we need crtcid here 73a90ebd77SClemens Zeidler 74a90ebd77SClemens Zeidler return gInfo->shared_info->mode_count; 75a90ebd77SClemens Zeidler } 76a90ebd77SClemens Zeidler 77a90ebd77SClemens Zeidler 78a90ebd77SClemens Zeidler status_t 79a90ebd77SClemens Zeidler radeon_get_mode_list(display_mode* modeList) 80a90ebd77SClemens Zeidler { 81333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 8200bc40adSAlexander von Gluck IV // TODO: multi-monitor? we need crtcid here 83a90ebd77SClemens Zeidler memcpy(modeList, gInfo->mode_list, 84a90ebd77SClemens Zeidler gInfo->shared_info->mode_count * sizeof(display_mode)); 85a90ebd77SClemens Zeidler return B_OK; 86a90ebd77SClemens Zeidler } 87a90ebd77SClemens Zeidler 88a90ebd77SClemens Zeidler 8988bfef92SAlexander von Gluck IV status_t 904bd6c200SAlexander von Gluck IV radeon_get_preferred_mode(display_mode* preferredMode) 914bd6c200SAlexander von Gluck IV { 924bd6c200SAlexander von Gluck IV TRACE("%s\n", __func__); 9300bc40adSAlexander von Gluck IV // TODO: multi-monitor? we need crtcid here 944bd6c200SAlexander von Gluck IV 954bd6c200SAlexander von Gluck IV uint8_t crtc = 0; 964bd6c200SAlexander von Gluck IV 974bd6c200SAlexander von Gluck IV if (gDisplay[crtc]->preferredMode.virtual_width > 0 984bd6c200SAlexander von Gluck IV && gDisplay[crtc]->preferredMode.virtual_height > 0) { 994bd6c200SAlexander von Gluck IV TRACE("%s: preferred mode was found for display %" B_PRIu8 "\n", 1004bd6c200SAlexander von Gluck IV __func__, crtc); 1014bd6c200SAlexander von Gluck IV memcpy(preferredMode, &gDisplay[crtc]->preferredMode, 1024bd6c200SAlexander von Gluck IV sizeof(gDisplay[crtc]->preferredMode)); 1034bd6c200SAlexander von Gluck IV return B_OK; 1044bd6c200SAlexander von Gluck IV } 1054bd6c200SAlexander von Gluck IV 1064bd6c200SAlexander von Gluck IV return B_ERROR; 1074bd6c200SAlexander von Gluck IV } 1084bd6c200SAlexander von Gluck IV 1094bd6c200SAlexander von Gluck IV 1104bd6c200SAlexander von Gluck IV status_t 11188bfef92SAlexander von Gluck IV radeon_get_edid_info(void* info, size_t size, uint32* edid_version) 11288bfef92SAlexander von Gluck IV { 113*339a0181SAlexander von Gluck IV // TODO: multi-monitor? for now we use display 0 114878a8d3fSAlexander von Gluck IV uint8 crtcID = 0; 115f35af704SAlexander von Gluck IV 11688bfef92SAlexander von Gluck IV TRACE("%s\n", __func__); 11788bfef92SAlexander von Gluck IV if (!gInfo->shared_info->has_edid) 11888bfef92SAlexander von Gluck IV return B_ERROR; 11988bfef92SAlexander von Gluck IV if (size < sizeof(struct edid1_info)) 12088bfef92SAlexander von Gluck IV return B_BUFFER_OVERFLOW; 12188bfef92SAlexander von Gluck IV 122878a8d3fSAlexander von Gluck IV //memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 12307a90a63SAlexander von Gluck IV // VESA 124878a8d3fSAlexander von Gluck IV memcpy(info, &gDisplay[crtcID]->edidData, sizeof(struct edid1_info)); 12500bc40adSAlexander von Gluck IV // Display 0 12607a90a63SAlexander von Gluck IV 12788bfef92SAlexander von Gluck IV *edid_version = EDID_VERSION_1; 12888bfef92SAlexander von Gluck IV 12988bfef92SAlexander von Gluck IV return B_OK; 13088bfef92SAlexander von Gluck IV } 13188bfef92SAlexander von Gluck IV 13288bfef92SAlexander von Gluck IV 1337934da0fSAlexander von Gluck IV uint32 1347934da0fSAlexander von Gluck IV radeon_dpms_capabilities(void) 1357934da0fSAlexander von Gluck IV { 1367934da0fSAlexander von Gluck IV // These should be pretty universally supported on Radeon HD cards 1377934da0fSAlexander von Gluck IV return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; 1387934da0fSAlexander von Gluck IV } 1397934da0fSAlexander von Gluck IV 1407934da0fSAlexander von Gluck IV 1417934da0fSAlexander von Gluck IV uint32 1427934da0fSAlexander von Gluck IV radeon_dpms_mode(void) 1437934da0fSAlexander von Gluck IV { 1447934da0fSAlexander von Gluck IV // TODO: this really isn't a good long-term solution 1457934da0fSAlexander von Gluck IV // we may need to look at the encoder dpms scratch registers 1467934da0fSAlexander von Gluck IV return gInfo->dpms_mode; 1477934da0fSAlexander von Gluck IV } 1487934da0fSAlexander von Gluck IV 1497934da0fSAlexander von Gluck IV 150b54c8119SAlexander von Gluck IV void 15100bc40adSAlexander von Gluck IV radeon_dpms_set(uint8 id, int mode) 152b54c8119SAlexander von Gluck IV { 15300bc40adSAlexander von Gluck IV if (mode == B_DPMS_ON) { 15400bc40adSAlexander von Gluck IV display_crtc_dpms(id, mode); 15500bc40adSAlexander von Gluck IV encoder_dpms_set(id, mode); 15600bc40adSAlexander von Gluck IV } else { 15764ff3d18SAlexander von Gluck IV encoder_dpms_set(id, mode); 1582399d174SAlexander von Gluck IV display_crtc_dpms(id, mode); 15964ff3d18SAlexander von Gluck IV } 1607934da0fSAlexander von Gluck IV gInfo->dpms_mode = mode; 161b54c8119SAlexander von Gluck IV } 162b54c8119SAlexander von Gluck IV 163b54c8119SAlexander von Gluck IV 16400bc40adSAlexander von Gluck IV void 16500bc40adSAlexander von Gluck IV radeon_dpms_set_hook(int mode) 16600bc40adSAlexander von Gluck IV { 167*339a0181SAlexander von Gluck IV // TODO: multi-monitor? 16800bc40adSAlexander von Gluck IV 169*339a0181SAlexander von Gluck IV uint8 crtcID = 0; 170*339a0181SAlexander von Gluck IV 171*339a0181SAlexander von Gluck IV if (gDisplay[crtcID]->attached) 172*339a0181SAlexander von Gluck IV radeon_dpms_set(crtcID, mode); 17300bc40adSAlexander von Gluck IV } 17400bc40adSAlexander von Gluck IV 17500bc40adSAlexander von Gluck IV 176a90ebd77SClemens Zeidler status_t 177a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode* mode) 178a90ebd77SClemens Zeidler { 17900bc40adSAlexander von Gluck IV // TODO: multi-monitor? For now we set the mode on 180*339a0181SAlexander von Gluck IV // the first display found. 181f089aa52SAlexander von Gluck IV 182*339a0181SAlexander von Gluck IV uint8 crtcID = 0; 183*339a0181SAlexander von Gluck IV 184*339a0181SAlexander von Gluck IV if (gDisplay[crtcID]->attached == false) 185*339a0181SAlexander von Gluck IV return B_ERROR; 186f2fe29a0SAlexander von Gluck IV 18700bc40adSAlexander von Gluck IV // Copy this display mode into the "current mode" for the display 188*339a0181SAlexander von Gluck IV memcpy(&gDisplay[crtcID]->currentMode, mode, sizeof(display_mode)); 18900bc40adSAlexander von Gluck IV 190*339a0181SAlexander von Gluck IV uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 19117b66d82SAlexander von Gluck IV 19209aaa658SAlexander von Gluck IV // Determine DP lanes if DP 1934e7e3e33SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) { 1944e7e3e33SAlexander von Gluck IV dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo; 1954e7e3e33SAlexander von Gluck IV dpInfo->laneCount = dp_get_lane_count(connectorIndex, mode); 1964e7e3e33SAlexander von Gluck IV dpInfo->linkRate = dp_get_link_rate(connectorIndex, mode); 1974e7e3e33SAlexander von Gluck IV } 19809aaa658SAlexander von Gluck IV 199bb228d7cSAlexander von Gluck IV // *** crtc and encoder prep 200b54c8119SAlexander von Gluck IV encoder_output_lock(true); 201*339a0181SAlexander von Gluck IV display_crtc_lock(crtcID, ATOM_ENABLE); 202*339a0181SAlexander von Gluck IV radeon_dpms_set(crtcID, B_DPMS_OFF); 203f35af704SAlexander von Gluck IV 204bb228d7cSAlexander von Gluck IV // *** Set up encoder -> crtc routing 205*339a0181SAlexander von Gluck IV encoder_assign_crtc(crtcID); 206bb228d7cSAlexander von Gluck IV 207b54c8119SAlexander von Gluck IV // *** CRT controler mode set 20847274433SAlexander von Gluck IV // Set up PLL for connector 20947274433SAlexander von Gluck IV pll_pick(connectorIndex); 21047274433SAlexander von Gluck IV pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 21147274433SAlexander von Gluck IV TRACE("%s: pll %d selected for connector %" B_PRIu32 "\n", __func__, 21247274433SAlexander von Gluck IV pll->id, connectorIndex); 213*339a0181SAlexander von Gluck IV pll_set(mode, crtcID); 21447274433SAlexander von Gluck IV 215*339a0181SAlexander von Gluck IV display_crtc_set_dtd(crtcID, mode); 216b54c8119SAlexander von Gluck IV 217*339a0181SAlexander von Gluck IV display_crtc_fb_set(crtcID, mode); 218b54c8119SAlexander von Gluck IV // atombios_overscan_setup 219*339a0181SAlexander von Gluck IV display_crtc_scale(crtcID, mode); 2206ab8261bSAlexander von Gluck IV 221b54c8119SAlexander von Gluck IV // *** encoder mode set 222*339a0181SAlexander von Gluck IV encoder_mode_set(crtcID); 223b54c8119SAlexander von Gluck IV 22400bc40adSAlexander von Gluck IV // *** encoder and CRT controller commit 225*339a0181SAlexander von Gluck IV radeon_dpms_set(crtcID, B_DPMS_ON); 226*339a0181SAlexander von Gluck IV display_crtc_lock(crtcID, ATOM_DISABLE); 227b54c8119SAlexander von Gluck IV encoder_output_lock(false); 2286604b1b6SAlexander von Gluck IV 22900bc40adSAlexander von Gluck IV #ifdef TRACE_MODE 230245fe001SAlexander von Gluck IV // for debugging 23100bc40adSAlexander von Gluck IV debug_dp_info(); 232d92959abSAlexander von Gluck IV 23393aac98dSAlexander von Gluck IV TRACE("D1CRTC_STATUS Value: 0x%X\n", 23493aac98dSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_STATUS)); 23593aac98dSAlexander von Gluck IV TRACE("D2CRTC_STATUS Value: 0x%X\n", 23693aac98dSAlexander von Gluck IV Read32(CRT, AVIVO_D2CRTC_STATUS)); 23793aac98dSAlexander von Gluck IV TRACE("D1CRTC_CONTROL Value: 0x%X\n", 23893aac98dSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_CONTROL)); 23993aac98dSAlexander von Gluck IV TRACE("D2CRTC_CONTROL Value: 0x%X\n", 24093aac98dSAlexander von Gluck IV Read32(CRT, AVIVO_D2CRTC_CONTROL)); 241025d4eedSAlexander von Gluck IV TRACE("D1GRPH_ENABLE Value: 0x%X\n", 242025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1GRPH_ENABLE)); 243025d4eedSAlexander von Gluck IV TRACE("D2GRPH_ENABLE Value: 0x%X\n", 244025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2GRPH_ENABLE)); 245025d4eedSAlexander von Gluck IV TRACE("D1SCL_ENABLE Value: 0x%X\n", 246025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); 247025d4eedSAlexander von Gluck IV TRACE("D2SCL_ENABLE Value: 0x%X\n", 248025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); 24946af8165SAlexander von Gluck IV TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", 250025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 25146af8165SAlexander von Gluck IV TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", 252025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 25300bc40adSAlexander von Gluck IV #endif 2543be5e036SAlexander von Gluck IV 255a90ebd77SClemens Zeidler return B_OK; 256a90ebd77SClemens Zeidler } 257a90ebd77SClemens Zeidler 258a90ebd77SClemens Zeidler 259a90ebd77SClemens Zeidler status_t 260a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode* _currentMode) 261a90ebd77SClemens Zeidler { 262d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 263a90ebd77SClemens Zeidler 264192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 26500bc40adSAlexander von Gluck IV //*_currentMode = gDisplay[X]->currentMode; 266a90ebd77SClemens Zeidler return B_OK; 267a90ebd77SClemens Zeidler } 268a90ebd77SClemens Zeidler 269a90ebd77SClemens Zeidler 270a90ebd77SClemens Zeidler status_t 271a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config* config) 272a90ebd77SClemens Zeidler { 273d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 274a90ebd77SClemens Zeidler 2753be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 2763be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8*)gInfo->shared_info->frame_buffer_phys; 27751a43d0fSAlexander von Gluck IV 278a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 279a90ebd77SClemens Zeidler 280a90ebd77SClemens Zeidler return B_OK; 281a90ebd77SClemens Zeidler } 282a90ebd77SClemens Zeidler 283a90ebd77SClemens Zeidler 284a90ebd77SClemens Zeidler status_t 285a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high) 286a90ebd77SClemens Zeidler { 287d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 288e7e76b29SAlexander von Gluck IV 289a90ebd77SClemens Zeidler if (_low != NULL) { 290a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 2915f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 2925f6744a8SAlexander von Gluck IV * (uint32)mode->timing.v_total; 293a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 294e7e76b29SAlexander von Gluck IV 295d3e8b642SAlexander von Gluck IV if (low < PLL_MIN_DEFAULT) 296d3e8b642SAlexander von Gluck IV low = PLL_MIN_DEFAULT; 297d3e8b642SAlexander von Gluck IV else if (low > PLL_MAX_DEFAULT) 298a90ebd77SClemens Zeidler return B_ERROR; 299a90ebd77SClemens Zeidler 300a90ebd77SClemens Zeidler *_low = low; 301a90ebd77SClemens Zeidler } 302a90ebd77SClemens Zeidler 303a90ebd77SClemens Zeidler if (_high != NULL) 304d3e8b642SAlexander von Gluck IV *_high = PLL_MAX_DEFAULT; 305e7e76b29SAlexander von Gluck IV 306e7e76b29SAlexander von Gluck IV //*_low = 48L; 307e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 308a90ebd77SClemens Zeidler return B_OK; 309a90ebd77SClemens Zeidler } 310a90ebd77SClemens Zeidler 311a90ebd77SClemens Zeidler 312192781ddSAlexander von Gluck IV bool 313192781ddSAlexander von Gluck IV is_mode_supported(display_mode* mode) 314192781ddSAlexander von Gluck IV { 315f52ca69cSAlexander von Gluck IV bool sane = true; 316d1d65a79SAlexander von Gluck IV 3171dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 318192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 319f52ca69cSAlexander von Gluck IV sane = false; 320192781ddSAlexander von Gluck IV 32195e1d7e8SAlexander von Gluck IV // TODO: is_mode_supported on *which* display? 322d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 3231dac4469SAlexander von Gluck IV 324d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 325e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 326f4647825SAlexander von Gluck IV && gDisplay[crtid]->foundRanges) { 3271dac4469SAlexander von Gluck IV 328f52ca69cSAlexander von Gluck IV // validate horizontal frequency range 329d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 330f4647825SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreqMax + 1 331f4647825SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreqMin - 1) { 332f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of hfreq range!\n"); 333f52ca69cSAlexander von Gluck IV sane = false; 334d1d65a79SAlexander von Gluck IV } 335d1d65a79SAlexander von Gluck IV 336f52ca69cSAlexander von Gluck IV // validate vertical frequency range 337d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 338d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 339f4647825SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreqMax + 1 340f4647825SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreqMin - 1) { 341f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of vfreq range!\n"); 342f52ca69cSAlexander von Gluck IV sane = false; 343d1d65a79SAlexander von Gluck IV } 344e1b9d6e6SAlexander von Gluck IV } 345e1b9d6e6SAlexander von Gluck IV 346142345a5SAlexander von Gluck IV #if 0 347142345a5SAlexander von Gluck IV // Lots of spam, but good for understanding what modelines are in use 348f52ca69cSAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d is %s\n", 349f52ca69cSAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 350f52ca69cSAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 351f52ca69cSAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 352f52ca69cSAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 353f52ca69cSAlexander von Gluck IV mode->timing.v_total, 354f52ca69cSAlexander von Gluck IV sane ? "OK." : "BAD, out of range!"); 355142345a5SAlexander von Gluck IV #endif 356192781ddSAlexander von Gluck IV 357f52ca69cSAlexander von Gluck IV return sane; 358192781ddSAlexander von Gluck IV } 359192781ddSAlexander von Gluck IV 360192781ddSAlexander von Gluck IV 361d5c3acacSAlexander von Gluck IV /* 362d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 363d5c3acacSAlexander von Gluck IV */ 364d5c3acacSAlexander von Gluck IV status_t 365192781ddSAlexander von Gluck IV is_mode_sane(display_mode* mode) 366d5c3acacSAlexander von Gluck IV { 367333bd770SAlexander von Gluck IV // horizontal timing 368333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 369333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 37091235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 37191235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 372333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 373333bd770SAlexander von Gluck IV return B_ERROR; 374333bd770SAlexander von Gluck IV } 375333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 376333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 37791235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 37891235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 379333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 380d5c3acacSAlexander von Gluck IV return B_ERROR; 381d5c3acacSAlexander von Gluck IV } 382d5c3acacSAlexander von Gluck IV 383333bd770SAlexander von Gluck IV // vertical timing 384333bd770SAlexander von Gluck IV // validate v_start is less then v_end 385333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 38691235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 38791235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\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 } 391333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 392333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 39391235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 39491235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 395333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 396d5c3acacSAlexander von Gluck IV return B_ERROR; 397d5c3acacSAlexander von Gluck IV } 398d5c3acacSAlexander von Gluck IV 39991235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 40091235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 40191235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 40291235829SAlexander von Gluck IV 40391235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 40491235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 40591235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 40691235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 40791235829SAlexander von Gluck IV return B_ERROR; 40891235829SAlexander von Gluck IV } 40991235829SAlexander von Gluck IV 410d5c3acacSAlexander von Gluck IV return B_OK; 411d5c3acacSAlexander von Gluck IV } 412d5c3acacSAlexander von Gluck IV 413d1d65a79SAlexander von Gluck IV 41409aaa658SAlexander von Gluck IV uint32 41509aaa658SAlexander von Gluck IV get_mode_bpp(display_mode* mode) 41609aaa658SAlexander von Gluck IV { 41709aaa658SAlexander von Gluck IV // Get bitsPerPixel for given mode 41809aaa658SAlexander von Gluck IV 41909aaa658SAlexander von Gluck IV switch (mode->space) { 42009aaa658SAlexander von Gluck IV case B_CMAP8: 42109aaa658SAlexander von Gluck IV return 8; 42209aaa658SAlexander von Gluck IV case B_RGB15_LITTLE: 42309aaa658SAlexander von Gluck IV return 15; 42409aaa658SAlexander von Gluck IV case B_RGB16_LITTLE: 42509aaa658SAlexander von Gluck IV return 16; 42609aaa658SAlexander von Gluck IV case B_RGB24_LITTLE: 42709aaa658SAlexander von Gluck IV case B_RGB32_LITTLE: 42809aaa658SAlexander von Gluck IV return 32; 42909aaa658SAlexander von Gluck IV } 43009aaa658SAlexander von Gluck IV ERROR("%s: Unknown colorspace for mode, guessing 32 bits per pixel\n", 43109aaa658SAlexander von Gluck IV __func__); 43209aaa658SAlexander von Gluck IV return 32; 43309aaa658SAlexander von Gluck IV } 434