diff options
author | Dave Airlie <airlied@redhat.com> | 2012-02-07 10:29:04 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-02-07 10:29:04 -0500 |
commit | 198ceac091049003ffcc4b7cda76785510fc3b59 (patch) | |
tree | c38ebdd90a52bae47a1811ab879f2108ad728670 /drivers/gpu/drm/i915 | |
parent | 83b316fdafcc37e3e65b4a650afb7aab5cc2d271 (diff) | |
parent | 3d29b842e58fbca2c13a9f458fddbaa535c6e578 (diff) |
Merge branch 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel into drm-core-next
* 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel:
drm/i915: add a LLC feature flag in device description
drm/i915: kill i915_mem.c
drm/i915: Use kcalloc instead of kzalloc to allocate array
drm/i915/dp: Check for AUXCH error before checking for success
drm/i915/dp: Use auxch precharge value of 5 everywhere
drm/i915/dp: Tweak auxch clock divider for PCH
drm/i915: Remove a comment about PCH from the non-PCH path
drm/i915: Fix assert_pch_hdmi_disabled to mention HDMI (not DP)
drm/i915: Implement plane-disabled assertion for PCH too
drivers: i915: Fix BLC PWM register setup
drm/i915: Check that plane/pipe is disabled before removing the fb
drm/i915: fix typo in function name
drm/i915: split out pll divider code
drm/i915: split 9xx refclk & sdvo tv code out
agp/intel: Add pci id for hostbridge from has/qemu
drm/i915: there is no pipe CxSR on ironlake
drm/i915: Only look for matching clocks for LVDS downclock
drm/i915: Silence _DSM errors
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_mem.c | 387 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_acpi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 239 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 4 |
12 files changed, 176 insertions, 518 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 808b255d7fc6..ce7fc77678b4 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
4 | 4 | ||
5 | ccflags-y := -Iinclude/drm | 5 | ccflags-y := -Iinclude/drm |
6 | i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | 6 | i915-y := i915_drv.o i915_dma.o i915_irq.o \ |
7 | i915_debugfs.o \ | 7 | i915_debugfs.o \ |
8 | i915_suspend.o \ | 8 | i915_suspend.o \ |
9 | i915_gem.o \ | 9 | i915_gem.o \ |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index deaa657292b4..9717bf42f846 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -83,6 +83,7 @@ static int i915_capabilities(struct seq_file *m, void *data) | |||
83 | B(supports_tv); | 83 | B(supports_tv); |
84 | B(has_bsd_ring); | 84 | B(has_bsd_ring); |
85 | B(has_blt_ring); | 85 | B(has_blt_ring); |
86 | B(has_llc); | ||
86 | #undef B | 87 | #undef B |
87 | 88 | ||
88 | return 0; | 89 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ddfe3d902b2a..448848cbc1db 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -784,6 +784,9 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
784 | case I915_PARAM_HAS_GEN7_SOL_RESET: | 784 | case I915_PARAM_HAS_GEN7_SOL_RESET: |
785 | value = 1; | 785 | value = 1; |
786 | break; | 786 | break; |
787 | case I915_PARAM_HAS_LLC: | ||
788 | value = HAS_LLC(dev); | ||
789 | break; | ||
787 | default: | 790 | default: |
788 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", | 791 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", |
789 | param->param); | 792 | param->param); |
@@ -2247,18 +2250,12 @@ void i915_driver_lastclose(struct drm_device * dev) | |||
2247 | 2250 | ||
2248 | i915_gem_lastclose(dev); | 2251 | i915_gem_lastclose(dev); |
2249 | 2252 | ||
2250 | if (dev_priv->agp_heap) | ||
2251 | i915_mem_takedown(&(dev_priv->agp_heap)); | ||
2252 | |||
2253 | i915_dma_cleanup(dev); | 2253 | i915_dma_cleanup(dev); |
2254 | } | 2254 | } |
2255 | 2255 | ||
2256 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) | 2256 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) |
2257 | { | 2257 | { |
2258 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
2259 | i915_gem_release(dev, file_priv); | 2258 | i915_gem_release(dev, file_priv); |
2260 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
2261 | i915_mem_release(dev, file_priv, dev_priv->agp_heap); | ||
2262 | } | 2259 | } |
2263 | 2260 | ||
2264 | void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) | 2261 | void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) |
@@ -2277,11 +2274,11 @@ struct drm_ioctl_desc i915_ioctls[] = { | |||
2277 | DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), | 2274 | DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), |
2278 | DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH), | 2275 | DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH), |
2279 | DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 2276 | DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
2280 | DRM_IOCTL_DEF_DRV(I915_ALLOC, i915_mem_alloc, DRM_AUTH), | 2277 | DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH), |
2281 | DRM_IOCTL_DEF_DRV(I915_FREE, i915_mem_free, DRM_AUTH), | 2278 | DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH), |
2282 | DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 2279 | DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
2283 | DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), | 2280 | DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), |
2284 | DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 2281 | DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
2285 | DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 2282 | DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
2286 | DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH), | 2283 | DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH), |
2287 | DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), | 2284 | DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 308f81913562..3d92d822c395 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -198,7 +198,7 @@ static const struct intel_device_info intel_pineview_info = { | |||
198 | 198 | ||
199 | static const struct intel_device_info intel_ironlake_d_info = { | 199 | static const struct intel_device_info intel_ironlake_d_info = { |
200 | .gen = 5, | 200 | .gen = 5, |
201 | .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, | 201 | .need_gfx_hws = 1, .has_hotplug = 1, |
202 | .has_bsd_ring = 1, | 202 | .has_bsd_ring = 1, |
203 | }; | 203 | }; |
204 | 204 | ||
@@ -214,6 +214,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { | |||
214 | .need_gfx_hws = 1, .has_hotplug = 1, | 214 | .need_gfx_hws = 1, .has_hotplug = 1, |
215 | .has_bsd_ring = 1, | 215 | .has_bsd_ring = 1, |
216 | .has_blt_ring = 1, | 216 | .has_blt_ring = 1, |
217 | .has_llc = 1, | ||
217 | }; | 218 | }; |
218 | 219 | ||
219 | static const struct intel_device_info intel_sandybridge_m_info = { | 220 | static const struct intel_device_info intel_sandybridge_m_info = { |
@@ -222,6 +223,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { | |||
222 | .has_fbc = 1, | 223 | .has_fbc = 1, |
223 | .has_bsd_ring = 1, | 224 | .has_bsd_ring = 1, |
224 | .has_blt_ring = 1, | 225 | .has_blt_ring = 1, |
226 | .has_llc = 1, | ||
225 | }; | 227 | }; |
226 | 228 | ||
227 | static const struct intel_device_info intel_ivybridge_d_info = { | 229 | static const struct intel_device_info intel_ivybridge_d_info = { |
@@ -229,6 +231,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { | |||
229 | .need_gfx_hws = 1, .has_hotplug = 1, | 231 | .need_gfx_hws = 1, .has_hotplug = 1, |
230 | .has_bsd_ring = 1, | 232 | .has_bsd_ring = 1, |
231 | .has_blt_ring = 1, | 233 | .has_blt_ring = 1, |
234 | .has_llc = 1, | ||
232 | }; | 235 | }; |
233 | 236 | ||
234 | static const struct intel_device_info intel_ivybridge_m_info = { | 237 | static const struct intel_device_info intel_ivybridge_m_info = { |
@@ -237,6 +240,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { | |||
237 | .has_fbc = 0, /* FBC is not enabled on Ivybridge mobile yet */ | 240 | .has_fbc = 0, /* FBC is not enabled on Ivybridge mobile yet */ |
238 | .has_bsd_ring = 1, | 241 | .has_bsd_ring = 1, |
239 | .has_blt_ring = 1, | 242 | .has_blt_ring = 1, |
243 | .has_llc = 1, | ||
240 | }; | 244 | }; |
241 | 245 | ||
242 | static const struct pci_device_id pciidlist[] = { /* aka */ | 246 | static const struct pci_device_id pciidlist[] = { /* aka */ |
@@ -633,7 +637,7 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags) | |||
633 | } | 637 | } |
634 | 638 | ||
635 | /** | 639 | /** |
636 | * i965_reset - reset chip after a hang | 640 | * i915_reset - reset chip after a hang |
637 | * @dev: drm device to reset | 641 | * @dev: drm device to reset |
638 | * @flags: reset domains | 642 | * @flags: reset domains |
639 | * | 643 | * |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9689ca38b2b3..32737a37edd0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -255,6 +255,7 @@ struct intel_device_info { | |||
255 | u8 supports_tv:1; | 255 | u8 supports_tv:1; |
256 | u8 has_bsd_ring:1; | 256 | u8 has_bsd_ring:1; |
257 | u8 has_blt_ring:1; | 257 | u8 has_blt_ring:1; |
258 | u8 has_llc:1; | ||
258 | }; | 259 | }; |
259 | 260 | ||
260 | enum no_fbc_reason { | 261 | enum no_fbc_reason { |
@@ -335,7 +336,6 @@ typedef struct drm_i915_private { | |||
335 | 336 | ||
336 | int tex_lru_log_granularity; | 337 | int tex_lru_log_granularity; |
337 | int allow_batchbuffer; | 338 | int allow_batchbuffer; |
338 | struct mem_block *agp_heap; | ||
339 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; | 339 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; |
340 | int vblank_pipe; | 340 | int vblank_pipe; |
341 | int num_pipe; | 341 | int num_pipe; |
@@ -974,6 +974,7 @@ struct drm_i915_file_private { | |||
974 | 974 | ||
975 | #define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) | 975 | #define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) |
976 | #define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) | 976 | #define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) |
977 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) | ||
977 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) | 978 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) |
978 | 979 | ||
979 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) | 980 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) |
@@ -1079,18 +1080,6 @@ extern void i915_destroy_error_state(struct drm_device *dev); | |||
1079 | #endif | 1080 | #endif |
1080 | 1081 | ||
1081 | 1082 | ||
1082 | /* i915_mem.c */ | ||
1083 | extern int i915_mem_alloc(struct drm_device *dev, void *data, | ||
1084 | struct drm_file *file_priv); | ||
1085 | extern int i915_mem_free(struct drm_device *dev, void *data, | ||
1086 | struct drm_file *file_priv); | ||
1087 | extern int i915_mem_init_heap(struct drm_device *dev, void *data, | ||
1088 | struct drm_file *file_priv); | ||
1089 | extern int i915_mem_destroy_heap(struct drm_device *dev, void *data, | ||
1090 | struct drm_file *file_priv); | ||
1091 | extern void i915_mem_takedown(struct mem_block **heap); | ||
1092 | extern void i915_mem_release(struct drm_device * dev, | ||
1093 | struct drm_file *file_priv, struct mem_block *heap); | ||
1094 | /* i915_gem.c */ | 1083 | /* i915_gem.c */ |
1095 | int i915_gem_init_ioctl(struct drm_device *dev, void *data, | 1084 | int i915_gem_init_ioctl(struct drm_device *dev, void *data, |
1096 | struct drm_file *file_priv); | 1085 | struct drm_file *file_priv); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e55badb2d86d..eb98a7f55cfe 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3619,8 +3619,8 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, | |||
3619 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; | 3619 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; |
3620 | obj->base.read_domains = I915_GEM_DOMAIN_CPU; | 3620 | obj->base.read_domains = I915_GEM_DOMAIN_CPU; |
3621 | 3621 | ||
3622 | if (IS_GEN6(dev) || IS_GEN7(dev)) { | 3622 | if (HAS_LLC(dev)) { |
3623 | /* On Gen6, we can have the GPU use the LLC (the CPU | 3623 | /* On some devices, we can have the GPU use the LLC (the CPU |
3624 | * cache) for about a 10% performance improvement | 3624 | * cache) for about a 10% performance improvement |
3625 | * compared to uncached. Graphics requests other than | 3625 | * compared to uncached. Graphics requests other than |
3626 | * display scanout are coherent with the CPU in | 3626 | * display scanout are coherent with the CPU in |
diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c deleted file mode 100644 index cc8f6d49cf20..000000000000 --- a/drivers/gpu/drm/i915/i915_mem.c +++ /dev/null | |||
@@ -1,387 +0,0 @@ | |||
1 | /* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- | ||
2 | */ | ||
3 | /* | ||
4 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||
5 | * All Rights Reserved. | ||
6 | * | ||
7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
8 | * copy of this software and associated documentation files (the | ||
9 | * "Software"), to deal in the Software without restriction, including | ||
10 | * without limitation the rights to use, copy, modify, merge, publish, | ||
11 | * distribute, sub license, and/or sell copies of the Software, and to | ||
12 | * permit persons to whom the Software is furnished to do so, subject to | ||
13 | * the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the | ||
16 | * next paragraph) shall be included in all copies or substantial portions | ||
17 | * of the Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||
22 | * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||
23 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
24 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
25 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include "drmP.h" | ||
30 | #include "drm.h" | ||
31 | #include "i915_drm.h" | ||
32 | #include "i915_drv.h" | ||
33 | |||
34 | /* This memory manager is integrated into the global/local lru | ||
35 | * mechanisms used by the clients. Specifically, it operates by | ||
36 | * setting the 'in_use' fields of the global LRU to indicate whether | ||
37 | * this region is privately allocated to a client. | ||
38 | * | ||
39 | * This does require the client to actually respect that field. | ||
40 | * | ||
41 | * Currently no effort is made to allocate 'private' memory in any | ||
42 | * clever way - the LRU information isn't used to determine which | ||
43 | * block to allocate, and the ring is drained prior to allocations -- | ||
44 | * in other words allocation is expensive. | ||
45 | */ | ||
46 | static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) | ||
47 | { | ||
48 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
49 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; | ||
50 | drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv; | ||
51 | struct drm_tex_region *list; | ||
52 | unsigned shift, nr; | ||
53 | unsigned start; | ||
54 | unsigned end; | ||
55 | unsigned i; | ||
56 | int age; | ||
57 | |||
58 | shift = dev_priv->tex_lru_log_granularity; | ||
59 | nr = I915_NR_TEX_REGIONS; | ||
60 | |||
61 | start = p->start >> shift; | ||
62 | end = (p->start + p->size - 1) >> shift; | ||
63 | |||
64 | age = ++sarea_priv->texAge; | ||
65 | list = sarea_priv->texList; | ||
66 | |||
67 | /* Mark the regions with the new flag and update their age. Move | ||
68 | * them to head of list to preserve LRU semantics. | ||
69 | */ | ||
70 | for (i = start; i <= end; i++) { | ||
71 | list[i].in_use = in_use; | ||
72 | list[i].age = age; | ||
73 | |||
74 | /* remove_from_list(i) | ||
75 | */ | ||
76 | list[(unsigned)list[i].next].prev = list[i].prev; | ||
77 | list[(unsigned)list[i].prev].next = list[i].next; | ||
78 | |||
79 | /* insert_at_head(list, i) | ||
80 | */ | ||
81 | list[i].prev = nr; | ||
82 | list[i].next = list[nr].next; | ||
83 | list[(unsigned)list[nr].next].prev = i; | ||
84 | list[nr].next = i; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | /* Very simple allocator for agp memory, working on a static range | ||
89 | * already mapped into each client's address space. | ||
90 | */ | ||
91 | |||
92 | static struct mem_block *split_block(struct mem_block *p, int start, int size, | ||
93 | struct drm_file *file_priv) | ||
94 | { | ||
95 | /* Maybe cut off the start of an existing block */ | ||
96 | if (start > p->start) { | ||
97 | struct mem_block *newblock = kmalloc(sizeof(*newblock), | ||
98 | GFP_KERNEL); | ||
99 | if (!newblock) | ||
100 | goto out; | ||
101 | newblock->start = start; | ||
102 | newblock->size = p->size - (start - p->start); | ||
103 | newblock->file_priv = NULL; | ||
104 | newblock->next = p->next; | ||
105 | newblock->prev = p; | ||
106 | p->next->prev = newblock; | ||
107 | p->next = newblock; | ||
108 | p->size -= newblock->size; | ||
109 | p = newblock; | ||
110 | } | ||
111 | |||
112 | /* Maybe cut off the end of an existing block */ | ||
113 | if (size < p->size) { | ||
114 | struct mem_block *newblock = kmalloc(sizeof(*newblock), | ||
115 | GFP_KERNEL); | ||
116 | if (!newblock) | ||
117 | goto out; | ||
118 | newblock->start = start + size; | ||
119 | newblock->size = p->size - size; | ||
120 | newblock->file_priv = NULL; | ||
121 | newblock->next = p->next; | ||
122 | newblock->prev = p; | ||
123 | p->next->prev = newblock; | ||
124 | p->next = newblock; | ||
125 | p->size = size; | ||
126 | } | ||
127 | |||
128 | out: | ||
129 | /* Our block is in the middle */ | ||
130 | p->file_priv = file_priv; | ||
131 | return p; | ||
132 | } | ||
133 | |||
134 | static struct mem_block *alloc_block(struct mem_block *heap, int size, | ||
135 | int align2, struct drm_file *file_priv) | ||
136 | { | ||
137 | struct mem_block *p; | ||
138 | int mask = (1 << align2) - 1; | ||
139 | |||
140 | for (p = heap->next; p != heap; p = p->next) { | ||
141 | int start = (p->start + mask) & ~mask; | ||
142 | if (p->file_priv == NULL && start + size <= p->start + p->size) | ||
143 | return split_block(p, start, size, file_priv); | ||
144 | } | ||
145 | |||
146 | return NULL; | ||
147 | } | ||
148 | |||
149 | static struct mem_block *find_block(struct mem_block *heap, int start) | ||
150 | { | ||
151 | struct mem_block *p; | ||
152 | |||
153 | for (p = heap->next; p != heap; p = p->next) | ||
154 | if (p->start == start) | ||
155 | return p; | ||
156 | |||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | static void free_block(struct mem_block *p) | ||
161 | { | ||
162 | p->file_priv = NULL; | ||
163 | |||
164 | /* Assumes a single contiguous range. Needs a special file_priv in | ||
165 | * 'heap' to stop it being subsumed. | ||
166 | */ | ||
167 | if (p->next->file_priv == NULL) { | ||
168 | struct mem_block *q = p->next; | ||
169 | p->size += q->size; | ||
170 | p->next = q->next; | ||
171 | p->next->prev = p; | ||
172 | kfree(q); | ||
173 | } | ||
174 | |||
175 | if (p->prev->file_priv == NULL) { | ||
176 | struct mem_block *q = p->prev; | ||
177 | q->size += p->size; | ||
178 | q->next = p->next; | ||
179 | q->next->prev = q; | ||
180 | kfree(p); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /* Initialize. How to check for an uninitialized heap? | ||
185 | */ | ||
186 | static int init_heap(struct mem_block **heap, int start, int size) | ||
187 | { | ||
188 | struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); | ||
189 | |||
190 | if (!blocks) | ||
191 | return -ENOMEM; | ||
192 | |||
193 | *heap = kmalloc(sizeof(**heap), GFP_KERNEL); | ||
194 | if (!*heap) { | ||
195 | kfree(blocks); | ||
196 | return -ENOMEM; | ||
197 | } | ||
198 | |||
199 | blocks->start = start; | ||
200 | blocks->size = size; | ||
201 | blocks->file_priv = NULL; | ||
202 | blocks->next = blocks->prev = *heap; | ||
203 | |||
204 | memset(*heap, 0, sizeof(**heap)); | ||
205 | (*heap)->file_priv = (struct drm_file *) -1; | ||
206 | (*heap)->next = (*heap)->prev = blocks; | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | /* Free all blocks associated with the releasing file. | ||
211 | */ | ||
212 | void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv, | ||
213 | struct mem_block *heap) | ||
214 | { | ||
215 | struct mem_block *p; | ||
216 | |||
217 | if (!heap || !heap->next) | ||
218 | return; | ||
219 | |||
220 | for (p = heap->next; p != heap; p = p->next) { | ||
221 | if (p->file_priv == file_priv) { | ||
222 | p->file_priv = NULL; | ||
223 | mark_block(dev, p, 0); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /* Assumes a single contiguous range. Needs a special file_priv in | ||
228 | * 'heap' to stop it being subsumed. | ||
229 | */ | ||
230 | for (p = heap->next; p != heap; p = p->next) { | ||
231 | while (p->file_priv == NULL && p->next->file_priv == NULL) { | ||
232 | struct mem_block *q = p->next; | ||
233 | p->size += q->size; | ||
234 | p->next = q->next; | ||
235 | p->next->prev = p; | ||
236 | kfree(q); | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /* Shutdown. | ||
242 | */ | ||
243 | void i915_mem_takedown(struct mem_block **heap) | ||
244 | { | ||
245 | struct mem_block *p; | ||
246 | |||
247 | if (!*heap) | ||
248 | return; | ||
249 | |||
250 | for (p = (*heap)->next; p != *heap;) { | ||
251 | struct mem_block *q = p; | ||
252 | p = p->next; | ||
253 | kfree(q); | ||
254 | } | ||
255 | |||
256 | kfree(*heap); | ||
257 | *heap = NULL; | ||
258 | } | ||
259 | |||
260 | static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) | ||
261 | { | ||
262 | switch (region) { | ||
263 | case I915_MEM_REGION_AGP: | ||
264 | return &dev_priv->agp_heap; | ||
265 | default: | ||
266 | return NULL; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /* IOCTL HANDLERS */ | ||
271 | |||
272 | int i915_mem_alloc(struct drm_device *dev, void *data, | ||
273 | struct drm_file *file_priv) | ||
274 | { | ||
275 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
276 | drm_i915_mem_alloc_t *alloc = data; | ||
277 | struct mem_block *block, **heap; | ||
278 | |||
279 | if (!dev_priv) { | ||
280 | DRM_ERROR("called with no initialization\n"); | ||
281 | return -EINVAL; | ||
282 | } | ||
283 | |||
284 | heap = get_heap(dev_priv, alloc->region); | ||
285 | if (!heap || !*heap) | ||
286 | return -EFAULT; | ||
287 | |||
288 | /* Make things easier on ourselves: all allocations at least | ||
289 | * 4k aligned. | ||
290 | */ | ||
291 | if (alloc->alignment < 12) | ||
292 | alloc->alignment = 12; | ||
293 | |||
294 | block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); | ||
295 | |||
296 | if (!block) | ||
297 | return -ENOMEM; | ||
298 | |||
299 | mark_block(dev, block, 1); | ||
300 | |||
301 | if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, | ||
302 | sizeof(int))) { | ||
303 | DRM_ERROR("copy_to_user\n"); | ||
304 | return -EFAULT; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | int i915_mem_free(struct drm_device *dev, void *data, | ||
311 | struct drm_file *file_priv) | ||
312 | { | ||
313 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
314 | drm_i915_mem_free_t *memfree = data; | ||
315 | struct mem_block *block, **heap; | ||
316 | |||
317 | if (!dev_priv) { | ||
318 | DRM_ERROR("called with no initialization\n"); | ||
319 | return -EINVAL; | ||
320 | } | ||
321 | |||
322 | heap = get_heap(dev_priv, memfree->region); | ||
323 | if (!heap || !*heap) | ||
324 | return -EFAULT; | ||
325 | |||
326 | block = find_block(*heap, memfree->region_offset); | ||
327 | if (!block) | ||
328 | return -EFAULT; | ||
329 | |||
330 | if (block->file_priv != file_priv) | ||
331 | return -EPERM; | ||
332 | |||
333 | mark_block(dev, block, 0); | ||
334 | free_block(block); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int i915_mem_init_heap(struct drm_device *dev, void *data, | ||
339 | struct drm_file *file_priv) | ||
340 | { | ||
341 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
342 | drm_i915_mem_init_heap_t *initheap = data; | ||
343 | struct mem_block **heap; | ||
344 | |||
345 | if (!dev_priv) { | ||
346 | DRM_ERROR("called with no initialization\n"); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
350 | heap = get_heap(dev_priv, initheap->region); | ||
351 | if (!heap) | ||
352 | return -EFAULT; | ||
353 | |||
354 | if (*heap) { | ||
355 | DRM_ERROR("heap already initialized?"); | ||
356 | return -EFAULT; | ||
357 | } | ||
358 | |||
359 | return init_heap(heap, initheap->start, initheap->size); | ||
360 | } | ||
361 | |||
362 | int i915_mem_destroy_heap(struct drm_device *dev, void *data, | ||
363 | struct drm_file *file_priv) | ||
364 | { | ||
365 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
366 | drm_i915_mem_destroy_heap_t *destroyheap = data; | ||
367 | struct mem_block **heap; | ||
368 | |||
369 | if (!dev_priv) { | ||
370 | DRM_ERROR("called with no initialization\n"); | ||
371 | return -EINVAL; | ||
372 | } | ||
373 | |||
374 | heap = get_heap(dev_priv, destroyheap->region); | ||
375 | if (!heap) { | ||
376 | DRM_ERROR("get_heap failed"); | ||
377 | return -EFAULT; | ||
378 | } | ||
379 | |||
380 | if (!*heap) { | ||
381 | DRM_ERROR("heap not initialized?"); | ||
382 | return -EFAULT; | ||
383 | } | ||
384 | |||
385 | i915_mem_takedown(heap); | ||
386 | return 0; | ||
387 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index cb912106d1a2..bae3edf956a4 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c | |||
@@ -208,7 +208,7 @@ static bool intel_dsm_pci_probe(struct pci_dev *pdev) | |||
208 | 208 | ||
209 | ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0); | 209 | ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0); |
210 | if (ret < 0) { | 210 | if (ret < 0) { |
211 | DRM_ERROR("failed to get supported _DSM functions\n"); | 211 | DRM_DEBUG_KMS("failed to get supported _DSM functions\n"); |
212 | return false; | 212 | return false; |
213 | } | 213 | } |
214 | 214 | ||
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 63880e2e5cfd..50656339d922 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -572,7 +572,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
572 | DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); | 572 | DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); |
573 | return; | 573 | return; |
574 | } | 574 | } |
575 | dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); | 575 | dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); |
576 | if (!dev_priv->child_dev) { | 576 | if (!dev_priv->child_dev) { |
577 | DRM_DEBUG_KMS("No memory space for child device\n"); | 577 | DRM_DEBUG_KMS("No memory space for child device\n"); |
578 | return; | 578 | return; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b3b51c43dad0..5ba19df199e4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -75,7 +75,7 @@ struct intel_limit { | |||
75 | intel_range_t dot, vco, n, m, m1, m2, p, p1; | 75 | intel_range_t dot, vco, n, m, m1, m2, p, p1; |
76 | intel_p2_t p2; | 76 | intel_p2_t p2; |
77 | bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, | 77 | bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, |
78 | int, int, intel_clock_t *); | 78 | int, int, intel_clock_t *, intel_clock_t *); |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* FDI */ | 81 | /* FDI */ |
@@ -83,17 +83,21 @@ struct intel_limit { | |||
83 | 83 | ||
84 | static bool | 84 | static bool |
85 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 85 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
86 | int target, int refclk, intel_clock_t *best_clock); | 86 | int target, int refclk, intel_clock_t *match_clock, |
87 | intel_clock_t *best_clock); | ||
87 | static bool | 88 | static bool |
88 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 89 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
89 | int target, int refclk, intel_clock_t *best_clock); | 90 | int target, int refclk, intel_clock_t *match_clock, |
91 | intel_clock_t *best_clock); | ||
90 | 92 | ||
91 | static bool | 93 | static bool |
92 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, | 94 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
93 | int target, int refclk, intel_clock_t *best_clock); | 95 | int target, int refclk, intel_clock_t *match_clock, |
96 | intel_clock_t *best_clock); | ||
94 | static bool | 97 | static bool |
95 | intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, | 98 | intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, |
96 | int target, int refclk, intel_clock_t *best_clock); | 99 | int target, int refclk, intel_clock_t *match_clock, |
100 | intel_clock_t *best_clock); | ||
97 | 101 | ||
98 | static inline u32 /* units of 100MHz */ | 102 | static inline u32 /* units of 100MHz */ |
99 | intel_fdi_link_freq(struct drm_device *dev) | 103 | intel_fdi_link_freq(struct drm_device *dev) |
@@ -515,7 +519,8 @@ static bool intel_PLL_is_valid(struct drm_device *dev, | |||
515 | 519 | ||
516 | static bool | 520 | static bool |
517 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 521 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
518 | int target, int refclk, intel_clock_t *best_clock) | 522 | int target, int refclk, intel_clock_t *match_clock, |
523 | intel_clock_t *best_clock) | ||
519 | 524 | ||
520 | { | 525 | { |
521 | struct drm_device *dev = crtc->dev; | 526 | struct drm_device *dev = crtc->dev; |
@@ -562,6 +567,9 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
562 | if (!intel_PLL_is_valid(dev, limit, | 567 | if (!intel_PLL_is_valid(dev, limit, |
563 | &clock)) | 568 | &clock)) |
564 | continue; | 569 | continue; |
570 | if (match_clock && | ||
571 | clock.p != match_clock->p) | ||
572 | continue; | ||
565 | 573 | ||
566 | this_err = abs(clock.dot - target); | 574 | this_err = abs(clock.dot - target); |
567 | if (this_err < err) { | 575 | if (this_err < err) { |
@@ -578,7 +586,8 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
578 | 586 | ||
579 | static bool | 587 | static bool |
580 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 588 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
581 | int target, int refclk, intel_clock_t *best_clock) | 589 | int target, int refclk, intel_clock_t *match_clock, |
590 | intel_clock_t *best_clock) | ||
582 | { | 591 | { |
583 | struct drm_device *dev = crtc->dev; | 592 | struct drm_device *dev = crtc->dev; |
584 | struct drm_i915_private *dev_priv = dev->dev_private; | 593 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -625,6 +634,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
625 | if (!intel_PLL_is_valid(dev, limit, | 634 | if (!intel_PLL_is_valid(dev, limit, |
626 | &clock)) | 635 | &clock)) |
627 | continue; | 636 | continue; |
637 | if (match_clock && | ||
638 | clock.p != match_clock->p) | ||
639 | continue; | ||
628 | 640 | ||
629 | this_err = abs(clock.dot - target); | 641 | this_err = abs(clock.dot - target); |
630 | if (this_err < err_most) { | 642 | if (this_err < err_most) { |
@@ -642,7 +654,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
642 | 654 | ||
643 | static bool | 655 | static bool |
644 | intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | 656 | intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, |
645 | int target, int refclk, intel_clock_t *best_clock) | 657 | int target, int refclk, intel_clock_t *match_clock, |
658 | intel_clock_t *best_clock) | ||
646 | { | 659 | { |
647 | struct drm_device *dev = crtc->dev; | 660 | struct drm_device *dev = crtc->dev; |
648 | intel_clock_t clock; | 661 | intel_clock_t clock; |
@@ -668,7 +681,8 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
668 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | 681 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ |
669 | static bool | 682 | static bool |
670 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | 683 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, |
671 | int target, int refclk, intel_clock_t *best_clock) | 684 | int target, int refclk, intel_clock_t *match_clock, |
685 | intel_clock_t *best_clock) | ||
672 | { | 686 | { |
673 | intel_clock_t clock; | 687 | intel_clock_t clock; |
674 | if (target < 200000) { | 688 | if (target < 200000) { |
@@ -930,19 +944,24 @@ void assert_pipe(struct drm_i915_private *dev_priv, | |||
930 | pipe_name(pipe), state_string(state), state_string(cur_state)); | 944 | pipe_name(pipe), state_string(state), state_string(cur_state)); |
931 | } | 945 | } |
932 | 946 | ||
933 | static void assert_plane_enabled(struct drm_i915_private *dev_priv, | 947 | static void assert_plane(struct drm_i915_private *dev_priv, |
934 | enum plane plane) | 948 | enum plane plane, bool state) |
935 | { | 949 | { |
936 | int reg; | 950 | int reg; |
937 | u32 val; | 951 | u32 val; |
952 | bool cur_state; | ||
938 | 953 | ||
939 | reg = DSPCNTR(plane); | 954 | reg = DSPCNTR(plane); |
940 | val = I915_READ(reg); | 955 | val = I915_READ(reg); |
941 | WARN(!(val & DISPLAY_PLANE_ENABLE), | 956 | cur_state = !!(val & DISPLAY_PLANE_ENABLE); |
942 | "plane %c assertion failure, should be active but is disabled\n", | 957 | WARN(cur_state != state, |
943 | plane_name(plane)); | 958 | "plane %c assertion failure (expected %s, current %s)\n", |
959 | plane_name(plane), state_string(state), state_string(cur_state)); | ||
944 | } | 960 | } |
945 | 961 | ||
962 | #define assert_plane_enabled(d, p) assert_plane(d, p, true) | ||
963 | #define assert_plane_disabled(d, p) assert_plane(d, p, false) | ||
964 | |||
946 | static void assert_planes_disabled(struct drm_i915_private *dev_priv, | 965 | static void assert_planes_disabled(struct drm_i915_private *dev_priv, |
947 | enum pipe pipe) | 966 | enum pipe pipe) |
948 | { | 967 | { |
@@ -951,8 +970,14 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, | |||
951 | int cur_pipe; | 970 | int cur_pipe; |
952 | 971 | ||
953 | /* Planes are fixed to pipes on ILK+ */ | 972 | /* Planes are fixed to pipes on ILK+ */ |
954 | if (HAS_PCH_SPLIT(dev_priv->dev)) | 973 | if (HAS_PCH_SPLIT(dev_priv->dev)) { |
974 | reg = DSPCNTR(pipe); | ||
975 | val = I915_READ(reg); | ||
976 | WARN((val & DISPLAY_PLANE_ENABLE), | ||
977 | "plane %c assertion failure, should be disabled but not\n", | ||
978 | plane_name(pipe)); | ||
955 | return; | 979 | return; |
980 | } | ||
956 | 981 | ||
957 | /* Need to check both planes against the pipe */ | 982 | /* Need to check both planes against the pipe */ |
958 | for (i = 0; i < 2; i++) { | 983 | for (i = 0; i < 2; i++) { |
@@ -1071,7 +1096,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | |||
1071 | { | 1096 | { |
1072 | u32 val = I915_READ(reg); | 1097 | u32 val = I915_READ(reg); |
1073 | WARN(hdmi_pipe_enabled(dev_priv, val, pipe), | 1098 | WARN(hdmi_pipe_enabled(dev_priv, val, pipe), |
1074 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | 1099 | "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", |
1075 | reg, pipe_name(pipe)); | 1100 | reg, pipe_name(pipe)); |
1076 | } | 1101 | } |
1077 | 1102 | ||
@@ -3321,6 +3346,8 @@ static void intel_crtc_disable(struct drm_crtc *crtc) | |||
3321 | struct drm_device *dev = crtc->dev; | 3346 | struct drm_device *dev = crtc->dev; |
3322 | 3347 | ||
3323 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | 3348 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); |
3349 | assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); | ||
3350 | assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); | ||
3324 | 3351 | ||
3325 | if (crtc->fb) { | 3352 | if (crtc->fb) { |
3326 | mutex_lock(&dev->struct_mutex); | 3353 | mutex_lock(&dev->struct_mutex); |
@@ -4968,6 +4995,82 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
4968 | return display_bpc != bpc; | 4995 | return display_bpc != bpc; |
4969 | } | 4996 | } |
4970 | 4997 | ||
4998 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) | ||
4999 | { | ||
5000 | struct drm_device *dev = crtc->dev; | ||
5001 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
5002 | int refclk; | ||
5003 | |||
5004 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
5005 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { | ||
5006 | refclk = dev_priv->lvds_ssc_freq * 1000; | ||
5007 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | ||
5008 | refclk / 1000); | ||
5009 | } else if (!IS_GEN2(dev)) { | ||
5010 | refclk = 96000; | ||
5011 | } else { | ||
5012 | refclk = 48000; | ||
5013 | } | ||
5014 | |||
5015 | return refclk; | ||
5016 | } | ||
5017 | |||
5018 | static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode, | ||
5019 | intel_clock_t *clock) | ||
5020 | { | ||
5021 | /* SDVO TV has fixed PLL values depend on its clock range, | ||
5022 | this mirrors vbios setting. */ | ||
5023 | if (adjusted_mode->clock >= 100000 | ||
5024 | && adjusted_mode->clock < 140500) { | ||
5025 | clock->p1 = 2; | ||
5026 | clock->p2 = 10; | ||
5027 | clock->n = 3; | ||
5028 | clock->m1 = 16; | ||
5029 | clock->m2 = 8; | ||
5030 | } else if (adjusted_mode->clock >= 140500 | ||
5031 | && adjusted_mode->clock <= 200000) { | ||
5032 | clock->p1 = 1; | ||
5033 | clock->p2 = 10; | ||
5034 | clock->n = 6; | ||
5035 | clock->m1 = 12; | ||
5036 | clock->m2 = 8; | ||
5037 | } | ||
5038 | } | ||
5039 | |||
5040 | static void i9xx_update_pll_dividers(struct drm_crtc *crtc, | ||
5041 | intel_clock_t *clock, | ||
5042 | intel_clock_t *reduced_clock) | ||
5043 | { | ||
5044 | struct drm_device *dev = crtc->dev; | ||
5045 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
5046 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
5047 | int pipe = intel_crtc->pipe; | ||
5048 | u32 fp, fp2 = 0; | ||
5049 | |||
5050 | if (IS_PINEVIEW(dev)) { | ||
5051 | fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2; | ||
5052 | if (reduced_clock) | ||
5053 | fp2 = (1 << reduced_clock->n) << 16 | | ||
5054 | reduced_clock->m1 << 8 | reduced_clock->m2; | ||
5055 | } else { | ||
5056 | fp = clock->n << 16 | clock->m1 << 8 | clock->m2; | ||
5057 | if (reduced_clock) | ||
5058 | fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 | | ||
5059 | reduced_clock->m2; | ||
5060 | } | ||
5061 | |||
5062 | I915_WRITE(FP0(pipe), fp); | ||
5063 | |||
5064 | intel_crtc->lowfreq_avail = false; | ||
5065 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
5066 | reduced_clock && i915_powersave) { | ||
5067 | I915_WRITE(FP1(pipe), fp2); | ||
5068 | intel_crtc->lowfreq_avail = true; | ||
5069 | } else { | ||
5070 | I915_WRITE(FP1(pipe), fp); | ||
5071 | } | ||
5072 | } | ||
5073 | |||
4971 | static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | 5074 | static int i9xx_crtc_mode_set(struct drm_crtc *crtc, |
4972 | struct drm_display_mode *mode, | 5075 | struct drm_display_mode *mode, |
4973 | struct drm_display_mode *adjusted_mode, | 5076 | struct drm_display_mode *adjusted_mode, |
@@ -4981,7 +5084,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
4981 | int plane = intel_crtc->plane; | 5084 | int plane = intel_crtc->plane; |
4982 | int refclk, num_connectors = 0; | 5085 | int refclk, num_connectors = 0; |
4983 | intel_clock_t clock, reduced_clock; | 5086 | intel_clock_t clock, reduced_clock; |
4984 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; | 5087 | u32 dpll, dspcntr, pipeconf; |
4985 | bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; | 5088 | bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; |
4986 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; | 5089 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
4987 | struct drm_mode_config *mode_config = &dev->mode_config; | 5090 | struct drm_mode_config *mode_config = &dev->mode_config; |
@@ -5022,15 +5125,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5022 | num_connectors++; | 5125 | num_connectors++; |
5023 | } | 5126 | } |
5024 | 5127 | ||
5025 | if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { | 5128 | refclk = i9xx_get_refclk(crtc, num_connectors); |
5026 | refclk = dev_priv->lvds_ssc_freq * 1000; | ||
5027 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | ||
5028 | refclk / 1000); | ||
5029 | } else if (!IS_GEN2(dev)) { | ||
5030 | refclk = 96000; | ||
5031 | } else { | ||
5032 | refclk = 48000; | ||
5033 | } | ||
5034 | 5129 | ||
5035 | /* | 5130 | /* |
5036 | * Returns a set of divisors for the desired target clock with the given | 5131 | * Returns a set of divisors for the desired target clock with the given |
@@ -5038,7 +5133,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5038 | * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. | 5133 | * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. |
5039 | */ | 5134 | */ |
5040 | limit = intel_limit(crtc, refclk); | 5135 | limit = intel_limit(crtc, refclk); |
5041 | ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); | 5136 | ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, |
5137 | &clock); | ||
5042 | if (!ok) { | 5138 | if (!ok) { |
5043 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); | 5139 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); |
5044 | return -EINVAL; | 5140 | return -EINVAL; |
@@ -5048,53 +5144,24 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5048 | intel_crtc_update_cursor(crtc, true); | 5144 | intel_crtc_update_cursor(crtc, true); |
5049 | 5145 | ||
5050 | if (is_lvds && dev_priv->lvds_downclock_avail) { | 5146 | if (is_lvds && dev_priv->lvds_downclock_avail) { |
5147 | /* | ||
5148 | * Ensure we match the reduced clock's P to the target clock. | ||
5149 | * If the clocks don't match, we can't switch the display clock | ||
5150 | * by using the FP0/FP1. In such case we will disable the LVDS | ||
5151 | * downclock feature. | ||
5152 | */ | ||
5051 | has_reduced_clock = limit->find_pll(limit, crtc, | 5153 | has_reduced_clock = limit->find_pll(limit, crtc, |
5052 | dev_priv->lvds_downclock, | 5154 | dev_priv->lvds_downclock, |
5053 | refclk, | 5155 | refclk, |
5156 | &clock, | ||
5054 | &reduced_clock); | 5157 | &reduced_clock); |
5055 | if (has_reduced_clock && (clock.p != reduced_clock.p)) { | ||
5056 | /* | ||
5057 | * If the different P is found, it means that we can't | ||
5058 | * switch the display clock by using the FP0/FP1. | ||
5059 | * In such case we will disable the LVDS downclock | ||
5060 | * feature. | ||
5061 | */ | ||
5062 | DRM_DEBUG_KMS("Different P is found for " | ||
5063 | "LVDS clock/downclock\n"); | ||
5064 | has_reduced_clock = 0; | ||
5065 | } | ||
5066 | } | ||
5067 | /* SDVO TV has fixed PLL values depend on its clock range, | ||
5068 | this mirrors vbios setting. */ | ||
5069 | if (is_sdvo && is_tv) { | ||
5070 | if (adjusted_mode->clock >= 100000 | ||
5071 | && adjusted_mode->clock < 140500) { | ||
5072 | clock.p1 = 2; | ||
5073 | clock.p2 = 10; | ||
5074 | clock.n = 3; | ||
5075 | clock.m1 = 16; | ||
5076 | clock.m2 = 8; | ||
5077 | } else if (adjusted_mode->clock >= 140500 | ||
5078 | && adjusted_mode->clock <= 200000) { | ||
5079 | clock.p1 = 1; | ||
5080 | clock.p2 = 10; | ||
5081 | clock.n = 6; | ||
5082 | clock.m1 = 12; | ||
5083 | clock.m2 = 8; | ||
5084 | } | ||
5085 | } | 5158 | } |
5086 | 5159 | ||
5087 | if (IS_PINEVIEW(dev)) { | 5160 | if (is_sdvo && is_tv) |
5088 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; | 5161 | i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); |
5089 | if (has_reduced_clock) | 5162 | |
5090 | fp2 = (1 << reduced_clock.n) << 16 | | 5163 | i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ? |
5091 | reduced_clock.m1 << 8 | reduced_clock.m2; | 5164 | &reduced_clock : NULL); |
5092 | } else { | ||
5093 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | ||
5094 | if (has_reduced_clock) | ||
5095 | fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | | ||
5096 | reduced_clock.m2; | ||
5097 | } | ||
5098 | 5165 | ||
5099 | dpll = DPLL_VGA_MODE_DIS; | 5166 | dpll = DPLL_VGA_MODE_DIS; |
5100 | 5167 | ||
@@ -5168,8 +5235,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5168 | /* Set up the display plane register */ | 5235 | /* Set up the display plane register */ |
5169 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 5236 | dspcntr = DISPPLANE_GAMMA_ENABLE; |
5170 | 5237 | ||
5171 | /* Ironlake's plane is forced to pipe, bit 24 is to | ||
5172 | enable color space conversion */ | ||
5173 | if (pipe == 0) | 5238 | if (pipe == 0) |
5174 | dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; | 5239 | dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; |
5175 | else | 5240 | else |
@@ -5204,7 +5269,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5204 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | 5269 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); |
5205 | drm_mode_debug_printmodeline(mode); | 5270 | drm_mode_debug_printmodeline(mode); |
5206 | 5271 | ||
5207 | I915_WRITE(FP0(pipe), fp); | ||
5208 | I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); | 5272 | I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); |
5209 | 5273 | ||
5210 | POSTING_READ(DPLL(pipe)); | 5274 | POSTING_READ(DPLL(pipe)); |
@@ -5291,17 +5355,11 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5291 | I915_WRITE(DPLL(pipe), dpll); | 5355 | I915_WRITE(DPLL(pipe), dpll); |
5292 | } | 5356 | } |
5293 | 5357 | ||
5294 | intel_crtc->lowfreq_avail = false; | 5358 | if (HAS_PIPE_CXSR(dev)) { |
5295 | if (is_lvds && has_reduced_clock && i915_powersave) { | 5359 | if (intel_crtc->lowfreq_avail) { |
5296 | I915_WRITE(FP1(pipe), fp2); | ||
5297 | intel_crtc->lowfreq_avail = true; | ||
5298 | if (HAS_PIPE_CXSR(dev)) { | ||
5299 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); | 5360 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); |
5300 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; | 5361 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; |
5301 | } | 5362 | } else { |
5302 | } else { | ||
5303 | I915_WRITE(FP1(pipe), fp); | ||
5304 | if (HAS_PIPE_CXSR(dev)) { | ||
5305 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); | 5363 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); |
5306 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; | 5364 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; |
5307 | } | 5365 | } |
@@ -5583,7 +5641,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
5583 | * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. | 5641 | * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. |
5584 | */ | 5642 | */ |
5585 | limit = intel_limit(crtc, refclk); | 5643 | limit = intel_limit(crtc, refclk); |
5586 | ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); | 5644 | ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, |
5645 | &clock); | ||
5587 | if (!ok) { | 5646 | if (!ok) { |
5588 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); | 5647 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); |
5589 | return -EINVAL; | 5648 | return -EINVAL; |
@@ -5593,21 +5652,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
5593 | intel_crtc_update_cursor(crtc, true); | 5652 | intel_crtc_update_cursor(crtc, true); |
5594 | 5653 | ||
5595 | if (is_lvds && dev_priv->lvds_downclock_avail) { | 5654 | if (is_lvds && dev_priv->lvds_downclock_avail) { |
5655 | /* | ||
5656 | * Ensure we match the reduced clock's P to the target clock. | ||
5657 | * If the clocks don't match, we can't switch the display clock | ||
5658 | * by using the FP0/FP1. In such case we will disable the LVDS | ||
5659 | * downclock feature. | ||
5660 | */ | ||
5596 | has_reduced_clock = limit->find_pll(limit, crtc, | 5661 | has_reduced_clock = limit->find_pll(limit, crtc, |
5597 | dev_priv->lvds_downclock, | 5662 | dev_priv->lvds_downclock, |
5598 | refclk, | 5663 | refclk, |
5664 | &clock, | ||
5599 | &reduced_clock); | 5665 | &reduced_clock); |
5600 | if (has_reduced_clock && (clock.p != reduced_clock.p)) { | ||
5601 | /* | ||
5602 | * If the different P is found, it means that we can't | ||
5603 | * switch the display clock by using the FP0/FP1. | ||
5604 | * In such case we will disable the LVDS downclock | ||
5605 | * feature. | ||
5606 | */ | ||
5607 | DRM_DEBUG_KMS("Different P is found for " | ||
5608 | "LVDS clock/downclock\n"); | ||
5609 | has_reduced_clock = 0; | ||
5610 | } | ||
5611 | } | 5666 | } |
5612 | /* SDVO TV has fixed PLL values depend on its clock range, | 5667 | /* SDVO TV has fixed PLL values depend on its clock range, |
5613 | this mirrors vbios setting. */ | 5668 | this mirrors vbios setting. */ |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index db3b461ad412..8f1148c04108 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -362,7 +362,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
362 | int recv_bytes; | 362 | int recv_bytes; |
363 | uint32_t status; | 363 | uint32_t status; |
364 | uint32_t aux_clock_divider; | 364 | uint32_t aux_clock_divider; |
365 | int try, precharge; | 365 | int try, precharge = 5; |
366 | 366 | ||
367 | intel_dp_check_edp(intel_dp); | 367 | intel_dp_check_edp(intel_dp); |
368 | /* The clock divider is based off the hrawclk, | 368 | /* The clock divider is based off the hrawclk, |
@@ -378,15 +378,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
378 | else | 378 | else |
379 | aux_clock_divider = 225; /* eDP input clock at 450Mhz */ | 379 | aux_clock_divider = 225; /* eDP input clock at 450Mhz */ |
380 | } else if (HAS_PCH_SPLIT(dev)) | 380 | } else if (HAS_PCH_SPLIT(dev)) |
381 | aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */ | 381 | aux_clock_divider = 63; /* IRL input clock fixed at 125Mhz */ |
382 | else | 382 | else |
383 | aux_clock_divider = intel_hrawclk(dev) / 2; | 383 | aux_clock_divider = intel_hrawclk(dev) / 2; |
384 | 384 | ||
385 | if (IS_GEN6(dev)) | ||
386 | precharge = 3; | ||
387 | else | ||
388 | precharge = 5; | ||
389 | |||
390 | /* Try to wait for any previous AUX channel activity */ | 385 | /* Try to wait for any previous AUX channel activity */ |
391 | for (try = 0; try < 3; try++) { | 386 | for (try = 0; try < 3; try++) { |
392 | status = I915_READ(ch_ctl); | 387 | status = I915_READ(ch_ctl); |
@@ -431,6 +426,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
431 | DP_AUX_CH_CTL_DONE | | 426 | DP_AUX_CH_CTL_DONE | |
432 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | 427 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
433 | DP_AUX_CH_CTL_RECEIVE_ERROR); | 428 | DP_AUX_CH_CTL_RECEIVE_ERROR); |
429 | |||
430 | if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
431 | DP_AUX_CH_CTL_RECEIVE_ERROR)) | ||
432 | continue; | ||
434 | if (status & DP_AUX_CH_CTL_DONE) | 433 | if (status & DP_AUX_CH_CTL_DONE) |
435 | break; | 434 | break; |
436 | } | 435 | } |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 04d79fd1dc9d..c935cdaa2154 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -141,8 +141,8 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) | |||
141 | dev_priv->saveBLC_PWM_CTL2 = val; | 141 | dev_priv->saveBLC_PWM_CTL2 = val; |
142 | } else if (val == 0) { | 142 | } else if (val == 0) { |
143 | I915_WRITE(BLC_PWM_PCH_CTL2, | 143 | I915_WRITE(BLC_PWM_PCH_CTL2, |
144 | dev_priv->saveBLC_PWM_CTL); | 144 | dev_priv->saveBLC_PWM_CTL2); |
145 | val = dev_priv->saveBLC_PWM_CTL; | 145 | val = dev_priv->saveBLC_PWM_CTL2; |
146 | } | 146 | } |
147 | } else { | 147 | } else { |
148 | val = I915_READ(BLC_PWM_CTL); | 148 | val = I915_READ(BLC_PWM_CTL); |