Commit e14cbee401cd00779a5267128371506b22c77bc9

Authored by Michel Dänzer
Committed by Dave Airlie
1 parent b1e3a6d1c4

drm: Fix shifts which were miscalculated when converting from bitfields.

Looks like I managed to mess up most shifts when converting from bitfields. :(

The patch below works on my Thinkpad T500 (as well as on my PowerBook,
where the previous change worked as well, maybe out of luck...). I'd
appreciate more testing and eyes looking over it though.

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Tested-by: Michael Pyne <mpyne@kde.org>
Signed-off-by: Dave Airlie <airlied@linux.ie>

Showing 2 changed files with 25 additions and 25 deletions Inline Diff

drivers/gpu/drm/drm_edid.c
1 /* 1 /*
2 * Copyright (c) 2006 Luc Verhaegen (quirks list) 2 * Copyright (c) 2006 Luc Verhaegen (quirks list)
3 * Copyright (c) 2007-2008 Intel Corporation 3 * Copyright (c) 2007-2008 Intel Corporation
4 * Jesse Barnes <jesse.barnes@intel.com> 4 * Jesse Barnes <jesse.barnes@intel.com>
5 * 5 *
6 * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from 6 * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
7 * FB layer. 7 * FB layer.
8 * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com> 8 * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
9 * 9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a 10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"), 11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation 12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sub license, 13 * the rights to use, copy, modify, merge, publish, distribute, sub license,
14 * and/or sell copies of the Software, and to permit persons to whom the 14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions: 15 * Software is furnished to do so, subject to the following conditions:
16 * 16 *
17 * The above copyright notice and this permission notice (including the 17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions 18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software. 19 * of the Software.
20 * 20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 23 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE. 27 * DEALINGS IN THE SOFTWARE.
28 */ 28 */
29 #include <linux/kernel.h> 29 #include <linux/kernel.h>
30 #include <linux/i2c.h> 30 #include <linux/i2c.h>
31 #include <linux/i2c-algo-bit.h> 31 #include <linux/i2c-algo-bit.h>
32 #include "drmP.h" 32 #include "drmP.h"
33 #include "drm_edid.h" 33 #include "drm_edid.h"
34 34
35 /* 35 /*
36 * TODO: 36 * TODO:
37 * - support EDID 1.4 (incl. CE blocks) 37 * - support EDID 1.4 (incl. CE blocks)
38 */ 38 */
39 39
40 /* 40 /*
41 * EDID blocks out in the wild have a variety of bugs, try to collect 41 * EDID blocks out in the wild have a variety of bugs, try to collect
42 * them here (note that userspace may work around broken monitors first, 42 * them here (note that userspace may work around broken monitors first,
43 * but fixes should make their way here so that the kernel "just works" 43 * but fixes should make their way here so that the kernel "just works"
44 * on as many displays as possible). 44 * on as many displays as possible).
45 */ 45 */
46 46
47 /* First detailed mode wrong, use largest 60Hz mode */ 47 /* First detailed mode wrong, use largest 60Hz mode */
48 #define EDID_QUIRK_PREFER_LARGE_60 (1 << 0) 48 #define EDID_QUIRK_PREFER_LARGE_60 (1 << 0)
49 /* Reported 135MHz pixel clock is too high, needs adjustment */ 49 /* Reported 135MHz pixel clock is too high, needs adjustment */
50 #define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1) 50 #define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1)
51 /* Prefer the largest mode at 75 Hz */ 51 /* Prefer the largest mode at 75 Hz */
52 #define EDID_QUIRK_PREFER_LARGE_75 (1 << 2) 52 #define EDID_QUIRK_PREFER_LARGE_75 (1 << 2)
53 /* Detail timing is in cm not mm */ 53 /* Detail timing is in cm not mm */
54 #define EDID_QUIRK_DETAILED_IN_CM (1 << 3) 54 #define EDID_QUIRK_DETAILED_IN_CM (1 << 3)
55 /* Detailed timing descriptors have bogus size values, so just take the 55 /* Detailed timing descriptors have bogus size values, so just take the
56 * maximum size and use that. 56 * maximum size and use that.
57 */ 57 */
58 #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) 58 #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4)
59 /* Monitor forgot to set the first detailed is preferred bit. */ 59 /* Monitor forgot to set the first detailed is preferred bit. */
60 #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) 60 #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
61 /* use +hsync +vsync for detailed mode */ 61 /* use +hsync +vsync for detailed mode */
62 #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) 62 #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
63 63
64 static struct edid_quirk { 64 static struct edid_quirk {
65 char *vendor; 65 char *vendor;
66 int product_id; 66 int product_id;
67 u32 quirks; 67 u32 quirks;
68 } edid_quirk_list[] = { 68 } edid_quirk_list[] = {
69 /* Acer AL1706 */ 69 /* Acer AL1706 */
70 { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, 70 { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
71 /* Acer F51 */ 71 /* Acer F51 */
72 { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 }, 72 { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 },
73 /* Unknown Acer */ 73 /* Unknown Acer */
74 { "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, 74 { "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
75 75
76 /* Belinea 10 15 55 */ 76 /* Belinea 10 15 55 */
77 { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, 77 { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
78 { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, 78 { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
79 79
80 /* Envision Peripherals, Inc. EN-7100e */ 80 /* Envision Peripherals, Inc. EN-7100e */
81 { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, 81 { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH },
82 82
83 /* Funai Electronics PM36B */ 83 /* Funai Electronics PM36B */
84 { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | 84 { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
85 EDID_QUIRK_DETAILED_IN_CM }, 85 EDID_QUIRK_DETAILED_IN_CM },
86 86
87 /* LG Philips LCD LP154W01-A5 */ 87 /* LG Philips LCD LP154W01-A5 */
88 { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, 88 { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
89 { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, 89 { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
90 90
91 /* Philips 107p5 CRT */ 91 /* Philips 107p5 CRT */
92 { "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, 92 { "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
93 93
94 /* Proview AY765C */ 94 /* Proview AY765C */
95 { "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, 95 { "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
96 96
97 /* Samsung SyncMaster 205BW. Note: irony */ 97 /* Samsung SyncMaster 205BW. Note: irony */
98 { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP }, 98 { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP },
99 /* Samsung SyncMaster 22[5-6]BW */ 99 /* Samsung SyncMaster 22[5-6]BW */
100 { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, 100 { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
101 { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, 101 { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
102 }; 102 };
103 103
104 104
105 /* Valid EDID header has these bytes */ 105 /* Valid EDID header has these bytes */
106 static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; 106 static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
107 107
108 /** 108 /**
109 * edid_is_valid - sanity check EDID data 109 * edid_is_valid - sanity check EDID data
110 * @edid: EDID data 110 * @edid: EDID data
111 * 111 *
112 * Sanity check the EDID block by looking at the header, the version number 112 * Sanity check the EDID block by looking at the header, the version number
113 * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's 113 * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's
114 * valid. 114 * valid.
115 */ 115 */
116 static bool edid_is_valid(struct edid *edid) 116 static bool edid_is_valid(struct edid *edid)
117 { 117 {
118 int i; 118 int i;
119 u8 csum = 0; 119 u8 csum = 0;
120 u8 *raw_edid = (u8 *)edid; 120 u8 *raw_edid = (u8 *)edid;
121 121
122 if (memcmp(edid->header, edid_header, sizeof(edid_header))) 122 if (memcmp(edid->header, edid_header, sizeof(edid_header)))
123 goto bad; 123 goto bad;
124 if (edid->version != 1) { 124 if (edid->version != 1) {
125 DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); 125 DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
126 goto bad; 126 goto bad;
127 } 127 }
128 if (edid->revision > 4) 128 if (edid->revision > 4)
129 DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); 129 DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
130 130
131 for (i = 0; i < EDID_LENGTH; i++) 131 for (i = 0; i < EDID_LENGTH; i++)
132 csum += raw_edid[i]; 132 csum += raw_edid[i];
133 if (csum) { 133 if (csum) {
134 DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); 134 DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
135 goto bad; 135 goto bad;
136 } 136 }
137 137
138 return 1; 138 return 1;
139 139
140 bad: 140 bad:
141 if (raw_edid) { 141 if (raw_edid) {
142 DRM_ERROR("Raw EDID:\n"); 142 DRM_ERROR("Raw EDID:\n");
143 print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); 143 print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
144 printk("\n"); 144 printk("\n");
145 } 145 }
146 return 0; 146 return 0;
147 } 147 }
148 148
149 /** 149 /**
150 * edid_vendor - match a string against EDID's obfuscated vendor field 150 * edid_vendor - match a string against EDID's obfuscated vendor field
151 * @edid: EDID to match 151 * @edid: EDID to match
152 * @vendor: vendor string 152 * @vendor: vendor string
153 * 153 *
154 * Returns true if @vendor is in @edid, false otherwise 154 * Returns true if @vendor is in @edid, false otherwise
155 */ 155 */
156 static bool edid_vendor(struct edid *edid, char *vendor) 156 static bool edid_vendor(struct edid *edid, char *vendor)
157 { 157 {
158 char edid_vendor[3]; 158 char edid_vendor[3];
159 159
160 edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@'; 160 edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@';
161 edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) | 161 edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) |
162 ((edid->mfg_id[1] & 0xe0) >> 5)) + '@'; 162 ((edid->mfg_id[1] & 0xe0) >> 5)) + '@';
163 edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@'; 163 edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@';
164 164
165 return !strncmp(edid_vendor, vendor, 3); 165 return !strncmp(edid_vendor, vendor, 3);
166 } 166 }
167 167
168 /** 168 /**
169 * edid_get_quirks - return quirk flags for a given EDID 169 * edid_get_quirks - return quirk flags for a given EDID
170 * @edid: EDID to process 170 * @edid: EDID to process
171 * 171 *
172 * This tells subsequent routines what fixes they need to apply. 172 * This tells subsequent routines what fixes they need to apply.
173 */ 173 */
174 static u32 edid_get_quirks(struct edid *edid) 174 static u32 edid_get_quirks(struct edid *edid)
175 { 175 {
176 struct edid_quirk *quirk; 176 struct edid_quirk *quirk;
177 int i; 177 int i;
178 178
179 for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) { 179 for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
180 quirk = &edid_quirk_list[i]; 180 quirk = &edid_quirk_list[i];
181 181
182 if (edid_vendor(edid, quirk->vendor) && 182 if (edid_vendor(edid, quirk->vendor) &&
183 (EDID_PRODUCT_ID(edid) == quirk->product_id)) 183 (EDID_PRODUCT_ID(edid) == quirk->product_id))
184 return quirk->quirks; 184 return quirk->quirks;
185 } 185 }
186 186
187 return 0; 187 return 0;
188 } 188 }
189 189
190 #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) 190 #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
191 #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) 191 #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh))
192 192
193 193
194 /** 194 /**
195 * edid_fixup_preferred - set preferred modes based on quirk list 195 * edid_fixup_preferred - set preferred modes based on quirk list
196 * @connector: has mode list to fix up 196 * @connector: has mode list to fix up
197 * @quirks: quirks list 197 * @quirks: quirks list
198 * 198 *
199 * Walk the mode list for @connector, clearing the preferred status 199 * Walk the mode list for @connector, clearing the preferred status
200 * on existing modes and setting it anew for the right mode ala @quirks. 200 * on existing modes and setting it anew for the right mode ala @quirks.
201 */ 201 */
202 static void edid_fixup_preferred(struct drm_connector *connector, 202 static void edid_fixup_preferred(struct drm_connector *connector,
203 u32 quirks) 203 u32 quirks)
204 { 204 {
205 struct drm_display_mode *t, *cur_mode, *preferred_mode; 205 struct drm_display_mode *t, *cur_mode, *preferred_mode;
206 int target_refresh = 0; 206 int target_refresh = 0;
207 207
208 if (list_empty(&connector->probed_modes)) 208 if (list_empty(&connector->probed_modes))
209 return; 209 return;
210 210
211 if (quirks & EDID_QUIRK_PREFER_LARGE_60) 211 if (quirks & EDID_QUIRK_PREFER_LARGE_60)
212 target_refresh = 60; 212 target_refresh = 60;
213 if (quirks & EDID_QUIRK_PREFER_LARGE_75) 213 if (quirks & EDID_QUIRK_PREFER_LARGE_75)
214 target_refresh = 75; 214 target_refresh = 75;
215 215
216 preferred_mode = list_first_entry(&connector->probed_modes, 216 preferred_mode = list_first_entry(&connector->probed_modes,
217 struct drm_display_mode, head); 217 struct drm_display_mode, head);
218 218
219 list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) { 219 list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) {
220 cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED; 220 cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED;
221 221
222 if (cur_mode == preferred_mode) 222 if (cur_mode == preferred_mode)
223 continue; 223 continue;
224 224
225 /* Largest mode is preferred */ 225 /* Largest mode is preferred */
226 if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode)) 226 if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode))
227 preferred_mode = cur_mode; 227 preferred_mode = cur_mode;
228 228
229 /* At a given size, try to get closest to target refresh */ 229 /* At a given size, try to get closest to target refresh */
230 if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) && 230 if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) &&
231 MODE_REFRESH_DIFF(cur_mode, target_refresh) < 231 MODE_REFRESH_DIFF(cur_mode, target_refresh) <
232 MODE_REFRESH_DIFF(preferred_mode, target_refresh)) { 232 MODE_REFRESH_DIFF(preferred_mode, target_refresh)) {
233 preferred_mode = cur_mode; 233 preferred_mode = cur_mode;
234 } 234 }
235 } 235 }
236 236
237 preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; 237 preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
238 } 238 }
239 239
240 /** 240 /**
241 * drm_mode_std - convert standard mode info (width, height, refresh) into mode 241 * drm_mode_std - convert standard mode info (width, height, refresh) into mode
242 * @t: standard timing params 242 * @t: standard timing params
243 * 243 *
244 * Take the standard timing params (in this case width, aspect, and refresh) 244 * Take the standard timing params (in this case width, aspect, and refresh)
245 * and convert them into a real mode using CVT. 245 * and convert them into a real mode using CVT.
246 * 246 *
247 * Punts for now, but should eventually use the FB layer's CVT based mode 247 * Punts for now, but should eventually use the FB layer's CVT based mode
248 * generation code. 248 * generation code.
249 */ 249 */
250 struct drm_display_mode *drm_mode_std(struct drm_device *dev, 250 struct drm_display_mode *drm_mode_std(struct drm_device *dev,
251 struct std_timing *t) 251 struct std_timing *t)
252 { 252 {
253 struct drm_display_mode *mode; 253 struct drm_display_mode *mode;
254 int hsize = t->hsize * 8 + 248, vsize; 254 int hsize = t->hsize * 8 + 248, vsize;
255 unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) 255 unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
256 >> EDID_TIMING_ASPECT_SHIFT; 256 >> EDID_TIMING_ASPECT_SHIFT;
257 257
258 mode = drm_mode_create(dev); 258 mode = drm_mode_create(dev);
259 if (!mode) 259 if (!mode)
260 return NULL; 260 return NULL;
261 261
262 if (aspect_ratio == 0) 262 if (aspect_ratio == 0)
263 vsize = (hsize * 10) / 16; 263 vsize = (hsize * 10) / 16;
264 else if (aspect_ratio == 1) 264 else if (aspect_ratio == 1)
265 vsize = (hsize * 3) / 4; 265 vsize = (hsize * 3) / 4;
266 else if (aspect_ratio == 2) 266 else if (aspect_ratio == 2)
267 vsize = (hsize * 4) / 5; 267 vsize = (hsize * 4) / 5;
268 else 268 else
269 vsize = (hsize * 9) / 16; 269 vsize = (hsize * 9) / 16;
270 270
271 drm_mode_set_name(mode); 271 drm_mode_set_name(mode);
272 272
273 return mode; 273 return mode;
274 } 274 }
275 275
276 /** 276 /**
277 * drm_mode_detailed - create a new mode from an EDID detailed timing section 277 * drm_mode_detailed - create a new mode from an EDID detailed timing section
278 * @dev: DRM device (needed to create new mode) 278 * @dev: DRM device (needed to create new mode)
279 * @edid: EDID block 279 * @edid: EDID block
280 * @timing: EDID detailed timing info 280 * @timing: EDID detailed timing info
281 * @quirks: quirks to apply 281 * @quirks: quirks to apply
282 * 282 *
283 * An EDID detailed timing block contains enough info for us to create and 283 * An EDID detailed timing block contains enough info for us to create and
284 * return a new struct drm_display_mode. 284 * return a new struct drm_display_mode.
285 */ 285 */
286 static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, 286 static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
287 struct edid *edid, 287 struct edid *edid,
288 struct detailed_timing *timing, 288 struct detailed_timing *timing,
289 u32 quirks) 289 u32 quirks)
290 { 290 {
291 struct drm_display_mode *mode; 291 struct drm_display_mode *mode;
292 struct detailed_pixel_timing *pt = &timing->data.pixel_data; 292 struct detailed_pixel_timing *pt = &timing->data.pixel_data;
293 unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo; 293 unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
294 unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; 294 unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
295 unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; 295 unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
296 unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; 296 unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
297 unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo; 297 unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
298 unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo; 298 unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
299 unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf); 299 unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
300 unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; 300 unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
301 301
302 /* ignore tiny modes */ 302 /* ignore tiny modes */
303 if (hactive < 64 || vactive < 64) 303 if (hactive < 64 || vactive < 64)
304 return NULL; 304 return NULL;
305 305
306 if (pt->misc & DRM_EDID_PT_STEREO) { 306 if (pt->misc & DRM_EDID_PT_STEREO) {
307 printk(KERN_WARNING "stereo mode not supported\n"); 307 printk(KERN_WARNING "stereo mode not supported\n");
308 return NULL; 308 return NULL;
309 } 309 }
310 if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { 310 if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
311 printk(KERN_WARNING "integrated sync not supported\n"); 311 printk(KERN_WARNING "integrated sync not supported\n");
312 return NULL; 312 return NULL;
313 } 313 }
314 314
315 mode = drm_mode_create(dev); 315 mode = drm_mode_create(dev);
316 if (!mode) 316 if (!mode)
317 return NULL; 317 return NULL;
318 318
319 mode->type = DRM_MODE_TYPE_DRIVER; 319 mode->type = DRM_MODE_TYPE_DRIVER;
320 320
321 if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) 321 if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
322 timing->pixel_clock = cpu_to_le16(1088); 322 timing->pixel_clock = cpu_to_le16(1088);
323 323
324 mode->clock = le16_to_cpu(timing->pixel_clock) * 10; 324 mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
325 325
326 mode->hdisplay = hactive; 326 mode->hdisplay = hactive;
327 mode->hsync_start = mode->hdisplay + hsync_offset; 327 mode->hsync_start = mode->hdisplay + hsync_offset;
328 mode->hsync_end = mode->hsync_start + hsync_pulse_width; 328 mode->hsync_end = mode->hsync_start + hsync_pulse_width;
329 mode->htotal = mode->hdisplay + hblank; 329 mode->htotal = mode->hdisplay + hblank;
330 330
331 mode->vdisplay = vactive; 331 mode->vdisplay = vactive;
332 mode->vsync_start = mode->vdisplay + vsync_offset; 332 mode->vsync_start = mode->vdisplay + vsync_offset;
333 mode->vsync_end = mode->vsync_start + vsync_pulse_width; 333 mode->vsync_end = mode->vsync_start + vsync_pulse_width;
334 mode->vtotal = mode->vdisplay + vblank; 334 mode->vtotal = mode->vdisplay + vblank;
335 335
336 drm_mode_set_name(mode); 336 drm_mode_set_name(mode);
337 337
338 if (pt->misc & DRM_EDID_PT_INTERLACED) 338 if (pt->misc & DRM_EDID_PT_INTERLACED)
339 mode->flags |= DRM_MODE_FLAG_INTERLACE; 339 mode->flags |= DRM_MODE_FLAG_INTERLACE;
340 340
341 if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { 341 if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
342 pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; 342 pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
343 } 343 }
344 344
345 mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? 345 mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
346 DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; 346 DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
347 mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? 347 mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
348 DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; 348 DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
349 349
350 mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; 350 mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
351 mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; 351 mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
352 352
353 if (quirks & EDID_QUIRK_DETAILED_IN_CM) { 353 if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
354 mode->width_mm *= 10; 354 mode->width_mm *= 10;
355 mode->height_mm *= 10; 355 mode->height_mm *= 10;
356 } 356 }
357 357
358 if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { 358 if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
359 mode->width_mm = edid->width_cm * 10; 359 mode->width_mm = edid->width_cm * 10;
360 mode->height_mm = edid->height_cm * 10; 360 mode->height_mm = edid->height_cm * 10;
361 } 361 }
362 362
363 return mode; 363 return mode;
364 } 364 }
365 365
366 /* 366 /*
367 * Detailed mode info for the EDID "established modes" data to use. 367 * Detailed mode info for the EDID "established modes" data to use.
368 */ 368 */
369 static struct drm_display_mode edid_est_modes[] = { 369 static struct drm_display_mode edid_est_modes[] = {
370 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, 370 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
371 968, 1056, 0, 600, 601, 605, 628, 0, 371 968, 1056, 0, 600, 601, 605, 628, 0,
372 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ 372 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */
373 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, 373 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
374 896, 1024, 0, 600, 601, 603, 625, 0, 374 896, 1024, 0, 600, 601, 603, 625, 0,
375 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ 375 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */
376 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, 376 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
377 720, 840, 0, 480, 481, 484, 500, 0, 377 720, 840, 0, 480, 481, 484, 500, 0,
378 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ 378 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */
379 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, 379 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
380 704, 832, 0, 480, 489, 491, 520, 0, 380 704, 832, 0, 480, 489, 491, 520, 0,
381 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ 381 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */
382 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, 382 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704,
383 768, 864, 0, 480, 483, 486, 525, 0, 383 768, 864, 0, 480, 483, 486, 525, 0,
384 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ 384 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */
385 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, 385 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656,
386 752, 800, 0, 480, 490, 492, 525, 0, 386 752, 800, 0, 480, 490, 492, 525, 0,
387 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ 387 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */
388 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, 388 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738,
389 846, 900, 0, 400, 421, 423, 449, 0, 389 846, 900, 0, 400, 421, 423, 449, 0,
390 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ 390 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */
391 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, 391 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738,
392 846, 900, 0, 400, 412, 414, 449, 0, 392 846, 900, 0, 400, 412, 414, 449, 0,
393 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ 393 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */
394 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, 394 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
395 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, 395 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
396 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ 396 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */
397 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, 397 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040,
398 1136, 1312, 0, 768, 769, 772, 800, 0, 398 1136, 1312, 0, 768, 769, 772, 800, 0,
399 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ 399 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */
400 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, 400 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
401 1184, 1328, 0, 768, 771, 777, 806, 0, 401 1184, 1328, 0, 768, 771, 777, 806, 0,
402 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ 402 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */
403 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, 403 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
404 1184, 1344, 0, 768, 771, 777, 806, 0, 404 1184, 1344, 0, 768, 771, 777, 806, 0,
405 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ 405 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */
406 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, 406 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
407 1208, 1264, 0, 768, 768, 776, 817, 0, 407 1208, 1264, 0, 768, 768, 776, 817, 0,
408 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ 408 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */
409 { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, 409 { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
410 928, 1152, 0, 624, 625, 628, 667, 0, 410 928, 1152, 0, 624, 625, 628, 667, 0,
411 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ 411 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */
412 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, 412 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
413 896, 1056, 0, 600, 601, 604, 625, 0, 413 896, 1056, 0, 600, 601, 604, 625, 0,
414 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ 414 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */
415 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, 415 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
416 976, 1040, 0, 600, 637, 643, 666, 0, 416 976, 1040, 0, 600, 637, 643, 666, 0,
417 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ 417 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */
418 { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, 418 { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
419 1344, 1600, 0, 864, 865, 868, 900, 0, 419 1344, 1600, 0, 864, 865, 868, 900, 0,
420 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ 420 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */
421 }; 421 };
422 422
423 #define EDID_EST_TIMINGS 16 423 #define EDID_EST_TIMINGS 16
424 #define EDID_STD_TIMINGS 8 424 #define EDID_STD_TIMINGS 8
425 #define EDID_DETAILED_TIMINGS 4 425 #define EDID_DETAILED_TIMINGS 4
426 426
427 /** 427 /**
428 * add_established_modes - get est. modes from EDID and add them 428 * add_established_modes - get est. modes from EDID and add them
429 * @edid: EDID block to scan 429 * @edid: EDID block to scan
430 * 430 *
431 * Each EDID block contains a bitmap of the supported "established modes" list 431 * Each EDID block contains a bitmap of the supported "established modes" list
432 * (defined above). Tease them out and add them to the global modes list. 432 * (defined above). Tease them out and add them to the global modes list.
433 */ 433 */
434 static int add_established_modes(struct drm_connector *connector, struct edid *edid) 434 static int add_established_modes(struct drm_connector *connector, struct edid *edid)
435 { 435 {
436 struct drm_device *dev = connector->dev; 436 struct drm_device *dev = connector->dev;
437 unsigned long est_bits = edid->established_timings.t1 | 437 unsigned long est_bits = edid->established_timings.t1 |
438 (edid->established_timings.t2 << 8) | 438 (edid->established_timings.t2 << 8) |
439 ((edid->established_timings.mfg_rsvd & 0x80) << 9); 439 ((edid->established_timings.mfg_rsvd & 0x80) << 9);
440 int i, modes = 0; 440 int i, modes = 0;
441 441
442 for (i = 0; i <= EDID_EST_TIMINGS; i++) 442 for (i = 0; i <= EDID_EST_TIMINGS; i++)
443 if (est_bits & (1<<i)) { 443 if (est_bits & (1<<i)) {
444 struct drm_display_mode *newmode; 444 struct drm_display_mode *newmode;
445 newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); 445 newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
446 if (newmode) { 446 if (newmode) {
447 drm_mode_probed_add(connector, newmode); 447 drm_mode_probed_add(connector, newmode);
448 modes++; 448 modes++;
449 } 449 }
450 } 450 }
451 451
452 return modes; 452 return modes;
453 } 453 }
454 454
455 /** 455 /**
456 * add_standard_modes - get std. modes from EDID and add them 456 * add_standard_modes - get std. modes from EDID and add them
457 * @edid: EDID block to scan 457 * @edid: EDID block to scan
458 * 458 *
459 * Standard modes can be calculated using the CVT standard. Grab them from 459 * Standard modes can be calculated using the CVT standard. Grab them from
460 * @edid, calculate them, and add them to the list. 460 * @edid, calculate them, and add them to the list.
461 */ 461 */
462 static int add_standard_modes(struct drm_connector *connector, struct edid *edid) 462 static int add_standard_modes(struct drm_connector *connector, struct edid *edid)
463 { 463 {
464 struct drm_device *dev = connector->dev; 464 struct drm_device *dev = connector->dev;
465 int i, modes = 0; 465 int i, modes = 0;
466 466
467 for (i = 0; i < EDID_STD_TIMINGS; i++) { 467 for (i = 0; i < EDID_STD_TIMINGS; i++) {
468 struct std_timing *t = &edid->standard_timings[i]; 468 struct std_timing *t = &edid->standard_timings[i];
469 struct drm_display_mode *newmode; 469 struct drm_display_mode *newmode;
470 470
471 /* If std timings bytes are 1, 1 it's empty */ 471 /* If std timings bytes are 1, 1 it's empty */
472 if (t->hsize == 1 && t->vfreq_aspect == 1) 472 if (t->hsize == 1 && t->vfreq_aspect == 1)
473 continue; 473 continue;
474 474
475 newmode = drm_mode_std(dev, &edid->standard_timings[i]); 475 newmode = drm_mode_std(dev, &edid->standard_timings[i]);
476 if (newmode) { 476 if (newmode) {
477 drm_mode_probed_add(connector, newmode); 477 drm_mode_probed_add(connector, newmode);
478 modes++; 478 modes++;
479 } 479 }
480 } 480 }
481 481
482 return modes; 482 return modes;
483 } 483 }
484 484
485 /** 485 /**
486 * add_detailed_modes - get detailed mode info from EDID data 486 * add_detailed_modes - get detailed mode info from EDID data
487 * @connector: attached connector 487 * @connector: attached connector
488 * @edid: EDID block to scan 488 * @edid: EDID block to scan
489 * @quirks: quirks to apply 489 * @quirks: quirks to apply
490 * 490 *
491 * Some of the detailed timing sections may contain mode information. Grab 491 * Some of the detailed timing sections may contain mode information. Grab
492 * it and add it to the list. 492 * it and add it to the list.
493 */ 493 */
494 static int add_detailed_info(struct drm_connector *connector, 494 static int add_detailed_info(struct drm_connector *connector,
495 struct edid *edid, u32 quirks) 495 struct edid *edid, u32 quirks)
496 { 496 {
497 struct drm_device *dev = connector->dev; 497 struct drm_device *dev = connector->dev;
498 int i, j, modes = 0; 498 int i, j, modes = 0;
499 499
500 for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { 500 for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
501 struct detailed_timing *timing = &edid->detailed_timings[i]; 501 struct detailed_timing *timing = &edid->detailed_timings[i];
502 struct detailed_non_pixel *data = &timing->data.other_data; 502 struct detailed_non_pixel *data = &timing->data.other_data;
503 struct drm_display_mode *newmode; 503 struct drm_display_mode *newmode;
504 504
505 /* EDID up to and including 1.2 may put monitor info here */ 505 /* EDID up to and including 1.2 may put monitor info here */
506 if (edid->version == 1 && edid->revision < 3) 506 if (edid->version == 1 && edid->revision < 3)
507 continue; 507 continue;
508 508
509 /* Detailed mode timing */ 509 /* Detailed mode timing */
510 if (timing->pixel_clock) { 510 if (timing->pixel_clock) {
511 newmode = drm_mode_detailed(dev, edid, timing, quirks); 511 newmode = drm_mode_detailed(dev, edid, timing, quirks);
512 if (!newmode) 512 if (!newmode)
513 continue; 513 continue;
514 514
515 /* First detailed mode is preferred */ 515 /* First detailed mode is preferred */
516 if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) 516 if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
517 newmode->type |= DRM_MODE_TYPE_PREFERRED; 517 newmode->type |= DRM_MODE_TYPE_PREFERRED;
518 drm_mode_probed_add(connector, newmode); 518 drm_mode_probed_add(connector, newmode);
519 519
520 modes++; 520 modes++;
521 continue; 521 continue;
522 } 522 }
523 523
524 /* Other timing or info */ 524 /* Other timing or info */
525 switch (data->type) { 525 switch (data->type) {
526 case EDID_DETAIL_MONITOR_SERIAL: 526 case EDID_DETAIL_MONITOR_SERIAL:
527 break; 527 break;
528 case EDID_DETAIL_MONITOR_STRING: 528 case EDID_DETAIL_MONITOR_STRING:
529 break; 529 break;
530 case EDID_DETAIL_MONITOR_RANGE: 530 case EDID_DETAIL_MONITOR_RANGE:
531 /* Get monitor range data */ 531 /* Get monitor range data */
532 break; 532 break;
533 case EDID_DETAIL_MONITOR_NAME: 533 case EDID_DETAIL_MONITOR_NAME:
534 break; 534 break;
535 case EDID_DETAIL_MONITOR_CPDATA: 535 case EDID_DETAIL_MONITOR_CPDATA:
536 break; 536 break;
537 case EDID_DETAIL_STD_MODES: 537 case EDID_DETAIL_STD_MODES:
538 /* Five modes per detailed section */ 538 /* Five modes per detailed section */
539 for (j = 0; j < 5; i++) { 539 for (j = 0; j < 5; i++) {
540 struct std_timing *std; 540 struct std_timing *std;
541 struct drm_display_mode *newmode; 541 struct drm_display_mode *newmode;
542 542
543 std = &data->data.timings[j]; 543 std = &data->data.timings[j];
544 newmode = drm_mode_std(dev, std); 544 newmode = drm_mode_std(dev, std);
545 if (newmode) { 545 if (newmode) {
546 drm_mode_probed_add(connector, newmode); 546 drm_mode_probed_add(connector, newmode);
547 modes++; 547 modes++;
548 } 548 }
549 } 549 }
550 break; 550 break;
551 default: 551 default:
552 break; 552 break;
553 } 553 }
554 } 554 }
555 555
556 return modes; 556 return modes;
557 } 557 }
558 558
559 #define DDC_ADDR 0x50 559 #define DDC_ADDR 0x50
560 /** 560 /**
561 * Get EDID information via I2C. 561 * Get EDID information via I2C.
562 * 562 *
563 * \param adapter : i2c device adaptor 563 * \param adapter : i2c device adaptor
564 * \param buf : EDID data buffer to be filled 564 * \param buf : EDID data buffer to be filled
565 * \param len : EDID data buffer length 565 * \param len : EDID data buffer length
566 * \return 0 on success or -1 on failure. 566 * \return 0 on success or -1 on failure.
567 * 567 *
568 * Try to fetch EDID information by calling i2c driver function. 568 * Try to fetch EDID information by calling i2c driver function.
569 */ 569 */
570 int drm_do_probe_ddc_edid(struct i2c_adapter *adapter, 570 int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
571 unsigned char *buf, int len) 571 unsigned char *buf, int len)
572 { 572 {
573 unsigned char start = 0x0; 573 unsigned char start = 0x0;
574 struct i2c_msg msgs[] = { 574 struct i2c_msg msgs[] = {
575 { 575 {
576 .addr = DDC_ADDR, 576 .addr = DDC_ADDR,
577 .flags = 0, 577 .flags = 0,
578 .len = 1, 578 .len = 1,
579 .buf = &start, 579 .buf = &start,
580 }, { 580 }, {
581 .addr = DDC_ADDR, 581 .addr = DDC_ADDR,
582 .flags = I2C_M_RD, 582 .flags = I2C_M_RD,
583 .len = len, 583 .len = len,
584 .buf = buf, 584 .buf = buf,
585 } 585 }
586 }; 586 };
587 587
588 if (i2c_transfer(adapter, msgs, 2) == 2) 588 if (i2c_transfer(adapter, msgs, 2) == 2)
589 return 0; 589 return 0;
590 590
591 dev_info(&adapter->dev, "unable to read EDID block.\n"); 591 dev_info(&adapter->dev, "unable to read EDID block.\n");
592 return -1; 592 return -1;
593 } 593 }
594 EXPORT_SYMBOL(drm_do_probe_ddc_edid); 594 EXPORT_SYMBOL(drm_do_probe_ddc_edid);
595 595
596 static int drm_ddc_read_edid(struct drm_connector *connector, 596 static int drm_ddc_read_edid(struct drm_connector *connector,
597 struct i2c_adapter *adapter, 597 struct i2c_adapter *adapter,
598 char *buf, int len) 598 char *buf, int len)
599 { 599 {
600 int ret; 600 int ret;
601 601
602 ret = drm_do_probe_ddc_edid(adapter, buf, len); 602 ret = drm_do_probe_ddc_edid(adapter, buf, len);
603 if (ret != 0) { 603 if (ret != 0) {
604 dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n", 604 dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
605 drm_get_connector_name(connector)); 605 drm_get_connector_name(connector));
606 goto end; 606 goto end;
607 } 607 }
608 if (!edid_is_valid((struct edid *)buf)) { 608 if (!edid_is_valid((struct edid *)buf)) {
609 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", 609 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
610 drm_get_connector_name(connector)); 610 drm_get_connector_name(connector));
611 ret = -1; 611 ret = -1;
612 } 612 }
613 end: 613 end:
614 return ret; 614 return ret;
615 } 615 }
616 616
617 #define MAX_EDID_EXT_NUM 4 617 #define MAX_EDID_EXT_NUM 4
618 /** 618 /**
619 * drm_get_edid - get EDID data, if available 619 * drm_get_edid - get EDID data, if available
620 * @connector: connector we're probing 620 * @connector: connector we're probing
621 * @adapter: i2c adapter to use for DDC 621 * @adapter: i2c adapter to use for DDC
622 * 622 *
623 * Poke the given connector's i2c channel to grab EDID data if possible. 623 * Poke the given connector's i2c channel to grab EDID data if possible.
624 * 624 *
625 * Return edid data or NULL if we couldn't find any. 625 * Return edid data or NULL if we couldn't find any.
626 */ 626 */
627 struct edid *drm_get_edid(struct drm_connector *connector, 627 struct edid *drm_get_edid(struct drm_connector *connector,
628 struct i2c_adapter *adapter) 628 struct i2c_adapter *adapter)
629 { 629 {
630 int ret; 630 int ret;
631 struct edid *edid; 631 struct edid *edid;
632 632
633 edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1), 633 edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
634 GFP_KERNEL); 634 GFP_KERNEL);
635 if (edid == NULL) { 635 if (edid == NULL) {
636 dev_warn(&connector->dev->pdev->dev, 636 dev_warn(&connector->dev->pdev->dev,
637 "Failed to allocate EDID\n"); 637 "Failed to allocate EDID\n");
638 goto end; 638 goto end;
639 } 639 }
640 640
641 /* Read first EDID block */ 641 /* Read first EDID block */
642 ret = drm_ddc_read_edid(connector, adapter, 642 ret = drm_ddc_read_edid(connector, adapter,
643 (unsigned char *)edid, EDID_LENGTH); 643 (unsigned char *)edid, EDID_LENGTH);
644 if (ret != 0) 644 if (ret != 0)
645 goto clean_up; 645 goto clean_up;
646 646
647 /* There are EDID extensions to be read */ 647 /* There are EDID extensions to be read */
648 if (edid->extensions != 0) { 648 if (edid->extensions != 0) {
649 int edid_ext_num = edid->extensions; 649 int edid_ext_num = edid->extensions;
650 650
651 if (edid_ext_num > MAX_EDID_EXT_NUM) { 651 if (edid_ext_num > MAX_EDID_EXT_NUM) {
652 dev_warn(&connector->dev->pdev->dev, 652 dev_warn(&connector->dev->pdev->dev,
653 "The number of extension(%d) is " 653 "The number of extension(%d) is "
654 "over max (%d), actually read number (%d)\n", 654 "over max (%d), actually read number (%d)\n",
655 edid_ext_num, MAX_EDID_EXT_NUM, 655 edid_ext_num, MAX_EDID_EXT_NUM,
656 MAX_EDID_EXT_NUM); 656 MAX_EDID_EXT_NUM);
657 /* Reset EDID extension number to be read */ 657 /* Reset EDID extension number to be read */
658 edid_ext_num = MAX_EDID_EXT_NUM; 658 edid_ext_num = MAX_EDID_EXT_NUM;
659 } 659 }
660 /* Read EDID including extensions too */ 660 /* Read EDID including extensions too */
661 ret = drm_ddc_read_edid(connector, adapter, (char *)edid, 661 ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
662 EDID_LENGTH * (edid_ext_num + 1)); 662 EDID_LENGTH * (edid_ext_num + 1));
663 if (ret != 0) 663 if (ret != 0)
664 goto clean_up; 664 goto clean_up;
665 665
666 } 666 }
667 667
668 connector->display_info.raw_edid = (char *)edid; 668 connector->display_info.raw_edid = (char *)edid;
669 goto end; 669 goto end;
670 670
671 clean_up: 671 clean_up:
672 kfree(edid); 672 kfree(edid);
673 edid = NULL; 673 edid = NULL;
674 end: 674 end:
675 return edid; 675 return edid;
676 676
677 } 677 }
678 EXPORT_SYMBOL(drm_get_edid); 678 EXPORT_SYMBOL(drm_get_edid);
679 679
680 #define HDMI_IDENTIFIER 0x000C03 680 #define HDMI_IDENTIFIER 0x000C03
681 #define VENDOR_BLOCK 0x03 681 #define VENDOR_BLOCK 0x03
682 /** 682 /**
683 * drm_detect_hdmi_monitor - detect whether monitor is hdmi. 683 * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
684 * @edid: monitor EDID information 684 * @edid: monitor EDID information
685 * 685 *
686 * Parse the CEA extension according to CEA-861-B. 686 * Parse the CEA extension according to CEA-861-B.
687 * Return true if HDMI, false if not or unknown. 687 * Return true if HDMI, false if not or unknown.
688 */ 688 */
689 bool drm_detect_hdmi_monitor(struct edid *edid) 689 bool drm_detect_hdmi_monitor(struct edid *edid)
690 { 690 {
691 char *edid_ext = NULL; 691 char *edid_ext = NULL;
692 int i, hdmi_id, edid_ext_num; 692 int i, hdmi_id, edid_ext_num;
693 int start_offset, end_offset; 693 int start_offset, end_offset;
694 bool is_hdmi = false; 694 bool is_hdmi = false;
695 695
696 /* No EDID or EDID extensions */ 696 /* No EDID or EDID extensions */
697 if (edid == NULL || edid->extensions == 0) 697 if (edid == NULL || edid->extensions == 0)
698 goto end; 698 goto end;
699 699
700 /* Chose real EDID extension number */ 700 /* Chose real EDID extension number */
701 edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? 701 edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
702 MAX_EDID_EXT_NUM : edid->extensions; 702 MAX_EDID_EXT_NUM : edid->extensions;
703 703
704 /* Find CEA extension */ 704 /* Find CEA extension */
705 for (i = 0; i < edid_ext_num; i++) { 705 for (i = 0; i < edid_ext_num; i++) {
706 edid_ext = (char *)edid + EDID_LENGTH * (i + 1); 706 edid_ext = (char *)edid + EDID_LENGTH * (i + 1);
707 /* This block is CEA extension */ 707 /* This block is CEA extension */
708 if (edid_ext[0] == 0x02) 708 if (edid_ext[0] == 0x02)
709 break; 709 break;
710 } 710 }
711 711
712 if (i == edid_ext_num) 712 if (i == edid_ext_num)
713 goto end; 713 goto end;
714 714
715 /* Data block offset in CEA extension block */ 715 /* Data block offset in CEA extension block */
716 start_offset = 4; 716 start_offset = 4;
717 end_offset = edid_ext[2]; 717 end_offset = edid_ext[2];
718 718
719 /* 719 /*
720 * Because HDMI identifier is in Vendor Specific Block, 720 * Because HDMI identifier is in Vendor Specific Block,
721 * search it from all data blocks of CEA extension. 721 * search it from all data blocks of CEA extension.
722 */ 722 */
723 for (i = start_offset; i < end_offset; 723 for (i = start_offset; i < end_offset;
724 /* Increased by data block len */ 724 /* Increased by data block len */
725 i += ((edid_ext[i] & 0x1f) + 1)) { 725 i += ((edid_ext[i] & 0x1f) + 1)) {
726 /* Find vendor specific block */ 726 /* Find vendor specific block */
727 if ((edid_ext[i] >> 5) == VENDOR_BLOCK) { 727 if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
728 hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) | 728 hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
729 edid_ext[i + 3] << 16; 729 edid_ext[i + 3] << 16;
730 /* Find HDMI identifier */ 730 /* Find HDMI identifier */
731 if (hdmi_id == HDMI_IDENTIFIER) 731 if (hdmi_id == HDMI_IDENTIFIER)
732 is_hdmi = true; 732 is_hdmi = true;
733 break; 733 break;
734 } 734 }
735 } 735 }
736 736
737 end: 737 end:
738 return is_hdmi; 738 return is_hdmi;
739 } 739 }
740 EXPORT_SYMBOL(drm_detect_hdmi_monitor); 740 EXPORT_SYMBOL(drm_detect_hdmi_monitor);
741 741
742 /** 742 /**
743 * drm_add_edid_modes - add modes from EDID data, if available 743 * drm_add_edid_modes - add modes from EDID data, if available
744 * @connector: connector we're probing 744 * @connector: connector we're probing
745 * @edid: edid data 745 * @edid: edid data
746 * 746 *
747 * Add the specified modes to the connector's mode list. 747 * Add the specified modes to the connector's mode list.
748 * 748 *
749 * Return number of modes added or 0 if we couldn't find any. 749 * Return number of modes added or 0 if we couldn't find any.
750 */ 750 */
751 int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) 751 int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
752 { 752 {
753 int num_modes = 0; 753 int num_modes = 0;
754 u32 quirks; 754 u32 quirks;
755 755
756 if (edid == NULL) { 756 if (edid == NULL) {
757 return 0; 757 return 0;
758 } 758 }
759 if (!edid_is_valid(edid)) { 759 if (!edid_is_valid(edid)) {
760 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", 760 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
761 drm_get_connector_name(connector)); 761 drm_get_connector_name(connector));
762 return 0; 762 return 0;
763 } 763 }
764 764
765 quirks = edid_get_quirks(edid); 765 quirks = edid_get_quirks(edid);
766 766
767 num_modes += add_established_modes(connector, edid); 767 num_modes += add_established_modes(connector, edid);
768 num_modes += add_standard_modes(connector, edid); 768 num_modes += add_standard_modes(connector, edid);
769 num_modes += add_detailed_info(connector, edid, quirks); 769 num_modes += add_detailed_info(connector, edid, quirks);
770 770
771 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) 771 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
772 edid_fixup_preferred(connector, quirks); 772 edid_fixup_preferred(connector, quirks);
773 773
774 connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0; 774 connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0;
775 connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0; 775 connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0;
776 connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0; 776 connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0;
777 connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0; 777 connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0;
778 connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0; 778 connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0;
779 connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5; 779 connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5;
780 connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0; 780 connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0;
781 connector->display_info.width_mm = edid->width_cm * 10; 781 connector->display_info.width_mm = edid->width_cm * 10;
782 connector->display_info.height_mm = edid->height_cm * 10; 782 connector->display_info.height_mm = edid->height_cm * 10;
783 connector->display_info.gamma = edid->gamma; 783 connector->display_info.gamma = edid->gamma;
784 connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0; 784 connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0;
785 connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0; 785 connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0;
786 connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3; 786 connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3;
787 connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0; 787 connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0;
788 connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0; 788 connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0;
789 connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0; 789 connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0;
790 connector->display_info.gamma = edid->gamma; 790 connector->display_info.gamma = edid->gamma;
791 791
792 return num_modes; 792 return num_modes;
793 } 793 }
794 EXPORT_SYMBOL(drm_add_edid_modes); 794 EXPORT_SYMBOL(drm_add_edid_modes);
795 795
include/drm/drm_edid.h
1 /* 1 /*
2 * Copyright © 2007-2008 Intel Corporation 2 * Copyright © 2007-2008 Intel Corporation
3 * Jesse Barnes <jesse.barnes@intel.com> 3 * Jesse Barnes <jesse.barnes@intel.com>
4 * 4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a 5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"), 6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation 7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the 9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions: 10 * Software is furnished to do so, subject to the following conditions:
11 * 11 *
12 * The above copyright notice and this permission notice shall be included in 12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software. 13 * all copies or substantial portions of the Software.
14 * 14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE. 21 * OTHER DEALINGS IN THE SOFTWARE.
22 */ 22 */
23 #ifndef __DRM_EDID_H__ 23 #ifndef __DRM_EDID_H__
24 #define __DRM_EDID_H__ 24 #define __DRM_EDID_H__
25 25
26 #include <linux/types.h> 26 #include <linux/types.h>
27 27
28 #define EDID_LENGTH 128 28 #define EDID_LENGTH 128
29 #define DDC_ADDR 0x50 29 #define DDC_ADDR 0x50
30 30
31 struct est_timings { 31 struct est_timings {
32 u8 t1; 32 u8 t1;
33 u8 t2; 33 u8 t2;
34 u8 mfg_rsvd; 34 u8 mfg_rsvd;
35 } __attribute__((packed)); 35 } __attribute__((packed));
36 36
37 /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ 37 /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
38 #define EDID_TIMING_ASPECT_SHIFT 0 38 #define EDID_TIMING_ASPECT_SHIFT 6
39 #define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT) 39 #define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT)
40 40
41 /* need to add 60 */ 41 /* need to add 60 */
42 #define EDID_TIMING_VFREQ_SHIFT 2 42 #define EDID_TIMING_VFREQ_SHIFT 0
43 #define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT) 43 #define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT)
44 44
45 struct std_timing { 45 struct std_timing {
46 u8 hsize; /* need to multiply by 8 then add 248 */ 46 u8 hsize; /* need to multiply by 8 then add 248 */
47 u8 vfreq_aspect; 47 u8 vfreq_aspect;
48 } __attribute__((packed)); 48 } __attribute__((packed));
49 49
50 #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 6) 50 #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
51 #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 5) 51 #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
52 #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) 52 #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3)
53 #define DRM_EDID_PT_STEREO (1 << 2) 53 #define DRM_EDID_PT_STEREO (1 << 5)
54 #define DRM_EDID_PT_INTERLACED (1 << 1) 54 #define DRM_EDID_PT_INTERLACED (1 << 7)
55 55
56 /* If detailed data is pixel timing */ 56 /* If detailed data is pixel timing */
57 struct detailed_pixel_timing { 57 struct detailed_pixel_timing {
58 u8 hactive_lo; 58 u8 hactive_lo;
59 u8 hblank_lo; 59 u8 hblank_lo;
60 u8 hactive_hblank_hi; 60 u8 hactive_hblank_hi;
61 u8 vactive_lo; 61 u8 vactive_lo;
62 u8 vblank_lo; 62 u8 vblank_lo;
63 u8 vactive_vblank_hi; 63 u8 vactive_vblank_hi;
64 u8 hsync_offset_lo; 64 u8 hsync_offset_lo;
65 u8 hsync_pulse_width_lo; 65 u8 hsync_pulse_width_lo;
66 u8 vsync_offset_pulse_width_lo; 66 u8 vsync_offset_pulse_width_lo;
67 u8 hsync_vsync_offset_pulse_width_hi; 67 u8 hsync_vsync_offset_pulse_width_hi;
68 u8 width_mm_lo; 68 u8 width_mm_lo;
69 u8 height_mm_lo; 69 u8 height_mm_lo;
70 u8 width_height_mm_hi; 70 u8 width_height_mm_hi;
71 u8 hborder; 71 u8 hborder;
72 u8 vborder; 72 u8 vborder;
73 u8 misc; 73 u8 misc;
74 } __attribute__((packed)); 74 } __attribute__((packed));
75 75
76 /* If it's not pixel timing, it'll be one of the below */ 76 /* If it's not pixel timing, it'll be one of the below */
77 struct detailed_data_string { 77 struct detailed_data_string {
78 u8 str[13]; 78 u8 str[13];
79 } __attribute__((packed)); 79 } __attribute__((packed));
80 80
81 struct detailed_data_monitor_range { 81 struct detailed_data_monitor_range {
82 u8 min_vfreq; 82 u8 min_vfreq;
83 u8 max_vfreq; 83 u8 max_vfreq;
84 u8 min_hfreq_khz; 84 u8 min_hfreq_khz;
85 u8 max_hfreq_khz; 85 u8 max_hfreq_khz;
86 u8 pixel_clock_mhz; /* need to multiply by 10 */ 86 u8 pixel_clock_mhz; /* need to multiply by 10 */
87 __le16 sec_gtf_toggle; /* A000=use above, 20=use below */ 87 __le16 sec_gtf_toggle; /* A000=use above, 20=use below */
88 u8 hfreq_start_khz; /* need to multiply by 2 */ 88 u8 hfreq_start_khz; /* need to multiply by 2 */
89 u8 c; /* need to divide by 2 */ 89 u8 c; /* need to divide by 2 */
90 __le16 m; 90 __le16 m;
91 u8 k; 91 u8 k;
92 u8 j; /* need to divide by 2 */ 92 u8 j; /* need to divide by 2 */
93 } __attribute__((packed)); 93 } __attribute__((packed));
94 94
95 struct detailed_data_wpindex { 95 struct detailed_data_wpindex {
96 u8 white_xy_lo; /* Upper 2 bits each */ 96 u8 white_yx_lo; /* Lower 2 bits each */
97 u8 white_x_hi; 97 u8 white_x_hi;
98 u8 white_y_hi; 98 u8 white_y_hi;
99 u8 gamma; /* need to divide by 100 then add 1 */ 99 u8 gamma; /* need to divide by 100 then add 1 */
100 } __attribute__((packed)); 100 } __attribute__((packed));
101 101
102 struct detailed_data_color_point { 102 struct detailed_data_color_point {
103 u8 windex1; 103 u8 windex1;
104 u8 wpindex1[3]; 104 u8 wpindex1[3];
105 u8 windex2; 105 u8 windex2;
106 u8 wpindex2[3]; 106 u8 wpindex2[3];
107 } __attribute__((packed)); 107 } __attribute__((packed));
108 108
109 struct detailed_non_pixel { 109 struct detailed_non_pixel {
110 u8 pad1; 110 u8 pad1;
111 u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name 111 u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
112 fb=color point data, fa=standard timing data, 112 fb=color point data, fa=standard timing data,
113 f9=undefined, f8=mfg. reserved */ 113 f9=undefined, f8=mfg. reserved */
114 u8 pad2; 114 u8 pad2;
115 union { 115 union {
116 struct detailed_data_string str; 116 struct detailed_data_string str;
117 struct detailed_data_monitor_range range; 117 struct detailed_data_monitor_range range;
118 struct detailed_data_wpindex color; 118 struct detailed_data_wpindex color;
119 struct std_timing timings[5]; 119 struct std_timing timings[5];
120 } data; 120 } data;
121 } __attribute__((packed)); 121 } __attribute__((packed));
122 122
123 #define EDID_DETAIL_STD_MODES 0xfa 123 #define EDID_DETAIL_STD_MODES 0xfa
124 #define EDID_DETAIL_MONITOR_CPDATA 0xfb 124 #define EDID_DETAIL_MONITOR_CPDATA 0xfb
125 #define EDID_DETAIL_MONITOR_NAME 0xfc 125 #define EDID_DETAIL_MONITOR_NAME 0xfc
126 #define EDID_DETAIL_MONITOR_RANGE 0xfd 126 #define EDID_DETAIL_MONITOR_RANGE 0xfd
127 #define EDID_DETAIL_MONITOR_STRING 0xfe 127 #define EDID_DETAIL_MONITOR_STRING 0xfe
128 #define EDID_DETAIL_MONITOR_SERIAL 0xff 128 #define EDID_DETAIL_MONITOR_SERIAL 0xff
129 129
130 struct detailed_timing { 130 struct detailed_timing {
131 __le16 pixel_clock; /* need to multiply by 10 KHz */ 131 __le16 pixel_clock; /* need to multiply by 10 KHz */
132 union { 132 union {
133 struct detailed_pixel_timing pixel_data; 133 struct detailed_pixel_timing pixel_data;
134 struct detailed_non_pixel other_data; 134 struct detailed_non_pixel other_data;
135 } data; 135 } data;
136 } __attribute__((packed)); 136 } __attribute__((packed));
137 137
138 #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 7) 138 #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0)
139 #define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 5) 139 #define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 1)
140 #define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 4) 140 #define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 2)
141 #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3) 141 #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3)
142 #define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 2) 142 #define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4)
143 #define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 1) 143 #define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5)
144 #define DRM_EDID_INPUT_DIGITAL (1 << 0) /* bits above must be zero if set */ 144 #define DRM_EDID_INPUT_DIGITAL (1 << 7) /* bits below must be zero if set */
145 145
146 #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 7) 146 #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0)
147 #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 6) 147 #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)
148 #define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 5) 148 #define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2)
149 #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ 149 #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
150 #define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 2) 150 #define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 5)
151 #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 1) 151 #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6)
152 #define DRM_EDID_FEATURE_PM_STANDBY (1 << 0) 152 #define DRM_EDID_FEATURE_PM_STANDBY (1 << 7)
153 153
154 struct edid { 154 struct edid {
155 u8 header[8]; 155 u8 header[8];
156 /* Vendor & product info */ 156 /* Vendor & product info */
157 u8 mfg_id[2]; 157 u8 mfg_id[2];
158 u8 prod_code[2]; 158 u8 prod_code[2];
159 u32 serial; /* FIXME: byte order */ 159 u32 serial; /* FIXME: byte order */
160 u8 mfg_week; 160 u8 mfg_week;
161 u8 mfg_year; 161 u8 mfg_year;
162 /* EDID version */ 162 /* EDID version */
163 u8 version; 163 u8 version;
164 u8 revision; 164 u8 revision;
165 /* Display info: */ 165 /* Display info: */
166 u8 input; 166 u8 input;
167 u8 width_cm; 167 u8 width_cm;
168 u8 height_cm; 168 u8 height_cm;
169 u8 gamma; 169 u8 gamma;
170 u8 features; 170 u8 features;
171 /* Color characteristics */ 171 /* Color characteristics */
172 u8 red_green_lo; 172 u8 red_green_lo;
173 u8 black_white_lo; 173 u8 black_white_lo;
174 u8 red_x; 174 u8 red_x;
175 u8 red_y; 175 u8 red_y;
176 u8 green_x; 176 u8 green_x;
177 u8 green_y; 177 u8 green_y;
178 u8 blue_x; 178 u8 blue_x;
179 u8 blue_y; 179 u8 blue_y;
180 u8 white_x; 180 u8 white_x;
181 u8 white_y; 181 u8 white_y;
182 /* Est. timings and mfg rsvd timings*/ 182 /* Est. timings and mfg rsvd timings*/
183 struct est_timings established_timings; 183 struct est_timings established_timings;
184 /* Standard timings 1-8*/ 184 /* Standard timings 1-8*/
185 struct std_timing standard_timings[8]; 185 struct std_timing standard_timings[8];
186 /* Detailing timings 1-4 */ 186 /* Detailing timings 1-4 */
187 struct detailed_timing detailed_timings[4]; 187 struct detailed_timing detailed_timings[4];
188 /* Number of 128 byte ext. blocks */ 188 /* Number of 128 byte ext. blocks */
189 u8 extensions; 189 u8 extensions;
190 /* Checksum */ 190 /* Checksum */
191 u8 checksum; 191 u8 checksum;
192 } __attribute__((packed)); 192 } __attribute__((packed));
193 193
194 #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8)) 194 #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
195 195
196 #endif /* __DRM_EDID_H__ */ 196 #endif /* __DRM_EDID_H__ */
197 197