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 40*09aaa658SAlexander 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; 136936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 137b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 138f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 139b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 1406c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 141936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 142b54c8119SAlexander von Gluck IV } 143b54c8119SAlexander von Gluck IV break; 144b54c8119SAlexander von Gluck IV case B_DPMS_STAND_BY: 145b54c8119SAlexander von Gluck IV case B_DPMS_SUSPEND: 146b54c8119SAlexander von Gluck IV case B_DPMS_OFF: 147936aec74SAlexander von Gluck IV TRACE("%s: OFF\n", __func__); 148b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 149b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 150b54c8119SAlexander von Gluck IV continue; 151936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1526c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 153f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 154b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 155b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 156936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 157b54c8119SAlexander von Gluck IV } 158b54c8119SAlexander von Gluck IV break; 159b54c8119SAlexander von Gluck IV } 1607934da0fSAlexander von Gluck IV gInfo->dpms_mode = mode; 161b54c8119SAlexander von Gluck IV } 162b54c8119SAlexander von Gluck IV 163b54c8119SAlexander von Gluck IV 164a90ebd77SClemens Zeidler status_t 165a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode* mode) 166a90ebd77SClemens Zeidler { 167f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 168f089aa52SAlexander von Gluck IV 1696ab8261bSAlexander von Gluck IV // Set mode on each display 1706ab8261bSAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 171b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 1726ab8261bSAlexander von Gluck IV continue; 173f2fe29a0SAlexander von Gluck IV 1746b0b621bSAlexander von Gluck IV uint16 connectorIndex = gDisplay[id]->connectorIndex; 17517b66d82SAlexander von Gluck IV 176*09aaa658SAlexander von Gluck IV // Determine DP lanes if DP 177*09aaa658SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) 178*09aaa658SAlexander von Gluck IV gDPInfo[connectorIndex]->laneCount 179*09aaa658SAlexander von Gluck IV = dp_get_lane_count(connectorIndex, mode); 180*09aaa658SAlexander von Gluck IV 181b54c8119SAlexander von Gluck IV // *** encoder prep 182b54c8119SAlexander von Gluck IV encoder_output_lock(true); 183e774cb4bSAlexander von Gluck IV encoder_dpms_set(id, gConnector[connectorIndex]->encoder.objectID, 184ffb494caSAlexander von Gluck IV B_DPMS_OFF); 18517b66d82SAlexander von Gluck IV encoder_assign_crtc(id); 186e53d6375SAlexander von Gluck IV 187b54c8119SAlexander von Gluck IV // *** CRT controler prep 188b54c8119SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1896c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 190f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 191936aec74SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 192936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 193f35af704SAlexander von Gluck IV 194b54c8119SAlexander von Gluck IV // *** CRT controler mode set 19517b66d82SAlexander von Gluck IV // TODO: program SS 196e7d0abaeSAlexander von Gluck IV pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id); 197e7d0abaeSAlexander von Gluck IV // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so 1986da3f7d4SAlexander von Gluck IV display_crtc_set_dtd(id, mode); 199b54c8119SAlexander von Gluck IV 200afbd52f1SAlexander von Gluck IV display_crtc_fb_set(id, mode); 201b54c8119SAlexander von Gluck IV // atombios_overscan_setup 2026da3f7d4SAlexander von Gluck IV display_crtc_scale(id, mode); 2036ab8261bSAlexander von Gluck IV 204b54c8119SAlexander von Gluck IV // *** encoder mode set 205b54c8119SAlexander von Gluck IV encoder_mode_set(id, mode->timing.pixel_clock); 206b54c8119SAlexander von Gluck IV 207b54c8119SAlexander von Gluck IV // *** CRT controler commit 208936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 209f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 210245fe001SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 2116c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 2126da3f7d4SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 213b54c8119SAlexander von Gluck IV 214b54c8119SAlexander von Gluck IV // *** encoder commit 215c8677fb1SAlexander von Gluck IV 216c8677fb1SAlexander von Gluck IV // handle DisplayPort link training 217c8677fb1SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) { 218c8677fb1SAlexander von Gluck IV if (info.dceMajor >= 4) 219c8677fb1SAlexander von Gluck IV encoder_dig_setup(connectorIndex, 220c8677fb1SAlexander von Gluck IV ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 221c8677fb1SAlexander von Gluck IV 222c8677fb1SAlexander von Gluck IV dp_link_train(id, mode); 223c8677fb1SAlexander von Gluck IV 224c8677fb1SAlexander von Gluck IV if (info.dceMajor >= 4) 225c8677fb1SAlexander von Gluck IV encoder_dig_setup(connectorIndex, 226c8677fb1SAlexander von Gluck IV ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 227c8677fb1SAlexander von Gluck IV } 228c8677fb1SAlexander von Gluck IV 229e774cb4bSAlexander von Gluck IV encoder_dpms_set(id, gConnector[connectorIndex]->encoder.objectID, 230ffb494caSAlexander von Gluck IV B_DPMS_ON); 231c8677fb1SAlexander von Gluck IV 232b54c8119SAlexander von Gluck IV encoder_output_lock(false); 2336ab8261bSAlexander von Gluck IV } 2346604b1b6SAlexander von Gluck IV 235245fe001SAlexander von Gluck IV // for debugging 236245fe001SAlexander von Gluck IV TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, D1CRTC_STATUS)); 237245fe001SAlexander von Gluck IV TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, D2CRTC_STATUS)); 238245fe001SAlexander von Gluck IV TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D1CRTC_CONTROL)); 239245fe001SAlexander von Gluck IV TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D2CRTC_CONTROL)); 240025d4eedSAlexander von Gluck IV TRACE("D1GRPH_ENABLE Value: 0x%X\n", 241025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1GRPH_ENABLE)); 242025d4eedSAlexander von Gluck IV TRACE("D2GRPH_ENABLE Value: 0x%X\n", 243025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2GRPH_ENABLE)); 244025d4eedSAlexander von Gluck IV TRACE("D1SCL_ENABLE Value: 0x%X\n", 245025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); 246025d4eedSAlexander von Gluck IV TRACE("D2SCL_ENABLE Value: 0x%X\n", 247025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); 24846af8165SAlexander von Gluck IV TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", 249025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 25046af8165SAlexander von Gluck IV TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", 251025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 2523be5e036SAlexander von Gluck IV 253a90ebd77SClemens Zeidler return B_OK; 254a90ebd77SClemens Zeidler } 255a90ebd77SClemens Zeidler 256a90ebd77SClemens Zeidler 257a90ebd77SClemens Zeidler status_t 258a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode* _currentMode) 259a90ebd77SClemens Zeidler { 260d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 261a90ebd77SClemens Zeidler 262192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 263a90ebd77SClemens Zeidler return B_OK; 264a90ebd77SClemens Zeidler } 265a90ebd77SClemens Zeidler 266a90ebd77SClemens Zeidler 267a90ebd77SClemens Zeidler status_t 268a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config* config) 269a90ebd77SClemens Zeidler { 270d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 271a90ebd77SClemens Zeidler 2723be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 2733be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8*)gInfo->shared_info->frame_buffer_phys; 27451a43d0fSAlexander von Gluck IV 275a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 276a90ebd77SClemens Zeidler 277a90ebd77SClemens Zeidler return B_OK; 278a90ebd77SClemens Zeidler } 279a90ebd77SClemens Zeidler 280a90ebd77SClemens Zeidler 281a90ebd77SClemens Zeidler status_t 282a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high) 283a90ebd77SClemens Zeidler { 284d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 285e7e76b29SAlexander von Gluck IV 286a90ebd77SClemens Zeidler if (_low != NULL) { 287a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 2885f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 2895f6744a8SAlexander von Gluck IV * (uint32)mode->timing.v_total; 290a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 291e7e76b29SAlexander von Gluck IV 292d3e8b642SAlexander von Gluck IV if (low < PLL_MIN_DEFAULT) 293d3e8b642SAlexander von Gluck IV low = PLL_MIN_DEFAULT; 294d3e8b642SAlexander von Gluck IV else if (low > PLL_MAX_DEFAULT) 295a90ebd77SClemens Zeidler return B_ERROR; 296a90ebd77SClemens Zeidler 297a90ebd77SClemens Zeidler *_low = low; 298a90ebd77SClemens Zeidler } 299a90ebd77SClemens Zeidler 300a90ebd77SClemens Zeidler if (_high != NULL) 301d3e8b642SAlexander von Gluck IV *_high = PLL_MAX_DEFAULT; 302e7e76b29SAlexander von Gluck IV 303e7e76b29SAlexander von Gluck IV //*_low = 48L; 304e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 305a90ebd77SClemens Zeidler return B_OK; 306a90ebd77SClemens Zeidler } 307a90ebd77SClemens Zeidler 308a90ebd77SClemens Zeidler 309192781ddSAlexander von Gluck IV bool 310192781ddSAlexander von Gluck IV is_mode_supported(display_mode* mode) 311192781ddSAlexander von Gluck IV { 312f52ca69cSAlexander von Gluck IV bool sane = true; 313d1d65a79SAlexander von Gluck IV 3141dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 315192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 316f52ca69cSAlexander von Gluck IV sane = false; 317192781ddSAlexander von Gluck IV 31895e1d7e8SAlexander von Gluck IV // TODO: is_mode_supported on *which* display? 319d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 3201dac4469SAlexander von Gluck IV 321d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 322e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 323e1b9d6e6SAlexander von Gluck IV && gDisplay[crtid]->found_ranges) { 3241dac4469SAlexander von Gluck IV 325f52ca69cSAlexander von Gluck IV // validate horizontal frequency range 326d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 32795e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 32895e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 329f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of hfreq range!\n"); 330f52ca69cSAlexander von Gluck IV sane = false; 331d1d65a79SAlexander von Gluck IV } 332d1d65a79SAlexander von Gluck IV 333f52ca69cSAlexander von Gluck IV // validate vertical frequency range 334d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 335d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 33695e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 33795e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 338f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of vfreq range!\n"); 339f52ca69cSAlexander von Gluck IV sane = false; 340d1d65a79SAlexander von Gluck IV } 341e1b9d6e6SAlexander von Gluck IV } 342e1b9d6e6SAlexander von Gluck IV 343f52ca69cSAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d is %s\n", 344f52ca69cSAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 345f52ca69cSAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 346f52ca69cSAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 347f52ca69cSAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 348f52ca69cSAlexander von Gluck IV mode->timing.v_total, 349f52ca69cSAlexander von Gluck IV sane ? "OK." : "BAD, out of range!"); 350192781ddSAlexander von Gluck IV 351f52ca69cSAlexander von Gluck IV return sane; 352192781ddSAlexander von Gluck IV } 353192781ddSAlexander von Gluck IV 354192781ddSAlexander von Gluck IV 355d5c3acacSAlexander von Gluck IV /* 356d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 357d5c3acacSAlexander von Gluck IV */ 358d5c3acacSAlexander von Gluck IV status_t 359192781ddSAlexander von Gluck IV is_mode_sane(display_mode* mode) 360d5c3acacSAlexander von Gluck IV { 361333bd770SAlexander von Gluck IV // horizontal timing 362333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 363333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 36491235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 36591235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 366333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 367333bd770SAlexander von Gluck IV return B_ERROR; 368333bd770SAlexander von Gluck IV } 369333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 370333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 37191235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 37291235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 373333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 374d5c3acacSAlexander von Gluck IV return B_ERROR; 375d5c3acacSAlexander von Gluck IV } 376d5c3acacSAlexander von Gluck IV 377333bd770SAlexander von Gluck IV // vertical timing 378333bd770SAlexander von Gluck IV // validate v_start is less then v_end 379333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 38091235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 38191235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\n", 382333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 383d5c3acacSAlexander von Gluck IV return B_ERROR; 384d5c3acacSAlexander von Gluck IV } 385333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 386333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 38791235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 38891235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 389333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 390d5c3acacSAlexander von Gluck IV return B_ERROR; 391d5c3acacSAlexander von Gluck IV } 392d5c3acacSAlexander von Gluck IV 39391235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 39491235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 39591235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 39691235829SAlexander von Gluck IV 39791235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 39891235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 39991235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 40091235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 40191235829SAlexander von Gluck IV return B_ERROR; 40291235829SAlexander von Gluck IV } 40391235829SAlexander von Gluck IV 404d5c3acacSAlexander von Gluck IV return B_OK; 405d5c3acacSAlexander von Gluck IV } 406d5c3acacSAlexander von Gluck IV 407d1d65a79SAlexander von Gluck IV 408*09aaa658SAlexander von Gluck IV uint32 409*09aaa658SAlexander von Gluck IV get_mode_bpp(display_mode* mode) 410*09aaa658SAlexander von Gluck IV { 411*09aaa658SAlexander von Gluck IV // Get bitsPerPixel for given mode 412*09aaa658SAlexander von Gluck IV 413*09aaa658SAlexander von Gluck IV switch (mode->space) { 414*09aaa658SAlexander von Gluck IV case B_CMAP8: 415*09aaa658SAlexander von Gluck IV return 8; 416*09aaa658SAlexander von Gluck IV case B_RGB15_LITTLE: 417*09aaa658SAlexander von Gluck IV return 15; 418*09aaa658SAlexander von Gluck IV case B_RGB16_LITTLE: 419*09aaa658SAlexander von Gluck IV return 16; 420*09aaa658SAlexander von Gluck IV case B_RGB24_LITTLE: 421*09aaa658SAlexander von Gluck IV case B_RGB32_LITTLE: 422*09aaa658SAlexander von Gluck IV return 32; 423*09aaa658SAlexander von Gluck IV } 424*09aaa658SAlexander von Gluck IV ERROR("%s: Unknown colorspace for mode, guessing 32 bits per pixel\n", 425*09aaa658SAlexander von Gluck IV __func__); 426*09aaa658SAlexander von Gluck IV return 32; 427*09aaa658SAlexander von Gluck IV } 428