1/*
2 * Copyright (c) 2002, Thomas Kurschel
3 * Distributed under the terms of the MIT License.
4 */
5
6/*!	Public mode-specific info functions */
7
8
9#include "radeon_accelerant.h"
10#include "GlobalData.h"
11#include "generic.h"
12
13#include <GraphicsDefs.h>
14
15#include <string.h>
16
17
18status_t
19GET_DISPLAY_MODE(display_mode *mode)
20{
21	virtual_card *vc = ai->vc;
22
23	// TBD: there is a race condition if someone else is just setting it
24	//      we won't lock up but return non-sense
25
26	*mode = vc->mode;
27
28	// we hide multi-monitor-mode because :-
29	// - we want to look like an ordinary single-screen driver
30	// - the multi-mode is already adapted to current screen configuration,
31	//   and the mode should be configuration-independant
32	Radeon_HideMultiMode(vc, mode);
33	return B_OK;
34}
35
36
37status_t
38GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb)
39{
40	virtual_card *vc = ai->vc;
41
42	// TBD: race condition again
43
44	// easy again, as the last mode set stored the info in a convienient form
45	*afb = vc->fbc;
46	return B_OK;
47}
48
49
50status_t
51GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
52{
53	// we ignore stuff like DVI/LCD restrictions -
54	// they are handled	automatically on set_display_mode
55	uint32 total_pix = (uint32)dm->timing.h_total * (uint32)dm->timing.v_total;
56	uint32 clock_limit = ai->si->pll.max_pll_freq * 10;
57
58	/* lower limit of about 48Hz vertical refresh */
59	*low = (total_pix * 48L) / 1000L;
60	if (*low > clock_limit)
61		return B_ERROR;
62
63	*high = clock_limit;
64	return B_OK;
65}
66
67
68#ifdef __HAIKU__
69
70status_t
71radeon_get_preferred_display_mode(display_mode* mode)
72{
73	fp_info *fpInfo = &ai->si->flatpanels[0];
74	disp_entity* routes = &ai->si->routing;
75	uint32 i;
76
77	if (routes->port_info[0].edid_valid || routes->port_info[1].edid_valid) {
78		// prefer EDID data in this case
79		return B_ERROR;
80	}
81
82	if ((ai->vc->connected_displays & (dd_dvi | dd_dvi_ext | dd_lvds)) == 0)
83		return B_NOT_SUPPORTED;
84
85	// Mode has already been added by addFPMode(), just return it
86
87	for (i = 0; i < ai->si->mode_count; ++i) {
88		if (ai->mode_list[i].timing.h_display == fpInfo->panel_xres
89			&& ai->mode_list[i].timing.v_display == fpInfo->panel_yres
90			&& ai->mode_list[i].virtual_width == fpInfo->panel_xres
91			&& ai->mode_list[i].virtual_height == fpInfo->panel_yres
92			&& ai->mode_list[i].space == B_RGB32_LITTLE) {
93			memcpy(mode, &ai->mode_list[i], sizeof(display_mode));
94			return B_OK;
95		}
96	}
97
98	return B_ERROR;
99}
100
101
102status_t
103radeon_get_edid_info(void* info, size_t size, uint32* _version)
104{
105	disp_entity* routes = &ai->si->routing;
106	int32 index;
107
108	if (size < sizeof(struct edid1_info))
109		return B_BUFFER_OVERFLOW;
110
111	if (routes->port_info[0].edid_valid)
112		index = 0;
113	else if (routes->port_info[1].edid_valid)
114		index = 1;
115	else
116		return B_ERROR;
117
118	memcpy(info, &routes->port_info[index].edid, sizeof(struct edid1_info));
119	*_version = EDID_VERSION_1;
120	return B_OK;
121}
122
123#endif	// __HAIKU__
124
125/*
126	Return the semaphore id that will be used to signal a vertical retrace
127	occured.
128*/
129sem_id
130ACCELERANT_RETRACE_SEMAPHORE(void)
131{
132	virtual_card *vc = ai->vc;
133
134	/*
135	NOTE:
136		The kernel driver created this for us.  We don't know if the system is
137		using real interrupts, or if we're faking it, and we don't care.
138		If we choose not to support this at all, we'd just return B_ERROR here,
139		and the user wouldn't get any kind of vertical retrace support.
140	*/
141	// with multi-monitor mode, we have two vertical blanks!
142	// until we find a better solution, we always return virtual port 0,
143	// which may be either physical port 0 or 1
144	int crtcIndex;
145
146	if( vc->used_crtc[0] )
147		crtcIndex = 0;
148	else
149		crtcIndex = 1;
150
151	//SHOW_INFO( 3, "semaphore: %x", ai->si->ports[physical_port].vblank );
152
153	return ai->si->crtc[crtcIndex].vblank;
154}
155