st/xorg: Add a possibility to prune modes and limit fb allocation size based on max...
[mesa.git] / src / gallium / state_trackers / xorg / xorg_output.c
1 /*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31 #include "xorg-server.h"
32 #include <xf86.h>
33 #include <xf86i2c.h>
34 #include <xf86Crtc.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdint.h>
41 #include <string.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44
45 #ifdef HAVE_XEXTPROTO_71
46 #include <X11/extensions/dpmsconst.h>
47 #else
48 #define DPMS_SERVER
49 #include <X11/extensions/dpms.h>
50 #endif
51
52 #include "xorg_tracker.h"
53
54 struct output_private
55 {
56 drmModeConnectorPtr drm_connector;
57
58 int c;
59 };
60
61 static char *output_enum_list[] = {
62 "Unknown",
63 "VGA",
64 "DVI",
65 "DVI",
66 "DVI",
67 "Composite",
68 "SVIDEO",
69 "LVDS",
70 "CTV",
71 "DIN",
72 "DP",
73 "HDMI",
74 "HDMI",
75 };
76
77 static void
78 output_create_resources(xf86OutputPtr output)
79 {
80 #ifdef RANDR_12_INTERFACE
81 #endif /* RANDR_12_INTERFACE */
82 }
83
84 static void
85 output_dpms(xf86OutputPtr output, int mode)
86 {
87 }
88
89 static xf86OutputStatus
90 output_detect(xf86OutputPtr output)
91 {
92 modesettingPtr ms = modesettingPTR(output->scrn);
93 struct output_private *priv = output->driver_private;
94 drmModeConnectorPtr drm_connector;
95 xf86OutputStatus status;
96
97 drm_connector = drmModeGetConnector(ms->fd, priv->drm_connector->connector_id);
98 if (drm_connector) {
99 drmModeFreeConnector(priv->drm_connector);
100 priv->drm_connector = drm_connector;
101 } else {
102 drm_connector = priv->drm_connector;
103 }
104
105 switch (drm_connector->connection) {
106 case DRM_MODE_CONNECTED:
107 status = XF86OutputStatusConnected;
108 break;
109 case DRM_MODE_DISCONNECTED:
110 status = XF86OutputStatusDisconnected;
111 break;
112 default:
113 status = XF86OutputStatusUnknown;
114 }
115
116 return status;
117 }
118
119 static DisplayModePtr
120 output_get_modes(xf86OutputPtr output)
121 {
122 struct output_private *priv = output->driver_private;
123 drmModeConnectorPtr drm_connector = priv->drm_connector;
124 drmModeModeInfoPtr drm_mode = NULL;
125 DisplayModePtr modes = NULL, mode = NULL;
126 int i;
127
128 for (i = 0; i < drm_connector->count_modes; i++) {
129 drm_mode = &drm_connector->modes[i];
130 if (drm_mode) {
131 mode = xcalloc(1, sizeof(DisplayModeRec));
132 if (!mode)
133 continue;
134 mode->Clock = drm_mode->clock;
135 mode->HDisplay = drm_mode->hdisplay;
136 mode->HSyncStart = drm_mode->hsync_start;
137 mode->HSyncEnd = drm_mode->hsync_end;
138 mode->HTotal = drm_mode->htotal;
139 mode->VDisplay = drm_mode->vdisplay;
140 mode->VSyncStart = drm_mode->vsync_start;
141 mode->VSyncEnd = drm_mode->vsync_end;
142 mode->VTotal = drm_mode->vtotal;
143 mode->Flags = drm_mode->flags;
144 mode->HSkew = drm_mode->hskew;
145 mode->VScan = drm_mode->vscan;
146 mode->VRefresh = xf86ModeVRefresh(mode);
147 mode->Private = (void *)drm_mode;
148 mode->type = 0;
149 if (drm_mode->type & DRM_MODE_TYPE_PREFERRED)
150 mode->type |= M_T_PREFERRED;
151 if (drm_mode->type & DRM_MODE_TYPE_DRIVER)
152 mode->type |= M_T_DRIVER;
153 xf86SetModeDefaultName(mode);
154 modes = xf86ModesAdd(modes, mode);
155 xf86PrintModeline(0, mode);
156 }
157 }
158
159 return modes;
160 }
161
162 static int
163 output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
164 {
165 modesettingPtr ms = modesettingPTR(output->scrn);
166 CustomizerPtr cust = ms->cust;
167
168 if (cust && cust->winsys_check_fb_size &&
169 !cust->winsys_check_fb_size(cust, pMode->HDisplay *
170 output->scrn->bitsPerPixel / 8,
171 pMode->VDisplay))
172 return MODE_BAD;
173
174 return MODE_OK;
175 }
176
177 #ifdef RANDR_12_INTERFACE
178 static Bool
179 output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value)
180 {
181 return TRUE;
182 }
183 #endif /* RANDR_12_INTERFACE */
184
185 #ifdef RANDR_13_INTERFACE
186 static Bool
187 output_get_property(xf86OutputPtr output, Atom property)
188 {
189 return TRUE;
190 }
191 #endif /* RANDR_13_INTERFACE */
192
193 static void
194 output_destroy(xf86OutputPtr output)
195 {
196 struct output_private *priv = output->driver_private;
197 drmModeFreeConnector(priv->drm_connector);
198 xfree(priv);
199 output->driver_private = NULL;
200 }
201
202 static const xf86OutputFuncsRec output_funcs = {
203 .create_resources = output_create_resources,
204 #ifdef RANDR_12_INTERFACE
205 .set_property = output_set_property,
206 #endif
207 #ifdef RANDR_13_INTERFACE
208 .get_property = output_get_property,
209 #endif
210 .dpms = output_dpms,
211 .detect = output_detect,
212
213 .get_modes = output_get_modes,
214 .mode_valid = output_mode_valid,
215 .destroy = output_destroy,
216 };
217
218 void
219 xorg_output_init(ScrnInfoPtr pScrn)
220 {
221 modesettingPtr ms = modesettingPTR(pScrn);
222 xf86OutputPtr output;
223 drmModeResPtr res;
224 drmModeConnectorPtr drm_connector = NULL;
225 drmModeEncoderPtr drm_encoder = NULL;
226 struct output_private *priv;
227 char name[32];
228 int c, v, p;
229
230 res = drmModeGetResources(ms->fd);
231 if (res == 0) {
232 DRV_ERROR("Failed drmModeGetResources\n");
233 return;
234 }
235
236 for (c = 0; c < res->count_connectors; c++) {
237 drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
238 if (!drm_connector)
239 goto out;
240
241 #if 0
242 for (p = 0; p < drm_connector->count_props; p++) {
243 drmModePropertyPtr prop;
244
245 prop = drmModeGetProperty(ms->fd, drm_connector->props[p]);
246
247 name = NULL;
248 if (prop) {
249 ErrorF("VALUES %d\n", prop->count_values);
250
251 for (v = 0; v < prop->count_values; v++)
252 ErrorF("%s %lld\n", prop->name, prop->values[v]);
253 }
254 }
255 #else
256 (void)p;
257 (void)v;
258 #endif
259
260 snprintf(name, 32, "%s%d",
261 output_enum_list[drm_connector->connector_type],
262 drm_connector->connector_type_id);
263
264
265 priv = xcalloc(sizeof(*priv), 1);
266 if (!priv) {
267 continue;
268 }
269
270 output = xf86OutputCreate(pScrn, &output_funcs, name);
271 if (!output) {
272 xfree(priv);
273 continue;
274 }
275
276 drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
277 if (drm_encoder) {
278 output->possible_crtcs = drm_encoder->possible_crtcs;
279 output->possible_clones = drm_encoder->possible_clones;
280 } else {
281 output->possible_crtcs = 0;
282 output->possible_clones = 0;
283 }
284 priv->c = c;
285 priv->drm_connector = drm_connector;
286 output->driver_private = priv;
287 output->subpixel_order = SubPixelHorizontalRGB;
288 output->interlaceAllowed = FALSE;
289 output->doubleScanAllowed = FALSE;
290 }
291
292 out:
293 drmModeFreeResources(res);
294 }
295
296 unsigned
297 xorg_output_get_id(xf86OutputPtr output)
298 {
299 struct output_private *priv = output->driver_private;
300 return priv->drm_connector->connector_id;
301 }
302
303 /* vim: set sw=4 ts=8 sts=4: */