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