aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbdev.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c85
1 files changed, 51 insertions, 34 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 4babefc51eb2..86b00c6db1a6 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -362,23 +362,24 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
362 bool *enabled, int width, int height) 362 bool *enabled, int width, int height)
363{ 363{
364 struct drm_device *dev = fb_helper->dev; 364 struct drm_device *dev = fb_helper->dev;
365 unsigned long conn_configured, mask;
366 unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
365 int i, j; 367 int i, j;
366 bool *save_enabled; 368 bool *save_enabled;
367 bool fallback = true; 369 bool fallback = true;
368 int num_connectors_enabled = 0; 370 int num_connectors_enabled = 0;
369 int num_connectors_detected = 0; 371 int num_connectors_detected = 0;
370 uint64_t conn_configured = 0, mask;
371 int pass = 0; 372 int pass = 0;
372 373
373 save_enabled = kcalloc(fb_helper->connector_count, sizeof(bool), 374 save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
374 GFP_KERNEL);
375 if (!save_enabled) 375 if (!save_enabled)
376 return false; 376 return false;
377 377
378 memcpy(save_enabled, enabled, fb_helper->connector_count); 378 memcpy(save_enabled, enabled, count);
379 mask = (1 << fb_helper->connector_count) - 1; 379 mask = BIT(count) - 1;
380 conn_configured = 0;
380retry: 381retry:
381 for (i = 0; i < fb_helper->connector_count; i++) { 382 for (i = 0; i < count; i++) {
382 struct drm_fb_helper_connector *fb_conn; 383 struct drm_fb_helper_connector *fb_conn;
383 struct drm_connector *connector; 384 struct drm_connector *connector;
384 struct drm_encoder *encoder; 385 struct drm_encoder *encoder;
@@ -388,7 +389,7 @@ retry:
388 fb_conn = fb_helper->connector_info[i]; 389 fb_conn = fb_helper->connector_info[i];
389 connector = fb_conn->connector; 390 connector = fb_conn->connector;
390 391
391 if (conn_configured & (1 << i)) 392 if (conn_configured & BIT(i))
392 continue; 393 continue;
393 394
394 if (pass == 0 && !connector->has_tile) 395 if (pass == 0 && !connector->has_tile)
@@ -400,7 +401,7 @@ retry:
400 if (!enabled[i]) { 401 if (!enabled[i]) {
401 DRM_DEBUG_KMS("connector %s not enabled, skipping\n", 402 DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
402 connector->name); 403 connector->name);
403 conn_configured |= (1 << i); 404 conn_configured |= BIT(i);
404 continue; 405 continue;
405 } 406 }
406 407
@@ -419,7 +420,7 @@ retry:
419 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", 420 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
420 connector->name); 421 connector->name);
421 enabled[i] = false; 422 enabled[i] = false;
422 conn_configured |= (1 << i); 423 conn_configured |= BIT(i);
423 continue; 424 continue;
424 } 425 }
425 426
@@ -432,14 +433,15 @@ retry:
432 intel_crtc->lut_b[j] = j; 433 intel_crtc->lut_b[j] = j;
433 } 434 }
434 435
435 new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc); 436 new_crtc = intel_fb_helper_crtc(fb_helper,
437 connector->state->crtc);
436 438
437 /* 439 /*
438 * Make sure we're not trying to drive multiple connectors 440 * Make sure we're not trying to drive multiple connectors
439 * with a single CRTC, since our cloning support may not 441 * with a single CRTC, since our cloning support may not
440 * match the BIOS. 442 * match the BIOS.
441 */ 443 */
442 for (j = 0; j < fb_helper->connector_count; j++) { 444 for (j = 0; j < count; j++) {
443 if (crtcs[j] == new_crtc) { 445 if (crtcs[j] == new_crtc) {
444 DRM_DEBUG_KMS("fallback: cloned configuration\n"); 446 DRM_DEBUG_KMS("fallback: cloned configuration\n");
445 goto bail; 447 goto bail;
@@ -498,7 +500,7 @@ retry:
498 modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :""); 500 modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
499 501
500 fallback = false; 502 fallback = false;
501 conn_configured |= (1 << i); 503 conn_configured |= BIT(i);
502 } 504 }
503 505
504 if ((conn_configured & mask) != mask) { 506 if ((conn_configured & mask) != mask) {
@@ -522,7 +524,7 @@ retry:
522 if (fallback) { 524 if (fallback) {
523bail: 525bail:
524 DRM_DEBUG_KMS("Not using firmware configuration\n"); 526 DRM_DEBUG_KMS("Not using firmware configuration\n");
525 memcpy(enabled, save_enabled, fb_helper->connector_count); 527 memcpy(enabled, save_enabled, count);
526 kfree(save_enabled); 528 kfree(save_enabled);
527 return false; 529 return false;
528 } 530 }
@@ -538,8 +540,7 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
538 .fb_probe = intelfb_create, 540 .fb_probe = intelfb_create,
539}; 541};
540 542
541static void intel_fbdev_destroy(struct drm_device *dev, 543static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
542 struct intel_fbdev *ifbdev)
543{ 544{
544 /* We rely on the object-free to release the VMA pinning for 545 /* We rely on the object-free to release the VMA pinning for
545 * the info->screen_base mmaping. Leaking the VMA is simpler than 546 * the info->screen_base mmaping. Leaking the VMA is simpler than
@@ -552,12 +553,14 @@ static void intel_fbdev_destroy(struct drm_device *dev,
552 drm_fb_helper_fini(&ifbdev->helper); 553 drm_fb_helper_fini(&ifbdev->helper);
553 554
554 if (ifbdev->fb) { 555 if (ifbdev->fb) {
555 mutex_lock(&dev->struct_mutex); 556 mutex_lock(&ifbdev->helper.dev->struct_mutex);
556 intel_unpin_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0)); 557 intel_unpin_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
557 mutex_unlock(&dev->struct_mutex); 558 mutex_unlock(&ifbdev->helper.dev->struct_mutex);
558 559
559 drm_framebuffer_remove(&ifbdev->fb->base); 560 drm_framebuffer_remove(&ifbdev->fb->base);
560 } 561 }
562
563 kfree(ifbdev);
561} 564}
562 565
563/* 566/*
@@ -690,9 +693,9 @@ out:
690 693
691static void intel_fbdev_suspend_worker(struct work_struct *work) 694static void intel_fbdev_suspend_worker(struct work_struct *work)
692{ 695{
693 intel_fbdev_set_suspend(container_of(work, 696 intel_fbdev_set_suspend(&container_of(work,
694 struct drm_i915_private, 697 struct drm_i915_private,
695 fbdev_suspend_work)->dev, 698 fbdev_suspend_work)->drm,
696 FBINFO_STATE_RUNNING, 699 FBINFO_STATE_RUNNING,
697 true); 700 true);
698} 701}
@@ -700,7 +703,7 @@ static void intel_fbdev_suspend_worker(struct work_struct *work)
700int intel_fbdev_init(struct drm_device *dev) 703int intel_fbdev_init(struct drm_device *dev)
701{ 704{
702 struct intel_fbdev *ifbdev; 705 struct intel_fbdev *ifbdev;
703 struct drm_i915_private *dev_priv = dev->dev_private; 706 struct drm_i915_private *dev_priv = to_i915(dev);
704 int ret; 707 int ret;
705 708
706 if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0)) 709 if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
@@ -732,38 +735,50 @@ int intel_fbdev_init(struct drm_device *dev)
732 735
733static void intel_fbdev_initial_config(void *data, async_cookie_t cookie) 736static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
734{ 737{
735 struct drm_i915_private *dev_priv = data; 738 struct intel_fbdev *ifbdev = data;
736 struct intel_fbdev *ifbdev = dev_priv->fbdev;
737 739
738 /* Due to peculiar init order wrt to hpd handling this is separate. */ 740 /* Due to peculiar init order wrt to hpd handling this is separate. */
739 if (drm_fb_helper_initial_config(&ifbdev->helper, 741 if (drm_fb_helper_initial_config(&ifbdev->helper,
740 ifbdev->preferred_bpp)) 742 ifbdev->preferred_bpp))
741 intel_fbdev_fini(dev_priv->dev); 743 intel_fbdev_fini(ifbdev->helper.dev);
742} 744}
743 745
744void intel_fbdev_initial_config_async(struct drm_device *dev) 746void intel_fbdev_initial_config_async(struct drm_device *dev)
745{ 747{
746 async_schedule(intel_fbdev_initial_config, to_i915(dev)); 748 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
749
750 ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
751}
752
753static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
754{
755 if (!ifbdev->cookie)
756 return;
757
758 /* Only serialises with all preceding async calls, hence +1 */
759 async_synchronize_cookie(ifbdev->cookie + 1);
760 ifbdev->cookie = 0;
747} 761}
748 762
749void intel_fbdev_fini(struct drm_device *dev) 763void intel_fbdev_fini(struct drm_device *dev)
750{ 764{
751 struct drm_i915_private *dev_priv = dev->dev_private; 765 struct drm_i915_private *dev_priv = to_i915(dev);
752 if (!dev_priv->fbdev) 766 struct intel_fbdev *ifbdev = dev_priv->fbdev;
767
768 if (!ifbdev)
753 return; 769 return;
754 770
755 flush_work(&dev_priv->fbdev_suspend_work); 771 flush_work(&dev_priv->fbdev_suspend_work);
756
757 if (!current_is_async()) 772 if (!current_is_async())
758 async_synchronize_full(); 773 intel_fbdev_sync(ifbdev);
759 intel_fbdev_destroy(dev, dev_priv->fbdev); 774
760 kfree(dev_priv->fbdev); 775 intel_fbdev_destroy(ifbdev);
761 dev_priv->fbdev = NULL; 776 dev_priv->fbdev = NULL;
762} 777}
763 778
764void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) 779void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
765{ 780{
766 struct drm_i915_private *dev_priv = dev->dev_private; 781 struct drm_i915_private *dev_priv = to_i915(dev);
767 struct intel_fbdev *ifbdev = dev_priv->fbdev; 782 struct intel_fbdev *ifbdev = dev_priv->fbdev;
768 struct fb_info *info; 783 struct fb_info *info;
769 784
@@ -812,7 +827,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
812 827
813void intel_fbdev_output_poll_changed(struct drm_device *dev) 828void intel_fbdev_output_poll_changed(struct drm_device *dev)
814{ 829{
815 struct drm_i915_private *dev_priv = dev->dev_private; 830 struct drm_i915_private *dev_priv = to_i915(dev);
816 if (dev_priv->fbdev) 831 if (dev_priv->fbdev)
817 drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); 832 drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
818} 833}
@@ -820,13 +835,15 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev)
820void intel_fbdev_restore_mode(struct drm_device *dev) 835void intel_fbdev_restore_mode(struct drm_device *dev)
821{ 836{
822 int ret; 837 int ret;
823 struct drm_i915_private *dev_priv = dev->dev_private; 838 struct drm_i915_private *dev_priv = to_i915(dev);
824 struct intel_fbdev *ifbdev = dev_priv->fbdev; 839 struct intel_fbdev *ifbdev = dev_priv->fbdev;
825 struct drm_fb_helper *fb_helper; 840 struct drm_fb_helper *fb_helper;
826 841
827 if (!ifbdev) 842 if (!ifbdev)
828 return; 843 return;
829 844
845 intel_fbdev_sync(ifbdev);
846
830 fb_helper = &ifbdev->helper; 847 fb_helper = &ifbdev->helper;
831 848
832 ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); 849 ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);