diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f112c769d533..50d1f782768c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -846,7 +846,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
846 | return 0; | 846 | return 0; |
847 | } | 847 | } |
848 | 848 | ||
849 | printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); | 849 | DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr); |
850 | 850 | ||
851 | dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); | 851 | dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); |
852 | 852 | ||
@@ -885,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
885 | * some RAM for the framebuffer at early boot. This code figures out | 885 | * some RAM for the framebuffer at early boot. This code figures out |
886 | * how much was set aside so we can use it for our own purposes. | 886 | * how much was set aside so we can use it for our own purposes. |
887 | */ | 887 | */ |
888 | static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | 888 | static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, |
889 | unsigned long *preallocated_size) | 889 | uint32_t *preallocated_size) |
890 | { | 890 | { |
891 | struct pci_dev *bridge_dev; | 891 | struct pci_dev *bridge_dev; |
892 | u16 tmp = 0; | 892 | u16 tmp = 0; |
@@ -984,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | |||
984 | return 0; | 984 | return 0; |
985 | } | 985 | } |
986 | 986 | ||
987 | static int i915_load_modeset_init(struct drm_device *dev) | 987 | static int i915_load_modeset_init(struct drm_device *dev, |
988 | unsigned long prealloc_size, | ||
989 | unsigned long agp_size) | ||
988 | { | 990 | { |
989 | struct drm_i915_private *dev_priv = dev->dev_private; | 991 | struct drm_i915_private *dev_priv = dev->dev_private; |
990 | unsigned long agp_size, prealloc_size; | ||
991 | int fb_bar = IS_I9XX(dev) ? 2 : 0; | 992 | int fb_bar = IS_I9XX(dev) ? 2 : 0; |
992 | int ret = 0; | 993 | int ret = 0; |
993 | 994 | ||
@@ -1002,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
1002 | if (IS_I965G(dev) || IS_G33(dev)) | 1003 | if (IS_I965G(dev) || IS_G33(dev)) |
1003 | dev_priv->cursor_needs_physical = false; | 1004 | dev_priv->cursor_needs_physical = false; |
1004 | 1005 | ||
1005 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size); | ||
1006 | if (ret) | ||
1007 | goto out; | ||
1008 | |||
1009 | /* Basic memrange allocator for stolen space (aka vram) */ | 1006 | /* Basic memrange allocator for stolen space (aka vram) */ |
1010 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); | 1007 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); |
1011 | 1008 | ||
@@ -1082,6 +1079,44 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) | |||
1082 | master->driver_priv = NULL; | 1079 | master->driver_priv = NULL; |
1083 | } | 1080 | } |
1084 | 1081 | ||
1082 | static void i915_get_mem_freq(struct drm_device *dev) | ||
1083 | { | ||
1084 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1085 | u32 tmp; | ||
1086 | |||
1087 | if (!IS_IGD(dev)) | ||
1088 | return; | ||
1089 | |||
1090 | tmp = I915_READ(CLKCFG); | ||
1091 | |||
1092 | switch (tmp & CLKCFG_FSB_MASK) { | ||
1093 | case CLKCFG_FSB_533: | ||
1094 | dev_priv->fsb_freq = 533; /* 133*4 */ | ||
1095 | break; | ||
1096 | case CLKCFG_FSB_800: | ||
1097 | dev_priv->fsb_freq = 800; /* 200*4 */ | ||
1098 | break; | ||
1099 | case CLKCFG_FSB_667: | ||
1100 | dev_priv->fsb_freq = 667; /* 167*4 */ | ||
1101 | break; | ||
1102 | case CLKCFG_FSB_400: | ||
1103 | dev_priv->fsb_freq = 400; /* 100*4 */ | ||
1104 | break; | ||
1105 | } | ||
1106 | |||
1107 | switch (tmp & CLKCFG_MEM_MASK) { | ||
1108 | case CLKCFG_MEM_533: | ||
1109 | dev_priv->mem_freq = 533; | ||
1110 | break; | ||
1111 | case CLKCFG_MEM_667: | ||
1112 | dev_priv->mem_freq = 667; | ||
1113 | break; | ||
1114 | case CLKCFG_MEM_800: | ||
1115 | dev_priv->mem_freq = 800; | ||
1116 | break; | ||
1117 | } | ||
1118 | } | ||
1119 | |||
1085 | /** | 1120 | /** |
1086 | * i915_driver_load - setup chip and create an initial config | 1121 | * i915_driver_load - setup chip and create an initial config |
1087 | * @dev: DRM device | 1122 | * @dev: DRM device |
@@ -1098,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1098 | struct drm_i915_private *dev_priv = dev->dev_private; | 1133 | struct drm_i915_private *dev_priv = dev->dev_private; |
1099 | resource_size_t base, size; | 1134 | resource_size_t base, size; |
1100 | int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; | 1135 | int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; |
1136 | uint32_t agp_size, prealloc_size; | ||
1101 | 1137 | ||
1102 | /* i915 has 4 more counters */ | 1138 | /* i915 has 4 more counters */ |
1103 | dev->counters += 4; | 1139 | dev->counters += 4; |
@@ -1146,9 +1182,29 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1146 | "performance may suffer.\n"); | 1182 | "performance may suffer.\n"); |
1147 | } | 1183 | } |
1148 | 1184 | ||
1185 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size); | ||
1186 | if (ret) | ||
1187 | goto out_iomapfree; | ||
1188 | |||
1189 | dev_priv->wq = create_workqueue("i915"); | ||
1190 | if (dev_priv->wq == NULL) { | ||
1191 | DRM_ERROR("Failed to create our workqueue.\n"); | ||
1192 | ret = -ENOMEM; | ||
1193 | goto out_iomapfree; | ||
1194 | } | ||
1195 | |||
1149 | /* enable GEM by default */ | 1196 | /* enable GEM by default */ |
1150 | dev_priv->has_gem = 1; | 1197 | dev_priv->has_gem = 1; |
1151 | 1198 | ||
1199 | if (prealloc_size > agp_size * 3 / 4) { | ||
1200 | DRM_ERROR("Detected broken video BIOS with %d/%dkB of video " | ||
1201 | "memory stolen.\n", | ||
1202 | prealloc_size / 1024, agp_size / 1024); | ||
1203 | DRM_ERROR("Disabling GEM. (try reducing stolen memory or " | ||
1204 | "updating the BIOS to fix).\n"); | ||
1205 | dev_priv->has_gem = 0; | ||
1206 | } | ||
1207 | |||
1152 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 1208 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
1153 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 1209 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
1154 | if (IS_G4X(dev) || IS_IGDNG(dev)) { | 1210 | if (IS_G4X(dev) || IS_IGDNG(dev)) { |
@@ -1162,9 +1218,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1162 | if (!I915_NEED_GFX_HWS(dev)) { | 1218 | if (!I915_NEED_GFX_HWS(dev)) { |
1163 | ret = i915_init_phys_hws(dev); | 1219 | ret = i915_init_phys_hws(dev); |
1164 | if (ret != 0) | 1220 | if (ret != 0) |
1165 | goto out_iomapfree; | 1221 | goto out_workqueue_free; |
1166 | } | 1222 | } |
1167 | 1223 | ||
1224 | i915_get_mem_freq(dev); | ||
1225 | |||
1168 | /* On the 945G/GM, the chipset reports the MSI capability on the | 1226 | /* On the 945G/GM, the chipset reports the MSI capability on the |
1169 | * integrated graphics even though the support isn't actually there | 1227 | * integrated graphics even though the support isn't actually there |
1170 | * according to the published specs. It doesn't appear to function | 1228 | * according to the published specs. It doesn't appear to function |
@@ -1180,6 +1238,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1180 | pci_enable_msi(dev->pdev); | 1238 | pci_enable_msi(dev->pdev); |
1181 | 1239 | ||
1182 | spin_lock_init(&dev_priv->user_irq_lock); | 1240 | spin_lock_init(&dev_priv->user_irq_lock); |
1241 | spin_lock_init(&dev_priv->error_lock); | ||
1183 | dev_priv->user_irq_refcount = 0; | 1242 | dev_priv->user_irq_refcount = 0; |
1184 | 1243 | ||
1185 | ret = drm_vblank_init(dev, I915_NUM_PIPE); | 1244 | ret = drm_vblank_init(dev, I915_NUM_PIPE); |
@@ -1190,10 +1249,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1190 | } | 1249 | } |
1191 | 1250 | ||
1192 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1251 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
1193 | ret = i915_load_modeset_init(dev); | 1252 | ret = i915_load_modeset_init(dev, prealloc_size, agp_size); |
1194 | if (ret < 0) { | 1253 | if (ret < 0) { |
1195 | DRM_ERROR("failed to init modeset\n"); | 1254 | DRM_ERROR("failed to init modeset\n"); |
1196 | goto out_rmmap; | 1255 | goto out_workqueue_free; |
1197 | } | 1256 | } |
1198 | } | 1257 | } |
1199 | 1258 | ||
@@ -1204,6 +1263,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1204 | 1263 | ||
1205 | return 0; | 1264 | return 0; |
1206 | 1265 | ||
1266 | out_workqueue_free: | ||
1267 | destroy_workqueue(dev_priv->wq); | ||
1207 | out_iomapfree: | 1268 | out_iomapfree: |
1208 | io_mapping_free(dev_priv->mm.gtt_mapping); | 1269 | io_mapping_free(dev_priv->mm.gtt_mapping); |
1209 | out_rmmap: | 1270 | out_rmmap: |
@@ -1217,6 +1278,8 @@ int i915_driver_unload(struct drm_device *dev) | |||
1217 | { | 1278 | { |
1218 | struct drm_i915_private *dev_priv = dev->dev_private; | 1279 | struct drm_i915_private *dev_priv = dev->dev_private; |
1219 | 1280 | ||
1281 | destroy_workqueue(dev_priv->wq); | ||
1282 | |||
1220 | io_mapping_free(dev_priv->mm.gtt_mapping); | 1283 | io_mapping_free(dev_priv->mm.gtt_mapping); |
1221 | if (dev_priv->mm.gtt_mtrr >= 0) { | 1284 | if (dev_priv->mm.gtt_mtrr >= 0) { |
1222 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, | 1285 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, |