diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 258 |
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 1b81b6a6d81b..b5d0809eecb1 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 | */ | ||
824 | int 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 | |||
899 | static 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 | |||
973 | modeset_cleanup: | ||
974 | intel_modeset_cleanup(dev); | ||
975 | destroy_ringbuffer: | ||
976 | i915_gem_cleanup_ringbuffer(dev); | ||
977 | out: | ||
978 | return ret; | ||
979 | } | ||
980 | |||
800 | int i915_master_create(struct drm_device *dev, struct drm_master *master) | 981 | int 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 | |||
1006 | int 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 | */ | ||
824 | int i915_driver_load(struct drm_device *dev, unsigned long flags) | 1024 | int 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 | |||
1110 | out_rmmap: | ||
1111 | iounmap(dev_priv->regs); | ||
1112 | free_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 | */ | ||
936 | void i915_driver_lastclose(struct drm_device * dev) | 1181 | void 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) | |||
951 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) | 1198 | void 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 | ||
957 | void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) | 1205 | void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) |