1/*
2 * Copyright 2005-2015, Axel D��rfler, axeld@pinc-software.de.
3 * Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include <stdlib.h>
9#include <string.h>
10
11#include <compute_display_timing.h>
12#include <create_display_modes.h>
13
14#include "accelerant_protos.h"
15#include "accelerant.h"
16#include "utility.h"
17
18
19//#define TRACE_MODE
20#ifdef TRACE_MODE
21extern "C" void _sPrintf(const char* format, ...);
22#	define TRACE(x) _sPrintf x
23#else
24#	define TRACE(x) ;
25#endif
26
27
28bool
29operator==(const display_mode &lhs, const display_mode &rhs)
30{
31	return lhs.space == rhs.space
32		&& lhs.virtual_width == rhs.virtual_width
33		&& lhs.virtual_height == rhs.virtual_height
34		&& lhs.h_display_start == rhs.h_display_start
35		&& lhs.v_display_start == rhs.v_display_start;
36}
37
38
39/*!	Checks if the specified \a mode can be set using VESA. */
40static bool
41is_mode_supported(display_mode* mode)
42{
43	return (mode != NULL) && (*mode == gInfo->shared_info->current_mode);
44}
45
46
47/*!	Creates the initial mode list of the primary accelerant.
48	It's called from vesa_init_accelerant().
49*/
50status_t
51create_mode_list(void)
52{
53	const color_space colorspace[] = {
54		(color_space)gInfo->shared_info->current_mode.space
55	};
56	display_mode mode = gInfo->shared_info->current_mode;
57
58	compute_display_timing(mode.virtual_width, mode.virtual_height, 60, false,
59		&mode.timing);
60	fill_display_mode(mode.virtual_width, mode.virtual_height, &mode);
61
62	gInfo->mode_list_area = create_display_modes("framebuffer modes",
63		NULL, &mode, 1, colorspace, 1, is_mode_supported, &gInfo->mode_list,
64		&gInfo->shared_info->mode_count);
65
66	if (gInfo->mode_list_area < 0)
67		return gInfo->mode_list_area;
68
69	gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
70	return B_OK;
71}
72
73
74//	#pragma mark -
75
76
77uint32
78framebuffer_accelerant_mode_count(void)
79{
80	TRACE(("framebuffer_accelerant_mode_count() = %d\n",
81		gInfo->shared_info->mode_count));
82	return gInfo->shared_info->mode_count;
83}
84
85
86status_t
87framebuffer_get_mode_list(display_mode* modeList)
88{
89	TRACE(("framebuffer_get_mode_info()\n"));
90	memcpy(modeList, gInfo->mode_list,
91		gInfo->shared_info->mode_count * sizeof(display_mode));
92	return B_OK;
93}
94
95
96status_t
97framebuffer_set_display_mode(display_mode* _mode)
98{
99	TRACE(("framebuffer_set_display_mode()\n"));
100	if (_mode != NULL && *_mode == gInfo->shared_info->current_mode)
101		return B_OK;
102
103	return B_UNSUPPORTED;
104}
105
106
107status_t
108framebuffer_get_display_mode(display_mode* _currentMode)
109{
110	TRACE(("framebuffer_get_display_mode()\n"));
111	*_currentMode = gInfo->shared_info->current_mode;
112	return B_OK;
113}
114
115
116status_t
117framebuffer_get_edid_info(void* info, size_t size, uint32* _version)
118{
119	TRACE(("framebuffer_get_edid_info()\n"));
120
121	if (!gInfo->shared_info->has_edid)
122		return B_ERROR;
123	if (size < sizeof(struct edid1_info))
124		return B_BUFFER_OVERFLOW;
125
126	memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
127	*_version = EDID_VERSION_1;
128	return B_OK;
129}
130
131
132status_t
133framebuffer_get_frame_buffer_config(frame_buffer_config* config)
134{
135	TRACE(("framebuffer_get_frame_buffer_config()\n"));
136
137	config->frame_buffer = gInfo->shared_info->frame_buffer;
138	config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
139	config->bytes_per_row = gInfo->shared_info->bytes_per_row;
140
141	return B_OK;
142}
143
144
145status_t
146framebuffer_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high)
147{
148	TRACE(("framebuffer_get_pixel_clock_limits()\n"));
149
150	// TODO: do some real stuff here (taken from radeon driver)
151	uint32 totalPixel = (uint32)mode->timing.h_total
152		* (uint32)mode->timing.v_total;
153	uint32 clockLimit = 2000000;
154
155	// lower limit of about 48Hz vertical refresh
156	*_low = totalPixel * 48L / 1000L;
157	if (*_low > clockLimit)
158		return B_ERROR;
159
160	*_high = clockLimit;
161	return B_OK;
162}
163
164