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