/[pkgs]/devel/kernel/drm-next.patch
ViewVC logotype

Contents of /devel/kernel/drm-next.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (show annotations) (download) (as text)
Tue Sep 8 22:51:11 2009 UTC (2 months, 2 weeks ago) by airlied
Branch: MAIN
CVS Tags: kernel-2_6_32-0_24_rc4_git0_fc13, kernel-2_6_32-0_47_rc7_git1_fc13, kernel-2_6_32-0_46_rc7_git1_fc13, kernel-2_6_31-0_213_rc9_git1_fc12, kernel-2_6_32-0_48_rc7_git1_fc13, kernel-2_6_32-0_14_rc0_git18_fc13, kernel-2_6_32-0_5_rc0_git4_fc13, kernel-2_6_32-0_33_rc5_git1_fc13, F-12-split, kernel-2_6_32-0_51_rc7_git2_fc13, kernel-2_6_31-0_219_rc9_git2_fc12, kernel-2_6_31-2_fc12, kernel-2_6_31-1_fc12, kernel-2_6_32-0_15_rc1_git0_fc13, kernel-2_6_31-0_218_rc9_git2_fc12, kernel-2_6_31-0_214_rc9_git1_fc12, kernel-2_6_32-0_39_rc5_git6_fc13, HEAD
Changes since 1.17: +23 -15 lines
File MIME type: text/x-patch
* Wed Sep 09 2009 Dave Airlie <airlied@redhat.com> 2.6.31-0.213.rc9.git1
- fix two bugs in r600 kms, fencing + mobile lvds
1 diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
2 index 39b393d..e4d971c 100644
3 --- a/drivers/gpu/drm/Kconfig
4 +++ b/drivers/gpu/drm/Kconfig
5 @@ -18,6 +18,14 @@ menuconfig DRM
6 details. You should also select and configure AGP
7 (/dev/agpgart) support.
8
9 +config DRM_KMS_HELPER
10 + tristate
11 + depends on DRM
12 + select FB
13 + select FRAMEBUFFER_CONSOLE if !EMBEDDED
14 + help
15 + FB and CRTC helpers for KMS drivers.
16 +
17 config DRM_TTM
18 tristate
19 depends on DRM
20 @@ -36,6 +44,7 @@ config DRM_TDFX
21 config DRM_R128
22 tristate "ATI Rage 128"
23 depends on DRM && PCI
24 + select FW_LOADER
25 help
26 Choose this option if you have an ATI Rage 128 graphics card. If M
27 is selected, the module will be called r128. AGP support for
28 @@ -47,8 +56,9 @@ config DRM_RADEON
29 select FB_CFB_FILLRECT
30 select FB_CFB_COPYAREA
31 select FB_CFB_IMAGEBLIT
32 - select FB
33 - select FRAMEBUFFER_CONSOLE if !EMBEDDED
34 + select FW_LOADER
35 + select DRM_KMS_HELPER
36 + select DRM_TTM
37 help
38 Choose this option if you have an ATI Radeon graphics card. There
39 are both PCI and AGP versions. You don't need to choose this to
40 @@ -82,11 +92,10 @@ config DRM_I830
41 config DRM_I915
42 tristate "i915 driver"
43 depends on AGP_INTEL
44 + select DRM_KMS_HELPER
45 select FB_CFB_FILLRECT
46 select FB_CFB_COPYAREA
47 select FB_CFB_IMAGEBLIT
48 - select FB
49 - select FRAMEBUFFER_CONSOLE if !EMBEDDED
50 # i915 depends on ACPI_VIDEO when ACPI is enabled
51 # but for select to work, need to select ACPI_VIDEO's dependencies, ick
52 select VIDEO_OUTPUT_CONTROL if ACPI
53 @@ -116,6 +125,7 @@ endchoice
54 config DRM_MGA
55 tristate "Matrox g200/g400"
56 depends on DRM
57 + select FW_LOADER
58 help
59 Choose this option if you have a Matrox G200, G400 or G450 graphics
60 card. If M is selected, the module will be called mga. AGP
61 diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
62 index fe23f29..3c8827a 100644
63 --- a/drivers/gpu/drm/Makefile
64 +++ b/drivers/gpu/drm/Makefile
65 @@ -10,11 +10,15 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
66 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
67 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
68 drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
69 - drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o \
70 - drm_info.o drm_debugfs.o
71 + drm_crtc.o drm_modes.o drm_edid.o \
72 + drm_info.o drm_debugfs.o drm_encoder_slave.o
73
74 drm-$(CONFIG_COMPAT) += drm_ioc32.o
75
76 +drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o
77 +
78 +obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
79 +
80 obj-$(CONFIG_DRM) += drm.o
81 obj-$(CONFIG_DRM_TTM) += ttm/
82 obj-$(CONFIG_DRM_TDFX) += tdfx/
83 diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
84 index 0e994a0..0e3bd5b 100644
85 --- a/drivers/gpu/drm/drm_cache.c
86 +++ b/drivers/gpu/drm/drm_cache.c
87 @@ -45,6 +45,23 @@ drm_clflush_page(struct page *page)
88 clflush(page_virtual + i);
89 kunmap_atomic(page_virtual, KM_USER0);
90 }
91 +
92 +static void drm_cache_flush_clflush(struct page *pages[],
93 + unsigned long num_pages)
94 +{
95 + unsigned long i;
96 +
97 + mb();
98 + for (i = 0; i < num_pages; i++)
99 + drm_clflush_page(*pages++);
100 + mb();
101 +}
102 +
103 +static void
104 +drm_clflush_ipi_handler(void *null)
105 +{
106 + wbinvd();
107 +}
108 #endif
109
110 void
111 @@ -53,17 +70,30 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
112
113 #if defined(CONFIG_X86)
114 if (cpu_has_clflush) {
115 - unsigned long i;
116 -
117 - mb();
118 - for (i = 0; i < num_pages; ++i)
119 - drm_clflush_page(*pages++);
120 - mb();
121 -
122 + drm_cache_flush_clflush(pages, num_pages);
123 return;
124 }
125
126 - wbinvd();
127 + if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
128 + printk(KERN_ERR "Timed out waiting for cache flush.\n");
129 +
130 +#elif defined(__powerpc__)
131 + unsigned long i;
132 + for (i = 0; i < num_pages; i++) {
133 + struct page *page = pages[i];
134 + void *page_virtual;
135 +
136 + if (unlikely(page == NULL))
137 + continue;
138 +
139 + page_virtual = kmap_atomic(page, KM_USER0);
140 + flush_dcache_range((unsigned long)page_virtual,
141 + (unsigned long)page_virtual + PAGE_SIZE);
142 + kunmap_atomic(page_virtual, KM_USER0);
143 + }
144 +#else
145 + printk(KERN_ERR "Architecture has no drm_cache.c support\n");
146 + WARN_ON_ONCE(1);
147 #endif
148 }
149 EXPORT_SYMBOL(drm_clflush_pages);
150 diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
151 index 2f631c7..ba728ad 100644
152 --- a/drivers/gpu/drm/drm_crtc.c
153 +++ b/drivers/gpu/drm/drm_crtc.c
154 @@ -68,10 +68,10 @@ DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
155 */
156 static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
157 {
158 - { DRM_MODE_SCALE_NON_GPU, "Non-GPU" },
159 - { DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" },
160 - { DRM_MODE_SCALE_NO_SCALE, "No scale" },
161 - { DRM_MODE_SCALE_ASPECT, "Aspect" },
162 + { DRM_MODE_SCALE_NONE, "None" },
163 + { DRM_MODE_SCALE_FULLSCREEN, "Full" },
164 + { DRM_MODE_SCALE_CENTER, "Center" },
165 + { DRM_MODE_SCALE_ASPECT, "Full aspect" },
166 };
167
168 static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
169 @@ -108,6 +108,7 @@ static struct drm_prop_enum_list drm_tv_select_enum_list[] =
170 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
171 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
172 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
173 + { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
174 };
175
176 DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
177 @@ -118,6 +119,7 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
178 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
179 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
180 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
181 + { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
182 };
183
184 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
185 @@ -146,6 +148,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
186 { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
187 { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
188 { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
189 + { DRM_MODE_CONNECTOR_TV, "TV", 0 },
190 };
191
192 static struct drm_prop_enum_list drm_encoder_enum_list[] =
193 @@ -165,6 +168,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder)
194 encoder->base.id);
195 return buf;
196 }
197 +EXPORT_SYMBOL(drm_get_encoder_name);
198
199 char *drm_get_connector_name(struct drm_connector *connector)
200 {
201 @@ -699,6 +703,42 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
202 drm_property_add_enum(dev->mode_config.tv_mode_property, i,
203 i, modes[i]);
204
205 + dev->mode_config.tv_brightness_property =
206 + drm_property_create(dev, DRM_MODE_PROP_RANGE,
207 + "brightness", 2);
208 + dev->mode_config.tv_brightness_property->values[0] = 0;
209 + dev->mode_config.tv_brightness_property->values[1] = 100;
210 +
211 + dev->mode_config.tv_contrast_property =
212 + drm_property_create(dev, DRM_MODE_PROP_RANGE,
213 + "contrast", 2);
214 + dev->mode_config.tv_contrast_property->values[0] = 0;
215 + dev->mode_config.tv_contrast_property->values[1] = 100;
216 +
217 + dev->mode_config.tv_flicker_reduction_property =
218 + drm_property_create(dev, DRM_MODE_PROP_RANGE,
219 + "flicker reduction", 2);
220 + dev->mode_config.tv_flicker_reduction_property->values[0] = 0;
221 + dev->mode_config.tv_flicker_reduction_property->values[1] = 100;
222 +
223 + dev->mode_config.tv_overscan_property =
224 + drm_property_create(dev, DRM_MODE_PROP_RANGE,
225 + "overscan", 2);
226 + dev->mode_config.tv_overscan_property->values[0] = 0;
227 + dev->mode_config.tv_overscan_property->values[1] = 100;
228 +
229 + dev->mode_config.tv_saturation_property =
230 + drm_property_create(dev, DRM_MODE_PROP_RANGE,
231 + "saturation", 2);
232 + dev->mode_config.tv_saturation_property->values[0] = 0;
233 + dev->mode_config.tv_saturation_property->values[1] = 100;
234 +
235 + dev->mode_config.tv_hue_property =
236 + drm_property_create(dev, DRM_MODE_PROP_RANGE,
237 + "hue", 2);
238 + dev->mode_config.tv_hue_property->values[0] = 0;
239 + dev->mode_config.tv_hue_property->values[1] = 100;
240 +
241 return 0;
242 }
243 EXPORT_SYMBOL(drm_mode_create_tv_properties);
244 @@ -1044,7 +1084,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
245 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
246 list_for_each_entry(crtc, &dev->mode_config.crtc_list,
247 head) {
248 - DRM_DEBUG("CRTC ID is %d\n", crtc->base.id);
249 + DRM_DEBUG_KMS("CRTC ID is %d\n", crtc->base.id);
250 if (put_user(crtc->base.id, crtc_id + copied)) {
251 ret = -EFAULT;
252 goto out;
253 @@ -1072,7 +1112,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
254 list_for_each_entry(encoder,
255 &dev->mode_config.encoder_list,
256 head) {
257 - DRM_DEBUG("ENCODER ID is %d\n",
258 + DRM_DEBUG_KMS("ENCODER ID is %d\n",
259 encoder->base.id);
260 if (put_user(encoder->base.id, encoder_id +
261 copied)) {
262 @@ -1103,7 +1143,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
263 list_for_each_entry(connector,
264 &dev->mode_config.connector_list,
265 head) {
266 - DRM_DEBUG("CONNECTOR ID is %d\n",
267 + DRM_DEBUG_KMS("CONNECTOR ID is %d\n",
268 connector->base.id);
269 if (put_user(connector->base.id,
270 connector_id + copied)) {
271 @@ -1127,7 +1167,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
272 }
273 card_res->count_connectors = connector_count;
274
275 - DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs,
276 + DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs,
277 card_res->count_connectors, card_res->count_encoders);
278
279 out:
280 @@ -1230,7 +1270,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
281
282 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
283
284 - DRM_DEBUG("connector id %d:\n", out_resp->connector_id);
285 + DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id);
286
287 mutex_lock(&dev->mode_config.mutex);
288
289 @@ -1406,7 +1446,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
290 obj = drm_mode_object_find(dev, crtc_req->crtc_id,
291 DRM_MODE_OBJECT_CRTC);
292 if (!obj) {
293 - DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id);
294 + DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
295 ret = -EINVAL;
296 goto out;
297 }
298 @@ -1419,7 +1459,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
299 list_for_each_entry(crtcfb,
300 &dev->mode_config.crtc_list, head) {
301 if (crtcfb == crtc) {
302 - DRM_DEBUG("Using current fb for setmode\n");
303 + DRM_DEBUG_KMS("Using current fb for "
304 + "setmode\n");
305 fb = crtc->fb;
306 }
307 }
308 @@ -1427,7 +1468,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
309 obj = drm_mode_object_find(dev, crtc_req->fb_id,
310 DRM_MODE_OBJECT_FB);
311 if (!obj) {
312 - DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id);
313 + DRM_DEBUG_KMS("Unknown FB ID%d\n",
314 + crtc_req->fb_id);
315 ret = -EINVAL;
316 goto out;
317 }
318 @@ -1440,13 +1482,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
319 }
320
321 if (crtc_req->count_connectors == 0 && mode) {
322 - DRM_DEBUG("Count connectors is 0 but mode set\n");
323 + DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
324 ret = -EINVAL;
325 goto out;
326 }
327
328 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
329 - DRM_DEBUG("Count connectors is %d but no mode or fb set\n",
330 + DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
331 crtc_req->count_connectors);
332 ret = -EINVAL;
333 goto out;
334 @@ -1479,7 +1521,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
335 obj = drm_mode_object_find(dev, out_id,
336 DRM_MODE_OBJECT_CONNECTOR);
337 if (!obj) {
338 - DRM_DEBUG("Connector id %d unknown\n", out_id);
339 + DRM_DEBUG_KMS("Connector id %d unknown\n",
340 + out_id);
341 ret = -EINVAL;
342 goto out;
343 }
344 @@ -1512,7 +1555,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
345 struct drm_crtc *crtc;
346 int ret = 0;
347
348 - DRM_DEBUG("\n");
349 + DRM_DEBUG_KMS("\n");
350
351 if (!req->flags) {
352 DRM_ERROR("no operation set\n");
353 @@ -1522,7 +1565,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
354 mutex_lock(&dev->mode_config.mutex);
355 obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
356 if (!obj) {
357 - DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc_id);
358 + DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
359 ret = -EINVAL;
360 goto out;
361 }
362 diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
363 index 6aaa2cb..ff447f1 100644
364 --- a/drivers/gpu/drm/drm_crtc_helper.c
365 +++ b/drivers/gpu/drm/drm_crtc_helper.c
366 @@ -33,15 +33,6 @@
367 #include "drm_crtc.h"
368 #include "drm_crtc_helper.h"
369
370 -/*
371 - * Detailed mode info for 800x600@60Hz
372 - */
373 -static struct drm_display_mode std_modes[] = {
374 - { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
375 - 968, 1056, 0, 600, 601, 605, 628, 0,
376 - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
377 -};
378 -
379 static void drm_mode_validate_flag(struct drm_connector *connector,
380 int flags)
381 {
382 @@ -94,7 +85,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
383 int count = 0;
384 int mode_flags = 0;
385
386 - DRM_DEBUG("%s\n", drm_get_connector_name(connector));
387 + DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
388 /* set all modes to the unverified state */
389 list_for_each_entry_safe(mode, t, &connector->modes, head)
390 mode->status = MODE_UNVERIFIED;
391 @@ -102,15 +93,17 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
392 connector->status = connector->funcs->detect(connector);
393
394 if (connector->status == connector_status_disconnected) {
395 - DRM_DEBUG("%s is disconnected\n",
396 + DRM_DEBUG_KMS("%s is disconnected\n",
397 drm_get_connector_name(connector));
398 - /* TODO set EDID to NULL */
399 - return 0;
400 + goto prune;
401 }
402
403 count = (*connector_funcs->get_modes)(connector);
404 - if (!count)
405 - return 0;
406 + if (!count) {
407 + count = drm_add_modes_noedid(connector, 800, 600);
408 + if (!count)
409 + return 0;
410 + }
411
412 drm_mode_connector_list_update(connector);
413
414 @@ -130,7 +123,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
415 mode);
416 }
417
418 -
419 +prune:
420 drm_mode_prune_invalid(dev, &connector->modes, true);
421
422 if (list_empty(&connector->modes))
423 @@ -138,7 +131,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
424
425 drm_mode_sort(&connector->modes);
426
427 - DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
428 + DRM_DEBUG_KMS("Probed modes for %s\n",
429 + drm_get_connector_name(connector));
430 list_for_each_entry_safe(mode, t, &connector->modes, head) {
431 mode->vrefresh = drm_mode_vrefresh(mode);
432
433 @@ -165,39 +159,6 @@ int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
434 }
435 EXPORT_SYMBOL(drm_helper_probe_connector_modes);
436
437 -static void drm_helper_add_std_modes(struct drm_device *dev,
438 - struct drm_connector *connector)
439 -{
440 - struct drm_display_mode *mode, *t;
441 - int i;
442 -
443 - for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
444 - struct drm_display_mode *stdmode;
445 -
446 - /*
447 - * When no valid EDID modes are available we end up
448 - * here and bailed in the past, now we add some standard
449 - * modes and move on.
450 - */
451 - stdmode = drm_mode_duplicate(dev, &std_modes[i]);
452 - drm_mode_probed_add(connector, stdmode);
453 - drm_mode_list_concat(&connector->probed_modes,
454 - &connector->modes);
455 -
456 - DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
457 - drm_get_connector_name(connector));
458 - }
459 - drm_mode_sort(&connector->modes);
460 -
461 - DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
462 - list_for_each_entry_safe(mode, t, &connector->modes, head) {
463 - mode->vrefresh = drm_mode_vrefresh(mode);
464 -
465 - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
466 - drm_mode_debug_printmodeline(mode);
467 - }
468 -}
469 -
470 /**
471 * drm_helper_encoder_in_use - check if a given encoder is in use
472 * @encoder: encoder to check
473 @@ -258,13 +219,27 @@ EXPORT_SYMBOL(drm_helper_crtc_in_use);
474 void drm_helper_disable_unused_functions(struct drm_device *dev)
475 {
476 struct drm_encoder *encoder;
477 + struct drm_connector *connector;
478 struct drm_encoder_helper_funcs *encoder_funcs;
479 struct drm_crtc *crtc;
480
481 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
482 + if (!connector->encoder)
483 + continue;
484 + if (connector->status == connector_status_disconnected)
485 + connector->encoder = NULL;
486 + }
487 +
488 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
489 encoder_funcs = encoder->helper_private;
490 - if (!drm_helper_encoder_in_use(encoder))
491 - (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
492 + if (!drm_helper_encoder_in_use(encoder)) {
493 + if (encoder_funcs->disable)
494 + (*encoder_funcs->disable)(encoder);
495 + else
496 + (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
497 + /* disconnector encoder from any connector */
498 + encoder->crtc = NULL;
499 + }
500 }
501
502 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
503 @@ -312,7 +287,7 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled)
504
505 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
506 enabled[i] = drm_connector_enabled(connector, true);
507 - DRM_DEBUG("connector %d enabled? %s\n", connector->base.id,
508 + DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
509 enabled[i] ? "yes" : "no");
510 any_enabled |= enabled[i];
511 i++;
512 @@ -342,7 +317,7 @@ static bool drm_target_preferred(struct drm_device *dev,
513 continue;
514 }
515
516 - DRM_DEBUG("looking for preferred mode on connector %d\n",
517 + DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
518 connector->base.id);
519
520 modes[i] = drm_has_preferred_mode(connector, width, height);
521 @@ -351,7 +326,7 @@ static bool drm_target_preferred(struct drm_device *dev,
522 list_for_each_entry(modes[i], &connector->modes, head)
523 break;
524 }
525 - DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
526 + DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
527 "none");
528 i++;
529 }
530 @@ -409,7 +384,7 @@ static int drm_pick_crtcs(struct drm_device *dev,
531 c = 0;
532 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
533
534 - if ((connector->encoder->possible_crtcs & (1 << c)) == 0) {
535 + if ((encoder->possible_crtcs & (1 << c)) == 0) {
536 c++;
537 continue;
538 }
539 @@ -452,7 +427,7 @@ static void drm_setup_crtcs(struct drm_device *dev)
540 int width, height;
541 int i, ret;
542
543 - DRM_DEBUG("\n");
544 + DRM_DEBUG_KMS("\n");
545
546 width = dev->mode_config.max_width;
547 height = dev->mode_config.max_height;
548 @@ -475,7 +450,7 @@ static void drm_setup_crtcs(struct drm_device *dev)
549 if (!ret)
550 DRM_ERROR("Unable to find initial modes\n");
551
552 - DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
553 + DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
554
555 drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
556
557 @@ -490,12 +465,14 @@ static void drm_setup_crtcs(struct drm_device *dev)
558 }
559
560 if (mode && crtc) {
561 - DRM_DEBUG("desired mode %s set on crtc %d\n",
562 + DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
563 mode->name, crtc->base.id);
564 crtc->desired_mode = mode;
565 connector->encoder->crtc = crtc;
566 - } else
567 + } else {
568 connector->encoder->crtc = NULL;
569 + connector->encoder = NULL;
570 + }
571 i++;
572 }
573
574 @@ -702,18 +679,17 @@ EXPORT_SYMBOL(drm_crtc_helper_set_mode);
575 int drm_crtc_helper_set_config(struct drm_mode_set *set)
576 {
577 struct drm_device *dev;
578 - struct drm_crtc **save_crtcs, *new_crtc;
579 - struct drm_encoder **save_encoders, *new_encoder;
580 + struct drm_crtc *save_crtcs, *new_crtc, *crtc;
581 + struct drm_encoder *save_encoders, *new_encoder, *encoder;
582 struct drm_framebuffer *old_fb = NULL;
583 - bool save_enabled;
584 bool mode_changed = false; /* if true do a full mode set */
585 bool fb_changed = false; /* if true and !mode_changed just do a flip */
586 - struct drm_connector *connector;
587 + struct drm_connector *save_connectors, *connector;
588 int count = 0, ro, fail = 0;
589 struct drm_crtc_helper_funcs *crtc_funcs;
590 int ret = 0;
591
592 - DRM_DEBUG("\n");
593 + DRM_DEBUG_KMS("\n");
594
595 if (!set)
596 return -EINVAL;
597 @@ -726,37 +702,60 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
598
599 crtc_funcs = set->crtc->helper_private;
600
601 - DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n",
602 + DRM_DEBUG_KMS("crtc: %p %d fb: %p connectors: %p num_connectors:"
603 + " %d (x, y) (%i, %i)\n",
604 set->crtc, set->crtc->base.id, set->fb, set->connectors,
605 (int)set->num_connectors, set->x, set->y);
606
607 dev = set->crtc->dev;
608
609 - /* save previous config */
610 - save_enabled = set->crtc->enabled;
611 -
612 - /*
613 - * We do mode_config.num_connectors here since we'll look at the
614 - * CRTC and encoder associated with each connector later.
615 - */
616 - save_crtcs = kzalloc(dev->mode_config.num_connector *
617 - sizeof(struct drm_crtc *), GFP_KERNEL);
618 + /* Allocate space for the backup of all (non-pointer) crtc, encoder and
619 + * connector data. */
620 + save_crtcs = kzalloc(dev->mode_config.num_crtc *
621 + sizeof(struct drm_crtc), GFP_KERNEL);
622 if (!save_crtcs)
623 return -ENOMEM;
624
625 - save_encoders = kzalloc(dev->mode_config.num_connector *
626 - sizeof(struct drm_encoders *), GFP_KERNEL);
627 + save_encoders = kzalloc(dev->mode_config.num_encoder *
628 + sizeof(struct drm_encoder), GFP_KERNEL);
629 if (!save_encoders) {
630 kfree(save_crtcs);
631 return -ENOMEM;
632 }
633
634 + save_connectors = kzalloc(dev->mode_config.num_connector *
635 + sizeof(struct drm_connector), GFP_KERNEL);
636 + if (!save_connectors) {
637 + kfree(save_crtcs);
638 + kfree(save_encoders);
639 + return -ENOMEM;
640 + }
641 +
642 + /* Copy data. Note that driver private data is not affected.
643 + * Should anything bad happen only the expected state is
644 + * restored, not the drivers personal bookkeeping.
645 + */
646 + count = 0;
647 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
648 + save_crtcs[count++] = *crtc;
649 + }
650 +
651 + count = 0;
652 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
653 + save_encoders[count++] = *encoder;
654 + }
655 +
656 + count = 0;
657 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
658 + save_connectors[count++] = *connector;
659 + }
660 +
661 /* We should be able to check here if the fb has the same properties
662 * and then just flip_or_move it */
663 if (set->crtc->fb != set->fb) {
664 /* If we have no fb then treat it as a full mode set */
665 if (set->crtc->fb == NULL) {
666 - DRM_DEBUG("crtc has no fb, full mode set\n");
667 + DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
668 mode_changed = true;
669 } else if (set->fb == NULL) {
670 mode_changed = true;
671 @@ -772,7 +771,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
672 fb_changed = true;
673
674 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
675 - DRM_DEBUG("modes are different, full mode set\n");
676 + DRM_DEBUG_KMS("modes are different, full mode set\n");
677 drm_mode_debug_printmodeline(&set->crtc->mode);
678 drm_mode_debug_printmodeline(set->mode);
679 mode_changed = true;
680 @@ -783,7 +782,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
681 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
682 struct drm_connector_helper_funcs *connector_funcs =
683 connector->helper_private;
684 - save_encoders[count++] = connector->encoder;
685 new_encoder = connector->encoder;
686 for (ro = 0; ro < set->num_connectors; ro++) {
687 if (set->connectors[ro] == connector) {
688 @@ -798,15 +796,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
689 }
690
691 if (new_encoder != connector->encoder) {
692 - DRM_DEBUG("encoder changed, full mode switch\n");
693 + DRM_DEBUG_KMS("encoder changed, full mode switch\n");
694 mode_changed = true;
695 + /* If the encoder is reused for another connector, then
696 + * the appropriate crtc will be set later.
697 + */
698 + if (connector->encoder)
699 + connector->encoder->crtc = NULL;
700 connector->encoder = new_encoder;
701 }
702 }
703
704 if (fail) {
705 ret = -EINVAL;
706 - goto fail_no_encoder;
707 + goto fail;
708 }
709
710 count = 0;
711 @@ -814,8 +817,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
712 if (!connector->encoder)
713 continue;
714
715 - save_crtcs[count++] = connector->encoder->crtc;
716 -
717 if (connector->encoder->crtc == set->crtc)
718 new_crtc = NULL;
719 else
720 @@ -830,14 +831,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
721 if (new_crtc &&
722 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
723 ret = -EINVAL;
724 - goto fail_set_mode;
725 + goto fail;
726 }
727 if (new_crtc != connector->encoder->crtc) {
728 - DRM_DEBUG("crtc changed, full mode switch\n");
729 + DRM_DEBUG_KMS("crtc changed, full mode switch\n");
730 mode_changed = true;
731 connector->encoder->crtc = new_crtc;
732 }
733 - DRM_DEBUG("setting connector %d crtc to %p\n",
734 + DRM_DEBUG_KMS("setting connector %d crtc to %p\n",
735 connector->base.id, new_crtc);
736 }
737
738 @@ -850,7 +851,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
739 set->crtc->fb = set->fb;
740 set->crtc->enabled = (set->mode != NULL);
741 if (set->mode != NULL) {
742 - DRM_DEBUG("attempting to set mode from userspace\n");
743 + DRM_DEBUG_KMS("attempting to set mode from"
744 + " userspace\n");
745 drm_mode_debug_printmodeline(set->mode);
746 if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
747 set->x, set->y,
748 @@ -858,7 +860,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
749 DRM_ERROR("failed to set mode on crtc %p\n",
750 set->crtc);
751 ret = -EINVAL;
752 - goto fail_set_mode;
753 + goto fail;
754 }
755 /* TODO are these needed? */
756 set->crtc->desired_x = set->x;
757 @@ -873,37 +875,41 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
758 ret = crtc_funcs->mode_set_base(set->crtc,
759 set->x, set->y, old_fb);
760 if (ret != 0)
761 - goto fail_set_mode;
762 + goto fail;
763 }
764
765 + kfree(save_connectors);
766 kfree(save_encoders);
767 kfree(save_crtcs);
768 return 0;
769
770 -fail_set_mode:
771 - set->crtc->enabled = save_enabled;
772 - set->crtc->fb = old_fb;
773 +fail:
774 + /* Restore all previous data. */
775 count = 0;
776 - list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
777 - if (!connector->encoder)
778 - continue;
779 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
780 + *crtc = save_crtcs[count++];
781 + }
782
783 - connector->encoder->crtc = save_crtcs[count++];
784 + count = 0;
785 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
786 + *encoder = save_encoders[count++];
787 }
788 -fail_no_encoder:
789 - kfree(save_crtcs);
790 +
791 count = 0;
792 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
793 - connector->encoder = save_encoders[count++];
794 + *connector = save_connectors[count++];
795 }
796 +
797 + kfree(save_connectors);
798 kfree(save_encoders);
799 + kfree(save_crtcs);
800 return ret;
801 }
802 EXPORT_SYMBOL(drm_crtc_helper_set_config);
803
804 bool drm_helper_plugged_event(struct drm_device *dev)
805 {
806 - DRM_DEBUG("\n");
807 + DRM_DEBUG_KMS("\n");
808
809 drm_helper_probe_connector_modes(dev, dev->mode_config.max_width,
810 dev->mode_config.max_height);
811 @@ -932,7 +938,6 @@ bool drm_helper_plugged_event(struct drm_device *dev)
812 */
813 bool drm_helper_initial_config(struct drm_device *dev)
814 {
815 - struct drm_connector *connector;
816 int count = 0;
817
818 count = drm_helper_probe_connector_modes(dev,
819 @@ -940,16 +945,9 @@ bool drm_helper_initial_config(struct drm_device *dev)
820 dev->mode_config.max_height);
821
822 /*
823 - * None of the available connectors had any modes, so add some
824 - * and try to light them up anyway
825 + * we shouldn't end up with no modes here.
826 */
827 - if (!count) {
828 - DRM_ERROR("connectors have no modes, using standard modes\n");
829 - list_for_each_entry(connector,
830 - &dev->mode_config.connector_list,
831 - head)
832 - drm_helper_add_std_modes(dev, connector);
833 - }
834 + WARN(!count, "Connected connector with 0 modes\n");
835
836 drm_setup_crtcs(dev);
837
838 diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
839 index b39d7bf..a75ca63 100644
840 --- a/drivers/gpu/drm/drm_drv.c
841 +++ b/drivers/gpu/drm/drm_drv.c
842 @@ -63,12 +63,12 @@ static struct drm_ioctl_desc drm_ioctls[] = {
843 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
844 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
845 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
846 - DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
847 + DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
848
849 DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
850 DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
851 DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
852 - DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
853 + DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
854
855 DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
856 DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
857 diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
858 index 7f2728b..90d76ba 100644
859 --- a/drivers/gpu/drm/drm_edid.c
860 +++ b/drivers/gpu/drm/drm_edid.c
861 @@ -60,6 +60,12 @@
862 #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
863 /* use +hsync +vsync for detailed mode */
864 #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
865 +/* define the number of Extension EDID block */
866 +#define MAX_EDID_EXT_NUM 4
867 +
868 +#define LEVEL_DMT 0
869 +#define LEVEL_GTF 1
870 +#define LEVEL_CVT 2
871
872 static struct edid_quirk {
873 char *vendor;
874 @@ -237,28 +243,291 @@ static void edid_fixup_preferred(struct drm_connector *connector,
875 preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
876 }
877
878 +/*
879 + * Add the Autogenerated from the DMT spec.
880 + * This table is copied from xfree86/modes/xf86EdidModes.c.
881 + * But the mode with Reduced blank feature is deleted.
882 + */
883 +static struct drm_display_mode drm_dmt_modes[] = {
884 + /* 640x350@85Hz */
885 + { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
886 + 736, 832, 0, 350, 382, 385, 445, 0,
887 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
888 + /* 640x400@85Hz */
889 + { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
890 + 736, 832, 0, 400, 401, 404, 445, 0,
891 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
892 + /* 720x400@85Hz */
893 + { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756,
894 + 828, 936, 0, 400, 401, 404, 446, 0,
895 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
896 + /* 640x480@60Hz */
897 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
898 + 752, 800, 0, 480, 489, 492, 525, 0,
899 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
900 + /* 640x480@72Hz */
901 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
902 + 704, 832, 0, 480, 489, 492, 520, 0,
903 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
904 + /* 640x480@75Hz */
905 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
906 + 720, 840, 0, 480, 481, 484, 500, 0,
907 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
908 + /* 640x480@85Hz */
909 + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696,
910 + 752, 832, 0, 480, 481, 484, 509, 0,
911 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
912 + /* 800x600@56Hz */
913 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
914 + 896, 1024, 0, 600, 601, 603, 625, 0,
915 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
916 + /* 800x600@60Hz */
917 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
918 + 968, 1056, 0, 600, 601, 605, 628, 0,
919 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
920 + /* 800x600@72Hz */
921 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
922 + 976, 1040, 0, 600, 637, 643, 666, 0,
923 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
924 + /* 800x600@75Hz */
925 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
926 + 896, 1056, 0, 600, 601, 604, 625, 0,
927 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
928 + /* 800x600@85Hz */
929 + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832,
930 + 896, 1048, 0, 600, 601, 604, 631, 0,
931 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
932 + /* 848x480@60Hz */
933 + { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864,
934 + 976, 1088, 0, 480, 486, 494, 517, 0,
935 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
936 + /* 1024x768@43Hz, interlace */
937 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
938 + 1208, 1264, 0, 768, 768, 772, 817, 0,
939 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
940 + DRM_MODE_FLAG_INTERLACE) },
941 + /* 1024x768@60Hz */
942 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
943 + 1184, 1344, 0, 768, 771, 777, 806, 0,
944 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
945 + /* 1024x768@70Hz */
946 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
947 + 1184, 1328, 0, 768, 771, 777, 806, 0,
948 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
949 + /* 1024x768@75Hz */
950 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040,
951 + 1136, 1312, 0, 768, 769, 772, 800, 0,
952 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
953 + /* 1024x768@85Hz */
954 + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
955 + 1072, 1376, 0, 768, 769, 772, 808, 0,
956 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
957 + /* 1152x864@75Hz */
958 + { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
959 + 1344, 1600, 0, 864, 865, 868, 900, 0,
960 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
961 + /* 1280x768@60Hz */
962 + { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
963 + 1472, 1664, 0, 768, 771, 778, 798, 0,
964 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
965 + /* 1280x768@75Hz */
966 + { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360,
967 + 1488, 1696, 0, 768, 771, 778, 805, 0,
968 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
969 + /* 1280x768@85Hz */
970 + { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360,
971 + 1496, 1712, 0, 768, 771, 778, 809, 0,
972 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
973 + /* 1280x800@60Hz */
974 + { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
975 + 1480, 1680, 0, 800, 803, 809, 831, 0,
976 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
977 + /* 1280x800@75Hz */
978 + { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360,
979 + 1488, 1696, 0, 800, 803, 809, 838, 0,
980 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
981 + /* 1280x800@85Hz */
982 + { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360,
983 + 1496, 1712, 0, 800, 803, 809, 843, 0,
984 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
985 + /* 1280x960@60Hz */
986 + { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
987 + 1488, 1800, 0, 960, 961, 964, 1000, 0,
988 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
989 + /* 1280x960@85Hz */
990 + { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344,
991 + 1504, 1728, 0, 960, 961, 964, 1011, 0,
992 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
993 + /* 1280x1024@60Hz */
994 + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
995 + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
996 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
997 + /* 1280x1024@75Hz */
998 + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
999 + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
1000 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1001 + /* 1280x1024@85Hz */
1002 + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344,
1003 + 1504, 1728, 0, 1024, 1025, 1028, 1072, 0,
1004 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1005 + /* 1360x768@60Hz */
1006 + { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
1007 + 1536, 1792, 0, 768, 771, 777, 795, 0,
1008 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1009 + /* 1440x1050@60Hz */
1010 + { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
1011 + 1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
1012 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1013 + /* 1440x1050@75Hz */
1014 + { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504,
1015 + 1648, 1896, 0, 1050, 1053, 1057, 1099, 0,
1016 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1017 + /* 1440x1050@85Hz */
1018 + { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504,
1019 + 1656, 1912, 0, 1050, 1053, 1057, 1105, 0,
1020 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1021 + /* 1440x900@60Hz */
1022 + { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
1023 + 1672, 1904, 0, 900, 903, 909, 934, 0,
1024 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1025 + /* 1440x900@75Hz */
1026 + { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536,
1027 + 1688, 1936, 0, 900, 903, 909, 942, 0,
1028 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1029 + /* 1440x900@85Hz */
1030 + { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544,
1031 + 1696, 1952, 0, 900, 903, 909, 948, 0,
1032 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1033 + /* 1600x1200@60Hz */
1034 + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
1035 + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
1036 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1037 + /* 1600x1200@65Hz */
1038 + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664,
1039 + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
1040 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1041 + /* 1600x1200@70Hz */
1042 + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664,
1043 + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
1044 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1045 + /* 1600x1200@75Hz */
1046 + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 2025000, 1600, 1664,
1047 + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
1048 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1049 + /* 1600x1200@85Hz */
1050 + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664,
1051 + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
1052 + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1053 + /* 1680x1050@60Hz */
1054 + { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
1055 + 1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
1056 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1057 + /* 1680x1050@75Hz */
1058 + { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800,
1059 + 1976, 2272, 0, 1050, 1053, 1059, 1099, 0,
1060 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1061 + /* 1680x1050@85Hz */
1062 + { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808,
1063 + 1984, 2288, 0, 1050, 1053, 1059, 1105, 0,
1064 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1065 + /* 1792x1344@60Hz */
1066 + { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
1067 + 2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
1068 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1069 + /* 1729x1344@75Hz */
1070 + { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888,
1071 + 2104, 2456, 0, 1344, 1345, 1348, 1417, 0,
1072 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1073 + /* 1853x1392@60Hz */
1074 + { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
1075 + 2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
1076 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1077 + /* 1856x1392@75Hz */
1078 + { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984,
1079 + 2208, 2560, 0, 1392, 1395, 1399, 1500, 0,
1080 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1081 + /* 1920x1200@60Hz */
1082 + { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
1083 + 2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
1084 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1085 + /* 1920x1200@75Hz */
1086 + { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056,
1087 + 2264, 2608, 0, 1200, 1203, 1209, 1255, 0,
1088 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1089 + /* 1920x1200@85Hz */
1090 + { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064,
1091 + 2272, 2624, 0, 1200, 1203, 1209, 1262, 0,
1092 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1093 + /* 1920x1440@60Hz */
1094 + { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
1095 + 2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
1096 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1097 + /* 1920x1440@75Hz */
1098 + { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064,
1099 + 2288, 2640, 0, 1440, 1441, 1444, 1500, 0,
1100 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1101 + /* 2560x1600@60Hz */
1102 + { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
1103 + 3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
1104 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1105 + /* 2560x1600@75HZ */
1106 + { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768,
1107 + 3048, 3536, 0, 1600, 1603, 1609, 1672, 0,
1108 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1109 + /* 2560x1600@85HZ */
1110 + { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768,
1111 + 3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
1112 + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
1113 +};
1114 +
1115 +static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
1116 + int hsize, int vsize, int fresh)
1117 +{
1118 + int i, count;
1119 + struct drm_display_mode *ptr, *mode;
1120 +
1121 + count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
1122 + mode = NULL;
1123 + for (i = 0; i < count; i++) {
1124 + ptr = &drm_dmt_modes[i];
1125 + if (hsize == ptr->hdisplay &&
1126 + vsize == ptr->vdisplay &&
1127 + fresh == drm_mode_vrefresh(ptr)) {
1128 + /* get the expected default mode */
1129 + mode = drm_mode_duplicate(dev, ptr);
1130 + break;
1131 + }
1132 + }
1133 + return mode;
1134 +}
1135 /**
1136 * drm_mode_std - convert standard mode info (width, height, refresh) into mode
1137 * @t: standard timing params
1138 + * @timing_level: standard timing level
1139 *
1140 * Take the standard timing params (in this case width, aspect, and refresh)
1141 - * and convert them into a real mode using CVT.
1142 + * and convert them into a real mode using CVT/GTF/DMT.
1143 *
1144 * Punts for now, but should eventually use the FB layer's CVT based mode
1145 * generation code.
1146 */
1147 struct drm_display_mode *drm_mode_std(struct drm_device *dev,
1148 - struct std_timing *t)
1149 + struct std_timing *t,
1150 + int timing_level)
1151 {
1152 struct drm_display_mode *mode;
1153 - int hsize = t->hsize * 8 + 248, vsize;
1154 + int hsize, vsize;
1155 + int vrefresh_rate;
1156 unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
1157 >> EDID_TIMING_ASPECT_SHIFT;
1158 -
1159 - mode = drm_mode_create(dev);
1160 - if (!mode)
1161 - return NULL;
1162 -
1163 + unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
1164 + >> EDID_TIMING_VFREQ_SHIFT;
1165 +
1166 + /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
1167 + hsize = t->hsize * 8 + 248;
1168 + /* vrefresh_rate = vfreq + 60 */
1169 + vrefresh_rate = vfreq + 60;
1170 + /* the vdisplay is calculated based on the aspect ratio */
1171 if (aspect_ratio == 0)
1172 vsize = (hsize * 10) / 16;
1173 else if (aspect_ratio == 1)
1174 @@ -267,9 +536,30 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
1175 vsize = (hsize * 4) / 5;
1176 else
1177 vsize = (hsize * 9) / 16;
1178 -
1179 - drm_mode_set_name(mode);
1180 -
1181 + /* HDTV hack */
1182 + if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) {
1183 + mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
1184 + mode->hdisplay = 1366;
1185 + mode->vsync_start = mode->vsync_start - 1;
1186 + mode->vsync_end = mode->vsync_end - 1;
1187 + return mode;
1188 + }
1189 + mode = NULL;
1190 + /* check whether it can be found in default mode table */
1191 + mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate);
1192 + if (mode)
1193 + return mode;
1194 +
1195 + switch (timing_level) {
1196 + case LEVEL_DMT:
1197 + break;
1198 + case LEVEL_GTF:
1199 + mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
1200 + break;
1201 + case LEVEL_CVT:
1202 + mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
1203 + break;
1204 + }
1205 return mode;
1206 }
1207
1208 @@ -451,6 +741,19 @@ static int add_established_modes(struct drm_connector *connector, struct edid *e
1209
1210 return modes;
1211 }
1212 +/**
1213 + * stanard_timing_level - get std. timing level(CVT/GTF/DMT)
1214 + * @edid: EDID block to scan
1215 + */
1216 +static int standard_timing_level(struct edid *edid)
1217 +{
1218 + if (edid->revision >= 2) {
1219 + if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
1220 + return LEVEL_CVT;
1221 + return LEVEL_GTF;
1222 + }
1223 + return LEVEL_DMT;
1224 +}
1225
1226 /**
1227 * add_standard_modes - get std. modes from EDID and add them
1228 @@ -463,6 +766,9 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
1229 {
1230 struct drm_device *dev = connector->dev;
1231 int i, modes = 0;
1232 + int timing_level;
1233 +
1234 + timing_level = standard_timing_level(edid);
1235
1236 for (i = 0; i < EDID_STD_TIMINGS; i++) {
1237 struct std_timing *t = &edid->standard_timings[i];
1238 @@ -472,7 +778,8 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
1239 if (t->hsize == 1 && t->vfreq_aspect == 1)
1240 continue;
1241
1242 - newmode = drm_mode_std(dev, &edid->standard_timings[i]);
1243 + newmode = drm_mode_std(dev, &edid->standard_timings[i],
1244 + timing_level);
1245 if (newmode) {
1246 drm_mode_probed_add(connector, newmode);
1247 modes++;
1248 @@ -496,6 +803,9 @@ static int add_detailed_info(struct drm_connector *connector,
1249 {
1250 struct drm_device *dev = connector->dev;
1251 int i, j, modes = 0;
1252 + int timing_level;
1253 +
1254 + timing_level = standard_timing_level(edid);
1255
1256 for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
1257 struct detailed_timing *timing = &edid->detailed_timings[i];
1258 @@ -525,7 +835,8 @@ static int add_detailed_info(struct drm_connector *connector,
1259 struct drm_display_mode *newmode;
1260
1261 std = &data->data.timings[j];
1262 - newmode = drm_mode_std(dev, std);
1263 + newmode = drm_mode_std(dev, std,
1264 + timing_level);
1265 if (newmode) {
1266 drm_mode_probed_add(connector, newmode);
1267 modes++;
1268 @@ -551,6 +862,122 @@ static int add_detailed_info(struct drm_connector *connector,
1269
1270 return modes;
1271 }
1272 +/**
1273 + * add_detailed_mode_eedid - get detailed mode info from addtional timing
1274 + * EDID block
1275 + * @connector: attached connector
1276 + * @edid: EDID block to scan(It is only to get addtional timing EDID block)
1277 + * @quirks: quirks to apply
1278 + *
1279 + * Some of the detailed timing sections may contain mode information. Grab
1280 + * it and add it to the list.
1281 + */
1282 +static int add_detailed_info_eedid(struct drm_connector *connector,
1283 + struct edid *edid, u32 quirks)
1284 +{
1285 + struct drm_device *dev = connector->dev;
1286 + int i, j, modes = 0;
1287 + char *edid_ext = NULL;
1288 + struct detailed_timing *timing;
1289 + struct detailed_non_pixel *data;
1290 + struct drm_display_mode *newmode;
1291 + int edid_ext_num;
1292 + int start_offset, end_offset;
1293 + int timing_level;
1294 +
1295 + if (edid->version == 1 && edid->revision < 3) {
1296 + /* If the EDID version is less than 1.3, there is no
1297 + * extension EDID.
1298 + */
1299 + return 0;
1300 + }
1301 + if (!edid->extensions) {
1302 + /* if there is no extension EDID, it is unnecessary to
1303 + * parse the E-EDID to get detailed info
1304 + */
1305 + return 0;
1306 + }
1307 +
1308 + /* Chose real EDID extension number */
1309 + edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
1310 + MAX_EDID_EXT_NUM : edid->extensions;
1311 +
1312 + /* Find CEA extension */
1313 + for (i = 0; i < edid_ext_num; i++) {
1314 + edid_ext = (char *)edid + EDID_LENGTH * (i + 1);
1315 + /* This block is CEA extension */
1316 + if (edid_ext[0] == 0x02)
1317 + break;
1318 + }
1319 +
1320 + if (i == edid_ext_num) {
1321 + /* if there is no additional timing EDID block, return */
1322 + return 0;
1323 + }
1324 +
1325 + /* Get the start offset of detailed timing block */
1326 + start_offset = edid_ext[2];
1327 + if (start_offset == 0) {
1328 + /* If the start_offset is zero, it means that neither detailed
1329 + * info nor data block exist. In such case it is also
1330 + * unnecessary to parse the detailed timing info.
1331 + */
1332 + return 0;
1333 + }
1334 +
1335 + timing_level = standard_timing_level(edid);
1336 + end_offset = EDID_LENGTH;
1337 + end_offset -= sizeof(struct detailed_timing);
1338 + for (i = start_offset; i < end_offset;
1339 + i += sizeof(struct detailed_timing)) {
1340 + timing = (struct detailed_timing *)(edid_ext + i);
1341 + data = &timing->data.other_data;
1342 + /* Detailed mode timing */
1343 + if (timing->pixel_clock) {
1344 + newmode = drm_mode_detailed(dev, edid, timing, quirks);
1345 + if (!newmode)
1346 + continue;
1347 +
1348 + drm_mode_probed_add(connector, newmode);
1349 +
1350 + modes++;
1351 + continue;
1352 + }
1353 +
1354 + /* Other timing or info */
1355 + switch (data->type) {
1356 + case EDID_DETAIL_MONITOR_SERIAL:
1357 + break;
1358 + case EDID_DETAIL_MONITOR_STRING:
1359 + break;
1360 + case EDID_DETAIL_MONITOR_RANGE:
1361 + /* Get monitor range data */
1362 + break;
1363 + case EDID_DETAIL_MONITOR_NAME:
1364 + break;
1365 + case EDID_DETAIL_MONITOR_CPDATA:
1366 + break;
1367 + case EDID_DETAIL_STD_MODES:
1368 + /* Five modes per detailed section */
1369 + for (j = 0; j < 5; i++) {
1370 + struct std_timing *std;
1371 + struct drm_display_mode *newmode;
1372 +
1373 + std = &data->data.timings[j];
1374 + newmode = drm_mode_std(dev, std, timing_level);
1375 + if (newmode) {
1376 + drm_mode_probed_add(connector, newmode);
1377 + modes++;
1378 + }
1379 + }
1380 + break;
1381 + default:
1382 + break;
1383 + }
1384 + }
1385 +
1386 + return modes;
1387 +}
1388
1389 #define DDC_ADDR 0x50
1390 /**
1391 @@ -584,7 +1011,6 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
1392 if (i2c_transfer(adapter, msgs, 2) == 2)
1393 return 0;
1394
1395 - dev_info(&adapter->dev, "unable to read EDID block.\n");
1396 return -1;
1397 }
1398 EXPORT_SYMBOL(drm_do_probe_ddc_edid);
1399 @@ -597,8 +1023,6 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
1400
1401 ret = drm_do_probe_ddc_edid(adapter, buf, len);
1402 if (ret != 0) {
1403 - dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
1404 - drm_get_connector_name(connector));
1405 goto end;
1406 }
1407 if (!edid_is_valid((struct edid *)buf)) {
1408 @@ -610,7 +1034,6 @@ end:
1409 return ret;
1410 }
1411
1412 -#define MAX_EDID_EXT_NUM 4
1413 /**
1414 * drm_get_edid - get EDID data, if available
1415 * @connector: connector we're probing
1416 @@ -763,6 +1186,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
1417 num_modes += add_established_modes(connector, edid);
1418 num_modes += add_standard_modes(connector, edid);
1419 num_modes += add_detailed_info(connector, edid, quirks);
1420 + num_modes += add_detailed_info_eedid(connector, edid, quirks);
1421
1422 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
1423 edid_fixup_preferred(connector, quirks);
1424 @@ -788,3 +1212,49 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
1425 return num_modes;
1426 }
1427 EXPORT_SYMBOL(drm_add_edid_modes);
1428 +
1429 +/**
1430 + * drm_add_modes_noedid - add modes for the connectors without EDID
1431 + * @connector: connector we're probing
1432 + * @hdisplay: the horizontal display limit
1433 + * @vdisplay: the vertical display limit
1434 + *
1435 + * Add the specified modes to the connector's mode list. Only when the
1436 + * hdisplay/vdisplay is not beyond the given limit, it will be added.
1437 + *
1438 + * Return number of modes added or 0 if we couldn't find any.
1439 + */
1440 +int drm_add_modes_noedid(struct drm_connector *connector,
1441 + int hdisplay, int vdisplay)
1442 +{
1443 + int i, count, num_modes = 0;
1444 + struct drm_display_mode *mode, *ptr;
1445 + struct drm_device *dev = connector->dev;
1446 +
1447 + count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
1448 + if (hdisplay < 0)
1449 + hdisplay = 0;
1450 + if (vdisplay < 0)
1451 + vdisplay = 0;
1452 +
1453 + for (i = 0; i < count; i++) {
1454 + ptr = &drm_dmt_modes[i];
1455 + if (hdisplay && vdisplay) {
1456 + /*
1457 + * Only when two are valid, they will be used to check
1458 + * whether the mode should be added to the mode list of
1459 + * the connector.
1460 + */
1461 + if (ptr->hdisplay > hdisplay ||
1462 + ptr->vdisplay > vdisplay)
1463 + continue;
1464 + }
1465 + mode = drm_mode_duplicate(dev, ptr);
1466 + if (mode) {
1467 + drm_mode_probed_add(connector, mode);
1468 + num_modes++;
1469 + }
1470 + }
1471 + return num_modes;
1472 +}
1473 +EXPORT_SYMBOL(drm_add_modes_noedid);
1474 diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c
1475 new file mode 100644
1476 index 0000000..f018469
1477 --- /dev/null
1478 +++ b/drivers/gpu/drm/drm_encoder_slave.c
1479 @@ -0,0 +1,116 @@
1480 +/*
1481 + * Copyright (C) 2009 Francisco Jerez.
1482 + * All Rights Reserved.
1483 + *
1484 + * Permission is hereby granted, free of charge, to any person obtaining
1485 + * a copy of this software and associated documentation files (the
1486 + * "Software"), to deal in the Software without restriction, including
1487 + * without limitation the rights to use, copy, modify, merge, publish,
1488 + * distribute, sublicense, and/or sell copies of the Software, and to
1489 + * permit persons to whom the Software is furnished to do so, subject to
1490 + * the following conditions:
1491 + *
1492 + * The above copyright notice and this permission notice (including the
1493 + * next paragraph) shall be included in all copies or substantial
1494 + * portions of the Software.
1495 + *
1496 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1497 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1498 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1499 + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
1500 + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1501 + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1502 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1503 + *
1504 + */
1505 +
1506 +#include "drm_encoder_slave.h"
1507 +
1508 +/**
1509 + * drm_i2c_encoder_init - Initialize an I2C slave encoder
1510 + * @dev: DRM device.
1511 + * @encoder: Encoder to be attached to the I2C device. You aren't
1512 + * required to have called drm_encoder_init() before.
1513 + * @adap: I2C adapter that will be used to communicate with
1514 + * the device.
1515 + * @info: Information that will be used to create the I2C device.
1516 + * Required fields are @addr and @type.
1517 + *
1518 + * Create an I2C device on the specified bus (the module containing its
1519 + * driver is transparently loaded) and attach it to the specified
1520 + * &drm_encoder_slave. The @slave_funcs field will be initialized with
1521 + * the hooks provided by the slave driver.
1522 + *
1523 + * Returns 0 on success or a negative errno on failure, in particular,
1524 + * -ENODEV is returned when no matching driver is found.
1525 + */
1526 +int drm_i2c_encoder_init(struct drm_device *dev,
1527 + struct drm_encoder_slave *encoder,
1528 + struct i2c_adapter *adap,
1529 + const struct i2c_board_info *info)
1530 +{
1531 + char modalias[sizeof(I2C_MODULE_PREFIX)
1532 + + I2C_NAME_SIZE];
1533 + struct module *module = NULL;
1534 + struct i2c_client *client;
1535 + struct drm_i2c_encoder_driver *encoder_drv;
1536 + int err = 0;
1537 +
1538 + snprintf(modalias, sizeof(modalias),
1539 + "%s%s", I2C_MODULE_PREFIX, info->type);
1540 + request_module(modalias);
1541 +
1542 + client = i2c_new_device(adap, info);
1543 + if (!client) {
1544 + err = -ENOMEM;
1545 + goto fail;
1546 + }
1547 +
1548 + if (!client->driver) {
1549 + err = -ENODEV;
1550 + goto fail_unregister;
1551 + }
1552 +
1553 + module = client->driver->driver.owner;
1554 + if (!try_module_get(module)) {
1555 + err = -ENODEV;
1556 + goto fail_unregister;
1557 + }
1558 +
1559 + encoder->bus_priv = client;
1560 +
1561 + encoder_drv = to_drm_i2c_encoder_driver(client->driver);
1562 +
1563 + err = encoder_drv->encoder_init(client, dev, encoder);
1564 + if (err)
1565 + goto fail_unregister;
1566 +
1567 + return 0;
1568 +
1569 +fail_unregister:
1570 + i2c_unregister_device(client);
1571 + module_put(module);
1572 +fail:
1573 + return err;
1574 +}
1575 +EXPORT_SYMBOL(drm_i2c_encoder_init);
1576 +
1577 +/**
1578 + * drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder
1579 + * @drm_encoder: Encoder to be unregistered.
1580 + *
1581 + * This should be called from the @destroy method of an I2C slave
1582 + * encoder driver once I2C access is no longer needed.
1583 + */
1584 +void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
1585 +{
1586 + struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder);
1587 + struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder);
1588 + struct module *module = client->driver->driver.owner;
1589 +
1590 + i2c_unregister_device(client);
1591 + encoder->bus_priv = NULL;
1592 +
1593 + module_put(module);
1594 +}
1595 +EXPORT_SYMBOL(drm_i2c_encoder_destroy);
1596 diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
1597 new file mode 100644
1598 index 0000000..8eee4a6
1599 --- /dev/null
1600 +++ b/drivers/gpu/drm/drm_fb_helper.c
1601 @@ -0,0 +1,701 @@
1602 +/*
1603 + * Copyright (c) 2006-2009 Red Hat Inc.
1604 + * Copyright (c) 2006-2008 Intel Corporation
1605 + * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
1606 + *
1607 + * DRM framebuffer helper functions
1608 + *
1609 + * Permission to use, copy, modify, distribute, and sell this software and its
1610 + * documentation for any purpose is hereby granted without fee, provided that
1611 + * the above copyright notice appear in all copies and that both that copyright
1612 + * notice and this permission notice appear in supporting documentation, and
1613 + * that the name of the copyright holders not be used in advertising or
1614 + * publicity pertaining to distribution of the software without specific,
1615 + * written prior permission. The copyright holders make no representations
1616 + * about the suitability of this software for any purpose. It is provided "as
1617 + * is" without express or implied warranty.
1618 + *
1619 + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1620 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1621 + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1622 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1623 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1624 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
1625 + * OF THIS SOFTWARE.
1626 + *
1627 + * Authors:
1628 + * Dave Airlie <airlied@linux.ie>
1629 + * Jesse Barnes <jesse.barnes@intel.com>
1630 + */
1631 +#include <linux/sysrq.h>
1632 +#include <linux/fb.h>
1633 +#include "drmP.h"
1634 +#include "drm_crtc.h"
1635 +#include "drm_fb_helper.h"
1636 +#include "drm_crtc_helper.h"
1637 +
1638 +MODULE_AUTHOR("David Airlie, Jesse Barnes");
1639 +MODULE_DESCRIPTION("DRM KMS helper");
1640 +MODULE_LICENSE("GPL and additional rights");
1641 +
1642 +static LIST_HEAD(kernel_fb_helper_list);
1643 +
1644 +bool drm_fb_helper_force_kernel_mode(void)
1645 +{
1646 + int i = 0;
1647 + bool ret, error = false;
1648 + struct drm_fb_helper *helper;
1649 +
1650 + if (list_empty(&kernel_fb_helper_list))
1651 + return false;
1652 +
1653 + list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
1654 + for (i = 0; i < helper->crtc_count; i++) {
1655 + struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
1656 + ret = drm_crtc_helper_set_config(mode_set);
1657 + if (ret)
1658 + error = true;
1659 + }
1660 + }
1661 + return error;
1662 +}
1663 +
1664 +int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
1665 + void *panic_str)
1666 +{
1667 + DRM_ERROR("panic occurred, switching back to text console\n");
1668 + return drm_fb_helper_force_kernel_mode();
1669 + return 0;
1670 +}
1671 +EXPORT_SYMBOL(drm_fb_helper_panic);
1672 +
1673 +static struct notifier_block paniced = {
1674 + .notifier_call = drm_fb_helper_panic,
1675 +};
1676 +
1677 +/**
1678 + * drm_fb_helper_restore - restore the framebuffer console (kernel) config
1679 + *
1680 + * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
1681 + */
1682 +void drm_fb_helper_restore(void)
1683 +{
1684 + bool ret;
1685 + ret = drm_fb_helper_force_kernel_mode();
1686 + if (ret == true)
1687 + DRM_ERROR("Failed to restore crtc configuration\n");
1688 +}
1689 +EXPORT_SYMBOL(drm_fb_helper_restore);
1690 +
1691 +static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
1692 +{
1693 + drm_fb_helper_restore();
1694 +}
1695 +static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
1696 +
1697 +static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3)
1698 +{
1699 + schedule_work(&drm_fb_helper_restore_work);
1700 +}
1701 +
1702 +static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
1703 + .handler = drm_fb_helper_sysrq,
1704 + .help_msg = "force-fb(V)",
1705 + .action_msg = "Restore framebuffer console",
1706 +};
1707 +
1708 +static void drm_fb_helper_on(struct fb_info *info)
1709 +{
1710 + struct drm_fb_helper *fb_helper = info->par;
1711 + struct drm_device *dev = fb_helper->dev;
1712 + struct drm_crtc *crtc;
1713 + struct drm_encoder *encoder;
1714 + int i;
1715 +
1716 + /*
1717 + * For each CRTC in this fb, turn the crtc on then,
1718 + * find all associated encoders and turn them on.
1719 + */
1720 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1721 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1722 +
1723 + for (i = 0; i < fb_helper->crtc_count; i++) {
1724 + if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
1725 + break;
1726 + }
1727 +
1728 + mutex_lock(&dev->mode_config.mutex);
1729 + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
1730 + mutex_unlock(&dev->mode_config.mutex);
1731 +
1732 + /* Found a CRTC on this fb, now find encoders */
1733 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1734 + if (encoder->crtc == crtc) {
1735 + struct drm_encoder_helper_funcs *encoder_funcs;
1736 +
1737 + encoder_funcs = encoder->helper_private;
1738 + mutex_lock(&dev->mode_config.mutex);
1739 + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
1740 + mutex_unlock(&dev->mode_config.mutex);
1741 + }
1742 + }
1743 + }
1744 +}
1745 +
1746 +static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
1747 +{
1748 + struct drm_fb_helper *fb_helper = info->par;
1749 + struct drm_device *dev = fb_helper->dev;
1750 + struct drm_crtc *crtc;
1751 + struct drm_encoder *encoder;
1752 + int i;
1753 +
1754 + /*
1755 + * For each CRTC in this fb, find all associated encoders
1756 + * and turn them off, then turn off the CRTC.
1757 + */
1758 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1759 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1760 +
1761 + for (i = 0; i < fb_helper->crtc_count; i++) {
1762 + if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
1763 + break;
1764 + }
1765 +
1766 + /* Found a CRTC on this fb, now find encoders */
1767 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1768 + if (encoder->crtc == crtc) {
1769 + struct drm_encoder_helper_funcs *encoder_funcs;
1770 +
1771 + encoder_funcs = encoder->helper_private;
1772 + mutex_lock(&dev->mode_config.mutex);
1773 + encoder_funcs->dpms(encoder, dpms_mode);
1774 + mutex_unlock(&dev->mode_config.mutex);
1775 + }
1776 + }
1777 + if (dpms_mode == DRM_MODE_DPMS_OFF) {
1778 + mutex_lock(&dev->mode_config.mutex);
1779 + crtc_funcs->dpms(crtc, dpms_mode);
1780 + mutex_unlock(&dev->mode_config.mutex);
1781 + }
1782 + }
1783 +}
1784 +
1785 +int drm_fb_helper_blank(int blank, struct fb_info *info)
1786 +{
1787 + switch (blank) {
1788 + case FB_BLANK_UNBLANK:
1789 + drm_fb_helper_on(info);
1790 + break;
1791 + case FB_BLANK_NORMAL:
1792 + drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
1793 + break;
1794 + case FB_BLANK_HSYNC_SUSPEND:
1795 + drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
1796 + break;
1797 + case FB_BLANK_VSYNC_SUSPEND:
1798 + drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
1799 + break;
1800 + case FB_BLANK_POWERDOWN:
1801 + drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
1802 + break;
1803 + }
1804 + return 0;
1805 +}
1806 +EXPORT_SYMBOL(drm_fb_helper_blank);
1807 +
1808 +static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
1809 +{
1810 + int i;
1811 +
1812 + for (i = 0; i < helper->crtc_count; i++)
1813 + kfree(helper->crtc_info[i].mode_set.connectors);
1814 + kfree(helper->crtc_info);
1815 +}
1816 +
1817 +int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn_count)
1818 +{
1819 + struct drm_device *dev = helper->dev;
1820 + struct drm_crtc *crtc;
1821 + int ret = 0;
1822 + int i;
1823 +
1824 + helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
1825 + if (!helper->crtc_info)
1826 + return -ENOMEM;
1827 +
1828 + helper->crtc_count = crtc_count;
1829 +
1830 + for (i = 0; i < crtc_count; i++) {
1831 + helper->crtc_info[i].mode_set.connectors =
1832 + kcalloc(max_conn_count,
1833 + sizeof(struct drm_connector *),
1834 + GFP_KERNEL);
1835 +
1836 + if (!helper->crtc_info[i].mode_set.connectors) {
1837 + ret = -ENOMEM;
1838 + goto out_free;
1839 + }
1840 + helper->crtc_info[i].mode_set.num_connectors = 0;
1841 + }
1842 +
1843 + i = 0;
1844 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1845 + helper->crtc_info[i].crtc_id = crtc->base.id;
1846 + helper->crtc_info[i].mode_set.crtc = crtc;
1847 + i++;
1848 + }
1849 + helper->conn_limit = max_conn_count;
1850 + return 0;
1851 +out_free:
1852 + drm_fb_helper_crtc_free(helper);
1853 + return -ENOMEM;
1854 +}
1855 +EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
1856 +
1857 +int drm_fb_helper_setcolreg(unsigned regno,
1858 + unsigned red,
1859 + unsigned green,
1860 + unsigned blue,
1861 + unsigned transp,
1862 + struct fb_info *info)
1863 +{
1864 + struct drm_fb_helper *fb_helper = info->par;
1865 + struct drm_device *dev = fb_helper->dev;
1866 + struct drm_crtc *crtc;
1867 + int i;
1868 +
1869 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1870 + struct drm_framebuffer *fb = fb_helper->fb;
1871 +
1872 + for (i = 0; i < fb_helper->crtc_count; i++) {
1873 + if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
1874 + break;
1875 + }
1876 + if (i == fb_helper->crtc_count)
1877 + continue;
1878 +
1879 + if (regno > 255)
1880 + return 1;
1881 +
1882 + if (fb->depth == 8) {
1883 + fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
1884 + return 0;
1885 + }
1886 +
1887 + if (regno < 16) {
1888 + switch (fb->depth) {
1889 + case 15:
1890 + fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
1891 + ((green & 0xf800) >> 6) |
1892 + ((blue & 0xf800) >> 11);
1893 + break;
1894 + case 16:
1895 + fb->pseudo_palette[regno] = (red & 0xf800) |
1896 + ((green & 0xfc00) >> 5) |
1897 + ((blue & 0xf800) >> 11);
1898 + break;
1899 + case 24:
1900 + case 32:
1901 + fb->pseudo_palette[regno] =
1902 + (((red >> 8) & 0xff) << info->var.red.offset) |
1903 + (((green >> 8) & 0xff) << info->var.green.offset) |
1904 + (((blue >> 8) & 0xff) << info->var.blue.offset);
1905 + break;
1906 + }
1907 + }
1908 + }
1909 + return 0;
1910 +}
1911 +EXPORT_SYMBOL(drm_fb_helper_setcolreg);
1912 +
1913 +int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
1914 + struct fb_info *info)
1915 +{
1916 + struct drm_fb_helper *fb_helper = info->par;
1917 + struct drm_framebuffer *fb = fb_helper->fb;
1918 + int depth;
1919 +
1920 + if (var->pixclock == -1 || !var->pixclock)
1921 + return -EINVAL;
1922 +
1923 + /* Need to resize the fb object !!! */
1924 + if (var->xres > fb->width || var->yres > fb->height) {
1925 + DRM_ERROR("Requested width/height is greater than current fb "
1926 + "object %dx%d > %dx%d\n", var->xres, var->yres,
1927 + fb->width, fb->height);
1928 + DRM_ERROR("Need resizing code.\n");
1929 + return -EINVAL;
1930 + }
1931 +
1932 + switch (var->bits_per_pixel) {
1933 + case 16:
1934 + depth = (var->green.length == 6) ? 16 : 15;
1935 + break;
1936 + case 32:
1937 + depth = (var->transp.length > 0) ? 32 : 24;
1938 + break;
1939 + default:
1940 + depth = var->bits_per_pixel;
1941 + break;
1942 + }
1943 +
1944 + switch (depth) {
1945 + case 8:
1946 + var->red.offset = 0;
1947 + var->green.offset = 0;
1948 + var->blue.offset = 0;
1949 + var->red.length = 8;
1950 + var->green.length = 8;
1951 + var->blue.length = 8;
1952 + var->transp.length = 0;
1953 + var->transp.offset = 0;
1954 + break;
1955 + case 15:
1956 + var->red.offset = 10;
1957 + var->green.offset = 5;
1958 + var->blue.offset = 0;
1959 + var->red.length = 5;
1960 + var->green.length = 5;
1961 + var->blue.length = 5;
1962 + var->transp.length = 1;
1963 + var->transp.offset = 15;
1964 + break;
1965 + case 16:
1966 + var->red.offset = 11;
1967 + var->green.offset = 5;
1968 + var->blue.offset = 0;
1969 + var->red.length = 5;
1970 + var->green.length = 6;
1971 + var->blue.length = 5;
1972 + var->transp.length = 0;
1973 + var->transp.offset = 0;
1974 + break;
1975 + case 24:
1976 + var->red.offset = 16;
1977 + var->green.offset = 8;
1978 + var->blue.offset = 0;
1979 + var->red.length = 8;
1980 + var->green.length = 8;
1981 + var->blue.length = 8;
1982 + var->transp.length = 0;
1983 + var->transp.offset = 0;
1984 + break;
1985 + case 32:
1986 + var->red.offset = 16;
1987 + var->green.offset = 8;
1988 + var->blue.offset = 0;
1989 + var->red.length = 8;
1990 + var->green.length = 8;
1991 + var->blue.length = 8;
1992 + var->transp.length = 8;
1993 + var->transp.offset = 24;
1994 + break;
1995 + default:
1996 + return -EINVAL;
1997 + }
1998 + return 0;
1999 +}
2000 +EXPORT_SYMBOL(drm_fb_helper_check_var);
2001 +
2002 +/* this will let fbcon do the mode init */
2003 +int drm_fb_helper_set_par(struct fb_info *info)
2004 +{
2005 + struct drm_fb_helper *fb_helper = info->par;
2006 + struct drm_device *dev = fb_helper->dev;
2007 + struct fb_var_screeninfo *var = &info->var;
2008 + struct drm_crtc *crtc;
2009 + int ret;
2010 + int i;
2011 +
2012 + if (var->pixclock != -1) {
2013 + DRM_ERROR("PIXEL CLCOK SET\n");
2014 + return -EINVAL;
2015