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 42*d2a69507SAlexander 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 47f35af704SAlexander von Gluck IV 48192781ddSAlexander von Gluck IV const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 49192781ddSAlexander von Gluck IV B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 50a90ebd77SClemens Zeidler 51192781ddSAlexander von Gluck IV gInfo->mode_list_area = create_display_modes("radeon HD modes", 522613175eSAlexander von Gluck IV gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL, 532613175eSAlexander von Gluck IV 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__); 72a90ebd77SClemens Zeidler 73a90ebd77SClemens Zeidler return gInfo->shared_info->mode_count; 74a90ebd77SClemens Zeidler } 75a90ebd77SClemens Zeidler 76a90ebd77SClemens Zeidler 77a90ebd77SClemens Zeidler status_t 78a90ebd77SClemens Zeidler radeon_get_mode_list(display_mode* modeList) 79a90ebd77SClemens Zeidler { 80333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 81a90ebd77SClemens Zeidler memcpy(modeList, gInfo->mode_list, 82a90ebd77SClemens Zeidler gInfo->shared_info->mode_count * sizeof(display_mode)); 83a90ebd77SClemens Zeidler return B_OK; 84a90ebd77SClemens Zeidler } 85a90ebd77SClemens Zeidler 86a90ebd77SClemens Zeidler 8788bfef92SAlexander von Gluck IV status_t 8888bfef92SAlexander von Gluck IV radeon_get_edid_info(void* info, size_t size, uint32* edid_version) 8988bfef92SAlexander von Gluck IV { 9007a90a63SAlexander von Gluck IV // TODO: multi-monitor? for now we use VESA edid 91f35af704SAlexander von Gluck IV 9288bfef92SAlexander von Gluck IV TRACE("%s\n", __func__); 9388bfef92SAlexander von Gluck IV if (!gInfo->shared_info->has_edid) 9488bfef92SAlexander von Gluck IV return B_ERROR; 9588bfef92SAlexander von Gluck IV if (size < sizeof(struct edid1_info)) 9688bfef92SAlexander von Gluck IV return B_BUFFER_OVERFLOW; 9788bfef92SAlexander von Gluck IV 9888bfef92SAlexander von Gluck IV memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 9907a90a63SAlexander von Gluck IV // VESA 10007a90a63SAlexander von Gluck IV //memcpy(info, &gDisplay[0]->edid_info, sizeof(struct edid1_info)); 10107a90a63SAlexander von Gluck IV // BitBanged display 0 10207a90a63SAlexander von Gluck IV 10388bfef92SAlexander von Gluck IV *edid_version = EDID_VERSION_1; 10488bfef92SAlexander von Gluck IV 10588bfef92SAlexander von Gluck IV return B_OK; 10688bfef92SAlexander von Gluck IV } 10788bfef92SAlexander von Gluck IV 10888bfef92SAlexander von Gluck IV 1097934da0fSAlexander von Gluck IV uint32 1107934da0fSAlexander von Gluck IV radeon_dpms_capabilities(void) 1117934da0fSAlexander von Gluck IV { 1127934da0fSAlexander von Gluck IV // These should be pretty universally supported on Radeon HD cards 1137934da0fSAlexander von Gluck IV return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; 1147934da0fSAlexander von Gluck IV } 1157934da0fSAlexander von Gluck IV 1167934da0fSAlexander von Gluck IV 1177934da0fSAlexander von Gluck IV uint32 1187934da0fSAlexander von Gluck IV radeon_dpms_mode(void) 1197934da0fSAlexander von Gluck IV { 1207934da0fSAlexander von Gluck IV // TODO: this really isn't a good long-term solution 1217934da0fSAlexander von Gluck IV // we may need to look at the encoder dpms scratch registers 1227934da0fSAlexander von Gluck IV return gInfo->dpms_mode; 1237934da0fSAlexander von Gluck IV } 1247934da0fSAlexander von Gluck IV 1257934da0fSAlexander von Gluck IV 126b54c8119SAlexander von Gluck IV void 127b54c8119SAlexander von Gluck IV radeon_dpms_set(int mode) 128b54c8119SAlexander von Gluck IV { 129f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 130f089aa52SAlexander von Gluck IV 131b54c8119SAlexander von Gluck IV switch (mode) { 132b54c8119SAlexander von Gluck IV case B_DPMS_ON: 133936aec74SAlexander von Gluck IV TRACE("%s: ON\n", __func__); 134b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 135b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 136b54c8119SAlexander von Gluck IV continue; 1377dde214bSAlexander von Gluck IV encoder_output_lock(true); 1384e9e0295SAlexander von Gluck IV encoder_dpms_set(id, mode); 1397dde214bSAlexander von Gluck IV encoder_output_lock(false); 140936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 141b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 142f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 143b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 1446c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 145936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 146b54c8119SAlexander von Gluck IV } 147b54c8119SAlexander von Gluck IV break; 148b54c8119SAlexander von Gluck IV case B_DPMS_STAND_BY: 149b54c8119SAlexander von Gluck IV case B_DPMS_SUSPEND: 150b54c8119SAlexander von Gluck IV case B_DPMS_OFF: 151936aec74SAlexander von Gluck IV TRACE("%s: OFF\n", __func__); 152b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 153b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 154b54c8119SAlexander von Gluck IV continue; 155936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1566c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 157f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 158b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 159b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 160936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 1617dde214bSAlexander von Gluck IV encoder_output_lock(true); 1624e9e0295SAlexander von Gluck IV encoder_dpms_set(id, mode); 1637dde214bSAlexander von Gluck IV encoder_output_lock(false); 164b54c8119SAlexander von Gluck IV } 165b54c8119SAlexander von Gluck IV break; 166b54c8119SAlexander von Gluck IV } 1677934da0fSAlexander von Gluck IV gInfo->dpms_mode = mode; 168b54c8119SAlexander von Gluck IV } 169b54c8119SAlexander von Gluck IV 170b54c8119SAlexander von Gluck IV 171a90ebd77SClemens Zeidler status_t 172a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode* mode) 173a90ebd77SClemens Zeidler { 174f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 175f089aa52SAlexander von Gluck IV 1766ab8261bSAlexander von Gluck IV // Set mode on each display 1776ab8261bSAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 178b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 1796ab8261bSAlexander von Gluck IV continue; 180f2fe29a0SAlexander von Gluck IV 1816b0b621bSAlexander von Gluck IV uint16 connectorIndex = gDisplay[id]->connectorIndex; 18217b66d82SAlexander von Gluck IV 18309aaa658SAlexander von Gluck IV // Determine DP lanes if DP 18409aaa658SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) 18509aaa658SAlexander von Gluck IV gDPInfo[connectorIndex]->laneCount 18609aaa658SAlexander von Gluck IV = dp_get_lane_count(connectorIndex, mode); 18709aaa658SAlexander von Gluck IV 188b54c8119SAlexander von Gluck IV // *** encoder prep 189b54c8119SAlexander von Gluck IV encoder_output_lock(true); 19045e71a9eSAlexander von Gluck IV encoder_dpms_set(id, B_DPMS_OFF); 19117b66d82SAlexander von Gluck IV encoder_assign_crtc(id); 192e53d6375SAlexander von Gluck IV 193b54c8119SAlexander von Gluck IV // *** CRT controler prep 194b54c8119SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1956c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 196f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 197936aec74SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 198936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 199f35af704SAlexander von Gluck IV 200b54c8119SAlexander von Gluck IV // *** CRT controler mode set 20117b66d82SAlexander von Gluck IV // TODO: program SS 202e7d0abaeSAlexander von Gluck IV pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id); 203e7d0abaeSAlexander von Gluck IV // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so 2046da3f7d4SAlexander von Gluck IV display_crtc_set_dtd(id, mode); 205b54c8119SAlexander von Gluck IV 206afbd52f1SAlexander von Gluck IV display_crtc_fb_set(id, mode); 207b54c8119SAlexander von Gluck IV // atombios_overscan_setup 2086da3f7d4SAlexander von Gluck IV display_crtc_scale(id, mode); 2096ab8261bSAlexander von Gluck IV 210b54c8119SAlexander von Gluck IV // *** encoder mode set 211b54c8119SAlexander von Gluck IV encoder_mode_set(id, mode->timing.pixel_clock); 212b54c8119SAlexander von Gluck IV 213b54c8119SAlexander von Gluck IV // *** CRT controler commit 214936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 215f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 216245fe001SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 2176c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 2186da3f7d4SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 219b54c8119SAlexander von Gluck IV 220b54c8119SAlexander von Gluck IV // *** encoder commit 221c8677fb1SAlexander von Gluck IV 222c8677fb1SAlexander von Gluck IV // handle DisplayPort link training 223c8677fb1SAlexander von Gluck IV if (connector_is_dp(connectorIndex)) { 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_OFF, 0); 227c8677fb1SAlexander von Gluck IV 228c8677fb1SAlexander von Gluck IV dp_link_train(id, mode); 229c8677fb1SAlexander von Gluck IV 230c8677fb1SAlexander von Gluck IV if (info.dceMajor >= 4) 231c8677fb1SAlexander von Gluck IV encoder_dig_setup(connectorIndex, 232c8677fb1SAlexander von Gluck IV ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 233c8677fb1SAlexander von Gluck IV } 234c8677fb1SAlexander von Gluck IV 23545e71a9eSAlexander von Gluck IV encoder_dpms_set(id, B_DPMS_ON); 236b54c8119SAlexander von Gluck IV encoder_output_lock(false); 2376ab8261bSAlexander von Gluck IV } 2386604b1b6SAlexander von Gluck IV 239245fe001SAlexander von Gluck IV // for debugging 240245fe001SAlexander von Gluck IV TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, D1CRTC_STATUS)); 241245fe001SAlexander von Gluck IV TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, D2CRTC_STATUS)); 242245fe001SAlexander von Gluck IV TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D1CRTC_CONTROL)); 243245fe001SAlexander von Gluck IV TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D2CRTC_CONTROL)); 244025d4eedSAlexander von Gluck IV TRACE("D1GRPH_ENABLE Value: 0x%X\n", 245025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1GRPH_ENABLE)); 246025d4eedSAlexander von Gluck IV TRACE("D2GRPH_ENABLE Value: 0x%X\n", 247025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2GRPH_ENABLE)); 248025d4eedSAlexander von Gluck IV TRACE("D1SCL_ENABLE Value: 0x%X\n", 249025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); 250025d4eedSAlexander von Gluck IV TRACE("D2SCL_ENABLE Value: 0x%X\n", 251025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); 25246af8165SAlexander von Gluck IV TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", 253025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 25446af8165SAlexander von Gluck IV TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", 255025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 2563be5e036SAlexander von Gluck IV 257a90ebd77SClemens Zeidler return B_OK; 258a90ebd77SClemens Zeidler } 259a90ebd77SClemens Zeidler 260a90ebd77SClemens Zeidler 261a90ebd77SClemens Zeidler status_t 262a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode* _currentMode) 263a90ebd77SClemens Zeidler { 264d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 265a90ebd77SClemens Zeidler 266192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 267a90ebd77SClemens Zeidler return B_OK; 268a90ebd77SClemens Zeidler } 269a90ebd77SClemens Zeidler 270a90ebd77SClemens Zeidler 271a90ebd77SClemens Zeidler status_t 272a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config* config) 273a90ebd77SClemens Zeidler { 274d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 275a90ebd77SClemens Zeidler 2763be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 2773be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8*)gInfo->shared_info->frame_buffer_phys; 27851a43d0fSAlexander von Gluck IV 279a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 280a90ebd77SClemens Zeidler 281a90ebd77SClemens Zeidler return B_OK; 282a90ebd77SClemens Zeidler } 283a90ebd77SClemens Zeidler 284a90ebd77SClemens Zeidler 285a90ebd77SClemens Zeidler status_t 286a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high) 287a90ebd77SClemens Zeidler { 288d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 289e7e76b29SAlexander von Gluck IV 290a90ebd77SClemens Zeidler if (_low != NULL) { 291a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 2925f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 2935f6744a8SAlexander von Gluck IV * (uint32)mode->timing.v_total; 294a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 295e7e76b29SAlexander von Gluck IV 296d3e8b642SAlexander von Gluck IV if (low < PLL_MIN_DEFAULT) 297d3e8b642SAlexander von Gluck IV low = PLL_MIN_DEFAULT; 298d3e8b642SAlexander von Gluck IV else if (low > PLL_MAX_DEFAULT) 299a90ebd77SClemens Zeidler return B_ERROR; 300a90ebd77SClemens Zeidler 301a90ebd77SClemens Zeidler *_low = low; 302a90ebd77SClemens Zeidler } 303a90ebd77SClemens Zeidler 304a90ebd77SClemens Zeidler if (_high != NULL) 305d3e8b642SAlexander von Gluck IV *_high = PLL_MAX_DEFAULT; 306e7e76b29SAlexander von Gluck IV 307e7e76b29SAlexander von Gluck IV //*_low = 48L; 308e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 309a90ebd77SClemens Zeidler return B_OK; 310a90ebd77SClemens Zeidler } 311a90ebd77SClemens Zeidler 312a90ebd77SClemens Zeidler 313192781ddSAlexander von Gluck IV bool 314192781ddSAlexander von Gluck IV is_mode_supported(display_mode* mode) 315192781ddSAlexander von Gluck IV { 316f52ca69cSAlexander von Gluck IV bool sane = true; 317d1d65a79SAlexander von Gluck IV 3181dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 319192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 320f52ca69cSAlexander von Gluck IV sane = false; 321192781ddSAlexander von Gluck IV 32295e1d7e8SAlexander von Gluck IV // TODO: is_mode_supported on *which* display? 323d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 3241dac4469SAlexander von Gluck IV 325d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 326e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 327e1b9d6e6SAlexander von Gluck IV && gDisplay[crtid]->found_ranges) { 3281dac4469SAlexander von Gluck IV 329f52ca69cSAlexander von Gluck IV // validate horizontal frequency range 330d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 33195e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 33295e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 333f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of hfreq range!\n"); 334f52ca69cSAlexander von Gluck IV sane = false; 335d1d65a79SAlexander von Gluck IV } 336d1d65a79SAlexander von Gluck IV 337f52ca69cSAlexander von Gluck IV // validate vertical frequency range 338d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 339d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 34095e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 34195e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 342f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of vfreq range!\n"); 343f52ca69cSAlexander von Gluck IV sane = false; 344d1d65a79SAlexander von Gluck IV } 345e1b9d6e6SAlexander von Gluck IV } 346e1b9d6e6SAlexander von Gluck IV 347f52ca69cSAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d is %s\n", 348f52ca69cSAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 349f52ca69cSAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 350f52ca69cSAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 351f52ca69cSAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 352f52ca69cSAlexander von Gluck IV mode->timing.v_total, 353f52ca69cSAlexander von Gluck IV sane ? "OK." : "BAD, out of range!"); 354192781ddSAlexander von Gluck IV 355f52ca69cSAlexander von Gluck IV return sane; 356192781ddSAlexander von Gluck IV } 357192781ddSAlexander von Gluck IV 358192781ddSAlexander von Gluck IV 359d5c3acacSAlexander von Gluck IV /* 360d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 361d5c3acacSAlexander von Gluck IV */ 362d5c3acacSAlexander von Gluck IV status_t 363192781ddSAlexander von Gluck IV is_mode_sane(display_mode* mode) 364d5c3acacSAlexander von Gluck IV { 365333bd770SAlexander von Gluck IV // horizontal timing 366333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 367333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 36891235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 36991235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 370333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 371333bd770SAlexander von Gluck IV return B_ERROR; 372333bd770SAlexander von Gluck IV } 373333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 374333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 37591235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 37691235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 377333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 378d5c3acacSAlexander von Gluck IV return B_ERROR; 379d5c3acacSAlexander von Gluck IV } 380d5c3acacSAlexander von Gluck IV 381333bd770SAlexander von Gluck IV // vertical timing 382333bd770SAlexander von Gluck IV // validate v_start is less then v_end 383333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 38491235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 38591235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\n", 386333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 387d5c3acacSAlexander von Gluck IV return B_ERROR; 388d5c3acacSAlexander von Gluck IV } 389333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 390333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 39191235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 39291235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 393333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 394d5c3acacSAlexander von Gluck IV return B_ERROR; 395d5c3acacSAlexander von Gluck IV } 396d5c3acacSAlexander von Gluck IV 39791235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 39891235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 39991235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 40091235829SAlexander von Gluck IV 40191235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 40291235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 40391235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 40491235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 40591235829SAlexander von Gluck IV return B_ERROR; 40691235829SAlexander von Gluck IV } 40791235829SAlexander von Gluck IV 408d5c3acacSAlexander von Gluck IV return B_OK; 409d5c3acacSAlexander von Gluck IV } 410d5c3acacSAlexander von Gluck IV 411d1d65a79SAlexander von Gluck IV 41209aaa658SAlexander von Gluck IV uint32 41309aaa658SAlexander von Gluck IV get_mode_bpp(display_mode* mode) 41409aaa658SAlexander von Gluck IV { 41509aaa658SAlexander von Gluck IV // Get bitsPerPixel for given mode 41609aaa658SAlexander von Gluck IV 41709aaa658SAlexander von Gluck IV switch (mode->space) { 41809aaa658SAlexander von Gluck IV case B_CMAP8: 41909aaa658SAlexander von Gluck IV return 8; 42009aaa658SAlexander von Gluck IV case B_RGB15_LITTLE: 42109aaa658SAlexander von Gluck IV return 15; 42209aaa658SAlexander von Gluck IV case B_RGB16_LITTLE: 42309aaa658SAlexander von Gluck IV return 16; 42409aaa658SAlexander von Gluck IV case B_RGB24_LITTLE: 42509aaa658SAlexander von Gluck IV case B_RGB32_LITTLE: 42609aaa658SAlexander von Gluck IV return 32; 42709aaa658SAlexander von Gluck IV } 42809aaa658SAlexander von Gluck IV ERROR("%s: Unknown colorspace for mode, guessing 32 bits per pixel\n", 42909aaa658SAlexander von Gluck IV __func__); 43009aaa658SAlexander von Gluck IV return 32; 43109aaa658SAlexander von Gluck IV } 432