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 { 85*07a90a63SAlexander 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)); 94*07a90a63SAlexander von Gluck IV // VESA 95*07a90a63SAlexander von Gluck IV //memcpy(info, &gDisplay[0]->edid_info, sizeof(struct edid1_info)); 96*07a90a63SAlexander von Gluck IV // BitBanged display 0 97*07a90a63SAlexander 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); 136b54c8119SAlexander von Gluck IV display_crtc_blank(id, ATOM_DISABLE); 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); 148b54c8119SAlexander von Gluck IV display_crtc_blank(id, ATOM_ENABLE); 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); 180936aec74SAlexander von Gluck IV display_crtc_blank(id, ATOM_ENABLE); 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); 202245fe001SAlexander von Gluck IV display_crtc_blank(id, ATOM_DISABLE); 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)); 216245fe001SAlexander von Gluck IV TRACE("D1GRPH_ENABLE Value: 0x%X\n", Read32(CRT, D1GRPH_ENABLE)); 217245fe001SAlexander von Gluck IV TRACE("D2GRPH_ENABLE Value: 0x%X\n", Read32(CRT, D2GRPH_ENABLE)); 218245fe001SAlexander von Gluck IV TRACE("D1SCL_ENABLE Value: 0x%X\n", Read32(CRT, D1SCL_ENABLE)); 219245fe001SAlexander von Gluck IV TRACE("D2SCL_ENABLE Value: 0x%X\n", Read32(CRT, D2SCL_ENABLE)); 220245fe001SAlexander von Gluck IV TRACE("RV620_DACA_ENABLE Value: 0x%X\n", Read32(CRT, RV620_DACA_ENABLE)); 221245fe001SAlexander von Gluck IV TRACE("RV620_DACB_ENABLE Value: 0x%X\n", Read32(CRT, RV620_DACB_ENABLE)); 2223be5e036SAlexander von Gluck IV 223a90ebd77SClemens Zeidler return B_OK; 224a90ebd77SClemens Zeidler } 225a90ebd77SClemens Zeidler 226a90ebd77SClemens Zeidler 227a90ebd77SClemens Zeidler status_t 228a90ebd77SClemens Zeidler radeon_get_display_mode(display_mode *_currentMode) 229a90ebd77SClemens Zeidler { 230d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 231a90ebd77SClemens Zeidler 232192781ddSAlexander von Gluck IV *_currentMode = gInfo->shared_info->current_mode; 233a90ebd77SClemens Zeidler return B_OK; 234a90ebd77SClemens Zeidler } 235a90ebd77SClemens Zeidler 236a90ebd77SClemens Zeidler 237a90ebd77SClemens Zeidler status_t 238a90ebd77SClemens Zeidler radeon_get_frame_buffer_config(frame_buffer_config *config) 239a90ebd77SClemens Zeidler { 240d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 241a90ebd77SClemens Zeidler 2423be5e036SAlexander von Gluck IV config->frame_buffer = gInfo->shared_info->frame_buffer; 2433be5e036SAlexander von Gluck IV config->frame_buffer_dma = (uint8 *)gInfo->shared_info->frame_buffer_phys; 24451a43d0fSAlexander von Gluck IV 245a90ebd77SClemens Zeidler config->bytes_per_row = gInfo->shared_info->bytes_per_row; 246a90ebd77SClemens Zeidler 247a90ebd77SClemens Zeidler return B_OK; 248a90ebd77SClemens Zeidler } 249a90ebd77SClemens Zeidler 250a90ebd77SClemens Zeidler 251a90ebd77SClemens Zeidler status_t 252a90ebd77SClemens Zeidler radeon_get_pixel_clock_limits(display_mode *mode, uint32 *_low, uint32 *_high) 253a90ebd77SClemens Zeidler { 254d5c3acacSAlexander von Gluck IV TRACE("%s\n", __func__); 255e7e76b29SAlexander von Gluck IV 256a90ebd77SClemens Zeidler if (_low != NULL) { 257a90ebd77SClemens Zeidler // lower limit of about 48Hz vertical refresh 2585f6744a8SAlexander von Gluck IV uint32 totalClocks = (uint32)mode->timing.h_total 2595f6744a8SAlexander von Gluck IV *(uint32)mode->timing.v_total; 260a90ebd77SClemens Zeidler uint32 low = (totalClocks * 48L) / 1000L; 261e7e76b29SAlexander von Gluck IV 262d3e8b642SAlexander von Gluck IV if (low < PLL_MIN_DEFAULT) 263d3e8b642SAlexander von Gluck IV low = PLL_MIN_DEFAULT; 264d3e8b642SAlexander von Gluck IV else if (low > PLL_MAX_DEFAULT) 265a90ebd77SClemens Zeidler return B_ERROR; 266a90ebd77SClemens Zeidler 267a90ebd77SClemens Zeidler *_low = low; 268a90ebd77SClemens Zeidler } 269a90ebd77SClemens Zeidler 270a90ebd77SClemens Zeidler if (_high != NULL) 271d3e8b642SAlexander von Gluck IV *_high = PLL_MAX_DEFAULT; 272e7e76b29SAlexander von Gluck IV 273e7e76b29SAlexander von Gluck IV //*_low = 48L; 274e7e76b29SAlexander von Gluck IV //*_high = 100 * 1000000L; 275a90ebd77SClemens Zeidler return B_OK; 276a90ebd77SClemens Zeidler } 277a90ebd77SClemens Zeidler 278a90ebd77SClemens Zeidler 279192781ddSAlexander von Gluck IV bool 280192781ddSAlexander von Gluck IV is_mode_supported(display_mode *mode) 281192781ddSAlexander von Gluck IV { 282d1d65a79SAlexander von Gluck IV TRACE("MODE: %d ; %d %d %d %d ; %d %d %d %d\n", 283d1d65a79SAlexander von Gluck IV mode->timing.pixel_clock, mode->timing.h_display, 284d1d65a79SAlexander von Gluck IV mode->timing.h_sync_start, mode->timing.h_sync_end, 285d1d65a79SAlexander von Gluck IV mode->timing.h_total, mode->timing.v_display, 286d1d65a79SAlexander von Gluck IV mode->timing.v_sync_start, mode->timing.v_sync_end, 287d1d65a79SAlexander von Gluck IV mode->timing.v_total); 288d1d65a79SAlexander von Gluck IV 2891dac4469SAlexander von Gluck IV // Validate modeline is within a sane range 290192781ddSAlexander von Gluck IV if (is_mode_sane(mode) != B_OK) 291192781ddSAlexander von Gluck IV return false; 292192781ddSAlexander von Gluck IV 29395e1d7e8SAlexander von Gluck IV // TODO: is_mode_supported on *which* display? 294d1d65a79SAlexander von Gluck IV uint32 crtid = 0; 2951dac4469SAlexander von Gluck IV 296d1d65a79SAlexander von Gluck IV // if we have edid info, check frequency adginst crt reported valid ranges 297e1b9d6e6SAlexander von Gluck IV if (gInfo->shared_info->has_edid 298e1b9d6e6SAlexander von Gluck IV && gDisplay[crtid]->found_ranges) { 2991dac4469SAlexander von Gluck IV 300d1d65a79SAlexander von Gluck IV uint32 hfreq = mode->timing.pixel_clock / mode->timing.h_total; 30195e1d7e8SAlexander von Gluck IV if (hfreq > gDisplay[crtid]->hfreq_max + 1 30295e1d7e8SAlexander von Gluck IV || hfreq < gDisplay[crtid]->hfreq_min - 1) { 303d1d65a79SAlexander von Gluck IV TRACE("!!! hfreq : %d , hfreq_min : %d, hfreq_max : %d\n", 30495e1d7e8SAlexander von Gluck IV hfreq, gDisplay[crtid]->hfreq_min, gDisplay[crtid]->hfreq_max); 305d1d65a79SAlexander von Gluck IV TRACE("!!! %dx%d falls outside of CRT %d's valid " 306d1d65a79SAlexander von Gluck IV "horizontal range.\n", mode->timing.h_display, 307d1d65a79SAlexander von Gluck IV mode->timing.v_display, crtid); 308d1d65a79SAlexander von Gluck IV return false; 309d1d65a79SAlexander von Gluck IV } 310d1d65a79SAlexander von Gluck IV 311d1d65a79SAlexander von Gluck IV uint32 vfreq = mode->timing.pixel_clock / ((mode->timing.v_total 312d1d65a79SAlexander von Gluck IV * mode->timing.h_total) / 1000); 313d1d65a79SAlexander von Gluck IV 31495e1d7e8SAlexander von Gluck IV if (vfreq > gDisplay[crtid]->vfreq_max + 1 31595e1d7e8SAlexander von Gluck IV || vfreq < gDisplay[crtid]->vfreq_min - 1) { 316d1d65a79SAlexander von Gluck IV TRACE("!!! vfreq : %d , vfreq_min : %d, vfreq_max : %d\n", 31795e1d7e8SAlexander von Gluck IV vfreq, gDisplay[crtid]->vfreq_min, gDisplay[crtid]->vfreq_max); 318d1d65a79SAlexander von Gluck IV TRACE("!!! %dx%d falls outside of CRT %d's valid vertical range\n", 319d1d65a79SAlexander von Gluck IV mode->timing.h_display, mode->timing.v_display, crtid); 320d1d65a79SAlexander von Gluck IV return false; 321d1d65a79SAlexander von Gluck IV } 322e1b9d6e6SAlexander von Gluck IV } 323e1b9d6e6SAlexander von Gluck IV 324d1d65a79SAlexander von Gluck IV TRACE("%dx%d is within CRT %d's valid frequency range\n", 325d1d65a79SAlexander von Gluck IV mode->timing.h_display, mode->timing.v_display, crtid); 326192781ddSAlexander von Gluck IV 327192781ddSAlexander von Gluck IV return true; 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