Rev 1221 | Rev 1404 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1123 | serge | 1 | /* |
2 | * Copyright (c) 2006-2008 Intel Corporation |
||
3 | * Copyright (c) 2007 Dave Airlie |
||
4 | * Copyright (c) 2008 Red Hat Inc. |
||
5 | * |
||
6 | * DRM core CRTC related functions |
||
7 | * |
||
8 | * Permission to use, copy, modify, distribute, and sell this software and its |
||
9 | * documentation for any purpose is hereby granted without fee, provided that |
||
10 | * the above copyright notice appear in all copies and that both that copyright |
||
11 | * notice and this permission notice appear in supporting documentation, and |
||
12 | * that the name of the copyright holders not be used in advertising or |
||
13 | * publicity pertaining to distribution of the software without specific, |
||
14 | * written prior permission. The copyright holders make no representations |
||
15 | * about the suitability of this software for any purpose. It is provided "as |
||
16 | * is" without express or implied warranty. |
||
17 | * |
||
18 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
||
19 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
||
20 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
||
21 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
||
22 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
||
23 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
||
24 | * OF THIS SOFTWARE. |
||
25 | * |
||
26 | * Authors: |
||
27 | * Keith Packard |
||
28 | * Eric Anholt |
||
29 | * Dave Airlie |
||
30 | * Jesse Barnes |
||
31 | */ |
||
1179 | serge | 32 | #include |
1123 | serge | 33 | #include "drm.h" |
34 | #include "drmP.h" |
||
35 | #include "drm_crtc.h" |
||
36 | |||
37 | struct drm_prop_enum_list { |
||
38 | int type; |
||
39 | char *name; |
||
40 | }; |
||
41 | |||
42 | /* Avoid boilerplate. I'm tired of typing. */ |
||
43 | #define DRM_ENUM_NAME_FN(fnname, list) \ |
||
44 | char *fnname(int val) \ |
||
45 | { \ |
||
46 | int i; \ |
||
47 | for (i = 0; i < ARRAY_SIZE(list); i++) { \ |
||
48 | if (list[i].type == val) \ |
||
49 | return list[i].name; \ |
||
50 | } \ |
||
51 | return "(unknown)"; \ |
||
52 | } |
||
53 | |||
54 | /* |
||
55 | * Global properties |
||
56 | */ |
||
57 | static struct drm_prop_enum_list drm_dpms_enum_list[] = |
||
58 | { { DRM_MODE_DPMS_ON, "On" }, |
||
59 | { DRM_MODE_DPMS_STANDBY, "Standby" }, |
||
60 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, |
||
61 | { DRM_MODE_DPMS_OFF, "Off" } |
||
62 | }; |
||
63 | |||
64 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) |
||
65 | |||
66 | /* |
||
67 | * Optional properties |
||
68 | */ |
||
69 | static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = |
||
70 | { |
||
1179 | serge | 71 | { DRM_MODE_SCALE_NONE, "None" }, |
72 | { DRM_MODE_SCALE_FULLSCREEN, "Full" }, |
||
73 | { DRM_MODE_SCALE_CENTER, "Center" }, |
||
74 | { DRM_MODE_SCALE_ASPECT, "Full aspect" }, |
||
1123 | serge | 75 | }; |
76 | |||
77 | static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = |
||
78 | { |
||
79 | { DRM_MODE_DITHERING_OFF, "Off" }, |
||
80 | { DRM_MODE_DITHERING_ON, "On" }, |
||
81 | }; |
||
82 | |||
83 | /* |
||
84 | * Non-global properties, but "required" for certain connectors. |
||
85 | */ |
||
86 | static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = |
||
87 | { |
||
88 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
||
89 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
||
90 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
||
91 | }; |
||
92 | |||
93 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) |
||
94 | |||
95 | static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = |
||
96 | { |
||
97 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
||
98 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
||
99 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
||
100 | }; |
||
101 | |||
102 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, |
||
103 | drm_dvi_i_subconnector_enum_list) |
||
104 | |||
105 | static struct drm_prop_enum_list drm_tv_select_enum_list[] = |
||
106 | { |
||
107 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
||
108 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
||
109 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
||
110 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
||
1179 | serge | 111 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ |
1123 | serge | 112 | }; |
113 | |||
114 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
||
115 | |||
116 | static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = |
||
117 | { |
||
118 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
||
119 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
||
120 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
||
121 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
||
1179 | serge | 122 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ |
1123 | serge | 123 | }; |
124 | |||
125 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, |
||
126 | drm_tv_subconnector_enum_list) |
||
127 | |||
1321 | serge | 128 | static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { |
129 | { DRM_MODE_DIRTY_OFF, "Off" }, |
||
130 | { DRM_MODE_DIRTY_ON, "On" }, |
||
131 | { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, |
||
132 | }; |
||
133 | |||
134 | DRM_ENUM_NAME_FN(drm_get_dirty_info_name, |
||
135 | drm_dirty_info_enum_list) |
||
136 | |||
1123 | serge | 137 | struct drm_conn_prop_enum_list { |
138 | int type; |
||
139 | char *name; |
||
140 | int count; |
||
141 | }; |
||
142 | |||
143 | /* |
||
144 | * Connector and encoder types. |
||
145 | */ |
||
146 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = |
||
147 | { { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 }, |
||
148 | { DRM_MODE_CONNECTOR_VGA, "VGA", 0 }, |
||
149 | { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 }, |
||
150 | { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 }, |
||
151 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 }, |
||
152 | { DRM_MODE_CONNECTOR_Composite, "Composite", 0 }, |
||
153 | { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, |
||
154 | { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, |
||
155 | { DRM_MODE_CONNECTOR_Component, "Component", 0 }, |
||
156 | { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 }, |
||
157 | { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 }, |
||
158 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, |
||
159 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, |
||
1179 | serge | 160 | { DRM_MODE_CONNECTOR_TV, "TV", 0 }, |
1123 | serge | 161 | }; |
162 | |||
163 | static struct drm_prop_enum_list drm_encoder_enum_list[] = |
||
164 | { { DRM_MODE_ENCODER_NONE, "None" }, |
||
165 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
||
166 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, |
||
167 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
||
168 | { DRM_MODE_ENCODER_TVDAC, "TV" }, |
||
169 | }; |
||
170 | |||
171 | char *drm_get_encoder_name(struct drm_encoder *encoder) |
||
172 | { |
||
173 | static char buf[32]; |
||
174 | |||
175 | snprintf(buf, 32, "%s-%d", |
||
176 | drm_encoder_enum_list[encoder->encoder_type].name, |
||
177 | encoder->base.id); |
||
178 | return buf; |
||
179 | } |
||
1179 | serge | 180 | EXPORT_SYMBOL(drm_get_encoder_name); |
1123 | serge | 181 | |
182 | char *drm_get_connector_name(struct drm_connector *connector) |
||
183 | { |
||
184 | static char buf[32]; |
||
185 | |||
186 | snprintf(buf, 32, "%s-%d", |
||
187 | drm_connector_enum_list[connector->connector_type].name, |
||
188 | connector->connector_type_id); |
||
189 | return buf; |
||
190 | } |
||
191 | EXPORT_SYMBOL(drm_get_connector_name); |
||
192 | |||
193 | char *drm_get_connector_status_name(enum drm_connector_status status) |
||
194 | { |
||
195 | if (status == connector_status_connected) |
||
196 | return "connected"; |
||
197 | else if (status == connector_status_disconnected) |
||
198 | return "disconnected"; |
||
199 | else |
||
200 | return "unknown"; |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * drm_mode_object_get - allocate a new identifier |
||
205 | * @dev: DRM device |
||
206 | * @ptr: object pointer, used to generate unique ID |
||
207 | * @type: object type |
||
208 | * |
||
209 | * LOCKING: |
||
210 | * |
||
211 | * Create a unique identifier based on @ptr in @dev's identifier space. Used |
||
212 | * for tracking modes, CRTCs and connectors. |
||
213 | * |
||
214 | * RETURNS: |
||
215 | * New unique (relative to other objects in @dev) integer identifier for the |
||
216 | * object. |
||
217 | */ |
||
218 | static int drm_mode_object_get(struct drm_device *dev, |
||
219 | struct drm_mode_object *obj, uint32_t obj_type) |
||
220 | { |
||
221 | int new_id = 0; |
||
222 | int ret; |
||
223 | |||
224 | again: |
||
225 | if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { |
||
226 | DRM_ERROR("Ran out memory getting a mode number\n"); |
||
227 | return -EINVAL; |
||
228 | } |
||
229 | |||
1179 | serge | 230 | mutex_lock(&dev->mode_config.idr_mutex); |
1123 | serge | 231 | ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); |
1179 | serge | 232 | mutex_unlock(&dev->mode_config.idr_mutex); |
1123 | serge | 233 | if (ret == -EAGAIN) |
1179 | serge | 234 | goto again; |
1123 | serge | 235 | |
236 | obj->id = new_id; |
||
237 | obj->type = obj_type; |
||
1179 | serge | 238 | return 0; |
1123 | serge | 239 | } |
240 | |||
241 | /** |
||
242 | * drm_mode_object_put - free an identifer |
||
243 | * @dev: DRM device |
||
244 | * @id: ID to free |
||
245 | * |
||
246 | * LOCKING: |
||
247 | * Caller must hold DRM mode_config lock. |
||
248 | * |
||
249 | * Free @id from @dev's unique identifier pool. |
||
250 | */ |
||
251< |