aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fbdev.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
commit2d65a9f48fcdf7866aab6457bc707ca233e0c791 (patch)
treef93e5838d6ac2e59434367f4ff905f7d9c45fc2b /drivers/gpu/drm/i915/intel_fbdev.c
parentda92da3638a04894afdca8b99e973ddd20268471 (diff)
parentdfda0df3426483cf5fc7441f23f318edbabecb03 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main git pull for the drm, I pretty much froze major pulls at -rc5/6 time, and haven't had much fallout, so will probably continue doing that. Lots of changes all over, big internal header cleanup to make it clear drm features are legacy things and what are things that modern KMS drivers should be using. Also big move to use the new generic fences in all the TTM drivers. core: atomic prep work, vblank rework changes, allows immediate vblank disables major header reworking and cleanups to better delinate legacy interfaces from what KMS drivers should be using. cursor planes locking fixes ttm: move to generic fences (affects all TTM drivers) ppc64 caching fixes radeon: userptr support, uvd for old asics, reset rework for fence changes better buffer placement changes, dpm feature enablement hdmi audio support fixes intel: Cherryview work, 180 degree rotation, skylake prep work, execlist command submission full ppgtt prep work cursor improvements edid caching, vdd handling improvements nouveau: fence reworking kepler memory clock work gt21x clock work fan control improvements hdmi infoframe fixes DP audio ast: ppc64 fixes caching fix rcar: rcar-du DT support ipuv3: prep work for capture support msm: LVDS support for mdp4, new panel, gpu refactoring exynos: exynos3250 SoC support, drop bad mmap interface, mipi dsi changes, and component match support" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (640 commits) drm/mst: rework payload table allocation to conform better. drm/ast: Fix HW cursor image drm/radeon/kv: add uvd/vce info to dpm debugfs output drm/radeon/ci: add uvd/vce info to dpm debugfs output drm/radeon: export reservation_object from dmabuf to ttm drm/radeon: cope with foreign fences inside the reservation object drm/radeon: cope with foreign fences inside display drm/core: use helper to check driver features drm/radeon/cik: write gfx ucode version to ucode addr reg drm/radeon/si: print full CS when we hit a packet 0 drm/radeon: remove unecessary includes drm/radeon/combios: declare legacy_connector_convert as static drm/radeon/atombios: declare connector convert tables as static drm/radeon: drop btc_get_max_clock_from_voltage_dependency_table drm/radeon/dpm: drop clk/voltage dependency filters for BTC drm/radeon/dpm: drop clk/voltage dependency filters for CI drm/radeon/dpm: drop clk/voltage dependency filters for SI drm/radeon/dpm: drop clk/voltage dependency filters for NI drm/radeon: disable audio when we disable hdmi (v2) drm/radeon: split audio enable between eg and r600 (v2) ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbdev.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c83
1 files changed, 59 insertions, 24 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index f475414671d8..9b584f3fbb99 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -24,8 +24,10 @@
24 * David Airlie 24 * David Airlie
25 */ 25 */
26 26
27#include <linux/async.h>
27#include <linux/module.h> 28#include <linux/module.h>
28#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/console.h>
29#include <linux/errno.h> 31#include <linux/errno.h>
30#include <linux/string.h> 32#include <linux/string.h>
31#include <linux/mm.h> 33#include <linux/mm.h>
@@ -331,24 +333,6 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
331 int num_connectors_enabled = 0; 333 int num_connectors_enabled = 0;
332 int num_connectors_detected = 0; 334 int num_connectors_detected = 0;
333 335
334 /*
335 * If the user specified any force options, just bail here
336 * and use that config.
337 */
338 for (i = 0; i < fb_helper->connector_count; i++) {
339 struct drm_fb_helper_connector *fb_conn;
340 struct drm_connector *connector;
341
342 fb_conn = fb_helper->connector_info[i];
343 connector = fb_conn->connector;
344
345 if (!enabled[i])
346 continue;
347
348 if (connector->force != DRM_FORCE_UNSPECIFIED)
349 return false;
350 }
351
352 save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool), 336 save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
353 GFP_KERNEL); 337 GFP_KERNEL);
354 if (!save_enabled) 338 if (!save_enabled)
@@ -374,8 +358,18 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
374 continue; 358 continue;
375 } 359 }
376 360
361 if (connector->force == DRM_FORCE_OFF) {
362 DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
363 connector->name);
364 enabled[i] = false;
365 continue;
366 }
367
377 encoder = connector->encoder; 368 encoder = connector->encoder;
378 if (!encoder || WARN_ON(!encoder->crtc)) { 369 if (!encoder || WARN_ON(!encoder->crtc)) {
370 if (connector->force > DRM_FORCE_OFF)
371 goto bail;
372
379 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", 373 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
380 connector->name); 374 connector->name);
381 enabled[i] = false; 375 enabled[i] = false;
@@ -394,8 +388,7 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
394 for (j = 0; j < fb_helper->connector_count; j++) { 388 for (j = 0; j < fb_helper->connector_count; j++) {
395 if (crtcs[j] == new_crtc) { 389 if (crtcs[j] == new_crtc) {
396 DRM_DEBUG_KMS("fallback: cloned configuration\n"); 390 DRM_DEBUG_KMS("fallback: cloned configuration\n");
397 fallback = true; 391 goto bail;
398 goto out;
399 } 392 }
400 } 393 }
401 394
@@ -466,8 +459,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
466 fallback = true; 459 fallback = true;
467 } 460 }
468 461
469out:
470 if (fallback) { 462 if (fallback) {
463bail:
471 DRM_DEBUG_KMS("Not using firmware configuration\n"); 464 DRM_DEBUG_KMS("Not using firmware configuration\n");
472 memcpy(enabled, save_enabled, dev->mode_config.num_connector); 465 memcpy(enabled, save_enabled, dev->mode_config.num_connector);
473 kfree(save_enabled); 466 kfree(save_enabled);
@@ -636,6 +629,15 @@ out:
636 return false; 629 return false;
637} 630}
638 631
632static void intel_fbdev_suspend_worker(struct work_struct *work)
633{
634 intel_fbdev_set_suspend(container_of(work,
635 struct drm_i915_private,
636 fbdev_suspend_work)->dev,
637 FBINFO_STATE_RUNNING,
638 true);
639}
640
639int intel_fbdev_init(struct drm_device *dev) 641int intel_fbdev_init(struct drm_device *dev)
640{ 642{
641 struct intel_fbdev *ifbdev; 643 struct intel_fbdev *ifbdev;
@@ -662,14 +664,16 @@ int intel_fbdev_init(struct drm_device *dev)
662 } 664 }
663 665
664 dev_priv->fbdev = ifbdev; 666 dev_priv->fbdev = ifbdev;
667 INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
668
665 drm_fb_helper_single_add_all_connectors(&ifbdev->helper); 669 drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
666 670
667 return 0; 671 return 0;
668} 672}
669 673
670void intel_fbdev_initial_config(struct drm_device *dev) 674void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
671{ 675{
672 struct drm_i915_private *dev_priv = dev->dev_private; 676 struct drm_i915_private *dev_priv = data;
673 struct intel_fbdev *ifbdev = dev_priv->fbdev; 677 struct intel_fbdev *ifbdev = dev_priv->fbdev;
674 678
675 /* Due to peculiar init order wrt to hpd handling this is separate. */ 679 /* Due to peculiar init order wrt to hpd handling this is separate. */
@@ -682,12 +686,15 @@ void intel_fbdev_fini(struct drm_device *dev)
682 if (!dev_priv->fbdev) 686 if (!dev_priv->fbdev)
683 return; 687 return;
684 688
689 flush_work(&dev_priv->fbdev_suspend_work);
690
691 async_synchronize_full();
685 intel_fbdev_destroy(dev, dev_priv->fbdev); 692 intel_fbdev_destroy(dev, dev_priv->fbdev);
686 kfree(dev_priv->fbdev); 693 kfree(dev_priv->fbdev);
687 dev_priv->fbdev = NULL; 694 dev_priv->fbdev = NULL;
688} 695}
689 696
690void intel_fbdev_set_suspend(struct drm_device *dev, int state) 697void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
691{ 698{
692 struct drm_i915_private *dev_priv = dev->dev_private; 699 struct drm_i915_private *dev_priv = dev->dev_private;
693 struct intel_fbdev *ifbdev = dev_priv->fbdev; 700 struct intel_fbdev *ifbdev = dev_priv->fbdev;
@@ -698,6 +705,33 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
698 705
699 info = ifbdev->helper.fbdev; 706 info = ifbdev->helper.fbdev;
700 707
708 if (synchronous) {
709 /* Flush any pending work to turn the console on, and then
710 * wait to turn it off. It must be synchronous as we are
711 * about to suspend or unload the driver.
712 *
713 * Note that from within the work-handler, we cannot flush
714 * ourselves, so only flush outstanding work upon suspend!
715 */
716 if (state != FBINFO_STATE_RUNNING)
717 flush_work(&dev_priv->fbdev_suspend_work);
718 console_lock();
719 } else {
720 /*
721 * The console lock can be pretty contented on resume due
722 * to all the printk activity. Try to keep it out of the hot
723 * path of resume if possible.
724 */
725 WARN_ON(state != FBINFO_STATE_RUNNING);
726 if (!console_trylock()) {
727 /* Don't block our own workqueue as this can
728 * be run in parallel with other i915.ko tasks.
729 */
730 schedule_work(&dev_priv->fbdev_suspend_work);
731 return;
732 }
733 }
734
701 /* On resume from hibernation: If the object is shmemfs backed, it has 735 /* On resume from hibernation: If the object is shmemfs backed, it has
702 * been restored from swap. If the object is stolen however, it will be 736 * been restored from swap. If the object is stolen however, it will be
703 * full of whatever garbage was left in there. 737 * full of whatever garbage was left in there.
@@ -706,6 +740,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
706 memset_io(info->screen_base, 0, info->screen_size); 740 memset_io(info->screen_base, 0, info->screen_size);
707 741
708 fb_set_suspend(info, state); 742 fb_set_suspend(info, state);
743 console_unlock();
709} 744}
710 745
711void intel_fbdev_output_poll_changed(struct drm_device *dev) 746void intel_fbdev_output_poll_changed(struct drm_device *dev)