aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-16 11:39:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-16 11:39:52 -0500
commit4c44323db15f26f4c744f06179daa43711cdb708 (patch)
treee9e7a1fc18127ac1f6016a9f292dde72ce3d2487 /drivers
parent50246dd41ccbcb47beb06d6c1d9355f6b7137a11 (diff)
parent34b8686e12eaf9878aaab89e92222060c3e7cc48 (diff)
Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm/i915: lock correct mutex around object unreference. drm/i915: add support for physical memory objects drm/i915: make LVDS fixed mode a preferred mode drm: handle depth & bpp changes correctly drm: initial KMS config fixes drm/i915: setup sarea properly in master_priv drm/i915: set vblank enabled flag correctly across IRQ install/uninstall drm/i915: don't enable vblanks on disabled pipes
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c175
-rw-r--r--drivers/gpu/drm/drm_irq.c18
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c10
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h23
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c189
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c6
-rw-r--r--drivers/gpu/drm/i915/intel_display.c43
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c7
8 files changed, 404 insertions, 67 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index d8a982b71296..964c5eb1fada 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -36,7 +36,7 @@
36/* 36/*
37 * Detailed mode info for 800x600@60Hz 37 * Detailed mode info for 800x600@60Hz
38 */ 38 */
39static struct drm_display_mode std_mode[] = { 39static struct drm_display_mode std_modes[] = {
40 { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840, 40 { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
41 968, 1056, 0, 600, 601, 605, 628, 0, 41 968, 1056, 0, 600, 601, 605, 628, 0,
42 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 42 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -60,15 +60,18 @@ static struct drm_display_mode std_mode[] = {
60 * changes have occurred. 60 * changes have occurred.
61 * 61 *
62 * FIXME: take into account monitor limits 62 * FIXME: take into account monitor limits
63 *
64 * RETURNS:
65 * Number of modes found on @connector.
63 */ 66 */
64void drm_helper_probe_single_connector_modes(struct drm_connector *connector, 67int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
65 uint32_t maxX, uint32_t maxY) 68 uint32_t maxX, uint32_t maxY)
66{ 69{
67 struct drm_device *dev = connector->dev; 70 struct drm_device *dev = connector->dev;
68 struct drm_display_mode *mode, *t; 71 struct drm_display_mode *mode, *t;
69 struct drm_connector_helper_funcs *connector_funcs = 72 struct drm_connector_helper_funcs *connector_funcs =
70 connector->helper_private; 73 connector->helper_private;
71 int ret; 74 int count = 0;
72 75
73 DRM_DEBUG("%s\n", drm_get_connector_name(connector)); 76 DRM_DEBUG("%s\n", drm_get_connector_name(connector));
74 /* set all modes to the unverified state */ 77 /* set all modes to the unverified state */
@@ -81,14 +84,14 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
81 DRM_DEBUG("%s is disconnected\n", 84 DRM_DEBUG("%s is disconnected\n",
82 drm_get_connector_name(connector)); 85 drm_get_connector_name(connector));
83 /* TODO set EDID to NULL */ 86 /* TODO set EDID to NULL */
84 return; 87 return 0;
85 } 88 }
86 89
87 ret = (*connector_funcs->get_modes)(connector); 90 count = (*connector_funcs->get_modes)(connector);
91 if (!count)
92 return 0;
88 93
89 if (ret) { 94 drm_mode_connector_list_update(connector);
90 drm_mode_connector_list_update(connector);
91 }
92 95
93 if (maxX && maxY) 96 if (maxX && maxY)
94 drm_mode_validate_size(dev, &connector->modes, maxX, 97 drm_mode_validate_size(dev, &connector->modes, maxX,
@@ -102,25 +105,8 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
102 105
103 drm_mode_prune_invalid(dev, &connector->modes, true); 106 drm_mode_prune_invalid(dev, &connector->modes, true);
104 107
105 if (list_empty(&connector->modes)) { 108 if (list_empty(&connector->modes))
106 struct drm_display_mode *stdmode; 109 return 0;
107
108 DRM_DEBUG("No valid modes on %s\n",
109 drm_get_connector_name(connector));
110
111 /* Should we do this here ???
112 * When no valid EDID modes are available we end up
113 * here and bailed in the past, now we add a standard
114 * 640x480@60Hz mode and carry on.
115 */
116 stdmode = drm_mode_duplicate(dev, &std_mode[0]);
117 drm_mode_probed_add(connector, stdmode);
118 drm_mode_list_concat(&connector->probed_modes,
119 &connector->modes);
120
121 DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
122 drm_get_connector_name(connector));
123 }
124 110
125 drm_mode_sort(&connector->modes); 111 drm_mode_sort(&connector->modes);
126 112
@@ -131,20 +117,58 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
131 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 117 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
132 drm_mode_debug_printmodeline(mode); 118 drm_mode_debug_printmodeline(mode);
133 } 119 }
120
121 return count;
134} 122}
135EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); 123EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
136 124
137void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, 125int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
138 uint32_t maxY) 126 uint32_t maxY)
139{ 127{
140 struct drm_connector *connector; 128 struct drm_connector *connector;
129 int count = 0;
141 130
142 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 131 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
143 drm_helper_probe_single_connector_modes(connector, maxX, maxY); 132 count += drm_helper_probe_single_connector_modes(connector,
133 maxX, maxY);
144 } 134 }
135
136 return count;
145} 137}
146EXPORT_SYMBOL(drm_helper_probe_connector_modes); 138EXPORT_SYMBOL(drm_helper_probe_connector_modes);
147 139
140static void drm_helper_add_std_modes(struct drm_device *dev,
141 struct drm_connector *connector)
142{
143 struct drm_display_mode *mode, *t;
144 int i;
145
146 for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
147 struct drm_display_mode *stdmode;
148
149 /*
150 * When no valid EDID modes are available we end up
151 * here and bailed in the past, now we add some standard
152 * modes and move on.
153 */
154 stdmode = drm_mode_duplicate(dev, &std_modes[i]);
155 drm_mode_probed_add(connector, stdmode);
156 drm_mode_list_concat(&connector->probed_modes,
157 &connector->modes);
158
159 DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
160 drm_get_connector_name(connector));
161 }
162 drm_mode_sort(&connector->modes);
163
164 DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
165 list_for_each_entry_safe(mode, t, &connector->modes, head) {
166 mode->vrefresh = drm_mode_vrefresh(mode);
167
168 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
169 drm_mode_debug_printmodeline(mode);
170 }
171}
148 172
149/** 173/**
150 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config 174 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
@@ -237,6 +261,8 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled)
237 261
238 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 262 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
239 enabled[i] = drm_connector_enabled(connector, true); 263 enabled[i] = drm_connector_enabled(connector, true);
264 DRM_DEBUG("connector %d enabled? %s\n", connector->base.id,
265 enabled[i] ? "yes" : "no");
240 any_enabled |= enabled[i]; 266 any_enabled |= enabled[i];
241 i++; 267 i++;
242 } 268 }
@@ -265,11 +291,17 @@ static bool drm_target_preferred(struct drm_device *dev,
265 continue; 291 continue;
266 } 292 }
267 293
294 DRM_DEBUG("looking for preferred mode on connector %d\n",
295 connector->base.id);
296
268 modes[i] = drm_has_preferred_mode(connector, width, height); 297 modes[i] = drm_has_preferred_mode(connector, width, height);
269 if (!modes[i]) { 298 /* No preferred modes, pick one off the list */
299 if (!modes[i] && !list_empty(&connector->modes)) {
270 list_for_each_entry(modes[i], &connector->modes, head) 300 list_for_each_entry(modes[i], &connector->modes, head)
271 break; 301 break;
272 } 302 }
303 DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
304 "none");
273 i++; 305 i++;
274 } 306 }
275 return true; 307 return true;
@@ -369,6 +401,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
369 int width, height; 401 int width, height;
370 int i, ret; 402 int i, ret;
371 403
404 DRM_DEBUG("\n");
405
372 width = dev->mode_config.max_width; 406 width = dev->mode_config.max_width;
373 height = dev->mode_config.max_height; 407 height = dev->mode_config.max_height;
374 408
@@ -390,6 +424,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
390 if (!ret) 424 if (!ret)
391 DRM_ERROR("Unable to find initial modes\n"); 425 DRM_ERROR("Unable to find initial modes\n");
392 426
427 DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
428
393 drm_pick_crtcs(dev, crtcs, modes, 0, width, height); 429 drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
394 430
395 i = 0; 431 i = 0;
@@ -403,6 +439,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
403 } 439 }
404 440
405 if (mode && crtc) { 441 if (mode && crtc) {
442 DRM_DEBUG("desired mode %s set on crtc %d\n",
443 mode->name, crtc->base.id);
406 crtc->desired_mode = mode; 444 crtc->desired_mode = mode;
407 connector->encoder->crtc = crtc; 445 connector->encoder->crtc = crtc;
408 } else 446 } else
@@ -442,6 +480,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
442 int saved_x, saved_y; 480 int saved_x, saved_y;
443 struct drm_encoder *encoder; 481 struct drm_encoder *encoder;
444 bool ret = true; 482 bool ret = true;
483 bool depth_changed, bpp_changed;
445 484
446 adjusted_mode = drm_mode_duplicate(dev, mode); 485 adjusted_mode = drm_mode_duplicate(dev, mode);
447 486
@@ -450,6 +489,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
450 if (!crtc->enabled) 489 if (!crtc->enabled)
451 return true; 490 return true;
452 491
492 if (old_fb && crtc->fb) {
493 depth_changed = (old_fb->depth != crtc->fb->depth);
494 bpp_changed = (old_fb->bits_per_pixel !=
495 crtc->fb->bits_per_pixel);
496 } else {
497 depth_changed = true;
498 bpp_changed = true;
499 }
500
453 saved_mode = crtc->mode; 501 saved_mode = crtc->mode;
454 saved_x = crtc->x; 502 saved_x = crtc->x;
455 saved_y = crtc->y; 503 saved_y = crtc->y;
@@ -462,7 +510,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
462 crtc->y = y; 510 crtc->y = y;
463 511
464 if (drm_mode_equal(&saved_mode, &crtc->mode)) { 512 if (drm_mode_equal(&saved_mode, &crtc->mode)) {
465 if (saved_x != crtc->x || saved_y != crtc->y) { 513 if (saved_x != crtc->x || saved_y != crtc->y ||
514 depth_changed || bpp_changed) {
466 crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, 515 crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
467 old_fb); 516 old_fb);
468 goto done; 517 goto done;
@@ -568,8 +617,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
568 struct drm_encoder **save_encoders, *new_encoder; 617 struct drm_encoder **save_encoders, *new_encoder;
569 struct drm_framebuffer *old_fb; 618 struct drm_framebuffer *old_fb;
570 bool save_enabled; 619 bool save_enabled;
571 bool changed = false; 620 bool mode_changed = false;
572 bool flip_or_move = false; 621 bool fb_changed = false;
573 struct drm_connector *connector; 622 struct drm_connector *connector;
574 int count = 0, ro, fail = 0; 623 int count = 0, ro, fail = 0;
575 struct drm_crtc_helper_funcs *crtc_funcs; 624 struct drm_crtc_helper_funcs *crtc_funcs;
@@ -597,7 +646,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
597 /* save previous config */ 646 /* save previous config */
598 save_enabled = set->crtc->enabled; 647 save_enabled = set->crtc->enabled;
599 648
600 /* this is meant to be num_connector not num_crtc */ 649 /*
650 * We do mode_config.num_connectors here since we'll look at the
651 * CRTC and encoder associated with each connector later.
652 */
601 save_crtcs = kzalloc(dev->mode_config.num_connector * 653 save_crtcs = kzalloc(dev->mode_config.num_connector *
602 sizeof(struct drm_crtc *), GFP_KERNEL); 654 sizeof(struct drm_crtc *), GFP_KERNEL);
603 if (!save_crtcs) 655 if (!save_crtcs)
@@ -613,21 +665,25 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
613 /* We should be able to check here if the fb has the same properties 665 /* We should be able to check here if the fb has the same properties
614 * and then just flip_or_move it */ 666 * and then just flip_or_move it */
615 if (set->crtc->fb != set->fb) { 667 if (set->crtc->fb != set->fb) {
616 /* if we have no fb then its a change not a flip */ 668 /* If we have no fb then treat it as a full mode set */
617 if (set->crtc->fb == NULL) 669 if (set->crtc->fb == NULL)
618 changed = true; 670 mode_changed = true;
671 else if ((set->fb->bits_per_pixel !=
672 set->crtc->fb->bits_per_pixel) ||
673 set->fb->depth != set->crtc->fb->depth)
674 fb_changed = true;
619 else 675 else
620 flip_or_move = true; 676 fb_changed = true;
621 } 677 }
622 678
623 if (set->x != set->crtc->x || set->y != set->crtc->y) 679 if (set->x != set->crtc->x || set->y != set->crtc->y)
624 flip_or_move = true; 680 fb_changed = true;
625 681
626 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { 682 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
627 DRM_DEBUG("modes are different\n"); 683 DRM_DEBUG("modes are different\n");
628 drm_mode_debug_printmodeline(&set->crtc->mode); 684 drm_mode_debug_printmodeline(&set->crtc->mode);
629 drm_mode_debug_printmodeline(set->mode); 685 drm_mode_debug_printmodeline(set->mode);
630 changed = true; 686 mode_changed = true;
631 } 687 }
632 688
633 /* a) traverse passed in connector list and get encoders for them */ 689 /* a) traverse passed in connector list and get encoders for them */
@@ -650,7 +706,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
650 } 706 }
651 707
652 if (new_encoder != connector->encoder) { 708 if (new_encoder != connector->encoder) {
653 changed = true; 709 mode_changed = true;
654 connector->encoder = new_encoder; 710 connector->encoder = new_encoder;
655 } 711 }
656 } 712 }
@@ -677,16 +733,16 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
677 new_crtc = set->crtc; 733 new_crtc = set->crtc;
678 } 734 }
679 if (new_crtc != connector->encoder->crtc) { 735 if (new_crtc != connector->encoder->crtc) {
680 changed = true; 736 mode_changed = true;
681 connector->encoder->crtc = new_crtc; 737 connector->encoder->crtc = new_crtc;
682 } 738 }
683 } 739 }
684 740
685 /* mode_set_base is not a required function */ 741 /* mode_set_base is not a required function */
686 if (flip_or_move && !crtc_funcs->mode_set_base) 742 if (fb_changed && !crtc_funcs->mode_set_base)
687 changed = true; 743 mode_changed = true;
688 744
689 if (changed) { 745 if (mode_changed) {
690 old_fb = set->crtc->fb; 746 old_fb = set->crtc->fb;
691 set->crtc->fb = set->fb; 747 set->crtc->fb = set->fb;
692 set->crtc->enabled = (set->mode != NULL); 748 set->crtc->enabled = (set->mode != NULL);
@@ -705,7 +761,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
705 set->crtc->desired_mode = set->mode; 761 set->crtc->desired_mode = set->mode;
706 } 762 }
707 drm_helper_disable_unused_functions(dev); 763 drm_helper_disable_unused_functions(dev);
708 } else if (flip_or_move) { 764 } else if (fb_changed) {
709 old_fb = set->crtc->fb; 765 old_fb = set->crtc->fb;
710 if (set->crtc->fb != set->fb) 766 if (set->crtc->fb != set->fb)
711 set->crtc->fb = set->fb; 767 set->crtc->fb = set->fb;
@@ -764,10 +820,31 @@ bool drm_helper_plugged_event(struct drm_device *dev)
764 */ 820 */
765bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) 821bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
766{ 822{
767 int ret = false; 823 struct drm_connector *connector;
824 int count = 0;
768 825
769 drm_helper_plugged_event(dev); 826 count = drm_helper_probe_connector_modes(dev,
770 return ret; 827 dev->mode_config.max_width,
828 dev->mode_config.max_height);
829
830 /*
831 * None of the available connectors had any modes, so add some
832 * and try to light them up anyway
833 */
834 if (!count) {
835 DRM_ERROR("connectors have no modes, using standard modes\n");
836 list_for_each_entry(connector,
837 &dev->mode_config.connector_list,
838 head)
839 drm_helper_add_std_modes(dev, connector);
840 }
841
842 drm_setup_crtcs(dev);
843
844 /* alert the driver fb layer */
845 dev->mode_config.funcs->fb_changed(dev);
846
847 return 0;
771} 848}
772EXPORT_SYMBOL(drm_helper_initial_config); 849EXPORT_SYMBOL(drm_helper_initial_config);
773 850
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 724e505873cf..477caa1b1e4b 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -267,7 +267,8 @@ EXPORT_SYMBOL(drm_irq_install);
267 */ 267 */
268int drm_irq_uninstall(struct drm_device * dev) 268int drm_irq_uninstall(struct drm_device * dev)
269{ 269{
270 int irq_enabled; 270 unsigned long irqflags;
271 int irq_enabled, i;
271 272
272 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 273 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
273 return -EINVAL; 274 return -EINVAL;
@@ -277,6 +278,16 @@ int drm_irq_uninstall(struct drm_device * dev)
277 dev->irq_enabled = 0; 278 dev->irq_enabled = 0;
278 mutex_unlock(&dev->struct_mutex); 279 mutex_unlock(&dev->struct_mutex);
279 280
281 /*
282 * Wake up any waiters so they don't hang.
283 */
284 spin_lock_irqsave(&dev->vbl_lock, irqflags);
285 for (i = 0; i < dev->num_crtcs; i++) {
286 DRM_WAKEUP(&dev->vbl_queue[i]);
287 dev->vblank_enabled[i] = 0;
288 }
289 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
290
280 if (!irq_enabled) 291 if (!irq_enabled)
281 return -EINVAL; 292 return -EINVAL;
282 293
@@ -652,8 +663,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
652 vblwait->request.sequence, crtc); 663 vblwait->request.sequence, crtc);
653 dev->last_vblank_wait[crtc] = vblwait->request.sequence; 664 dev->last_vblank_wait[crtc] = vblwait->request.sequence;
654 DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, 665 DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
655 ((drm_vblank_count(dev, crtc) 666 (((drm_vblank_count(dev, crtc) -
656 - vblwait->request.sequence) <= (1 << 23))); 667 vblwait->request.sequence) <= (1 << 23)) ||
668 !dev->irq_enabled));
657 669
658 if (ret != -EINTR) { 670 if (ret != -EINTR) {
659 struct timeval now; 671 struct timeval now;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 62a4bf7b49df..bbadf1c04142 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -177,6 +177,14 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
177 drm_i915_private_t *dev_priv = dev->dev_private; 177 drm_i915_private_t *dev_priv = dev->dev_private;
178 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 178 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
179 179
180 master_priv->sarea = drm_getsarea(dev);
181 if (master_priv->sarea) {
182 master_priv->sarea_priv = (drm_i915_sarea_t *)
183 ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
184 } else {
185 DRM_DEBUG("sarea not found assuming DRI2 userspace\n");
186 }
187
180 if (init->ring_size != 0) { 188 if (init->ring_size != 0) {
181 if (dev_priv->ring.ring_obj != NULL) { 189 if (dev_priv->ring.ring_obj != NULL) {
182 i915_dma_cleanup(dev); 190 i915_dma_cleanup(dev);
@@ -1152,6 +1160,8 @@ int i915_driver_unload(struct drm_device *dev)
1152 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 1160 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1153 intel_modeset_cleanup(dev); 1161 intel_modeset_cleanup(dev);
1154 1162
1163 i915_gem_free_all_phys_object(dev);
1164
1155 mutex_lock(&dev->struct_mutex); 1165 mutex_lock(&dev->struct_mutex);
1156 i915_gem_cleanup_ringbuffer(dev); 1166 i915_gem_cleanup_ringbuffer(dev);
1157 mutex_unlock(&dev->struct_mutex); 1167 mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 563de18063fd..e13518252007 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -72,6 +72,18 @@ enum pipe {
72#define WATCH_INACTIVE 0 72#define WATCH_INACTIVE 0
73#define WATCH_PWRITE 0 73#define WATCH_PWRITE 0
74 74
75#define I915_GEM_PHYS_CURSOR_0 1
76#define I915_GEM_PHYS_CURSOR_1 2
77#define I915_GEM_PHYS_OVERLAY_REGS 3
78#define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS)
79
80struct drm_i915_gem_phys_object {
81 int id;
82 struct page **page_list;
83 drm_dma_handle_t *handle;
84 struct drm_gem_object *cur_obj;
85};
86
75typedef struct _drm_i915_ring_buffer { 87typedef struct _drm_i915_ring_buffer {
76 int tail_mask; 88 int tail_mask;
77 unsigned long Size; 89 unsigned long Size;
@@ -358,6 +370,9 @@ typedef struct drm_i915_private {
358 uint32_t bit_6_swizzle_x; 370 uint32_t bit_6_swizzle_x;
359 /** Bit 6 swizzling required for Y tiling */ 371 /** Bit 6 swizzling required for Y tiling */
360 uint32_t bit_6_swizzle_y; 372 uint32_t bit_6_swizzle_y;
373
374 /* storage for physical objects */
375 struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
361 } mm; 376 } mm;
362} drm_i915_private_t; 377} drm_i915_private_t;
363 378
@@ -436,6 +451,9 @@ struct drm_i915_gem_object {
436 /** User space pin count and filp owning the pin */ 451 /** User space pin count and filp owning the pin */
437 uint32_t user_pin_count; 452 uint32_t user_pin_count;
438 struct drm_file *pin_filp; 453 struct drm_file *pin_filp;
454
455 /** for phy allocated objects */
456 struct drm_i915_gem_phys_object *phys_obj;
439}; 457};
440 458
441/** 459/**
@@ -598,6 +616,11 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start,
598int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 616int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
599int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, 617int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
600 int write); 618 int write);
619int i915_gem_attach_phys_object(struct drm_device *dev,
620 struct drm_gem_object *obj, int id);
621void i915_gem_detach_phys_object(struct drm_device *dev,
622 struct drm_gem_object *obj);
623void i915_gem_free_all_phys_object(struct drm_device *dev);
601 624
602/* i915_gem_tiling.c */ 625/* i915_gem_tiling.c */
603void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); 626void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1384d6686555..96316fd47233 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -55,6 +55,9 @@ static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
55static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj); 55static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
56static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); 56static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
57static int i915_gem_evict_something(struct drm_device *dev); 57static int i915_gem_evict_something(struct drm_device *dev);
58static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
59 struct drm_i915_gem_pwrite *args,
60 struct drm_file *file_priv);
58 61
59int i915_gem_do_init(struct drm_device *dev, unsigned long start, 62int i915_gem_do_init(struct drm_device *dev, unsigned long start,
60 unsigned long end) 63 unsigned long end)
@@ -386,8 +389,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
386 * pread/pwrite currently are reading and writing from the CPU 389 * pread/pwrite currently are reading and writing from the CPU
387 * perspective, requiring manual detiling by the client. 390 * perspective, requiring manual detiling by the client.
388 */ 391 */
389 if (obj_priv->tiling_mode == I915_TILING_NONE && 392 if (obj_priv->phys_obj)
390 dev->gtt_total != 0) 393 ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
394 else if (obj_priv->tiling_mode == I915_TILING_NONE &&
395 dev->gtt_total != 0)
391 ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv); 396 ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
392 else 397 else
393 ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv); 398 ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
@@ -2858,6 +2863,9 @@ void i915_gem_free_object(struct drm_gem_object *obj)
2858 while (obj_priv->pin_count > 0) 2863 while (obj_priv->pin_count > 0)
2859 i915_gem_object_unpin(obj); 2864 i915_gem_object_unpin(obj);
2860 2865
2866 if (obj_priv->phys_obj)
2867 i915_gem_detach_phys_object(dev, obj);
2868
2861 i915_gem_object_unbind(obj); 2869 i915_gem_object_unbind(obj);
2862 2870
2863 list = &obj->map_list; 2871 list = &obj->map_list;
@@ -3293,3 +3301,180 @@ i915_gem_load(struct drm_device *dev)
3293 3301
3294 i915_gem_detect_bit_6_swizzle(dev); 3302 i915_gem_detect_bit_6_swizzle(dev);
3295} 3303}
3304
3305/*
3306 * Create a physically contiguous memory object for this object
3307 * e.g. for cursor + overlay regs
3308 */
3309int i915_gem_init_phys_object(struct drm_device *dev,
3310 int id, int size)
3311{
3312 drm_i915_private_t *dev_priv = dev->dev_private;
3313 struct drm_i915_gem_phys_object *phys_obj;
3314 int ret;
3315
3316 if (dev_priv->mm.phys_objs[id - 1] || !size)
3317 return 0;
3318
3319 phys_obj = drm_calloc(1, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
3320 if (!phys_obj)
3321 return -ENOMEM;
3322
3323 phys_obj->id = id;
3324
3325 phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff);
3326 if (!phys_obj->handle) {
3327 ret = -ENOMEM;
3328 goto kfree_obj;
3329 }
3330#ifdef CONFIG_X86
3331 set_memory_wc((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE);
3332#endif
3333
3334 dev_priv->mm.phys_objs[id - 1] = phys_obj;
3335
3336 return 0;
3337kfree_obj:
3338 drm_free(phys_obj, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
3339 return ret;
3340}
3341
3342void i915_gem_free_phys_object(struct drm_device *dev, int id)
3343{
3344 drm_i915_private_t *dev_priv = dev->dev_private;
3345 struct drm_i915_gem_phys_object *phys_obj;
3346
3347 if (!dev_priv->mm.phys_objs[id - 1])
3348 return;
3349
3350 phys_obj = dev_priv->mm.phys_objs[id - 1];
3351 if (phys_obj->cur_obj) {
3352 i915_gem_detach_phys_object(dev, phys_obj->cur_obj);
3353 }
3354
3355#ifdef CONFIG_X86
3356 set_memory_wb((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE);
3357#endif
3358 drm_pci_free(dev, phys_obj->handle);
3359 kfree(phys_obj);
3360 dev_priv->mm.phys_objs[id - 1] = NULL;
3361}
3362
3363void i915_gem_free_all_phys_object(struct drm_device *dev)
3364{
3365 int i;
3366
3367 for (i = 0; i < I915_MAX_PHYS_OBJECT; i++)
3368 i915_gem_free_phys_object(dev, i);
3369}
3370
3371void i915_gem_detach_phys_object(struct drm_device *dev,
3372 struct drm_gem_object *obj)
3373{
3374 struct drm_i915_gem_object *obj_priv;
3375 int i;
3376 int ret;
3377 int page_count;
3378
3379 obj_priv = obj->driver_private;
3380 if (!obj_priv->phys_obj)
3381 return;
3382
3383 ret = i915_gem_object_get_page_list(obj);
3384 if (ret)
3385 goto out;
3386
3387 page_count = obj->size / PAGE_SIZE;
3388
3389 for (i = 0; i < page_count; i++) {
3390 char *dst = kmap_atomic(obj_priv->page_list[i], KM_USER0);
3391 char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
3392
3393 memcpy(dst, src, PAGE_SIZE);
3394 kunmap_atomic(dst, KM_USER0);
3395 }
3396 drm_clflush_pages(obj_priv->page_list, page_count);
3397 drm_agp_chipset_flush(dev);
3398out:
3399 obj_priv->phys_obj->cur_obj = NULL;
3400 obj_priv->phys_obj = NULL;
3401}
3402
3403int
3404i915_gem_attach_phys_object(struct drm_device *dev,
3405 struct drm_gem_object *obj, int id)
3406{
3407 drm_i915_private_t *dev_priv = dev->dev_private;
3408 struct drm_i915_gem_object *obj_priv;
3409 int ret = 0;
3410 int page_count;
3411 int i;
3412
3413 if (id > I915_MAX_PHYS_OBJECT)
3414 return -EINVAL;
3415
3416 obj_priv = obj->driver_private;
3417
3418 if (obj_priv->phys_obj) {
3419 if (obj_priv->phys_obj->id == id)
3420 return 0;
3421 i915_gem_detach_phys_object(dev, obj);
3422 }
3423
3424
3425 /* create a new object */
3426 if (!dev_priv->mm.phys_objs[id - 1]) {
3427 ret = i915_gem_init_phys_object(dev, id,
3428 obj->size);
3429 if (ret) {
3430 DRM_ERROR("failed to init phys object %d size: %d\n", id, obj->size);
3431 goto out;
3432 }
3433 }
3434
3435 /* bind to the object */
3436 obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1];
3437 obj_priv->phys_obj->cur_obj = obj;
3438
3439 ret = i915_gem_object_get_page_list(obj);
3440 if (ret) {
3441 DRM_ERROR("failed to get page list\n");
3442 goto out;
3443 }
3444
3445 page_count = obj->size / PAGE_SIZE;
3446
3447 for (i = 0; i < page_count; i++) {
3448 char *src = kmap_atomic(obj_priv->page_list[i], KM_USER0);
3449 char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
3450
3451 memcpy(dst, src, PAGE_SIZE);
3452 kunmap_atomic(src, KM_USER0);
3453 }
3454
3455 return 0;
3456out:
3457 return ret;
3458}
3459
3460static int
3461i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
3462 struct drm_i915_gem_pwrite *args,
3463 struct drm_file *file_priv)
3464{
3465 struct drm_i915_gem_object *obj_priv = obj->driver_private;
3466 void *obj_addr;
3467 int ret;
3468 char __user *user_data;
3469
3470 user_data = (char __user *) (uintptr_t) args->data_ptr;
3471 obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
3472
3473 DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size);
3474 ret = copy_from_user(obj_addr, user_data, args->size);
3475 if (ret)
3476 return -EFAULT;
3477
3478 drm_agp_chipset_flush(dev);
3479 return 0;
3480}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0cadafbef411..6290219de6c8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -411,6 +411,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
411{ 411{
412 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 412 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
413 unsigned long irqflags; 413 unsigned long irqflags;
414 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
415 u32 pipeconf;
416
417 pipeconf = I915_READ(pipeconf_reg);
418 if (!(pipeconf & PIPEACONF_ENABLE))
419 return -EINVAL;
414 420
415 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); 421 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
416 if (IS_I965G(dev)) 422 if (IS_I965G(dev))
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8ccb9c3ab868..31c3732b7a69 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -401,6 +401,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
401 I915_WRITE(dspstride, crtc->fb->pitch); 401 I915_WRITE(dspstride, crtc->fb->pitch);
402 402
403 dspcntr = I915_READ(dspcntr_reg); 403 dspcntr = I915_READ(dspcntr_reg);
404 /* Mask out pixel format bits in case we change it */
405 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
404 switch (crtc->fb->bits_per_pixel) { 406 switch (crtc->fb->bits_per_pixel) {
405 case 8: 407 case 8:
406 dspcntr |= DISPPLANE_8BPP; 408 dspcntr |= DISPPLANE_8BPP;
@@ -1014,21 +1016,25 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
1014 1016
1015 if (bo->size < width * height * 4) { 1017 if (bo->size < width * height * 4) {
1016 DRM_ERROR("buffer is to small\n"); 1018 DRM_ERROR("buffer is to small\n");
1017 drm_gem_object_unreference(bo); 1019 ret = -ENOMEM;
1018 return -ENOMEM; 1020 goto fail;
1019 } 1021 }
1020 1022
1021 if (dev_priv->cursor_needs_physical) { 1023 /* we only need to pin inside GTT if cursor is non-phy */
1022 addr = dev->agp->base + obj_priv->gtt_offset; 1024 if (!dev_priv->cursor_needs_physical) {
1023 } else { 1025 ret = i915_gem_object_pin(bo, PAGE_SIZE);
1026 if (ret) {
1027 DRM_ERROR("failed to pin cursor bo\n");
1028 goto fail;
1029 }
1024 addr = obj_priv->gtt_offset; 1030 addr = obj_priv->gtt_offset;
1025 } 1031 } else {
1026 1032 ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
1027 ret = i915_gem_object_pin(bo, PAGE_SIZE); 1033 if (ret) {
1028 if (ret) { 1034 DRM_ERROR("failed to attach phys object\n");
1029 DRM_ERROR("failed to pin cursor bo\n"); 1035 goto fail;
1030 drm_gem_object_unreference(bo); 1036 }
1031 return ret; 1037 addr = obj_priv->phys_obj->handle->busaddr;
1032 } 1038 }
1033 1039
1034 temp = 0; 1040 temp = 0;
@@ -1041,14 +1047,25 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
1041 I915_WRITE(base, addr); 1047 I915_WRITE(base, addr);
1042 1048
1043 if (intel_crtc->cursor_bo) { 1049 if (intel_crtc->cursor_bo) {
1044 i915_gem_object_unpin(intel_crtc->cursor_bo); 1050 if (dev_priv->cursor_needs_physical) {
1051 if (intel_crtc->cursor_bo != bo)
1052 i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
1053 } else
1054 i915_gem_object_unpin(intel_crtc->cursor_bo);
1055 mutex_lock(&dev->struct_mutex);
1045 drm_gem_object_unreference(intel_crtc->cursor_bo); 1056 drm_gem_object_unreference(intel_crtc->cursor_bo);
1057 mutex_unlock(&dev->struct_mutex);
1046 } 1058 }
1047 1059
1048 intel_crtc->cursor_addr = addr; 1060 intel_crtc->cursor_addr = addr;
1049 intel_crtc->cursor_bo = bo; 1061 intel_crtc->cursor_bo = bo;
1050 1062
1051 return 0; 1063 return 0;
1064fail:
1065 mutex_lock(&dev->struct_mutex);
1066 drm_gem_object_unreference(bo);
1067 mutex_unlock(&dev->struct_mutex);
1068 return ret;
1052} 1069}
1053 1070
1054static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) 1071static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index ccecfaf6307b..2fafdcc108fe 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -456,6 +456,13 @@ void intel_lvds_init(struct drm_device *dev)
456 dev_priv->panel_fixed_mode = 456 dev_priv->panel_fixed_mode =
457 drm_mode_duplicate(dev, dev_priv->vbt_mode); 457 drm_mode_duplicate(dev, dev_priv->vbt_mode);
458 mutex_unlock(&dev->mode_config.mutex); 458 mutex_unlock(&dev->mode_config.mutex);
459 if (dev_priv->panel_fixed_mode) {
460 dev_priv->panel_fixed_mode->type |=
461 DRM_MODE_TYPE_PREFERRED;
462 drm_mode_probed_add(connector,
463 dev_priv->panel_fixed_mode);
464 goto out;
465 }
459 } 466 }
460 467
461 /* 468 /*