aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_dma.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2008-11-07 17:24:08 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:23 -0500
commit79e539453b34e35f39299a899d263b0a1f1670bd (patch)
tree6d1285f2b78fab399aab75a3557b7d6bc0dbd112 /drivers/gpu/drm/i915/i915_dma.c
parentf453ba0460742ad027ae0c4c7d61e62817b3e7ef (diff)
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs. Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are supported. HDMI, DisplayPort and additional SDVO output support will follow. Support for the mode setting code is controlled by the new 'modeset' module option. A new config option, CONFIG_DRM_I915_KMS controls the default behavior, and whether a PCI ID list is built into the module for use by user level module utilities. Note that if mode setting is enabled, user level drivers that access display registers directly or that don't use the kernel graphics memory manager will likely corrupt kernel graphics memory, disrupt output configuration (possibly leading to hangs and/or blank displays), and prevent panic/oops messages from appearing. So use caution when enabling this code; be sure your user level code supports the new interfaces. A new SysRq key, 'g', provides emergency support for switching back to the kernel's framebuffer console; which is useful for testing. Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c258
1 files changed, 253 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 1b81b6a6d81..b5d0809eecb 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -28,6 +28,8 @@
28 28
29#include "drmP.h" 29#include "drmP.h"
30#include "drm.h" 30#include "drm.h"
31#include "drm_crtc_helper.h"
32#include "intel_drv.h"
31#include "i915_drm.h" 33#include "i915_drm.h"
32#include "i915_drv.h" 34#include "i915_drv.h"
33 35
@@ -125,6 +127,13 @@ void i915_kernel_lost_context(struct drm_device * dev)
125 struct drm_i915_master_private *master_priv; 127 struct drm_i915_master_private *master_priv;
126 drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 128 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
127 129
130 /*
131 * We should never lose context on the ring with modesetting
132 * as we don't expose it to userspace
133 */
134 if (drm_core_check_feature(dev, DRIVER_MODESET))
135 return;
136
128 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 137 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
129 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; 138 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
130 ring->space = ring->head - (ring->tail + 8); 139 ring->space = ring->head - (ring->tail + 8);
@@ -769,6 +778,11 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
769 return -EINVAL; 778 return -EINVAL;
770 } 779 }
771 780
781 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
782 WARN(1, "tried to set status page when mode setting active\n");
783 return 0;
784 }
785
772 printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); 786 printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
773 787
774 dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); 788 dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
@@ -797,6 +811,173 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
797 return 0; 811 return 0;
798} 812}
799 813
814/**
815 * i915_probe_agp - get AGP bootup configuration
816 * @pdev: PCI device
817 * @aperture_size: returns AGP aperture configured size
818 * @preallocated_size: returns size of BIOS preallocated AGP space
819 *
820 * Since Intel integrated graphics are UMA, the BIOS has to set aside
821 * some RAM for the framebuffer at early boot. This code figures out
822 * how much was set aside so we can use it for our own purposes.
823 */
824int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size,
825 unsigned long *preallocated_size)
826{
827 struct pci_dev *bridge_dev;
828 u16 tmp = 0;
829 unsigned long overhead;
830
831 bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
832 if (!bridge_dev) {
833 DRM_ERROR("bridge device not found\n");
834 return -1;
835 }
836
837 /* Get the fb aperture size and "stolen" memory amount. */
838 pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
839 pci_dev_put(bridge_dev);
840
841 *aperture_size = 1024 * 1024;
842 *preallocated_size = 1024 * 1024;
843
844 switch (pdev->device) {
845 case PCI_DEVICE_ID_INTEL_82830_CGC:
846 case PCI_DEVICE_ID_INTEL_82845G_IG:
847 case PCI_DEVICE_ID_INTEL_82855GM_IG:
848 case PCI_DEVICE_ID_INTEL_82865_IG:
849 if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
850 *aperture_size *= 64;
851 else
852 *aperture_size *= 128;
853 break;
854 default:
855 /* 9xx supports large sizes, just look at the length */
856 *aperture_size = pci_resource_len(pdev, 2);
857 break;
858 }
859
860 /*
861 * Some of the preallocated space is taken by the GTT
862 * and popup. GTT is 1K per MB of aperture size, and popup is 4K.
863 */
864 overhead = (*aperture_size / 1024) + 4096;
865 switch (tmp & INTEL_855_GMCH_GMS_MASK) {
866 case INTEL_855_GMCH_GMS_STOLEN_1M:
867 break; /* 1M already */
868 case INTEL_855_GMCH_GMS_STOLEN_4M:
869 *preallocated_size *= 4;
870 break;
871 case INTEL_855_GMCH_GMS_STOLEN_8M:
872 *preallocated_size *= 8;
873 break;
874 case INTEL_855_GMCH_GMS_STOLEN_16M:
875 *preallocated_size *= 16;
876 break;
877 case INTEL_855_GMCH_GMS_STOLEN_32M:
878 *preallocated_size *= 32;
879 break;
880 case INTEL_915G_GMCH_GMS_STOLEN_48M:
881 *preallocated_size *= 48;
882 break;
883 case INTEL_915G_GMCH_GMS_STOLEN_64M:
884 *preallocated_size *= 64;
885 break;
886 case INTEL_855_GMCH_GMS_DISABLED:
887 DRM_ERROR("video memory is disabled\n");
888 return -1;
889 default:
890 DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
891 tmp & INTEL_855_GMCH_GMS_MASK);
892 return -1;
893 }
894 *preallocated_size -= overhead;
895
896 return 0;
897}
898
899static int i915_load_modeset_init(struct drm_device *dev)
900{
901 struct drm_i915_private *dev_priv = dev->dev_private;
902 unsigned long agp_size, prealloc_size;
903 int fb_bar = IS_I9XX(dev) ? 2 : 0;
904 int ret = 0;
905
906 dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
907 0xff000000;
908
909 DRM_DEBUG("*** fb base 0x%08lx\n", dev->mode_config.fb_base);
910
911 if (IS_MOBILE(dev) || (IS_I9XX(dev) && !IS_I965G(dev) && !IS_G33(dev)))
912 dev_priv->cursor_needs_physical = true;
913 else
914 dev_priv->cursor_needs_physical = false;
915
916 i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
917
918 /* Basic memrange allocator for stolen space (aka vram) */
919 drm_mm_init(&dev_priv->vram, 0, prealloc_size);
920
921 /* Let GEM Manage from end of prealloc space to end of aperture */
922 i915_gem_do_init(dev, prealloc_size, agp_size);
923
924 ret = i915_gem_init_ringbuffer(dev);
925 if (ret)
926 goto out;
927
928 dev_priv->mm.gtt_mapping =
929 io_mapping_create_wc(dev->agp->base,
930 dev->agp->agp_info.aper_size * 1024*1024);
931
932 /* Allow hardware batchbuffers unless told otherwise.
933 */
934 dev_priv->allow_batchbuffer = 1;
935
936 ret = intel_init_bios(dev);
937 if (ret)
938 DRM_INFO("failed to find VBIOS tables\n");
939
940 ret = drm_irq_install(dev);
941 if (ret)
942 goto destroy_ringbuffer;
943
944 /* FIXME: re-add hotplug support */
945#if 0
946 ret = drm_hotplug_init(dev);
947 if (ret)
948 goto destroy_ringbuffer;
949#endif
950
951 /* Always safe in the mode setting case. */
952 /* FIXME: do pre/post-mode set stuff in core KMS code */
953 dev->vblank_disable_allowed = 1;
954
955 /*
956 * Initialize the hardware status page IRQ location.
957 */
958
959 I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
960
961 intel_modeset_init(dev);
962
963 drm_helper_initial_config(dev, false);
964
965 dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL);
966 if (!dev->devname) {
967 ret = -ENOMEM;
968 goto modeset_cleanup;
969 }
970
971 return 0;
972
973modeset_cleanup:
974 intel_modeset_cleanup(dev);
975destroy_ringbuffer:
976 i915_gem_cleanup_ringbuffer(dev);
977out:
978 return ret;
979}
980
800int i915_master_create(struct drm_device *dev, struct drm_master *master) 981int i915_master_create(struct drm_device *dev, struct drm_master *master)
801{ 982{
802 struct drm_i915_master_private *master_priv; 983 struct drm_i915_master_private *master_priv;
@@ -821,6 +1002,25 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
821 master->driver_priv = NULL; 1002 master->driver_priv = NULL;
822} 1003}
823 1004
1005
1006int i915_driver_firstopen(struct drm_device *dev)
1007{
1008 if (drm_core_check_feature(dev, DRIVER_MODESET))
1009 return 0;
1010 return 0;
1011}
1012
1013/**
1014 * i915_driver_load - setup chip and create an initial config
1015 * @dev: DRM device
1016 * @flags: startup flags
1017 *
1018 * The driver load routine has to do several things:
1019 * - drive output discovery via intel_modeset_init()
1020 * - initialize the memory manager
1021 * - allocate initial config memory
1022 * - setup the DRM framebuffer with the allocated memory
1023 */
824int i915_driver_load(struct drm_device *dev, unsigned long flags) 1024int i915_driver_load(struct drm_device *dev, unsigned long flags)
825{ 1025{
826 struct drm_i915_private *dev_priv = dev->dev_private; 1026 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -848,6 +1048,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
848 size = drm_get_resource_len(dev, mmio_bar); 1048 size = drm_get_resource_len(dev, mmio_bar);
849 1049
850 dev_priv->regs = ioremap(base, size); 1050 dev_priv->regs = ioremap(base, size);
1051 if (!dev_priv->regs) {
1052 DRM_ERROR("failed to map registers\n");
1053 ret = -EIO;
1054 goto free_priv;
1055 }
851 1056
852#ifdef CONFIG_HIGHMEM64G 1057#ifdef CONFIG_HIGHMEM64G
853 /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */ 1058 /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
@@ -863,7 +1068,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
863 if (!I915_NEED_GFX_HWS(dev)) { 1068 if (!I915_NEED_GFX_HWS(dev)) {
864 ret = i915_init_phys_hws(dev); 1069 ret = i915_init_phys_hws(dev);
865 if (ret != 0) 1070 if (ret != 0)
866 return ret; 1071 goto out_rmmap;
867 } 1072 }
868 1073
869 /* On the 945G/GM, the chipset reports the MSI capability on the 1074 /* On the 945G/GM, the chipset reports the MSI capability on the
@@ -883,6 +1088,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
883 intel_opregion_init(dev); 1088 intel_opregion_init(dev);
884 1089
885 spin_lock_init(&dev_priv->user_irq_lock); 1090 spin_lock_init(&dev_priv->user_irq_lock);
1091 dev_priv->user_irq_refcount = 0;
886 1092
887 ret = drm_vblank_init(dev, I915_NUM_PIPE); 1093 ret = drm_vblank_init(dev, I915_NUM_PIPE);
888 1094
@@ -891,6 +1097,20 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
891 return ret; 1097 return ret;
892 } 1098 }
893 1099
1100 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1101 ret = i915_load_modeset_init(dev);
1102 if (ret < 0) {
1103 DRM_ERROR("failed to init modeset\n");
1104 goto out_rmmap;
1105 }
1106 }
1107
1108 return 0;
1109
1110out_rmmap:
1111 iounmap(dev_priv->regs);
1112free_priv:
1113 drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
894 return ret; 1114 return ret;
895} 1115}
896 1116
@@ -898,16 +1118,29 @@ int i915_driver_unload(struct drm_device *dev)
898{ 1118{
899 struct drm_i915_private *dev_priv = dev->dev_private; 1119 struct drm_i915_private *dev_priv = dev->dev_private;
900 1120
1121 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1122 io_mapping_free(dev_priv->mm.gtt_mapping);
1123 drm_irq_uninstall(dev);
1124 }
1125
901 if (dev->pdev->msi_enabled) 1126 if (dev->pdev->msi_enabled)
902 pci_disable_msi(dev->pdev); 1127 pci_disable_msi(dev->pdev);
903 1128
904 i915_free_hws(dev);
905
906 if (dev_priv->regs != NULL) 1129 if (dev_priv->regs != NULL)
907 iounmap(dev_priv->regs); 1130 iounmap(dev_priv->regs);
908 1131
909 intel_opregion_free(dev); 1132 intel_opregion_free(dev);
910 1133
1134 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1135 intel_modeset_cleanup(dev);
1136
1137 mutex_lock(&dev->struct_mutex);
1138 i915_gem_cleanup_ringbuffer(dev);
1139 mutex_unlock(&dev->struct_mutex);
1140 drm_mm_takedown(&dev_priv->vram);
1141 i915_gem_lastclose(dev);
1142 }
1143
911 drm_free(dev->dev_private, sizeof(drm_i915_private_t), 1144 drm_free(dev->dev_private, sizeof(drm_i915_private_t),
912 DRM_MEM_DRIVER); 1145 DRM_MEM_DRIVER);
913 1146
@@ -933,12 +1166,26 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
933 return 0; 1166 return 0;
934} 1167}
935 1168
1169/**
1170 * i915_driver_lastclose - clean up after all DRM clients have exited
1171 * @dev: DRM device
1172 *
1173 * Take care of cleaning up after all DRM clients have exited. In the
1174 * mode setting case, we want to restore the kernel's initial mode (just
1175 * in case the last client left us in a bad state).
1176 *
1177 * Additionally, in the non-mode setting case, we'll tear down the AGP
1178 * and DMA structures, since the kernel won't be using them, and clea
1179 * up any GEM state.
1180 */
936void i915_driver_lastclose(struct drm_device * dev) 1181void i915_driver_lastclose(struct drm_device * dev)
937{ 1182{
938 drm_i915_private_t *dev_priv = dev->dev_private; 1183 drm_i915_private_t *dev_priv = dev->dev_private;
939 1184
940 if (!dev_priv) 1185 if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
1186 intelfb_restore();
941 return; 1187 return;
1188 }
942 1189
943 i915_gem_lastclose(dev); 1190 i915_gem_lastclose(dev);
944 1191
@@ -951,7 +1198,8 @@ void i915_driver_lastclose(struct drm_device * dev)
951void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) 1198void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
952{ 1199{
953 drm_i915_private_t *dev_priv = dev->dev_private; 1200 drm_i915_private_t *dev_priv = dev->dev_private;
954 i915_mem_release(dev, file_priv, dev_priv->agp_heap); 1201 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1202 i915_mem_release(dev, file_priv, dev_priv->agp_heap);
955} 1203}
956 1204
957void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) 1205void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)