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 14a90ebd77SClemens Zeidler #include "accelerant_protos.h" 15a90ebd77SClemens Zeidler #include "accelerant.h" 16d77ff85eSAlexander von Gluck IV #include "bios.h" 17a90ebd77SClemens Zeidler #include "utility.h" 18d5c3acacSAlexander von Gluck IV #include "mode.h" 196ab8261bSAlexander von Gluck IV #include "display.h" 20d3e8b642SAlexander von Gluck IV #include "pll.h" 21a90ebd77SClemens Zeidler 22a90ebd77SClemens Zeidler #include <stdio.h> 23a90ebd77SClemens Zeidler #include <string.h> 24a90ebd77SClemens Zeidler #include <math.h> 25a90ebd77SClemens Zeidler 26192781ddSAlexander von Gluck IV #include <create_display_modes.h> 27192781ddSAlexander von Gluck IV 28a90ebd77SClemens Zeidler 29a90ebd77SClemens Zeidler #define TRACE_MODE 30a90ebd77SClemens Zeidler #ifdef TRACE_MODE 31a90ebd77SClemens Zeidler extern "C" void _sPrintf(const char *format, ...); 32d5c3acacSAlexander von Gluck IV # define TRACE(x...) _sPrintf("radeon_hd: " x) 33a90ebd77SClemens Zeidler #else 34d5c3acacSAlexander von Gluck IV # define TRACE(x...) ; 35a90ebd77SClemens Zeidler #endif 36a90ebd77SClemens Zeidler 37a90ebd77SClemens Zeidler 38a90ebd77SClemens Zeidler status_t 39a90ebd77SClemens Zeidler create_mode_list(void) 40a90ebd77SClemens Zeidler { 41f35af704SAlexander von Gluck IV // TODO: multi-monitor? for now we use VESA and not gDisplay edid 42f35af704SAlexander von Gluck IV 43192781ddSAlexander von Gluck IV const color_space kRadeonHDSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 44192781ddSAlexander von Gluck IV B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 45a90ebd77SClemens Zeidler 46192781ddSAlexander von Gluck IV gInfo->mode_list_area = create_display_modes("radeon HD modes", 472613175eSAlexander von Gluck IV gInfo->shared_info->has_edid ? &gInfo->shared_info->edid_info : NULL, 482613175eSAlexander von Gluck IV NULL, 0, kRadeonHDSpaces, 49192781ddSAlexander von Gluck IV sizeof(kRadeonHDSpaces) / sizeof(kRadeonHDSpaces[0]), 50192781ddSAlexander von Gluck IV is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 51192781ddSAlexander von Gluck IV if (gInfo->mode_list_area < B_OK) 52192781ddSAlexander von Gluck IV return gInfo->mode_list_area; 53a90ebd77SClemens Zeidler 54192781ddSAlexander von Gluck IV gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 55d5c3acacSAlexander von Gluck IV 56a90ebd77SClemens Zeidler return B_OK; 57a90ebd77SClemens Zeidler } 58a90ebd77SClemens Zeidler 59a90ebd77SClemens Zeidler 60a90ebd77SClemens Zeidler // #pragma mark - 61a90ebd77SClemens Zeidler 62a90ebd77SClemens Zeidler 63a90ebd77SClemens Zeidler uint32 64a90ebd77SClemens Zeidler radeon_accelerant_mode_count(void) 65a90ebd77SClemens Zeidler { 66333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 67a90ebd77SClemens Zeidler 68a90ebd77SClemens Zeidler return gInfo->shared_info->mode_count; 69a90ebd77SClemens Zeidler } 70a90ebd77SClemens Zeidler 71a90ebd77SClemens Zeidler 72a90ebd77SClemens Zeidler status_t 73a90ebd77SClemens Zeidler radeon_get_mode_list(display_mode *modeList) 74a90ebd77SClemens Zeidler { 75333bd770SAlexander von Gluck IV TRACE("%s\n", __func__); 76a90ebd77SClemens Zeidler memcpy(modeList, gInfo->mode_list, 77a90ebd77SClemens Zeidler gInfo->shared_info->mode_count * sizeof(display_mode)); 78a90ebd77SClemens Zeidler return B_OK; 79a90ebd77SClemens Zeidler } 80a90ebd77SClemens Zeidler 81a90ebd77SClemens Zeidler 8288bfef92SAlexander von Gluck IV status_t 8388bfef92SAlexander von Gluck IV radeon_get_edid_info(void* info, size_t size, uint32* edid_version) 8488bfef92SAlexander von Gluck IV { 8507a90a63SAlexander von Gluck IV // TODO: multi-monitor? for now we use VESA edid 86f35af704SAlexander von Gluck IV 8788bfef92SAlexander von Gluck IV TRACE("%s\n", __func__); 8888bfef92SAlexander von Gluck IV if (!gInfo->shared_info->has_edid) 8988bfef92SAlexander von Gluck IV return B_ERROR; 9088bfef92SAlexander von Gluck IV if (size < sizeof(struct edid1_info)) 9188bfef92SAlexander von Gluck IV return B_BUFFER_OVERFLOW; 9288bfef92SAlexander von Gluck IV 9388bfef92SAlexander von Gluck IV memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); 9407a90a63SAlexander von Gluck IV // VESA 9507a90a63SAlexander von Gluck IV //memcpy(info, &gDisplay[0]->edid_info, sizeof(struct edid1_info)); 9607a90a63SAlexander von Gluck IV // BitBanged display 0 9707a90a63SAlexander von Gluck IV 9888bfef92SAlexander von Gluck IV *edid_version = EDID_VERSION_1; 9988bfef92SAlexander von Gluck IV 10088bfef92SAlexander von Gluck IV return B_OK; 10188bfef92SAlexander von Gluck IV } 10288bfef92SAlexander von Gluck IV 10388bfef92SAlexander von Gluck IV 1047934da0fSAlexander von Gluck IV uint32 1057934da0fSAlexander von Gluck IV radeon_dpms_capabilities(void) 1067934da0fSAlexander von Gluck IV { 1077934da0fSAlexander von Gluck IV // These should be pretty universally supported on Radeon HD cards 1087934da0fSAlexander von Gluck IV return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; 1097934da0fSAlexander von Gluck IV } 1107934da0fSAlexander von Gluck IV 1117934da0fSAlexander von Gluck IV 1127934da0fSAlexander von Gluck IV uint32 1137934da0fSAlexander von Gluck IV radeon_dpms_mode(void) 1147934da0fSAlexander von Gluck IV { 1157934da0fSAlexander von Gluck IV // TODO: this really isn't a good long-term solution 1167934da0fSAlexander von Gluck IV // we may need to look at the encoder dpms scratch registers 1177934da0fSAlexander von Gluck IV return gInfo->dpms_mode; 1187934da0fSAlexander von Gluck IV } 1197934da0fSAlexander von Gluck IV 1207934da0fSAlexander von Gluck IV 121b54c8119SAlexander von Gluck IV void 122b54c8119SAlexander von Gluck IV radeon_dpms_set(int mode) 123b54c8119SAlexander von Gluck IV { 124f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 125f089aa52SAlexander von Gluck IV 126b54c8119SAlexander von Gluck IV switch(mode) { 127b54c8119SAlexander von Gluck IV case B_DPMS_ON: 128936aec74SAlexander von Gluck IV TRACE("%s: ON\n", __func__); 129b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 130b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 131b54c8119SAlexander von Gluck IV continue; 132936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 133b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 134f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 135b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 1366c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 137936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 138b54c8119SAlexander von Gluck IV } 139b54c8119SAlexander von Gluck IV break; 140b54c8119SAlexander von Gluck IV case B_DPMS_STAND_BY: 141b54c8119SAlexander von Gluck IV case B_DPMS_SUSPEND: 142b54c8119SAlexander von Gluck IV case B_DPMS_OFF: 143936aec74SAlexander von Gluck IV TRACE("%s: OFF\n", __func__); 144b54c8119SAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 145b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 146b54c8119SAlexander von Gluck IV continue; 147936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1486c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 149f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 150b54c8119SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 151b54c8119SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 152936aec74SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 153b54c8119SAlexander von Gluck IV } 154b54c8119SAlexander von Gluck IV break; 155b54c8119SAlexander von Gluck IV } 1567934da0fSAlexander von Gluck IV gInfo->dpms_mode = mode; 157b54c8119SAlexander von Gluck IV } 158b54c8119SAlexander von Gluck IV 159b54c8119SAlexander von Gluck IV 160a90ebd77SClemens Zeidler status_t 161a90ebd77SClemens Zeidler radeon_set_display_mode(display_mode *mode) 162a90ebd77SClemens Zeidler { 163f089aa52SAlexander von Gluck IV radeon_shared_info &info = *gInfo->shared_info; 164f089aa52SAlexander von Gluck IV 1656ab8261bSAlexander von Gluck IV // Set mode on each display 1666ab8261bSAlexander von Gluck IV for (uint8 id = 0; id < MAX_DISPLAY; id++) { 167b54c8119SAlexander von Gluck IV if (gDisplay[id]->active == false) 1686ab8261bSAlexander von Gluck IV continue; 169f2fe29a0SAlexander von Gluck IV 1706b0b621bSAlexander von Gluck IV uint16 connectorIndex = gDisplay[id]->connectorIndex; 17117b66d82SAlexander von Gluck IV 172b54c8119SAlexander von Gluck IV // *** encoder prep 173b54c8119SAlexander von Gluck IV encoder_output_lock(true); 174e774cb4bSAlexander von Gluck IV encoder_dpms_set(id, gConnector[connectorIndex]->encoder.objectID, 175ffb494caSAlexander von Gluck IV B_DPMS_OFF); 17617b66d82SAlexander von Gluck IV encoder_assign_crtc(id); 177e53d6375SAlexander von Gluck IV 178b54c8119SAlexander von Gluck IV // *** CRT controler prep 179b54c8119SAlexander von Gluck IV display_crtc_lock(id, ATOM_ENABLE); 1806c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING); 181f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 182936aec74SAlexander von Gluck IV display_crtc_memreq(id, ATOM_DISABLE); 183936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_DISABLE); 184f35af704SAlexander von Gluck IV 185b54c8119SAlexander von Gluck IV // *** CRT controler mode set 18617b66d82SAlexander von Gluck IV // TODO: program SS 187e7d0abaeSAlexander von Gluck IV pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id); 188e7d0abaeSAlexander von Gluck IV // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so 1896da3f7d4SAlexander von Gluck IV display_crtc_set_dtd(id, mode); 190b54c8119SAlexander von Gluck IV 191afbd52f1SAlexander von Gluck IV display_crtc_fb_set(id, mode); 192b54c8119SAlexander von Gluck IV // atombios_overscan_setup 1936da3f7d4SAlexander von Gluck IV display_crtc_scale(id, mode); 1946ab8261bSAlexander von Gluck IV 195b54c8119SAlexander von Gluck IV // *** encoder mode set 196b54c8119SAlexander von Gluck IV encoder_mode_set(id, mode->timing.pixel_clock); 197b54c8119SAlexander von Gluck IV 198b54c8119SAlexander von Gluck IV // *** CRT controler commit 199936aec74SAlexander von Gluck IV display_crtc_power(id, ATOM_ENABLE); 200f089aa52SAlexander von Gluck IV if (info.dceMajor >= 3) 201245fe001SAlexander von Gluck IV display_crtc_memreq(id, ATOM_ENABLE); 2026c80b06bSAlexander von Gluck IV display_crtc_blank(id, ATOM_BLANKING_OFF); 2036da3f7d4SAlexander von Gluck IV display_crtc_lock(id, ATOM_DISABLE); 204b54c8119SAlexander von Gluck IV 205b54c8119SAlexander von Gluck IV // *** encoder commit 206e774cb4bSAlexander von Gluck IV encoder_dpms_set(id, gConnector[connectorIndex]->encoder.objectID, 207ffb494caSAlexander von Gluck IV B_DPMS_ON); 208b54c8119SAlexander von Gluck IV encoder_output_lock(false); 2096ab8261bSAlexander von Gluck IV } 2106604b1b6SAlexander von Gluck IV 211245fe001SAlexander von Gluck IV // for debugging 212245fe001SAlexander von Gluck IV TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, D1CRTC_STATUS)); 213245fe001SAlexander von Gluck IV TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, D2CRTC_STATUS)); 214245fe001SAlexander von Gluck IV TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D1CRTC_CONTROL)); 215245fe001SAlexander von Gluck IV TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, D2CRTC_CONTROL)); 216025d4eedSAlexander von Gluck IV TRACE("D1GRPH_ENABLE Value: 0x%X\n", 217025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1GRPH_ENABLE)); 218025d4eedSAlexander von Gluck IV TRACE("D2GRPH_ENABLE Value: 0x%X\n", 219025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2GRPH_ENABLE)); 220025d4eedSAlexander von Gluck IV TRACE("D1SCL_ENABLE Value: 0x%X\n", 221025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); 222025d4eedSAlexander von Gluck IV TRACE("D2SCL_ENABLE Value: 0x%X\n", 223025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); 22446af8165SAlexander von Gluck IV TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", 225025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 22646af8165SAlexander von Gluck IV TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", 227025d4eedSAlexander von Gluck IV Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); 2283be5e036SAlexander von Gluck IV 229a90ebd77SClemens Zeidler return B_OK; 230a90ebd77SClemens Zeidler } 231a90ebd77SClemens Zeidler 232a90ebd77SClemens Zeidler 233a90ebd77SClemens Zeidler status_t 234a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode *_currentMode) 235a90ebd77SClemens Zeidler { 236d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 237a90ebd77SClemens Zeidler 238192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 239a90ebd77SClemens Zeidler return B_OK; 240a90ebd77SClemens Zeidler } 241a90ebd77SClemens Zeidler 242a90ebd77SClemens Zeidler 243a90ebd77SClemens Zeidler status_t 244a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config *config) 245a90ebd77SClemens Zeidler { 246d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 247a90ebd77SClemens Zeidler 2483be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 2493be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8*)gInfo->shared_info->frame_buffer_phys; 25051a43d0fSAlexander von Gluck IV 251a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 252a90ebd77SClemens Zeidler 253a90ebd77SClemens Zeidler return B_OK; 254a90ebd77SClemens Zeidler } 255a90ebd77SClemens Zeidler 256a90ebd77SClemens Zeidler 257a90ebd77SClemens Zeidler status_t 258a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 259a90ebd77SClemens Zeidler { 260d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 261e7e76b29SAlexander von Gluck IV 262a90ebd77SClemens Zeidler if (_low != NULL) { 263a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 2645f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 2655f6744a8SAlexander von Gluck IV *(uint32)mode->timing.v_total; 266a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 267e7e76b29SAlexander von Gluck IV 268d3e8b642SAlexander von Gluck IV if (low < PLL_MIN_DEFAULT) 269d3e8b642SAlexander von Gluck IV low = PLL_MIN_DEFAULT; 270d3e8b642SAlexander von Gluck IV else if (low > PLL_MAX_DEFAULT) 271a90ebd77SClemens Zeidler return B_ERROR; 272a90ebd77SClemens Zeidler 273a90ebd77SClemens Zeidler *_low = low; 274a90ebd77SClemens Zeidler } 275a90ebd77SClemens Zeidler 276a90ebd77SClemens Zeidler if (_high != NULL) 277d3e8b642SAlexander von Gluck IV *_high = PLL_MAX_DEFAULT; 278e7e76b29SAlexander von Gluck IV 279e7e76b29SAlexander von Gluck IV //*_low = 48L; 280e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 281a90ebd77SClemens Zeidler return B_OK; 282a90ebd77SClemens Zeidler } 283a90ebd77SClemens Zeidler 284a90ebd77SClemens Zeidler 285192781ddSAlexander von Gluck IV bool 286192781ddSAlexander von Gluck IV is_mode_supported(display_mode *mode) 287192781ddSAlexander von Gluck IV { 288*f52ca69cSAlexander von Gluck IV bool sane = true; 289d1d65a79SAlexander von Gluck IV 2901dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 291192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 292*f52ca69cSAlexander von Gluck IV sane = false; 293192781ddSAlexander von Gluck IV 29495e1d7e8SAlexander von Gluck IV // TODO: is_mode_supported on *which* display? 295d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 2961dac4469SAlexander von Gluck IV 297d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 298e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 299e1b9d6e6SAlexander von Gluck IV && gDisplay[crtid]->found_ranges) { 3001dac4469SAlexander von Gluck IV 301*f52ca69cSAlexander von Gluck IV // validate horizontal frequency range 302d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 30395e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 30495e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 305*f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of hfreq range!\n"); 306*f52ca69cSAlexander von Gluck IV sane = false; 307d1d65a79SAlexander von Gluck IV } 308d1d65a79SAlexander von Gluck IV 309*f52ca69cSAlexander von Gluck IV // validate vertical frequency range 310d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 311d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 31295e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 31395e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 314*f52ca69cSAlexander von Gluck IV //TRACE("!!! mode below falls outside of vfreq range!\n"); 315*f52ca69cSAlexander von Gluck IV sane = false; 316d1d65a79SAlexander von Gluck IV } 317e1b9d6e6SAlexander von Gluck IV } 318e1b9d6e6SAlexander von Gluck IV 319*f52ca69cSAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d is %s\n", 320*f52ca69cSAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 321*f52ca69cSAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 322*f52ca69cSAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 323*f52ca69cSAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 324*f52ca69cSAlexander von Gluck IV mode->timing.v_total, 325*f52ca69cSAlexander von Gluck IV sane ? "OK." : "BAD, out of range!"); 326192781ddSAlexander von Gluck IV 327*f52ca69cSAlexander von Gluck IV return sane; 328192781ddSAlexander von Gluck IV } 329192781ddSAlexander von Gluck IV 330192781ddSAlexander von Gluck IV 331d5c3acacSAlexander von Gluck IV /* 332d5c3acacSAlexander von Gluck IV * A quick sanity check of the provided display_mode 333d5c3acacSAlexander von Gluck IV */ 334d5c3acacSAlexander von Gluck IV status_t 335192781ddSAlexander von Gluck IV is_mode_sane(display_mode *mode) 336d5c3acacSAlexander von Gluck IV { 337333bd770SAlexander von Gluck IV // horizontal timing 338333bd770SAlexander von Gluck IV // validate h_sync_start is less then h_sync_end 339333bd770SAlexander von Gluck IV if (mode->timing.h_sync_start > mode->timing.h_sync_end) { 34091235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 34191235829SAlexander von Gluck IV "received h_sync_start greater then h_sync_end!\n", 342333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 343333bd770SAlexander von Gluck IV return B_ERROR; 344333bd770SAlexander von Gluck IV } 345333bd770SAlexander von Gluck IV // validate h_total is greater then h_display 346333bd770SAlexander von Gluck IV if (mode->timing.h_total < mode->timing.h_display) { 34791235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 34891235829SAlexander von Gluck IV "received h_total greater then h_display!\n", 349333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 350d5c3acacSAlexander von Gluck IV return B_ERROR; 351d5c3acacSAlexander von Gluck IV } 352d5c3acacSAlexander von Gluck IV 353333bd770SAlexander von Gluck IV // vertical timing 354333bd770SAlexander von Gluck IV // validate v_start is less then v_end 355333bd770SAlexander von Gluck IV if (mode->timing.v_sync_start > mode->timing.v_sync_end) { 35691235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 35791235829SAlexander von Gluck IV "received v_sync_start greater then v_sync_end!\n", 358333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 359d5c3acacSAlexander von Gluck IV return B_ERROR; 360d5c3acacSAlexander von Gluck IV } 361333bd770SAlexander von Gluck IV // validate v_total is greater then v_display 362333bd770SAlexander von Gluck IV if (mode->timing.v_total < mode->timing.v_display) { 36391235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 36491235829SAlexander von Gluck IV "received v_total greater then v_display!\n", 365333bd770SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display); 366d5c3acacSAlexander von Gluck IV return B_ERROR; 367d5c3acacSAlexander von Gluck IV } 368d5c3acacSAlexander von Gluck IV 36991235829SAlexander von Gluck IV // calculate refresh rate for given timings to whole int (in Hz) 37091235829SAlexander von Gluck IV int refresh = mode->timing.pixel_clock * 1000 37191235829SAlexander von Gluck IV / (mode->timing.h_total * mode->timing.v_total); 37291235829SAlexander von Gluck IV 37391235829SAlexander von Gluck IV if (refresh < 30 || refresh > 250) { 37491235829SAlexander von Gluck IV TRACE("%s: ERROR: (%dx%d) " 37591235829SAlexander von Gluck IV "refresh rate of %dHz is unlikely for any kind of monitor!\n", 37691235829SAlexander von Gluck IV __func__, mode->timing.h_display, mode->timing.v_display, refresh); 37791235829SAlexander von Gluck IV return B_ERROR; 37891235829SAlexander von Gluck IV } 37991235829SAlexander von Gluck IV 380d5c3acacSAlexander von Gluck IV return B_OK; 381d5c3acacSAlexander von Gluck IV } 382d5c3acacSAlexander von Gluck IV 383d1d65a79SAlexander von Gluck IV 384