diff options
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 72 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 27 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 36 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_debugfs.c | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 143 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 60 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 221 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 30 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 448 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp_i2c.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 74 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 114 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo_regs.h | 1 |
19 files changed, 1159 insertions, 188 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a6f73f1e99d9..3da9cfa31848 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -1090,6 +1090,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) | |||
| 1090 | if (ret == false) | 1090 | if (ret == false) |
| 1091 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); | 1091 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); |
| 1092 | } | 1092 | } |
| 1093 | /* disable the unused connectors while restoring the modesetting */ | ||
| 1094 | drm_helper_disable_unused_functions(dev); | ||
| 1093 | return 0; | 1095 | return 0; |
| 1094 | } | 1096 | } |
| 1095 | EXPORT_SYMBOL(drm_helper_resume_force_mode); | 1097 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f112c769d533..8c4783180bf6 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,22 @@ 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 | |||
| 1149 | /* enable GEM by default */ | 1189 | /* enable GEM by default */ |
| 1150 | dev_priv->has_gem = 1; | 1190 | dev_priv->has_gem = 1; |
| 1151 | 1191 | ||
| 1192 | if (prealloc_size > agp_size * 3 / 4) { | ||
| 1193 | DRM_ERROR("Detected broken video BIOS with %d/%dkB of video " | ||
| 1194 | "memory stolen.\n", | ||
| 1195 | prealloc_size / 1024, agp_size / 1024); | ||
| 1196 | DRM_ERROR("Disabling GEM. (try reducing stolen memory or " | ||
| 1197 | "updating the BIOS to fix).\n"); | ||
| 1198 | dev_priv->has_gem = 0; | ||
| 1199 | } | ||
| 1200 | |||
| 1152 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 1201 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
| 1153 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 1202 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
| 1154 | if (IS_G4X(dev) || IS_IGDNG(dev)) { | 1203 | if (IS_G4X(dev) || IS_IGDNG(dev)) { |
| @@ -1165,6 +1214,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1165 | goto out_iomapfree; | 1214 | goto out_iomapfree; |
| 1166 | } | 1215 | } |
| 1167 | 1216 | ||
| 1217 | i915_get_mem_freq(dev); | ||
| 1218 | |||
| 1168 | /* On the 945G/GM, the chipset reports the MSI capability on the | 1219 | /* On the 945G/GM, the chipset reports the MSI capability on the |
| 1169 | * integrated graphics even though the support isn't actually there | 1220 | * integrated graphics even though the support isn't actually there |
| 1170 | * according to the published specs. It doesn't appear to function | 1221 | * according to the published specs. It doesn't appear to function |
| @@ -1180,6 +1231,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1180 | pci_enable_msi(dev->pdev); | 1231 | pci_enable_msi(dev->pdev); |
| 1181 | 1232 | ||
| 1182 | spin_lock_init(&dev_priv->user_irq_lock); | 1233 | spin_lock_init(&dev_priv->user_irq_lock); |
| 1234 | spin_lock_init(&dev_priv->error_lock); | ||
| 1183 | dev_priv->user_irq_refcount = 0; | 1235 | dev_priv->user_irq_refcount = 0; |
| 1184 | 1236 | ||
| 1185 | ret = drm_vblank_init(dev, I915_NUM_PIPE); | 1237 | ret = drm_vblank_init(dev, I915_NUM_PIPE); |
| @@ -1190,7 +1242,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1190 | } | 1242 | } |
| 1191 | 1243 | ||
| 1192 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1244 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1193 | ret = i915_load_modeset_init(dev); | 1245 | ret = i915_load_modeset_init(dev, prealloc_size, agp_size); |
| 1194 | if (ret < 0) { | 1246 | if (ret < 0) { |
| 1195 | DRM_ERROR("failed to init modeset\n"); | 1247 | DRM_ERROR("failed to init modeset\n"); |
| 1196 | goto out_rmmap; | 1248 | goto out_rmmap; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e3cb4025e323..fc4b68aa2d05 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #include "drm_pciids.h" | 36 | #include "drm_pciids.h" |
| 37 | #include <linux/console.h> | 37 | #include <linux/console.h> |
| 38 | #include "drm_crtc_helper.h" | ||
| 38 | 39 | ||
| 39 | static unsigned int i915_modeset = -1; | 40 | static unsigned int i915_modeset = -1; |
| 40 | module_param_named(modeset, i915_modeset, int, 0400); | 41 | module_param_named(modeset, i915_modeset, int, 0400); |
| @@ -57,8 +58,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 57 | struct drm_i915_private *dev_priv = dev->dev_private; | 58 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 58 | 59 | ||
| 59 | if (!dev || !dev_priv) { | 60 | if (!dev || !dev_priv) { |
| 60 | printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv); | 61 | DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv); |
| 61 | printk(KERN_ERR "DRM not initialized, aborting suspend.\n"); | 62 | DRM_ERROR("DRM not initialized, aborting suspend.\n"); |
| 62 | return -ENODEV; | 63 | return -ENODEV; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| @@ -115,6 +116,10 @@ static int i915_resume(struct drm_device *dev) | |||
| 115 | 116 | ||
| 116 | drm_irq_install(dev); | 117 | drm_irq_install(dev); |
| 117 | } | 118 | } |
| 119 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 120 | /* Resume the modeset for every activated CRTC */ | ||
| 121 | drm_helper_resume_force_mode(dev); | ||
| 122 | } | ||
| 118 | 123 | ||
| 119 | return ret; | 124 | return ret; |
| 120 | } | 125 | } |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bb4c2d387b6c..d08752875885 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -133,6 +133,22 @@ struct sdvo_device_mapping { | |||
| 133 | u8 initialized; | 133 | u8 initialized; |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | struct drm_i915_error_state { | ||
| 137 | u32 eir; | ||
| 138 | u32 pgtbl_er; | ||
| 139 | u32 pipeastat; | ||
| 140 | u32 pipebstat; | ||
| 141 | u32 ipeir; | ||
| 142 | u32 ipehr; | ||
| 143 | u32 instdone; | ||
| 144 | u32 acthd; | ||
| 145 | u32 instpm; | ||
| 146 | u32 instps; | ||
| 147 | u32 instdone1; | ||
| 148 | u32 seqno; | ||
| 149 | struct timeval time; | ||
| 150 | }; | ||
| 151 | |||
| 136 | typedef struct drm_i915_private { | 152 | typedef struct drm_i915_private { |
| 137 | struct drm_device *dev; | 153 | struct drm_device *dev; |
| 138 | 154 | ||
| @@ -209,6 +225,11 @@ typedef struct drm_i915_private { | |||
| 209 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ | 225 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ |
| 210 | int num_fence_regs; /* 8 on pre-965, 16 otherwise */ | 226 | int num_fence_regs; /* 8 on pre-965, 16 otherwise */ |
| 211 | 227 | ||
| 228 | unsigned int fsb_freq, mem_freq; | ||
| 229 | |||
| 230 | spinlock_t error_lock; | ||
| 231 | struct drm_i915_error_state *first_error; | ||
| 232 | |||
| 212 | /* Register state */ | 233 | /* Register state */ |
| 213 | u8 saveLBB; | 234 | u8 saveLBB; |
| 214 | u32 saveDSPACNTR; | 235 | u32 saveDSPACNTR; |
| @@ -468,9 +489,6 @@ struct drm_i915_gem_object { | |||
| 468 | */ | 489 | */ |
| 469 | int fence_reg; | 490 | int fence_reg; |
| 470 | 491 | ||
| 471 | /** Boolean whether this object has a valid gtt offset. */ | ||
| 472 | int gtt_bound; | ||
| 473 | |||
| 474 | /** How many users have pinned this object in GTT space */ | 492 | /** How many users have pinned this object in GTT space */ |
| 475 | int pin_count; | 493 | int pin_count; |
| 476 | 494 | ||
| @@ -655,6 +673,7 @@ void i915_gem_free_object(struct drm_gem_object *obj); | |||
| 655 | int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); | 673 | int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); |
| 656 | void i915_gem_object_unpin(struct drm_gem_object *obj); | 674 | void i915_gem_object_unpin(struct drm_gem_object *obj); |
| 657 | int i915_gem_object_unbind(struct drm_gem_object *obj); | 675 | int i915_gem_object_unbind(struct drm_gem_object *obj); |
| 676 | void i915_gem_release_mmap(struct drm_gem_object *obj); | ||
| 658 | void i915_gem_lastclose(struct drm_device *dev); | 677 | void i915_gem_lastclose(struct drm_device *dev); |
| 659 | uint32_t i915_get_gem_seqno(struct drm_device *dev); | 678 | uint32_t i915_get_gem_seqno(struct drm_device *dev); |
| 660 | int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); | 679 | int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); |
| @@ -870,6 +889,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
| 870 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | 889 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) |
| 871 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | 890 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) |
| 872 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) | 891 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) |
| 892 | /* dsparb controlled by hw only */ | ||
| 893 | #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | ||
| 873 | 894 | ||
| 874 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 895 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
| 875 | 896 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 876b65cb7629..5bf420378b6d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1252,6 +1252,31 @@ out_free_list: | |||
| 1252 | return ret; | 1252 | return ret; |
| 1253 | } | 1253 | } |
| 1254 | 1254 | ||
| 1255 | /** | ||
| 1256 | * i915_gem_release_mmap - remove physical page mappings | ||
| 1257 | * @obj: obj in question | ||
| 1258 | * | ||
| 1259 | * Preserve the reservation of the mmaping with the DRM core code, but | ||
| 1260 | * relinquish ownership of the pages back to the system. | ||
| 1261 | * | ||
| 1262 | * It is vital that we remove the page mapping if we have mapped a tiled | ||
| 1263 | * object through the GTT and then lose the fence register due to | ||
| 1264 | * resource pressure. Similarly if the object has been moved out of the | ||
| 1265 | * aperture, than pages mapped into userspace must be revoked. Removing the | ||
| 1266 | * mapping will then trigger a page fault on the next user access, allowing | ||
| 1267 | * fixup by i915_gem_fault(). | ||
| 1268 | */ | ||
| 1269 | void | ||
| 1270 | i915_gem_release_mmap(struct drm_gem_object *obj) | ||
| 1271 | { | ||
| 1272 | struct drm_device *dev = obj->dev; | ||
| 1273 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
| 1274 | |||
| 1275 | if (dev->dev_mapping) | ||
| 1276 | unmap_mapping_range(dev->dev_mapping, | ||
| 1277 | obj_priv->mmap_offset, obj->size, 1); | ||
| 1278 | } | ||
| 1279 | |||
| 1255 | static void | 1280 | static void |
| 1256 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) | 1281 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) |
| 1257 | { | 1282 | { |
| @@ -1861,7 +1886,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
| 1861 | { | 1886 | { |
| 1862 | struct drm_device *dev = obj->dev; | 1887 | struct drm_device *dev = obj->dev; |
| 1863 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1888 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1864 | loff_t offset; | ||
| 1865 | int ret = 0; | 1889 | int ret = 0; |
| 1866 | 1890 | ||
| 1867 | #if WATCH_BUF | 1891 | #if WATCH_BUF |
| @@ -1898,9 +1922,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
| 1898 | BUG_ON(obj_priv->active); | 1922 | BUG_ON(obj_priv->active); |
| 1899 | 1923 | ||
| 1900 | /* blow away mappings if mapped through GTT */ | 1924 | /* blow away mappings if mapped through GTT */ |
| 1901 | offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT; | 1925 | i915_gem_release_mmap(obj); |
| 1902 | if (dev->dev_mapping) | ||
| 1903 | unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1); | ||
| 1904 | 1926 | ||
| 1905 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 1927 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
| 1906 | i915_gem_clear_fence_reg(obj); | 1928 | i915_gem_clear_fence_reg(obj); |
| @@ -2222,7 +2244,6 @@ try_again: | |||
| 2222 | /* None available, try to steal one or wait for a user to finish */ | 2244 | /* None available, try to steal one or wait for a user to finish */ |
| 2223 | if (i == dev_priv->num_fence_regs) { | 2245 | if (i == dev_priv->num_fence_regs) { |
| 2224 | uint32_t seqno = dev_priv->mm.next_gem_seqno; | 2246 | uint32_t seqno = dev_priv->mm.next_gem_seqno; |
| 2225 | loff_t offset; | ||
| 2226 | 2247 | ||
| 2227 | if (avail == 0) | 2248 | if (avail == 0) |
| 2228 | return -ENOSPC; | 2249 | return -ENOSPC; |
| @@ -2274,10 +2295,7 @@ try_again: | |||
| 2274 | * Zap this virtual mapping so we can set up a fence again | 2295 | * Zap this virtual mapping so we can set up a fence again |
| 2275 | * for this object next time we need it. | 2296 | * for this object next time we need it. |
| 2276 | */ | 2297 | */ |
| 2277 | offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT; | 2298 | i915_gem_release_mmap(reg->obj); |
| 2278 | if (dev->dev_mapping) | ||
| 2279 | unmap_mapping_range(dev->dev_mapping, offset, | ||
| 2280 | reg->obj->size, 1); | ||
| 2281 | old_obj_priv->fence_reg = I915_FENCE_REG_NONE; | 2299 | old_obj_priv->fence_reg = I915_FENCE_REG_NONE; |
| 2282 | } | 2300 | } |
| 2283 | 2301 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index 28146e405e87..9a44bfcb8139 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c | |||
| @@ -75,11 +75,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
| 75 | case ACTIVE_LIST: | 75 | case ACTIVE_LIST: |
| 76 | seq_printf(m, "Active:\n"); | 76 | seq_printf(m, "Active:\n"); |
| 77 | lock = &dev_priv->mm.active_list_lock; | 77 | lock = &dev_priv->mm.active_list_lock; |
| 78 | spin_lock(lock); | ||
| 79 | head = &dev_priv->mm.active_list; | 78 | head = &dev_priv->mm.active_list; |
| 80 | break; | 79 | break; |
| 81 | case INACTIVE_LIST: | 80 | case INACTIVE_LIST: |
| 82 | seq_printf(m, "Inctive:\n"); | 81 | seq_printf(m, "Inactive:\n"); |
| 83 | head = &dev_priv->mm.inactive_list; | 82 | head = &dev_priv->mm.inactive_list; |
| 84 | break; | 83 | break; |
| 85 | case FLUSHING_LIST: | 84 | case FLUSHING_LIST: |
| @@ -91,6 +90,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
| 91 | return 0; | 90 | return 0; |
| 92 | } | 91 | } |
| 93 | 92 | ||
| 93 | if (lock) | ||
| 94 | spin_lock(lock); | ||
| 94 | list_for_each_entry(obj_priv, head, list) | 95 | list_for_each_entry(obj_priv, head, list) |
| 95 | { | 96 | { |
| 96 | struct drm_gem_object *obj = obj_priv->obj; | 97 | struct drm_gem_object *obj = obj_priv->obj; |
| @@ -104,7 +105,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
| 104 | if (obj->name) | 105 | if (obj->name) |
| 105 | seq_printf(m, " (name: %d)", obj->name); | 106 | seq_printf(m, " (name: %d)", obj->name); |
| 106 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 107 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
| 107 | seq_printf(m, " (fence: %d)\n", obj_priv->fence_reg); | 108 | seq_printf(m, " (fence: %d)", obj_priv->fence_reg); |
| 109 | if (obj_priv->gtt_space != NULL) | ||
| 110 | seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset); | ||
| 111 | |||
| 108 | seq_printf(m, "\n"); | 112 | seq_printf(m, "\n"); |
| 109 | } | 113 | } |
| 110 | 114 | ||
| @@ -323,6 +327,39 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) | |||
| 323 | return 0; | 327 | return 0; |
| 324 | } | 328 | } |
| 325 | 329 | ||
| 330 | static int i915_error_state(struct seq_file *m, void *unused) | ||
| 331 | { | ||
| 332 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 333 | struct drm_device *dev = node->minor->dev; | ||
| 334 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 335 | struct drm_i915_error_state *error; | ||
| 336 | unsigned long flags; | ||
| 337 | |||
| 338 | spin_lock_irqsave(&dev_priv->error_lock, flags); | ||
| 339 | if (!dev_priv->first_error) { | ||
| 340 | seq_printf(m, "no error state collected\n"); | ||
| 341 | goto out; | ||
| 342 | } | ||
| 343 | |||
| 344 | error = dev_priv->first_error; | ||
| 345 | |||
| 346 | seq_printf(m, "EIR: 0x%08x\n", error->eir); | ||
| 347 | seq_printf(m, " PGTBL_ER: 0x%08x\n", error->pgtbl_er); | ||
| 348 | seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); | ||
| 349 | seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir); | ||
| 350 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); | ||
| 351 | seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); | ||
| 352 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); | ||
| 353 | if (IS_I965G(dev)) { | ||
| 354 | seq_printf(m, " INSTPS: 0x%08x\n", error->instps); | ||
| 355 | seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); | ||
| 356 | } | ||
| 357 | |||
| 358 | out: | ||
| 359 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | ||
| 360 | |||
| 361 | return 0; | ||
| 362 | } | ||
| 326 | 363 | ||
| 327 | static struct drm_info_list i915_gem_debugfs_list[] = { | 364 | static struct drm_info_list i915_gem_debugfs_list[] = { |
| 328 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, | 365 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, |
| @@ -336,6 +373,7 @@ static struct drm_info_list i915_gem_debugfs_list[] = { | |||
| 336 | {"i915_ringbuffer_data", i915_ringbuffer_data, 0}, | 373 | {"i915_ringbuffer_data", i915_ringbuffer_data, 0}, |
| 337 | {"i915_ringbuffer_info", i915_ringbuffer_info, 0}, | 374 | {"i915_ringbuffer_info", i915_ringbuffer_info, 0}, |
| 338 | {"i915_batchbuffers", i915_batchbuffer_info, 0}, | 375 | {"i915_batchbuffers", i915_batchbuffer_info, 0}, |
| 376 | {"i915_error_state", i915_error_state, 0}, | ||
| 339 | }; | 377 | }; |
| 340 | #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) | 378 | #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) |
| 341 | 379 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index daeae62e1c28..a2d527b22ec4 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -521,6 +521,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
| 521 | goto err; | 521 | goto err; |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | /* If we've changed tiling, GTT-mappings of the object | ||
| 525 | * need to re-fault to ensure that the correct fence register | ||
| 526 | * setup is in place. | ||
| 527 | */ | ||
| 528 | i915_gem_release_mmap(obj); | ||
| 529 | |||
| 524 | obj_priv->tiling_mode = args->tiling_mode; | 530 | obj_priv->tiling_mode = args->tiling_mode; |
| 525 | obj_priv->stride = args->stride; | 531 | obj_priv->stride = args->stride; |
| 526 | } | 532 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 228546f6eaa4..7ba23a69a0c0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | * | 26 | * |
| 27 | */ | 27 | */ |
| 28 | 28 | ||
| 29 | #include <linux/sysrq.h> | ||
| 29 | #include "drmP.h" | 30 | #include "drmP.h" |
| 30 | #include "drm.h" | 31 | #include "drm.h" |
| 31 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
| @@ -41,9 +42,10 @@ | |||
| 41 | * we leave them always unmasked in IMR and then control enabling them through | 42 | * we leave them always unmasked in IMR and then control enabling them through |
| 42 | * PIPESTAT alone. | 43 | * PIPESTAT alone. |
| 43 | */ | 44 | */ |
| 44 | #define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ | 45 | #define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ |
| 45 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ | 46 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ |
| 46 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) | 47 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ |
| 48 | I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) | ||
| 47 | 49 | ||
| 48 | /** Interrupts that we mask and unmask at runtime. */ | 50 | /** Interrupts that we mask and unmask at runtime. */ |
| 49 | #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) | 51 | #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) |
| @@ -288,6 +290,47 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) | |||
| 288 | return ret; | 290 | return ret; |
| 289 | } | 291 | } |
| 290 | 292 | ||
| 293 | static void i915_capture_error_state(struct drm_device *dev) | ||
| 294 | { | ||
| 295 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 296 | struct drm_i915_error_state *error; | ||
| 297 | unsigned long flags; | ||
| 298 | |||
| 299 | spin_lock_irqsave(&dev_priv->error_lock, flags); | ||
| 300 | if (dev_priv->first_error) | ||
| 301 | goto out; | ||
| 302 | |||
| 303 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | ||
| 304 | if (!error) { | ||
| 305 | DRM_DEBUG("out ot memory, not capturing error state\n"); | ||
| 306 | goto out; | ||
| 307 | } | ||
| 308 | |||
| 309 | error->eir = I915_READ(EIR); | ||
| 310 | error->pgtbl_er = I915_READ(PGTBL_ER); | ||
| 311 | error->pipeastat = I915_READ(PIPEASTAT); | ||
| 312 | error->pipebstat = I915_READ(PIPEBSTAT); | ||
| 313 | error->instpm = I915_READ(INSTPM); | ||
| 314 | if (!IS_I965G(dev)) { | ||
| 315 | error->ipeir = I915_READ(IPEIR); | ||
| 316 | error->ipehr = I915_READ(IPEHR); | ||
| 317 | error->instdone = I915_READ(INSTDONE); | ||
| 318 | error->acthd = I915_READ(ACTHD); | ||
| 319 | } else { | ||
| 320 | error->ipeir = I915_READ(IPEIR_I965); | ||
| 321 | error->ipehr = I915_READ(IPEHR_I965); | ||
| 322 | error->instdone = I915_READ(INSTDONE_I965); | ||
| 323 | error->instps = I915_READ(INSTPS); | ||
| 324 | error->instdone1 = I915_READ(INSTDONE1); | ||
| 325 | error->acthd = I915_READ(ACTHD_I965); | ||
| 326 | } | ||
| 327 | |||
| 328 | dev_priv->first_error = error; | ||
| 329 | |||
| 330 | out: | ||
| 331 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | ||
| 332 | } | ||
| 333 | |||
| 291 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 334 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
| 292 | { | 335 | { |
| 293 | struct drm_device *dev = (struct drm_device *) arg; | 336 | struct drm_device *dev = (struct drm_device *) arg; |
| @@ -333,11 +376,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 333 | * Clear the PIPE(A|B)STAT regs before the IIR | 376 | * Clear the PIPE(A|B)STAT regs before the IIR |
| 334 | */ | 377 | */ |
| 335 | if (pipea_stats & 0x8000ffff) { | 378 | if (pipea_stats & 0x8000ffff) { |
| 379 | if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) | ||
| 380 | DRM_DEBUG("pipe a underrun\n"); | ||
| 336 | I915_WRITE(PIPEASTAT, pipea_stats); | 381 | I915_WRITE(PIPEASTAT, pipea_stats); |
| 337 | irq_received = 1; | 382 | irq_received = 1; |
| 338 | } | 383 | } |
| 339 | 384 | ||
| 340 | if (pipeb_stats & 0x8000ffff) { | 385 | if (pipeb_stats & 0x8000ffff) { |
| 386 | if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) | ||
| 387 | DRM_DEBUG("pipe b underrun\n"); | ||
| 341 | I915_WRITE(PIPEBSTAT, pipeb_stats); | 388 | I915_WRITE(PIPEBSTAT, pipeb_stats); |
| 342 | irq_received = 1; | 389 | irq_received = 1; |
| 343 | } | 390 | } |
| @@ -362,6 +409,80 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 362 | I915_READ(PORT_HOTPLUG_STAT); | 409 | I915_READ(PORT_HOTPLUG_STAT); |
| 363 | } | 410 | } |
| 364 | 411 | ||
| 412 | if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) { | ||
| 413 | u32 eir = I915_READ(EIR); | ||
| 414 | |||
| 415 | i915_capture_error_state(dev); | ||
| 416 | |||
| 417 | printk(KERN_ERR "render error detected, EIR: 0x%08x\n", | ||
| 418 | eir); | ||
| 419 | if (eir & I915_ERROR_PAGE_TABLE) { | ||
| 420 | u32 pgtbl_err = I915_READ(PGTBL_ER); | ||
| 421 | printk(KERN_ERR "page table error\n"); | ||
| 422 | printk(KERN_ERR " PGTBL_ER: 0x%08x\n", | ||
| 423 | pgtbl_err); | ||
| 424 | I915_WRITE(PGTBL_ER, pgtbl_err); | ||
| 425 | (void)I915_READ(PGTBL_ER); | ||
| 426 | } | ||
| 427 | if (eir & I915_ERROR_MEMORY_REFRESH) { | ||
| 428 | printk(KERN_ERR "memory refresh error\n"); | ||
| 429 | printk(KERN_ERR "PIPEASTAT: 0x%08x\n", | ||
| 430 | pipea_stats); | ||
| 431 | printk(KERN_ERR "PIPEBSTAT: 0x%08x\n", | ||
| 432 | pipeb_stats); | ||
| 433 | /* pipestat has already been acked */ | ||
| 434 | } | ||
| 435 | if (eir & I915_ERROR_INSTRUCTION) { | ||
| 436 | printk(KERN_ERR "instruction error\n"); | ||
| 437 | printk(KERN_ERR " INSTPM: 0x%08x\n", | ||
| 438 | I915_READ(INSTPM)); | ||
| 439 | if (!IS_I965G(dev)) { | ||
| 440 | u32 ipeir = I915_READ(IPEIR); | ||
| 441 | |||
| 442 | printk(KERN_ERR " IPEIR: 0x%08x\n", | ||
| 443 | I915_READ(IPEIR)); | ||
| 444 | printk(KERN_ERR " IPEHR: 0x%08x\n", | ||
| 445 | I915_READ(IPEHR)); | ||
| 446 | printk(KERN_ERR " INSTDONE: 0x%08x\n", | ||
| 447 | I915_READ(INSTDONE)); | ||
| 448 | printk(KERN_ERR " ACTHD: 0x%08x\n", | ||
| 449 | I915_READ(ACTHD)); | ||
| 450 | I915_WRITE(IPEIR, ipeir); | ||
| 451 | (void)I915_READ(IPEIR); | ||
| 452 | } else { | ||
| 453 | u32 ipeir = I915_READ(IPEIR_I965); | ||
| 454 | |||
| 455 | printk(KERN_ERR " IPEIR: 0x%08x\n", | ||
| 456 | I915_READ(IPEIR_I965)); | ||
| 457 | printk(KERN_ERR " IPEHR: 0x%08x\n", | ||
| 458 | I915_READ(IPEHR_I965)); | ||
| 459 | printk(KERN_ERR " INSTDONE: 0x%08x\n", | ||
| 460 | I915_READ(INSTDONE_I965)); | ||
| 461 | printk(KERN_ERR " INSTPS: 0x%08x\n", | ||
| 462 | I915_READ(INSTPS)); | ||
| 463 | printk(KERN_ERR " INSTDONE1: 0x%08x\n", | ||
| 464 | I915_READ(INSTDONE1)); | ||
| 465 | printk(KERN_ERR " ACTHD: 0x%08x\n", | ||
| 466 | I915_READ(ACTHD_I965)); | ||
| 467 | I915_WRITE(IPEIR_I965, ipeir); | ||
| 468 | (void)I915_READ(IPEIR_I965); | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | I915_WRITE(EIR, eir); | ||
| 473 | (void)I915_READ(EIR); | ||
| 474 | eir = I915_READ(EIR); | ||
| 475 | if (eir) { | ||
| 476 | /* | ||
| 477 | * some errors might have become stuck, | ||
| 478 | * mask them. | ||
| 479 | */ | ||
| 480 | DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir); | ||
| 481 | I915_WRITE(EMR, I915_READ(EMR) | eir); | ||
| 482 | I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 365 | I915_WRITE(IIR, iir); | 486 | I915_WRITE(IIR, iir); |
| 366 | new_iir = I915_READ(IIR); /* Flush posted writes */ | 487 | new_iir = I915_READ(IIR); /* Flush posted writes */ |
| 367 | 488 | ||
| @@ -732,6 +853,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
| 732 | { | 853 | { |
| 733 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 854 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 734 | u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; | 855 | u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; |
| 856 | u32 error_mask; | ||
| 735 | 857 | ||
| 736 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); | 858 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); |
| 737 | 859 | ||
| @@ -768,6 +890,21 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
| 768 | i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); | 890 | i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); |
| 769 | } | 891 | } |
| 770 | 892 | ||
| 893 | /* | ||
| 894 | * Enable some error detection, note the instruction error mask | ||
| 895 | * bit is reserved, so we leave it masked. | ||
| 896 | */ | ||
| 897 | if (IS_G4X(dev)) { | ||
| 898 | error_mask = ~(GM45_ERROR_PAGE_TABLE | | ||
| 899 | GM45_ERROR_MEM_PRIV | | ||
| 900 | GM45_ERROR_CP_PRIV | | ||
| 901 | I915_ERROR_MEMORY_REFRESH); | ||
| 902 | } else { | ||
| 903 | error_mask = ~(I915_ERROR_PAGE_TABLE | | ||
| 904 | I915_ERROR_MEMORY_REFRESH); | ||
| 905 | } | ||
| 906 | I915_WRITE(EMR, error_mask); | ||
| 907 | |||
| 771 | /* Disable pipe interrupt enables, clear pending pipe status */ | 908 | /* Disable pipe interrupt enables, clear pending pipe status */ |
| 772 | I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); | 909 | I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); |
| 773 | I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); | 910 | I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 88bf7521405f..6c0858484094 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -206,6 +206,7 @@ | |||
| 206 | /* | 206 | /* |
| 207 | * Instruction and interrupt control regs | 207 | * Instruction and interrupt control regs |
| 208 | */ | 208 | */ |
| 209 | #define PGTBL_ER 0x02024 | ||
| 209 | #define PRB0_TAIL 0x02030 | 210 | #define PRB0_TAIL 0x02030 |
| 210 | #define PRB0_HEAD 0x02034 | 211 | #define PRB0_HEAD 0x02034 |
| 211 | #define PRB0_START 0x02038 | 212 | #define PRB0_START 0x02038 |
| @@ -226,11 +227,18 @@ | |||
| 226 | #define PRB1_HEAD 0x02044 /* 915+ only */ | 227 | #define PRB1_HEAD 0x02044 /* 915+ only */ |
| 227 | #define PRB1_START 0x02048 /* 915+ only */ | 228 | #define PRB1_START 0x02048 /* 915+ only */ |
| 228 | #define PRB1_CTL 0x0204c /* 915+ only */ | 229 | #define PRB1_CTL 0x0204c /* 915+ only */ |
| 230 | #define IPEIR_I965 0x02064 | ||
| 231 | #define IPEHR_I965 0x02068 | ||
| 232 | #define INSTDONE_I965 0x0206c | ||
| 233 | #define INSTPS 0x02070 /* 965+ only */ | ||
| 234 | #define INSTDONE1 0x0207c /* 965+ only */ | ||
| 229 | #define ACTHD_I965 0x02074 | 235 | #define ACTHD_I965 0x02074 |
| 230 | #define HWS_PGA 0x02080 | 236 | #define HWS_PGA 0x02080 |
| 231 | #define HWS_ADDRESS_MASK 0xfffff000 | 237 | #define HWS_ADDRESS_MASK 0xfffff000 |
| 232 | #define HWS_START_ADDRESS_SHIFT 4 | 238 | #define HWS_START_ADDRESS_SHIFT 4 |
| 233 | #define IPEIR 0x02088 | 239 | #define IPEIR 0x02088 |
| 240 | #define IPEHR 0x0208c | ||
| 241 | #define INSTDONE 0x02090 | ||
| 234 | #define NOPID 0x02094 | 242 | #define NOPID 0x02094 |
| 235 | #define HWSTAM 0x02098 | 243 | #define HWSTAM 0x02098 |
| 236 | #define SCPD0 0x0209c /* 915+ only */ | 244 | #define SCPD0 0x0209c /* 915+ only */ |
| @@ -258,10 +266,22 @@ | |||
| 258 | #define EIR 0x020b0 | 266 | #define EIR 0x020b0 |
| 259 | #define EMR 0x020b4 | 267 | #define EMR 0x020b4 |
| 260 | #define ESR 0x020b8 | 268 | #define ESR 0x020b8 |
| 269 | #define GM45_ERROR_PAGE_TABLE (1<<5) | ||
| 270 | #define GM45_ERROR_MEM_PRIV (1<<4) | ||
| 271 | #define I915_ERROR_PAGE_TABLE (1<<4) | ||
| 272 | #define GM45_ERROR_CP_PRIV (1<<3) | ||
| 273 | #define I915_ERROR_MEMORY_REFRESH (1<<1) | ||
| 274 | #define I915_ERROR_INSTRUCTION (1<<0) | ||
| 261 | #define INSTPM 0x020c0 | 275 | #define INSTPM 0x020c0 |
| 262 | #define ACTHD 0x020c8 | 276 | #define ACTHD 0x020c8 |
| 263 | #define FW_BLC 0x020d8 | 277 | #define FW_BLC 0x020d8 |
| 278 | #define FW_BLC2 0x020dc | ||
| 264 | #define FW_BLC_SELF 0x020e0 /* 915+ only */ | 279 | #define FW_BLC_SELF 0x020e0 /* 915+ only */ |
| 280 | #define FW_BLC_SELF_EN (1<<15) | ||
| 281 | #define MM_BURST_LENGTH 0x00700000 | ||
| 282 | #define MM_FIFO_WATERMARK 0x0001F000 | ||
| 283 | #define LM_BURST_LENGTH 0x00000700 | ||
| 284 | #define LM_FIFO_WATERMARK 0x0000001F | ||
| 265 | #define MI_ARB_STATE 0x020e4 /* 915+ only */ | 285 | #define MI_ARB_STATE 0x020e4 /* 915+ only */ |
| 266 | #define CACHE_MODE_0 0x02120 /* 915+ only */ | 286 | #define CACHE_MODE_0 0x02120 /* 915+ only */ |
| 267 | #define CM0_MASK_SHIFT 16 | 287 | #define CM0_MASK_SHIFT 16 |
| @@ -571,17 +591,21 @@ | |||
| 571 | 591 | ||
| 572 | /* Clocking configuration register */ | 592 | /* Clocking configuration register */ |
| 573 | #define CLKCFG 0x10c00 | 593 | #define CLKCFG 0x10c00 |
| 574 | #define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */ | 594 | #define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ |
| 575 | #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ | 595 | #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ |
| 576 | #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ | 596 | #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ |
| 577 | #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ | 597 | #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ |
| 578 | #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ | 598 | #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ |
| 579 | #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ | 599 | #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ |
| 580 | /* this is a guess, could be 5 as well */ | 600 | /* Note, below two are guess */ |
| 581 | #define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ | 601 | #define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ |
| 582 | #define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */ | 602 | #define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */ |
| 583 | #define CLKCFG_FSB_MASK (7 << 0) | 603 | #define CLKCFG_FSB_MASK (7 << 0) |
| 584 | 604 | #define CLKCFG_MEM_533 (1 << 4) | |
| 605 | #define CLKCFG_MEM_667 (2 << 4) | ||
| 606 | #define CLKCFG_MEM_800 (3 << 4) | ||
| 607 | #define CLKCFG_MEM_MASK (7 << 4) | ||
| 608 | |||
| 585 | /** GM965 GM45 render standby register */ | 609 | /** GM965 GM45 render standby register */ |
| 586 | #define MCHBAR_RENDER_STANDBY 0x111B8 | 610 | #define MCHBAR_RENDER_STANDBY 0x111B8 |
| 587 | 611 | ||
| @@ -1581,6 +1605,34 @@ | |||
| 1581 | #define DSPARB_CSTART_SHIFT 7 | 1605 | #define DSPARB_CSTART_SHIFT 7 |
| 1582 | #define DSPARB_BSTART_MASK (0x7f) | 1606 | #define DSPARB_BSTART_MASK (0x7f) |
| 1583 | #define DSPARB_BSTART_SHIFT 0 | 1607 | #define DSPARB_BSTART_SHIFT 0 |
| 1608 | #define DSPARB_BEND_SHIFT 9 /* on 855 */ | ||
| 1609 | #define DSPARB_AEND_SHIFT 0 | ||
| 1610 | |||
| 1611 | #define DSPFW1 0x70034 | ||
| 1612 | #define DSPFW2 0x70038 | ||
| 1613 | #define DSPFW3 0x7003c | ||
| 1614 | #define IGD_SELF_REFRESH_EN (1<<30) | ||
| 1615 | |||
| 1616 | /* FIFO watermark sizes etc */ | ||
| 1617 | #define I915_FIFO_LINE_SIZE 64 | ||
| 1618 | #define I830_FIFO_LINE_SIZE 32 | ||
| 1619 | #define I945_FIFO_SIZE 127 /* 945 & 965 */ | ||
| 1620 | #define I915_FIFO_SIZE 95 | ||
| 1621 | #define I855GM_FIFO_SIZE 255 | ||
| 1622 | #define I830_FIFO_SIZE 95 | ||
| 1623 | #define I915_MAX_WM 0x3f | ||
| 1624 | |||
| 1625 | #define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ | ||
| 1626 | #define IGD_FIFO_LINE_SIZE 64 | ||
| 1627 | #define IGD_MAX_WM 0x1ff | ||
| 1628 | #define IGD_DFT_WM 0x3f | ||
| 1629 | #define IGD_DFT_HPLLOFF_WM 0 | ||
| 1630 | #define IGD_GUARD_WM 10 | ||
| 1631 | #define IGD_CURSOR_FIFO 64 | ||
| 1632 | #define IGD_CURSOR_MAX_WM 0x3f | ||
| 1633 | #define IGD_CURSOR_DFT_WM 0 | ||
| 1634 | #define IGD_CURSOR_GUARD_WM 5 | ||
| 1635 | |||
| 1584 | /* | 1636 | /* |
| 1585 | * The two pipe frame counter registers are not synchronized, so | 1637 | * The two pipe frame counter registers are not synchronized, so |
| 1586 | * reading a stable value is somewhat tricky. The following code | 1638 | * reading a stable value is somewhat tricky. The following code |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 8d8e083d14ab..9e1d16e5c3ea 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -222,23 +222,12 @@ static void i915_restore_vga(struct drm_device *dev) | |||
| 222 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); | 222 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | int i915_save_state(struct drm_device *dev) | 225 | static void i915_save_modeset_reg(struct drm_device *dev) |
| 226 | { | 226 | { |
| 227 | struct drm_i915_private *dev_priv = dev->dev_private; | 227 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 228 | int i; | ||
| 229 | |||
| 230 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); | ||
| 231 | |||
| 232 | /* Render Standby */ | ||
| 233 | if (IS_I965G(dev) && IS_MOBILE(dev)) | ||
| 234 | dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); | ||
| 235 | |||
| 236 | /* Hardware status page */ | ||
| 237 | dev_priv->saveHWS = I915_READ(HWS_PGA); | ||
| 238 | |||
| 239 | /* Display arbitration control */ | ||
| 240 | dev_priv->saveDSPARB = I915_READ(DSPARB); | ||
| 241 | 228 | ||
| 229 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 230 | return; | ||
| 242 | /* Pipe & plane A info */ | 231 | /* Pipe & plane A info */ |
| 243 | dev_priv->savePIPEACONF = I915_READ(PIPEACONF); | 232 | dev_priv->savePIPEACONF = I915_READ(PIPEACONF); |
| 244 | dev_priv->savePIPEASRC = I915_READ(PIPEASRC); | 233 | dev_priv->savePIPEASRC = I915_READ(PIPEASRC); |
| @@ -294,7 +283,122 @@ int i915_save_state(struct drm_device *dev) | |||
| 294 | } | 283 | } |
| 295 | i915_save_palette(dev, PIPE_B); | 284 | i915_save_palette(dev, PIPE_B); |
| 296 | dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); | 285 | dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); |
| 286 | return; | ||
| 287 | } | ||
| 288 | static void i915_restore_modeset_reg(struct drm_device *dev) | ||
| 289 | { | ||
| 290 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 291 | |||
| 292 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 293 | return; | ||
| 294 | |||
| 295 | /* Pipe & plane A info */ | ||
| 296 | /* Prime the clock */ | ||
| 297 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { | ||
| 298 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & | ||
| 299 | ~DPLL_VCO_ENABLE); | ||
| 300 | DRM_UDELAY(150); | ||
| 301 | } | ||
| 302 | I915_WRITE(FPA0, dev_priv->saveFPA0); | ||
| 303 | I915_WRITE(FPA1, dev_priv->saveFPA1); | ||
| 304 | /* Actually enable it */ | ||
| 305 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); | ||
| 306 | DRM_UDELAY(150); | ||
| 307 | if (IS_I965G(dev)) | ||
| 308 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); | ||
| 309 | DRM_UDELAY(150); | ||
| 310 | |||
| 311 | /* Restore mode */ | ||
| 312 | I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); | ||
| 313 | I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); | ||
| 314 | I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); | ||
| 315 | I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); | ||
| 316 | I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); | ||
| 317 | I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); | ||
| 318 | I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); | ||
| 319 | |||
| 320 | /* Restore plane info */ | ||
| 321 | I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); | ||
| 322 | I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); | ||
| 323 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); | ||
| 324 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); | ||
| 325 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); | ||
| 326 | if (IS_I965G(dev)) { | ||
| 327 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); | ||
| 328 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); | ||
| 329 | } | ||
| 330 | |||
| 331 | I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); | ||
| 332 | |||
| 333 | i915_restore_palette(dev, PIPE_A); | ||
| 334 | /* Enable the plane */ | ||
| 335 | I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); | ||
| 336 | I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); | ||
| 337 | |||
| 338 | /* Pipe & plane B info */ | ||
| 339 | if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { | ||
| 340 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & | ||
| 341 | ~DPLL_VCO_ENABLE); | ||
| 342 | DRM_UDELAY(150); | ||
| 343 | } | ||
| 344 | I915_WRITE(FPB0, dev_priv->saveFPB0); | ||
| 345 | I915_WRITE(FPB1, dev_priv->saveFPB1); | ||
| 346 | /* Actually enable it */ | ||
| 347 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); | ||
| 348 | DRM_UDELAY(150); | ||
| 349 | if (IS_I965G(dev)) | ||
| 350 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); | ||
| 351 | DRM_UDELAY(150); | ||
| 352 | |||
| 353 | /* Restore mode */ | ||
| 354 | I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); | ||
| 355 | I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); | ||
| 356 | I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); | ||
| 357 | I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); | ||
| 358 | I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); | ||
| 359 | I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); | ||
| 360 | I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); | ||
| 361 | |||
| 362 | /* Restore plane info */ | ||
| 363 | I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); | ||
| 364 | I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); | ||
| 365 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); | ||
| 366 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); | ||
| 367 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); | ||
| 368 | if (IS_I965G(dev)) { | ||
| 369 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); | ||
| 370 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); | ||
| 371 | } | ||
| 372 | |||
| 373 | I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); | ||
| 374 | |||
| 375 | i915_restore_palette(dev, PIPE_B); | ||
| 376 | /* Enable the plane */ | ||
| 377 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | ||
| 378 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | ||
| 297 | 379 | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | int i915_save_state(struct drm_device *dev) | ||
| 383 | { | ||
| 384 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 385 | int i; | ||
| 386 | |||
| 387 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); | ||
| 388 | |||
| 389 | /* Render Standby */ | ||
| 390 | if (IS_I965G(dev) && IS_MOBILE(dev)) | ||
| 391 | dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); | ||
| 392 | |||
| 393 | /* Hardware status page */ | ||
| 394 | dev_priv->saveHWS = I915_READ(HWS_PGA); | ||
| 395 | |||
| 396 | /* Display arbitration control */ | ||
| 397 | dev_priv->saveDSPARB = I915_READ(DSPARB); | ||
| 398 | |||
| 399 | /* This is only meaningful in non-KMS mode */ | ||
| 400 | /* Don't save them in KMS mode */ | ||
| 401 | i915_save_modeset_reg(dev); | ||
| 298 | /* Cursor state */ | 402 | /* Cursor state */ |
| 299 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | 403 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); |
| 300 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | 404 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); |
| @@ -430,92 +534,9 @@ int i915_restore_state(struct drm_device *dev) | |||
| 430 | I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); | 534 | I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); |
| 431 | I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); | 535 | I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); |
| 432 | } | 536 | } |
| 433 | 537 | /* This is only meaningful in non-KMS mode */ | |
| 434 | /* Pipe & plane A info */ | 538 | /* Don't restore them in KMS mode */ |
| 435 | /* Prime the clock */ | 539 | i915_restore_modeset_reg(dev); |
| 436 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { | ||
| 437 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & | ||
| 438 | ~DPLL_VCO_ENABLE); | ||
| 439 | DRM_UDELAY(150); | ||
| 440 | } | ||
| 441 | I915_WRITE(FPA0, dev_priv->saveFPA0); | ||
| 442 | I915_WRITE(FPA1, dev_priv->saveFPA1); | ||
| 443 | /* Actually enable it */ | ||
| 444 | I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); | ||
| 445 | DRM_UDELAY(150); | ||
| 446 | if (IS_I965G(dev)) | ||
| 447 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); | ||
| 448 | DRM_UDELAY(150); | ||
| 449 | |||
| 450 | /* Restore mode */ | ||
| 451 | I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); | ||
| 452 | I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); | ||
| 453 | I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); | ||
| 454 | I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); | ||
| 455 | I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); | ||
| 456 | I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); | ||
| 457 | I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); | ||
| 458 | |||
| 459 | /* Restore plane info */ | ||
| 460 | I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); | ||
| 461 | I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); | ||
| 462 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); | ||
| 463 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); | ||
| 464 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); | ||
| 465 | if (IS_I965G(dev)) { | ||
| 466 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); | ||
| 467 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); | ||
| 468 | } | ||
| 469 | |||
| 470 | I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); | ||
| 471 | |||
| 472 | i915_restore_palette(dev, PIPE_A); | ||
| 473 | /* Enable the plane */ | ||
| 474 | I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); | ||
| 475 | I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); | ||
| 476 | |||
| 477 | /* Pipe & plane B info */ | ||
| 478 | if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { | ||
| 479 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & | ||
| 480 | ~DPLL_VCO_ENABLE); | ||
| 481 | DRM_UDELAY(150); | ||
| 482 | } | ||
| 483 | I915_WRITE(FPB0, dev_priv->saveFPB0); | ||
| 484 | I915_WRITE(FPB1, dev_priv->saveFPB1); | ||
| 485 | /* Actually enable it */ | ||
| 486 | I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); | ||
| 487 | DRM_UDELAY(150); | ||
| 488 | if (IS_I965G(dev)) | ||
| 489 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); | ||
| 490 | DRM_UDELAY(150); | ||
| 491 | |||
| 492 | /* Restore mode */ | ||
| 493 | I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); | ||
| 494 | I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); | ||
| 495 | I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); | ||
| 496 | I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); | ||
| 497 | I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); | ||
| 498 | I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); | ||
| 499 | I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); | ||
| 500 | |||
| 501 | /* Restore plane info */ | ||
| 502 | I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); | ||
| 503 | I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); | ||
| 504 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); | ||
| 505 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); | ||
| 506 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); | ||
| 507 | if (IS_I965G(dev)) { | ||
| 508 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); | ||
| 509 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); | ||
| 510 | } | ||
| 511 | |||
| 512 | I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); | ||
| 513 | |||
| 514 | i915_restore_palette(dev, PIPE_B); | ||
| 515 | /* Enable the plane */ | ||
| 516 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | ||
| 517 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | ||
| 518 | |||
| 519 | /* Cursor state */ | 540 | /* Cursor state */ |
| 520 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | 541 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); |
| 521 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | 542 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 716409a57244..7cc447191028 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -97,6 +97,7 @@ static void | |||
| 97 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, | 97 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, |
| 98 | struct bdb_header *bdb) | 98 | struct bdb_header *bdb) |
| 99 | { | 99 | { |
| 100 | struct drm_device *dev = dev_priv->dev; | ||
| 100 | struct bdb_lvds_options *lvds_options; | 101 | struct bdb_lvds_options *lvds_options; |
| 101 | struct bdb_lvds_lfp_data *lvds_lfp_data; | 102 | struct bdb_lvds_lfp_data *lvds_lfp_data; |
| 102 | struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; | 103 | struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; |
| @@ -132,7 +133,14 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
| 132 | entry = (struct bdb_lvds_lfp_data_entry *) | 133 | entry = (struct bdb_lvds_lfp_data_entry *) |
| 133 | ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * | 134 | ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * |
| 134 | lvds_options->panel_type)); | 135 | lvds_options->panel_type)); |
| 135 | dvo_timing = &entry->dvo_timing; | 136 | |
| 137 | /* On IGDNG mobile, LVDS data block removes panel fitting registers. | ||
| 138 | So dec 2 dword from dvo_timing offset */ | ||
| 139 | if (IS_IGDNG(dev)) | ||
| 140 | dvo_timing = (struct lvds_dvo_timing *) | ||
| 141 | ((u8 *)&entry->dvo_timing - 8); | ||
| 142 | else | ||
| 143 | dvo_timing = &entry->dvo_timing; | ||
| 136 | 144 | ||
| 137 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 145 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
| 138 | 146 | ||
| @@ -195,10 +203,12 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
| 195 | dev_priv->lvds_use_ssc = general->enable_ssc; | 203 | dev_priv->lvds_use_ssc = general->enable_ssc; |
| 196 | 204 | ||
| 197 | if (dev_priv->lvds_use_ssc) { | 205 | if (dev_priv->lvds_use_ssc) { |
| 198 | if (IS_I855(dev_priv->dev)) | 206 | if (IS_I85X(dev_priv->dev)) |
| 199 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48; | 207 | dev_priv->lvds_ssc_freq = |
| 200 | else | 208 | general->ssc_freq ? 66 : 48; |
| 201 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96; | 209 | else |
| 210 | dev_priv->lvds_ssc_freq = | ||
| 211 | general->ssc_freq ? 100 : 96; | ||
| 202 | } | 212 | } |
| 203 | } | 213 | } |
| 204 | } | 214 | } |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6de97fc66029..d6a1a6e5539a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -46,7 +46,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
| 46 | 46 | ||
| 47 | temp = I915_READ(reg); | 47 | temp = I915_READ(reg); |
| 48 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 48 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
| 49 | temp |= ADPA_DAC_ENABLE; | 49 | temp &= ~ADPA_DAC_ENABLE; |
| 50 | 50 | ||
| 51 | switch(mode) { | 51 | switch(mode) { |
| 52 | case DRM_MODE_DPMS_ON: | 52 | case DRM_MODE_DPMS_ON: |
| @@ -428,8 +428,34 @@ static void intel_crt_destroy(struct drm_connector *connector) | |||
| 428 | 428 | ||
| 429 | static int intel_crt_get_modes(struct drm_connector *connector) | 429 | static int intel_crt_get_modes(struct drm_connector *connector) |
| 430 | { | 430 | { |
| 431 | int ret; | ||
| 431 | struct intel_output *intel_output = to_intel_output(connector); | 432 | struct intel_output *intel_output = to_intel_output(connector); |
| 432 | return intel_ddc_get_modes(intel_output); | 433 | struct i2c_adapter *ddcbus; |
| 434 | struct drm_device *dev = connector->dev; | ||
| 435 | |||
| 436 | |||
| 437 | ret = intel_ddc_get_modes(intel_output); | ||
| 438 | if (ret || !IS_G4X(dev)) | ||
| 439 | goto end; | ||
| 440 | |||
| 441 | ddcbus = intel_output->ddc_bus; | ||
| 442 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ | ||
| 443 | intel_output->ddc_bus = | ||
| 444 | intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); | ||
| 445 | |||
| 446 | if (!intel_output->ddc_bus) { | ||
| 447 | intel_output->ddc_bus = ddcbus; | ||
| 448 | dev_printk(KERN_ERR, &connector->dev->pdev->dev, | ||
| 449 | "DDC bus registration failed for CRTDDC_D.\n"); | ||
| 450 | goto end; | ||
| 451 | } | ||
| 452 | /* Try to get modes by GPIOD port */ | ||
| 453 | ret = intel_ddc_get_modes(intel_output); | ||
| 454 | intel_i2c_destroy(ddcbus); | ||
| 455 | |||
| 456 | end: | ||
| 457 | return ret; | ||
| 458 | |||
| 433 | } | 459 | } |
| 434 | 460 | ||
| 435 | static int intel_crt_set_property(struct drm_connector *connector, | 461 | static int intel_crt_set_property(struct drm_connector *connector, |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 73e7b9cecac8..508838ee31e0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
| 28 | #include <linux/kernel.h> | ||
| 28 | #include "drmP.h" | 29 | #include "drmP.h" |
| 29 | #include "intel_drv.h" | 30 | #include "intel_drv.h" |
| 30 | #include "i915_drm.h" | 31 | #include "i915_drm.h" |
| @@ -34,6 +35,7 @@ | |||
| 34 | #include "drm_crtc_helper.h" | 35 | #include "drm_crtc_helper.h" |
| 35 | 36 | ||
| 36 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | 37 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); |
| 38 | static void intel_update_watermarks(struct drm_device *dev); | ||
| 37 | 39 | ||
| 38 | typedef struct { | 40 | typedef struct { |
| 39 | /* given values */ | 41 | /* given values */ |
| @@ -814,24 +816,21 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 814 | { | 816 | { |
| 815 | intel_clock_t clock; | 817 | intel_clock_t clock; |
| 816 | if (target < 200000) { | 818 | if (target < 200000) { |
| 817 | clock.dot = 161670; | ||
| 818 | clock.p = 20; | ||
| 819 | clock.p1 = 2; | 819 | clock.p1 = 2; |
| 820 | clock.p2 = 10; | 820 | clock.p2 = 10; |
| 821 | clock.n = 0x01; | 821 | clock.n = 2; |
| 822 | clock.m = 97; | 822 | clock.m1 = 23; |
| 823 | clock.m1 = 0x10; | 823 | clock.m2 = 8; |
| 824 | clock.m2 = 0x05; | ||
| 825 | } else { | 824 | } else { |
| 826 | clock.dot = 270000; | ||
| 827 | clock.p = 10; | ||
| 828 | clock.p1 = 1; | 825 | clock.p1 = 1; |
| 829 | clock.p2 = 10; | 826 | clock.p2 = 10; |
| 830 | clock.n = 0x02; | 827 | clock.n = 1; |
| 831 | clock.m = 108; | 828 | clock.m1 = 14; |
| 832 | clock.m1 = 0x12; | 829 | clock.m2 = 2; |
| 833 | clock.m2 = 0x06; | ||
| 834 | } | 830 | } |
| 831 | clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); | ||
| 832 | clock.p = (clock.p1 * clock.p2); | ||
| 833 | clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; | ||
| 835 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | 834 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); |
| 836 | return true; | 835 | return true; |
| 837 | } | 836 | } |
| @@ -1005,7 +1004,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 1005 | struct drm_i915_private *dev_priv = dev->dev_private; | 1004 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1006 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1005 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 1007 | int pipe = intel_crtc->pipe; | 1006 | int pipe = intel_crtc->pipe; |
| 1008 | int plane = intel_crtc->pipe; | 1007 | int plane = intel_crtc->plane; |
| 1009 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | 1008 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; |
| 1010 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 1009 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
| 1011 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | 1010 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; |
| @@ -1335,8 +1334,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 1335 | 1334 | ||
| 1336 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | 1335 | /* Give the overlay scaler a chance to enable if it's on this pipe */ |
| 1337 | //intel_crtc_dpms_video(crtc, true); TODO | 1336 | //intel_crtc_dpms_video(crtc, true); TODO |
| 1337 | intel_update_watermarks(dev); | ||
| 1338 | break; | 1338 | break; |
| 1339 | case DRM_MODE_DPMS_OFF: | 1339 | case DRM_MODE_DPMS_OFF: |
| 1340 | intel_update_watermarks(dev); | ||
| 1340 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | 1341 | /* Give the overlay scaler a chance to disable if it's on this pipe */ |
| 1341 | //intel_crtc_dpms_video(crtc, FALSE); TODO | 1342 | //intel_crtc_dpms_video(crtc, FALSE); TODO |
| 1342 | 1343 | ||
| @@ -1515,7 +1516,6 @@ static int intel_get_core_clock_speed(struct drm_device *dev) | |||
| 1515 | return 0; /* Silence gcc warning */ | 1516 | return 0; /* Silence gcc warning */ |
| 1516 | } | 1517 | } |
| 1517 | 1518 | ||
| 1518 | |||
| 1519 | /** | 1519 | /** |
| 1520 | * Return the pipe currently connected to the panel fitter, | 1520 | * Return the pipe currently connected to the panel fitter, |
| 1521 | * or -1 if the panel fitter is not present or not in use | 1521 | * or -1 if the panel fitter is not present or not in use |
| @@ -1574,7 +1574,7 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, | |||
| 1574 | 1574 | ||
| 1575 | temp = (u64) DATA_N * pixel_clock; | 1575 | temp = (u64) DATA_N * pixel_clock; |
| 1576 | temp = div_u64(temp, link_clock); | 1576 | temp = div_u64(temp, link_clock); |
| 1577 | m_n->gmch_m = (temp * bytes_per_pixel) / nlanes; | 1577 | m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes); |
| 1578 | m_n->gmch_n = DATA_N; | 1578 | m_n->gmch_n = DATA_N; |
| 1579 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | 1579 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); |
| 1580 | 1580 | ||
| @@ -1585,6 +1585,420 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, | |||
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| 1587 | 1587 | ||
| 1588 | struct intel_watermark_params { | ||
| 1589 | unsigned long fifo_size; | ||
| 1590 | unsigned long max_wm; | ||
| 1591 | unsigned long default_wm; | ||
| 1592 | unsigned long guard_size; | ||
| 1593 | unsigned long cacheline_size; | ||
| 1594 | }; | ||
| 1595 | |||
| 1596 | /* IGD has different values for various configs */ | ||
| 1597 | static struct intel_watermark_params igd_display_wm = { | ||
| 1598 | IGD_DISPLAY_FIFO, | ||
| 1599 | IGD_MAX_WM, | ||
| 1600 | IGD_DFT_WM, | ||
| 1601 | IGD_GUARD_WM, | ||
| 1602 | IGD_FIFO_LINE_SIZE | ||
| 1603 | }; | ||
| 1604 | static struct intel_watermark_params igd_display_hplloff_wm = { | ||
| 1605 | IGD_DISPLAY_FIFO, | ||
| 1606 | IGD_MAX_WM, | ||
| 1607 | IGD_DFT_HPLLOFF_WM, | ||
| 1608 | IGD_GUARD_WM, | ||
| 1609 | IGD_FIFO_LINE_SIZE | ||
| 1610 | }; | ||
| 1611 | static struct intel_watermark_params igd_cursor_wm = { | ||
| 1612 | IGD_CURSOR_FIFO, | ||
| 1613 | IGD_CURSOR_MAX_WM, | ||
| 1614 | IGD_CURSOR_DFT_WM, | ||
| 1615 | IGD_CURSOR_GUARD_WM, | ||
| 1616 | IGD_FIFO_LINE_SIZE, | ||
| 1617 | }; | ||
| 1618 | static struct intel_watermark_params igd_cursor_hplloff_wm = { | ||
| 1619 | IGD_CURSOR_FIFO, | ||
| 1620 | IGD_CURSOR_MAX_WM, | ||
| 1621 | IGD_CURSOR_DFT_WM, | ||
| 1622 | IGD_CURSOR_GUARD_WM, | ||
| 1623 | IGD_FIFO_LINE_SIZE | ||
| 1624 | }; | ||
| 1625 | static struct intel_watermark_params i945_wm_info = { | ||
| 1626 | I915_FIFO_LINE_SIZE, | ||
| 1627 | I915_MAX_WM, | ||
| 1628 | 1, | ||
| 1629 | 0, | ||
| 1630 | IGD_FIFO_LINE_SIZE | ||
| 1631 | }; | ||
| 1632 | static struct intel_watermark_params i915_wm_info = { | ||
| 1633 | I945_FIFO_SIZE, | ||
| 1634 | I915_MAX_WM, | ||
| 1635 | 1, | ||
| 1636 | 0, | ||
| 1637 | I915_FIFO_LINE_SIZE | ||
| 1638 | }; | ||
| 1639 | static struct intel_watermark_params i855_wm_info = { | ||
| 1640 | I855GM_FIFO_SIZE, | ||
| 1641 | I915_MAX_WM, | ||
| 1642 | 1, | ||
| 1643 | 0, | ||
| 1644 | I830_FIFO_LINE_SIZE | ||
| 1645 | }; | ||
| 1646 | static struct intel_watermark_params i830_wm_info = { | ||
| 1647 | I830_FIFO_SIZE, | ||
| 1648 | I915_MAX_WM, | ||
| 1649 | 1, | ||
| 1650 | 0, | ||
| 1651 | I830_FIFO_LINE_SIZE | ||
| 1652 | }; | ||
| 1653 | |||
| 1654 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | ||
| 1655 | struct intel_watermark_params *wm, | ||
| 1656 | int pixel_size, | ||
| 1657 | unsigned long latency_ns) | ||
| 1658 | { | ||
| 1659 | unsigned long bytes_required, wm_size; | ||
| 1660 | |||
| 1661 | bytes_required = (clock_in_khz * pixel_size * latency_ns) / 1000000; | ||
| 1662 | bytes_required /= wm->cacheline_size; | ||
| 1663 | wm_size = wm->fifo_size - bytes_required - wm->guard_size; | ||
| 1664 | |||
| 1665 | if (wm_size > wm->max_wm) | ||
| 1666 | wm_size = wm->max_wm; | ||
| 1667 | if (wm_size == 0) | ||
| 1668 | wm_size = wm->default_wm; | ||
| 1669 | return wm_size; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | struct cxsr_latency { | ||
| 1673 | int is_desktop; | ||
| 1674 | unsigned long fsb_freq; | ||
| 1675 | unsigned long mem_freq; | ||
| 1676 | unsigned long display_sr; | ||
| 1677 | unsigned long display_hpll_disable; | ||
| 1678 | unsigned long cursor_sr; | ||
| 1679 | unsigned long cursor_hpll_disable; | ||
| 1680 | }; | ||
| 1681 | |||
| 1682 | static struct cxsr_latency cxsr_latency_table[] = { | ||
| 1683 | {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ | ||
| 1684 | {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ | ||
| 1685 | {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ | ||
| 1686 | |||
| 1687 | {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ | ||
| 1688 | {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ | ||
| 1689 | {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ | ||
| 1690 | |||
| 1691 | {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ | ||
| 1692 | {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ | ||
| 1693 | {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ | ||
| 1694 | |||
| 1695 | {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ | ||
| 1696 | {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ | ||
| 1697 | {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ | ||
| 1698 | |||
| 1699 | {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ | ||
| 1700 | {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ | ||
| 1701 | {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ | ||
| 1702 | |||
| 1703 | {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ | ||
| 1704 | {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ | ||
| 1705 | {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ | ||
| 1706 | }; | ||
| 1707 | |||
| 1708 | static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb, | ||
| 1709 | int mem) | ||
| 1710 | { | ||
| 1711 | int i; | ||
| 1712 | struct cxsr_latency *latency; | ||
| 1713 | |||
| 1714 | if (fsb == 0 || mem == 0) | ||
| 1715 | return NULL; | ||
| 1716 | |||
| 1717 | for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { | ||
| 1718 | latency = &cxsr_latency_table[i]; | ||
| 1719 | if (is_desktop == latency->is_desktop && | ||
| 1720 | fsb == latency->fsb_freq && mem == latency->mem_freq) | ||
| 1721 | break; | ||
| 1722 | } | ||
| 1723 | if (i >= ARRAY_SIZE(cxsr_latency_table)) { | ||
| 1724 | DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); | ||
| 1725 | return NULL; | ||
| 1726 | } | ||
| 1727 | return latency; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | static void igd_disable_cxsr(struct drm_device *dev) | ||
| 1731 | { | ||
| 1732 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1733 | u32 reg; | ||
| 1734 | |||
| 1735 | /* deactivate cxsr */ | ||
| 1736 | reg = I915_READ(DSPFW3); | ||
| 1737 | reg &= ~(IGD_SELF_REFRESH_EN); | ||
| 1738 | I915_WRITE(DSPFW3, reg); | ||
| 1739 | DRM_INFO("Big FIFO is disabled\n"); | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, | ||
| 1743 | int pixel_size) | ||
| 1744 | { | ||
| 1745 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1746 | u32 reg; | ||
| 1747 | unsigned long wm; | ||
| 1748 | struct cxsr_latency *latency; | ||
| 1749 | |||
| 1750 | latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq, | ||
| 1751 | dev_priv->mem_freq); | ||
| 1752 | if (!latency) { | ||
| 1753 | DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); | ||
| 1754 | igd_disable_cxsr(dev); | ||
| 1755 | return; | ||
| 1756 | } | ||
| 1757 | |||
| 1758 | /* Display SR */ | ||
| 1759 | wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size, | ||
| 1760 | latency->display_sr); | ||
| 1761 | reg = I915_READ(DSPFW1); | ||
| 1762 | reg &= 0x7fffff; | ||
| 1763 | reg |= wm << 23; | ||
| 1764 | I915_WRITE(DSPFW1, reg); | ||
| 1765 | DRM_DEBUG("DSPFW1 register is %x\n", reg); | ||
| 1766 | |||
| 1767 | /* cursor SR */ | ||
| 1768 | wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size, | ||
| 1769 | latency->cursor_sr); | ||
| 1770 | reg = I915_READ(DSPFW3); | ||
| 1771 | reg &= ~(0x3f << 24); | ||
| 1772 | reg |= (wm & 0x3f) << 24; | ||
| 1773 | I915_WRITE(DSPFW3, reg); | ||
| 1774 | |||
| 1775 | /* Display HPLL off SR */ | ||
| 1776 | wm = intel_calculate_wm(clock, &igd_display_hplloff_wm, | ||
| 1777 | latency->display_hpll_disable, I915_FIFO_LINE_SIZE); | ||
| 1778 | reg = I915_READ(DSPFW3); | ||
| 1779 | reg &= 0xfffffe00; | ||
| 1780 | reg |= wm & 0x1ff; | ||
| 1781 | I915_WRITE(DSPFW3, reg); | ||
| 1782 | |||
| 1783 | /* cursor HPLL off SR */ | ||
| 1784 | wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size, | ||
| 1785 | latency->cursor_hpll_disable); | ||
| 1786 | reg = I915_READ(DSPFW3); | ||
| 1787 | reg &= ~(0x3f << 16); | ||
| 1788 | reg |= (wm & 0x3f) << 16; | ||
| 1789 | I915_WRITE(DSPFW3, reg); | ||
| 1790 | DRM_DEBUG("DSPFW3 register is %x\n", reg); | ||
| 1791 | |||
| 1792 | /* activate cxsr */ | ||
| 1793 | reg = I915_READ(DSPFW3); | ||
| 1794 | reg |= IGD_SELF_REFRESH_EN; | ||
| 1795 | I915_WRITE(DSPFW3, reg); | ||
| 1796 | |||
| 1797 | DRM_INFO("Big FIFO is enabled\n"); | ||
| 1798 | |||
| 1799 | return; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | const static int latency_ns = 5000; /* default for non-igd platforms */ | ||
| 1803 | |||
| 1804 | |||
| 1805 | static void i965_update_wm(struct drm_device *dev) | ||
| 1806 | { | ||
| 1807 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1808 | |||
| 1809 | DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n"); | ||
| 1810 | |||
| 1811 | /* 965 has limitations... */ | ||
| 1812 | I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0)); | ||
| 1813 | I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | ||
| 1817 | int planeb_clock, int sr_hdisplay, int pixel_size) | ||
| 1818 | { | ||
| 1819 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1820 | uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; | ||
| 1821 | uint32_t fwater_hi = I915_READ(FW_BLC2) & LM_FIFO_WATERMARK; | ||
| 1822 | int bsize, asize, cwm, bwm = 1, awm = 1, srwm = 1; | ||
| 1823 | uint32_t dsparb = I915_READ(DSPARB); | ||
| 1824 | int planea_entries, planeb_entries; | ||
| 1825 | struct intel_watermark_params *wm_params; | ||
| 1826 | unsigned long line_time_us; | ||
| 1827 | int sr_clock, sr_entries = 0; | ||
| 1828 | |||
| 1829 | if (IS_I965GM(dev) || IS_I945GM(dev)) | ||
| 1830 | wm_params = &i945_wm_info; | ||
| 1831 | else if (IS_I9XX(dev)) | ||
| 1832 | wm_params = &i915_wm_info; | ||
| 1833 | else | ||
| 1834 | wm_params = &i855_wm_info; | ||
| 1835 | |||
| 1836 | planea_entries = intel_calculate_wm(planea_clock, wm_params, | ||
| 1837 | pixel_size, latency_ns); | ||
| 1838 | planeb_entries = intel_calculate_wm(planeb_clock, wm_params, | ||
| 1839 | pixel_size, latency_ns); | ||
| 1840 | |||
| 1841 | DRM_DEBUG("FIFO entries - A: %d, B: %d\n", planea_entries, | ||
| 1842 | planeb_entries); | ||
| 1843 | |||
| 1844 | if (IS_I9XX(dev)) { | ||
| 1845 | asize = dsparb & 0x7f; | ||
| 1846 | bsize = (dsparb >> DSPARB_CSTART_SHIFT) & 0x7f; | ||
| 1847 | } else { | ||
| 1848 | asize = dsparb & 0x1ff; | ||
| 1849 | bsize = (dsparb >> DSPARB_BEND_SHIFT) & 0x1ff; | ||
| 1850 | } | ||
| 1851 | DRM_DEBUG("FIFO size - A: %d, B: %d\n", asize, bsize); | ||
| 1852 | |||
| 1853 | /* Two extra entries for padding */ | ||
| 1854 | awm = asize - (planea_entries + 2); | ||
| 1855 | bwm = bsize - (planeb_entries + 2); | ||
| 1856 | |||
| 1857 | /* Sanity check against potentially bad FIFO allocations */ | ||
| 1858 | if (awm <= 0) { | ||
| 1859 | /* pipe is on but has too few FIFO entries */ | ||
| 1860 | if (planea_entries != 0) | ||
| 1861 | DRM_DEBUG("plane A needs more FIFO entries\n"); | ||
| 1862 | awm = 1; | ||
| 1863 | } | ||
| 1864 | if (bwm <= 0) { | ||
| 1865 | if (planeb_entries != 0) | ||
| 1866 | DRM_DEBUG("plane B needs more FIFO entries\n"); | ||
| 1867 | bwm = 1; | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | /* | ||
| 1871 | * Overlay gets an aggressive default since video jitter is bad. | ||
| 1872 | */ | ||
| 1873 | cwm = 2; | ||
| 1874 | |||
| 1875 | /* Calc sr entries for one pipe configs */ | ||
| 1876 | if (!planea_clock || !planeb_clock) { | ||
| 1877 | sr_clock = planea_clock ? planea_clock : planeb_clock; | ||
| 1878 | line_time_us = (sr_hdisplay * 1000) / sr_clock; | ||
| 1879 | sr_entries = (((latency_ns / line_time_us) + 1) * pixel_size * | ||
| 1880 | sr_hdisplay) / 1000; | ||
| 1881 | sr_entries = roundup(sr_entries / wm_params->cacheline_size, 1); | ||
| 1882 | if (sr_entries < wm_params->fifo_size) | ||
| 1883 | srwm = wm_params->fifo_size - sr_entries; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", | ||
| 1887 | awm, bwm, cwm, srwm); | ||
| 1888 | |||
| 1889 | fwater_lo = fwater_lo | ((bwm & 0x3f) << 16) | (awm & 0x3f); | ||
| 1890 | fwater_hi = fwater_hi | (cwm & 0x1f); | ||
| 1891 | |||
| 1892 | I915_WRITE(FW_BLC, fwater_lo); | ||
| 1893 | I915_WRITE(FW_BLC2, fwater_hi); | ||
| 1894 | if (IS_I9XX(dev)) | ||
| 1895 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | static void i830_update_wm(struct drm_device *dev, int planea_clock, | ||
| 1899 | int pixel_size) | ||
| 1900 | { | ||
| 1901 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1902 | uint32_t dsparb = I915_READ(DSPARB); | ||
| 1903 | uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; | ||
| 1904 | unsigned int asize, awm; | ||
| 1905 | int planea_entries; | ||
| 1906 | |||
| 1907 | planea_entries = intel_calculate_wm(planea_clock, &i830_wm_info, | ||
| 1908 | pixel_size, latency_ns); | ||
| 1909 | |||
| 1910 | asize = dsparb & 0x7f; | ||
| 1911 | |||
| 1912 | awm = asize - planea_entries; | ||
| 1913 | |||
| 1914 | fwater_lo = fwater_lo | awm; | ||
| 1915 | |||
| 1916 | I915_WRITE(FW_BLC, fwater_lo); | ||
| 1917 | } | ||
| 1918 | |||
| 1919 | /** | ||
| 1920 | * intel_update_watermarks - update FIFO watermark values based on current modes | ||
| 1921 | * | ||
| 1922 | * Calculate watermark values for the various WM regs based on current mode | ||
| 1923 | * and plane configuration. | ||
| 1924 | * | ||
| 1925 | * There are several cases to deal with here: | ||
| 1926 | * - normal (i.e. non-self-refresh) | ||
| 1927 | * - self-refresh (SR) mode | ||
| 1928 | * - lines are large relative to FIFO size (buffer can hold up to 2) | ||
| 1929 | * - lines are small relative to FIFO size (buffer can hold more than 2 | ||
| 1930 | * lines), so need to account for TLB latency | ||
| 1931 | * | ||
| 1932 | * The normal calculation is: | ||
| 1933 | * watermark = dotclock * bytes per pixel * latency | ||
| 1934 | * where latency is platform & configuration dependent (we assume pessimal | ||
| 1935 | * values here). | ||
| 1936 | * | ||
| 1937 | * The SR calculation is: | ||
| 1938 | * watermark = (trunc(latency/line time)+1) * surface width * | ||
| 1939 | * bytes per pixel | ||
| 1940 | * where | ||
| 1941 | * line time = htotal / dotclock | ||
| 1942 | * and latency is assumed to be high, as above. | ||
| 1943 | * | ||
| 1944 | * The final value programmed to the register should always be rounded up, | ||
| 1945 | * and include an extra 2 entries to account for clock crossings. | ||
| 1946 | * | ||
| 1947 | * We don't use the sprite, so we can ignore that. And on Crestline we have | ||
| 1948 | * to set the non-SR watermarks to 8. | ||
| 1949 | */ | ||
| 1950 | static void intel_update_watermarks(struct drm_device *dev) | ||
| 1951 | { | ||
| 1952 | struct drm_crtc *crtc; | ||
| 1953 | struct intel_crtc *intel_crtc; | ||
| 1954 | int sr_hdisplay = 0; | ||
| 1955 | unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; | ||
| 1956 | int enabled = 0, pixel_size = 0; | ||
| 1957 | |||
| 1958 | if (DSPARB_HWCONTROL(dev)) | ||
| 1959 | return; | ||
| 1960 | |||
| 1961 | /* Get the clock config from both planes */ | ||
| 1962 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 1963 | intel_crtc = to_intel_crtc(crtc); | ||
| 1964 | if (crtc->enabled) { | ||
| 1965 | enabled++; | ||
| 1966 | if (intel_crtc->plane == 0) { | ||
| 1967 | DRM_DEBUG("plane A (pipe %d) clock: %d\n", | ||
| 1968 | intel_crtc->pipe, crtc->mode.clock); | ||
| 1969 | planea_clock = crtc->mode.clock; | ||
| 1970 | } else { | ||
| 1971 | DRM_DEBUG("plane B (pipe %d) clock: %d\n", | ||
| 1972 | intel_crtc->pipe, crtc->mode.clock); | ||
| 1973 | planeb_clock = crtc->mode.clock; | ||
| 1974 | } | ||
| 1975 | sr_hdisplay = crtc->mode.hdisplay; | ||
| 1976 | sr_clock = crtc->mode.clock; | ||
| 1977 | if (crtc->fb) | ||
| 1978 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
| 1979 | else | ||
| 1980 | pixel_size = 4; /* by default */ | ||
| 1981 | } | ||
| 1982 | } | ||
| 1983 | |||
| 1984 | if (enabled <= 0) | ||
| 1985 | return; | ||
| 1986 | |||
| 1987 | /* Single pipe configs can enable self refresh */ | ||
| 1988 | if (enabled == 1 && IS_IGD(dev)) | ||
| 1989 | igd_enable_cxsr(dev, sr_clock, pixel_size); | ||
| 1990 | else if (IS_IGD(dev)) | ||
| 1991 | igd_disable_cxsr(dev); | ||
| 1992 | |||
| 1993 | if (IS_I965G(dev)) | ||
| 1994 | i965_update_wm(dev); | ||
| 1995 | else if (IS_I9XX(dev) || IS_MOBILE(dev)) | ||
| 1996 | i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay, | ||
| 1997 | pixel_size); | ||
| 1998 | else | ||
| 1999 | i830_update_wm(dev, planea_clock, pixel_size); | ||
| 2000 | } | ||
| 2001 | |||
| 1588 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 2002 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
| 1589 | struct drm_display_mode *mode, | 2003 | struct drm_display_mode *mode, |
| 1590 | struct drm_display_mode *adjusted_mode, | 2004 | struct drm_display_mode *adjusted_mode, |
| @@ -1951,6 +2365,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1951 | 2365 | ||
| 1952 | /* Flush the plane changes */ | 2366 | /* Flush the plane changes */ |
| 1953 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 2367 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
| 2368 | |||
| 2369 | intel_update_watermarks(dev); | ||
| 2370 | |||
| 1954 | drm_vblank_post_modeset(dev, pipe); | 2371 | drm_vblank_post_modeset(dev, pipe); |
| 1955 | 2372 | ||
| 1956 | return ret; | 2373 | return ret; |
| @@ -2439,6 +2856,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
| 2439 | 2856 | ||
| 2440 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); | 2857 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); |
| 2441 | intel_crtc->pipe = pipe; | 2858 | intel_crtc->pipe = pipe; |
| 2859 | intel_crtc->plane = pipe; | ||
| 2442 | for (i = 0; i < 256; i++) { | 2860 | for (i = 0; i < 256; i++) { |
| 2443 | intel_crtc->lut_r[i] = i; | 2861 | intel_crtc->lut_r[i] = i; |
| 2444 | intel_crtc->lut_g[i] = i; | 2862 | intel_crtc->lut_g[i] = i; |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8f8d37d5663a..6770ae88370d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -246,7 +246,7 @@ intel_dp_aux_ch(struct intel_output *intel_output, | |||
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { | 248 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { |
| 249 | printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); | 249 | DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); |
| 250 | return -EBUSY; | 250 | return -EBUSY; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| @@ -254,11 +254,14 @@ intel_dp_aux_ch(struct intel_output *intel_output, | |||
| 254 | * Timeouts occur when the sink is not connected | 254 | * Timeouts occur when the sink is not connected |
| 255 | */ | 255 | */ |
| 256 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { | 256 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { |
| 257 | printk(KERN_ERR "dp_aux_ch receive error status 0x%08x\n", status); | 257 | DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); |
| 258 | return -EIO; | 258 | return -EIO; |
| 259 | } | 259 | } |
| 260 | |||
| 261 | /* Timeouts occur when the device isn't connected, so they're | ||
| 262 | * "normal" -- don't fill the kernel log with these */ | ||
| 260 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { | 263 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { |
| 261 | printk(KERN_ERR "dp_aux_ch timeout status 0x%08x\n", status); | 264 | DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status); |
| 262 | return -ETIMEDOUT; | 265 | return -ETIMEDOUT; |
| 263 | } | 266 | } |
| 264 | 267 | ||
| @@ -411,7 +414,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 411 | dp_priv->link_bw = bws[clock]; | 414 | dp_priv->link_bw = bws[clock]; |
| 412 | dp_priv->lane_count = lane_count; | 415 | dp_priv->lane_count = lane_count; |
| 413 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); | 416 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); |
| 414 | printk(KERN_ERR "link bw %02x lane count %d clock %d\n", | 417 | DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n", |
| 415 | dp_priv->link_bw, dp_priv->lane_count, | 418 | dp_priv->link_bw, dp_priv->lane_count, |
| 416 | adjusted_mode->clock); | 419 | adjusted_mode->clock); |
| 417 | return true; | 420 | return true; |
diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c index 4e60f14b1a6d..a63b6f57d2d4 100644 --- a/drivers/gpu/drm/i915/intel_dp_i2c.c +++ b/drivers/gpu/drm/i915/intel_dp_i2c.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
| 30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
| 31 | #include "intel_dp.h" | 31 | #include "intel_dp.h" |
| 32 | #include "drmP.h" | ||
| 32 | 33 | ||
| 33 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ | 34 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ |
| 34 | 35 | ||
| @@ -84,7 +85,7 @@ i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | |||
| 84 | msg, msg_bytes, | 85 | msg, msg_bytes, |
| 85 | reply, reply_bytes); | 86 | reply, reply_bytes); |
| 86 | if (ret < 0) { | 87 | if (ret < 0) { |
| 87 | printk(KERN_ERR "aux_ch failed %d\n", ret); | 88 | DRM_DEBUG("aux_ch failed %d\n", ret); |
| 88 | return ret; | 89 | return ret; |
| 89 | } | 90 | } |
| 90 | switch (reply[0] & AUX_I2C_REPLY_MASK) { | 91 | switch (reply[0] & AUX_I2C_REPLY_MASK) { |
| @@ -94,14 +95,14 @@ i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | |||
| 94 | } | 95 | } |
| 95 | return reply_bytes - 1; | 96 | return reply_bytes - 1; |
| 96 | case AUX_I2C_REPLY_NACK: | 97 | case AUX_I2C_REPLY_NACK: |
| 97 | printk(KERN_ERR "aux_ch nack\n"); | 98 | DRM_DEBUG("aux_ch nack\n"); |
| 98 | return -EREMOTEIO; | 99 | return -EREMOTEIO; |
| 99 | case AUX_I2C_REPLY_DEFER: | 100 | case AUX_I2C_REPLY_DEFER: |
| 100 | printk(KERN_ERR "aux_ch defer\n"); | 101 | DRM_DEBUG("aux_ch defer\n"); |
| 101 | udelay(100); | 102 | udelay(100); |
| 102 | break; | 103 | break; |
| 103 | default: | 104 | default: |
| 104 | printk(KERN_ERR "aux_ch invalid reply 0x%02x\n", reply[0]); | 105 | DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); |
| 105 | return -EREMOTEIO; | 106 | return -EREMOTEIO; |
| 106 | } | 107 | } |
| 107 | } | 108 | } |
| @@ -223,7 +224,7 @@ i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, | |||
| 223 | if (ret >= 0) | 224 | if (ret >= 0) |
| 224 | ret = num; | 225 | ret = num; |
| 225 | i2c_algo_dp_aux_stop(adapter, reading); | 226 | i2c_algo_dp_aux_stop(adapter, reading); |
| 226 | printk(KERN_ERR "dp_aux_xfer return %d\n", ret); | 227 | DRM_DEBUG("dp_aux_xfer return %d\n", ret); |
| 227 | return ret; | 228 | return ret; |
| 228 | } | 229 | } |
| 229 | 230 | ||
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 1af7d68e3807..1d30802e773e 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -453,7 +453,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 453 | size = ALIGN(size, PAGE_SIZE); | 453 | size = ALIGN(size, PAGE_SIZE); |
| 454 | fbo = drm_gem_object_alloc(dev, size); | 454 | fbo = drm_gem_object_alloc(dev, size); |
| 455 | if (!fbo) { | 455 | if (!fbo) { |
| 456 | printk(KERN_ERR "failed to allocate framebuffer\n"); | 456 | DRM_ERROR("failed to allocate framebuffer\n"); |
| 457 | ret = -ENOMEM; | 457 | ret = -ENOMEM; |
| 458 | goto out; | 458 | goto out; |
| 459 | } | 459 | } |
| @@ -610,8 +610,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 610 | par->dev = dev; | 610 | par->dev = dev; |
| 611 | 611 | ||
| 612 | /* To allow resizeing without swapping buffers */ | 612 | /* To allow resizeing without swapping buffers */ |
| 613 | printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, | 613 | DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, |
| 614 | intel_fb->base.height, obj_priv->gtt_offset, fbo); | 614 | intel_fb->base.height, obj_priv->gtt_offset, fbo); |
| 615 | 615 | ||
| 616 | mutex_unlock(&dev->struct_mutex); | 616 | mutex_unlock(&dev->struct_mutex); |
| 617 | return 0; | 617 | return 0; |
| @@ -698,13 +698,13 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc * | |||
| 698 | } else | 698 | } else |
| 699 | intelfb_set_par(info); | 699 | intelfb_set_par(info); |
| 700 | 700 | ||
| 701 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 701 | DRM_INFO("fb%d: %s frame buffer device\n", info->node, |
| 702 | info->fix.id); | 702 | info->fix.id); |
| 703 | 703 | ||
| 704 | /* Switch back to kernel console on panic */ | 704 | /* Switch back to kernel console on panic */ |
| 705 | kernelfb_mode = *modeset; | 705 | kernelfb_mode = *modeset; |
| 706 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); | 706 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
| 707 | printk(KERN_INFO "registered panic notifier\n"); | 707 | DRM_DEBUG("registered panic notifier\n"); |
| 708 | 708 | ||
| 709 | return 0; | 709 | return 0; |
| 710 | } | 710 | } |
| @@ -852,13 +852,13 @@ static int intelfb_single_fb_probe(struct drm_device *dev) | |||
| 852 | } else | 852 | } else |
| 853 | intelfb_set_par(info); | 853 | intelfb_set_par(info); |
| 854 | 854 | ||
| 855 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 855 | DRM_INFO("fb%d: %s frame buffer device\n", info->node, |
| 856 | info->fix.id); | 856 | info->fix.id); |
| 857 | 857 | ||
| 858 | /* Switch back to kernel console on panic */ | 858 | /* Switch back to kernel console on panic */ |
| 859 | kernelfb_mode = *modeset; | 859 | kernelfb_mode = *modeset; |
| 860 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); | 860 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
| 861 | printk(KERN_INFO "registered panic notifier\n"); | 861 | DRM_DEBUG("registered panic notifier\n"); |
| 862 | 862 | ||
| 863 | return 0; | 863 | return 0; |
| 864 | } | 864 | } |
| @@ -872,8 +872,8 @@ void intelfb_restore(void) | |||
| 872 | { | 872 | { |
| 873 | int ret; | 873 | int ret; |
| 874 | if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) { | 874 | if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) { |
| 875 | printk(KERN_ERR "Failed to restore crtc configuration: %d\n", | 875 | DRM_ERROR("Failed to restore crtc configuration: %d\n", |
| 876 | ret); | 876 | ret); |
| 877 | } | 877 | } |
| 878 | } | 878 | } |
| 879 | 879 | ||
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 9564ca44a977..9ab38efffecf 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "intel_drv.h" | 36 | #include "intel_drv.h" |
| 37 | #include "i915_drm.h" | 37 | #include "i915_drm.h" |
| 38 | #include "i915_drv.h" | 38 | #include "i915_drv.h" |
| 39 | #include <linux/acpi.h> | ||
| 39 | 40 | ||
| 40 | #define I915_LVDS "i915_lvds" | 41 | #define I915_LVDS "i915_lvds" |
| 41 | 42 | ||
| @@ -252,14 +253,14 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 252 | 253 | ||
| 253 | /* Should never happen!! */ | 254 | /* Should never happen!! */ |
| 254 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { | 255 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { |
| 255 | printk(KERN_ERR "Can't support LVDS on pipe A\n"); | 256 | DRM_ERROR("Can't support LVDS on pipe A\n"); |
| 256 | return false; | 257 | return false; |
| 257 | } | 258 | } |
| 258 | 259 | ||
| 259 | /* Should never happen!! */ | 260 | /* Should never happen!! */ |
| 260 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { | 261 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { |
| 261 | if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { | 262 | if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { |
| 262 | printk(KERN_ERR "Can't enable LVDS and another " | 263 | DRM_ERROR("Can't enable LVDS and another " |
| 263 | "encoder on the same pipe\n"); | 264 | "encoder on the same pipe\n"); |
| 264 | return false; | 265 | return false; |
| 265 | } | 266 | } |
| @@ -788,6 +789,65 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 788 | { } /* terminating entry */ | 789 | { } /* terminating entry */ |
| 789 | }; | 790 | }; |
| 790 | 791 | ||
| 792 | #ifdef CONFIG_ACPI | ||
| 793 | /* | ||
| 794 | * check_lid_device -- check whether @handle is an ACPI LID device. | ||
| 795 | * @handle: ACPI device handle | ||
| 796 | * @level : depth in the ACPI namespace tree | ||
| 797 | * @context: the number of LID device when we find the device | ||
| 798 | * @rv: a return value to fill if desired (Not use) | ||
| 799 | */ | ||
| 800 | static acpi_status | ||
| 801 | check_lid_device(acpi_handle handle, u32 level, void *context, | ||
| 802 | void **return_value) | ||
| 803 | { | ||
| 804 | struct acpi_device *acpi_dev; | ||
| 805 | int *lid_present = context; | ||
| 806 | |||
| 807 | acpi_dev = NULL; | ||
| 808 | /* Get the acpi device for device handle */ | ||
| 809 | if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) { | ||
| 810 | /* If there is no ACPI device for handle, return */ | ||
| 811 | return AE_OK; | ||
| 812 | } | ||
| 813 | |||
| 814 | if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7)) | ||
| 815 | *lid_present = 1; | ||
| 816 | |||
| 817 | return AE_OK; | ||
| 818 | } | ||
| 819 | |||
| 820 | /** | ||
| 821 | * check whether there exists the ACPI LID device by enumerating the ACPI | ||
| 822 | * device tree. | ||
| 823 | */ | ||
| 824 | static int intel_lid_present(void) | ||
| 825 | { | ||
| 826 | int lid_present = 0; | ||
| 827 | |||
| 828 | if (acpi_disabled) { | ||
| 829 | /* If ACPI is disabled, there is no ACPI device tree to | ||
| 830 | * check, so assume the LID device would have been present. | ||
| 831 | */ | ||
| 832 | return 1; | ||
| 833 | } | ||
| 834 | |||
| 835 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 836 | ACPI_UINT32_MAX, | ||
| 837 | check_lid_device, &lid_present, NULL); | ||
| 838 | |||
| 839 | return lid_present; | ||
| 840 | } | ||
| 841 | #else | ||
| 842 | static int intel_lid_present(void) | ||
| 843 | { | ||
| 844 | /* In the absence of ACPI built in, assume that the LID device would | ||
| 845 | * have been present. | ||
| 846 | */ | ||
| 847 | return 1; | ||
| 848 | } | ||
| 849 | #endif | ||
| 850 | |||
| 791 | /** | 851 | /** |
| 792 | * intel_lvds_init - setup LVDS connectors on this device | 852 | * intel_lvds_init - setup LVDS connectors on this device |
| 793 | * @dev: drm device | 853 | * @dev: drm device |
| @@ -811,6 +871,16 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 811 | if (dmi_check_system(intel_no_lvds)) | 871 | if (dmi_check_system(intel_no_lvds)) |
| 812 | return; | 872 | return; |
| 813 | 873 | ||
| 874 | /* Assume that any device without an ACPI LID device also doesn't | ||
| 875 | * have an integrated LVDS. We would be better off parsing the BIOS | ||
| 876 | * to get a reliable indicator, but that code isn't written yet. | ||
| 877 | * | ||
| 878 | * In the case of all-in-one desktops using LVDS that we've seen, | ||
| 879 | * they're using SDVO LVDS. | ||
| 880 | */ | ||
| 881 | if (!intel_lid_present()) | ||
| 882 | return; | ||
| 883 | |||
| 814 | if (IS_IGDNG(dev)) { | 884 | if (IS_IGDNG(dev)) { |
| 815 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | 885 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
| 816 | return; | 886 | return; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f03473779feb..4f0c30948bc4 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -68,12 +68,23 @@ struct intel_sdvo_priv { | |||
| 68 | * This is set if we treat the device as HDMI, instead of DVI. | 68 | * This is set if we treat the device as HDMI, instead of DVI. |
| 69 | */ | 69 | */ |
| 70 | bool is_hdmi; | 70 | bool is_hdmi; |
| 71 | |||
| 71 | /** | 72 | /** |
| 72 | * This is set if we detect output of sdvo device as LVDS. | 73 | * This is set if we detect output of sdvo device as LVDS. |
| 73 | */ | 74 | */ |
| 74 | bool is_lvds; | 75 | bool is_lvds; |
| 75 | 76 | ||
| 76 | /** | 77 | /** |
| 78 | * This is sdvo flags for input timing. | ||
| 79 | */ | ||
| 80 | uint8_t sdvo_flags; | ||
| 81 | |||
| 82 | /** | ||
| 83 | * This is sdvo fixed pannel mode pointer | ||
| 84 | */ | ||
| 85 | struct drm_display_mode *sdvo_lvds_fixed_mode; | ||
| 86 | |||
| 87 | /** | ||
| 77 | * Returned SDTV resolutions allowed for the current format, if the | 88 | * Returned SDTV resolutions allowed for the current format, if the |
| 78 | * device reported it. | 89 | * device reported it. |
| 79 | */ | 90 | */ |
| @@ -592,6 +603,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, | |||
| 592 | uint16_t height) | 603 | uint16_t height) |
| 593 | { | 604 | { |
| 594 | struct intel_sdvo_preferred_input_timing_args args; | 605 | struct intel_sdvo_preferred_input_timing_args args; |
| 606 | struct intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
| 595 | uint8_t status; | 607 | uint8_t status; |
| 596 | 608 | ||
| 597 | memset(&args, 0, sizeof(args)); | 609 | memset(&args, 0, sizeof(args)); |
| @@ -599,7 +611,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, | |||
| 599 | args.width = width; | 611 | args.width = width; |
| 600 | args.height = height; | 612 | args.height = height; |
| 601 | args.interlace = 0; | 613 | args.interlace = 0; |
| 602 | args.scaled = 0; | 614 | |
| 615 | if (sdvo_priv->is_lvds && | ||
| 616 | (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width || | ||
| 617 | sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height)) | ||
| 618 | args.scaled = 1; | ||
| 619 | |||
| 603 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, | 620 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, |
| 604 | &args, sizeof(args)); | 621 | &args, sizeof(args)); |
| 605 | status = intel_sdvo_read_response(output, NULL, 0); | 622 | status = intel_sdvo_read_response(output, NULL, 0); |
| @@ -944,12 +961,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 944 | struct intel_output *output = enc_to_intel_output(encoder); | 961 | struct intel_output *output = enc_to_intel_output(encoder); |
| 945 | struct intel_sdvo_priv *dev_priv = output->dev_priv; | 962 | struct intel_sdvo_priv *dev_priv = output->dev_priv; |
| 946 | 963 | ||
| 947 | if (!dev_priv->is_tv) { | 964 | if (dev_priv->is_tv) { |
| 948 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | ||
| 949 | * SDVO device will be told of the multiplier during mode_set. | ||
| 950 | */ | ||
| 951 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
| 952 | } else { | ||
| 953 | struct intel_sdvo_dtd output_dtd; | 965 | struct intel_sdvo_dtd output_dtd; |
| 954 | bool success; | 966 | bool success; |
| 955 | 967 | ||
| @@ -980,6 +992,47 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 980 | intel_sdvo_get_preferred_input_timing(output, | 992 | intel_sdvo_get_preferred_input_timing(output, |
| 981 | &input_dtd); | 993 | &input_dtd); |
| 982 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | 994 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); |
| 995 | dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
| 996 | |||
| 997 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 998 | |||
| 999 | mode->clock = adjusted_mode->clock; | ||
| 1000 | |||
| 1001 | adjusted_mode->clock *= | ||
| 1002 | intel_sdvo_get_pixel_multiplier(mode); | ||
| 1003 | } else { | ||
| 1004 | return false; | ||
| 1005 | } | ||
| 1006 | } else if (dev_priv->is_lvds) { | ||
| 1007 | struct intel_sdvo_dtd output_dtd; | ||
| 1008 | bool success; | ||
| 1009 | |||
| 1010 | drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0); | ||
| 1011 | /* Set output timings */ | ||
| 1012 | intel_sdvo_get_dtd_from_mode(&output_dtd, | ||
| 1013 | dev_priv->sdvo_lvds_fixed_mode); | ||
| 1014 | |||
| 1015 | intel_sdvo_set_target_output(output, | ||
| 1016 | dev_priv->controlled_output); | ||
| 1017 | intel_sdvo_set_output_timing(output, &output_dtd); | ||
| 1018 | |||
| 1019 | /* Set the input timing to the screen. Assume always input 0. */ | ||
| 1020 | intel_sdvo_set_target_input(output, true, false); | ||
| 1021 | |||
| 1022 | |||
| 1023 | success = intel_sdvo_create_preferred_input_timing( | ||
| 1024 | output, | ||
| 1025 | mode->clock / 10, | ||
| 1026 | mode->hdisplay, | ||
| 1027 | mode->vdisplay); | ||
| 1028 | |||
| 1029 | if (success) { | ||
| 1030 | struct intel_sdvo_dtd input_dtd; | ||
| 1031 | |||
| 1032 | intel_sdvo_get_preferred_input_timing(output, | ||
| 1033 | &input_dtd); | ||
| 1034 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | ||
| 1035 | dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
| 983 | 1036 | ||
| 984 | drm_mode_set_crtcinfo(adjusted_mode, 0); | 1037 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
| 985 | 1038 | ||
| @@ -990,6 +1043,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 990 | } else { | 1043 | } else { |
| 991 | return false; | 1044 | return false; |
| 992 | } | 1045 | } |
| 1046 | |||
| 1047 | } else { | ||
| 1048 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | ||
| 1049 | * SDVO device will be told of the multiplier during mode_set. | ||
| 1050 | */ | ||
| 1051 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
| 993 | } | 1052 | } |
| 994 | return true; | 1053 | return true; |
| 995 | } | 1054 | } |
| @@ -1033,15 +1092,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1033 | 1092 | ||
| 1034 | /* We have tried to get input timing in mode_fixup, and filled into | 1093 | /* We have tried to get input timing in mode_fixup, and filled into |
| 1035 | adjusted_mode */ | 1094 | adjusted_mode */ |
| 1036 | if (sdvo_priv->is_tv) | 1095 | if (sdvo_priv->is_tv || sdvo_priv->is_lvds) { |
| 1037 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | 1096 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); |
| 1038 | else | 1097 | input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags; |
| 1098 | } else | ||
| 1039 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); | 1099 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); |
| 1040 | 1100 | ||
| 1041 | /* If it's a TV, we already set the output timing in mode_fixup. | 1101 | /* If it's a TV, we already set the output timing in mode_fixup. |
| 1042 | * Otherwise, the output timing is equal to the input timing. | 1102 | * Otherwise, the output timing is equal to the input timing. |
| 1043 | */ | 1103 | */ |
| 1044 | if (!sdvo_priv->is_tv) { | 1104 | if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) { |
| 1045 | /* Set the output timing to the screen */ | 1105 | /* Set the output timing to the screen */ |
| 1046 | intel_sdvo_set_target_output(output, | 1106 | intel_sdvo_set_target_output(output, |
| 1047 | sdvo_priv->controlled_output); | 1107 | sdvo_priv->controlled_output); |
| @@ -1116,6 +1176,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1116 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; | 1176 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; |
| 1117 | } | 1177 | } |
| 1118 | 1178 | ||
| 1179 | if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL) | ||
| 1180 | sdvox |= SDVO_STALL_SELECT; | ||
| 1119 | intel_sdvo_write_sdvox(output, sdvox); | 1181 | intel_sdvo_write_sdvox(output, sdvox); |
| 1120 | } | 1182 | } |
| 1121 | 1183 | ||
| @@ -1276,6 +1338,17 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, | |||
| 1276 | if (sdvo_priv->pixel_clock_max < mode->clock) | 1338 | if (sdvo_priv->pixel_clock_max < mode->clock) |
| 1277 | return MODE_CLOCK_HIGH; | 1339 | return MODE_CLOCK_HIGH; |
| 1278 | 1340 | ||
| 1341 | if (sdvo_priv->is_lvds == true) { | ||
| 1342 | if (sdvo_priv->sdvo_lvds_fixed_mode == NULL) | ||
| 1343 | return MODE_PANEL; | ||
| 1344 | |||
| 1345 | if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay) | ||
| 1346 | return MODE_PANEL; | ||
| 1347 | |||
| 1348 | if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay) | ||
| 1349 | return MODE_PANEL; | ||
| 1350 | } | ||
| 1351 | |||
| 1279 | return MODE_OK; | 1352 | return MODE_OK; |
| 1280 | } | 1353 | } |
| 1281 | 1354 | ||
| @@ -1549,6 +1622,8 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1549 | { | 1622 | { |
| 1550 | struct intel_output *intel_output = to_intel_output(connector); | 1623 | struct intel_output *intel_output = to_intel_output(connector); |
| 1551 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1624 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
| 1625 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1626 | struct drm_display_mode *newmode; | ||
| 1552 | 1627 | ||
| 1553 | /* | 1628 | /* |
| 1554 | * Attempt to get the mode list from DDC. | 1629 | * Attempt to get the mode list from DDC. |
| @@ -1557,11 +1632,10 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1557 | */ | 1632 | */ |
| 1558 | intel_ddc_get_modes(intel_output); | 1633 | intel_ddc_get_modes(intel_output); |
| 1559 | if (list_empty(&connector->probed_modes) == false) | 1634 | if (list_empty(&connector->probed_modes) == false) |
| 1560 | return; | 1635 | goto end; |
| 1561 | 1636 | ||
| 1562 | /* Fetch modes from VBT */ | 1637 | /* Fetch modes from VBT */ |
| 1563 | if (dev_priv->sdvo_lvds_vbt_mode != NULL) { | 1638 | if (dev_priv->sdvo_lvds_vbt_mode != NULL) { |
| 1564 | struct drm_display_mode *newmode; | ||
| 1565 | newmode = drm_mode_duplicate(connector->dev, | 1639 | newmode = drm_mode_duplicate(connector->dev, |
| 1566 | dev_priv->sdvo_lvds_vbt_mode); | 1640 | dev_priv->sdvo_lvds_vbt_mode); |
| 1567 | if (newmode != NULL) { | 1641 | if (newmode != NULL) { |
| @@ -1571,6 +1645,16 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1571 | drm_mode_probed_add(connector, newmode); | 1645 | drm_mode_probed_add(connector, newmode); |
| 1572 | } | 1646 | } |
| 1573 | } | 1647 | } |
| 1648 | |||
| 1649 | end: | ||
| 1650 | list_for_each_entry(newmode, &connector->probed_modes, head) { | ||
| 1651 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | ||
| 1652 | sdvo_priv->sdvo_lvds_fixed_mode = | ||
| 1653 | drm_mode_duplicate(connector->dev, newmode); | ||
| 1654 | break; | ||
| 1655 | } | ||
| 1656 | } | ||
| 1657 | |||
| 1574 | } | 1658 | } |
| 1575 | 1659 | ||
| 1576 | static int intel_sdvo_get_modes(struct drm_connector *connector) | 1660 | static int intel_sdvo_get_modes(struct drm_connector *connector) |
| @@ -1593,14 +1677,20 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) | |||
| 1593 | static void intel_sdvo_destroy(struct drm_connector *connector) | 1677 | static void intel_sdvo_destroy(struct drm_connector *connector) |
| 1594 | { | 1678 | { |
| 1595 | struct intel_output *intel_output = to_intel_output(connector); | 1679 | struct intel_output *intel_output = to_intel_output(connector); |
| 1680 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1596 | 1681 | ||
| 1597 | if (intel_output->i2c_bus) | 1682 | if (intel_output->i2c_bus) |
| 1598 | intel_i2c_destroy(intel_output->i2c_bus); | 1683 | intel_i2c_destroy(intel_output->i2c_bus); |
| 1599 | if (intel_output->ddc_bus) | 1684 | if (intel_output->ddc_bus) |
| 1600 | intel_i2c_destroy(intel_output->ddc_bus); | 1685 | intel_i2c_destroy(intel_output->ddc_bus); |
| 1601 | 1686 | ||
| 1687 | if (sdvo_priv->sdvo_lvds_fixed_mode != NULL) | ||
| 1688 | drm_mode_destroy(connector->dev, | ||
| 1689 | sdvo_priv->sdvo_lvds_fixed_mode); | ||
| 1690 | |||
| 1602 | drm_sysfs_connector_remove(connector); | 1691 | drm_sysfs_connector_remove(connector); |
| 1603 | drm_connector_cleanup(connector); | 1692 | drm_connector_cleanup(connector); |
| 1693 | |||
| 1604 | kfree(intel_output); | 1694 | kfree(intel_output); |
| 1605 | } | 1695 | } |
| 1606 | 1696 | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 193938b7d7f9..ba5cdf8ae40b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h | |||
| @@ -715,6 +715,7 @@ struct intel_sdvo_enhancements_arg { | |||
| 715 | #define SDVO_HBUF_TX_ONCE (2 << 6) | 715 | #define SDVO_HBUF_TX_ONCE (2 << 6) |
| 716 | #define SDVO_HBUF_TX_VSYNC (3 << 6) | 716 | #define SDVO_HBUF_TX_VSYNC (3 << 6) |
| 717 | #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c | 717 | #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c |
| 718 | #define SDVO_NEED_TO_STALL (1 << 7) | ||
| 718 | 719 | ||
| 719 | struct intel_sdvo_encode{ | 720 | struct intel_sdvo_encode{ |
| 720 | u8 dvi_rev; | 721 | u8 dvi_rev; |
