diff options
Diffstat (limited to 'drivers/gpu/drm')
181 files changed, 15252 insertions, 9242 deletions
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index f3a23a329f4e..997c43d04909 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | ccflags-y := -Iinclude/drm | 5 | ccflags-y := -Iinclude/drm |
6 | 6 | ||
7 | drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ | 7 | drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ |
8 | drm_context.o drm_dma.o drm_drawable.o \ | 8 | drm_context.o drm_dma.o \ |
9 | drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ | 9 | drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ |
10 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ | 10 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ |
11 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ | 11 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ |
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c index ba38e0147220..252fdb98b73a 100644 --- a/drivers/gpu/drm/drm_agpsupport.c +++ b/drivers/gpu/drm/drm_agpsupport.c | |||
@@ -193,7 +193,7 @@ int drm_agp_enable_ioctl(struct drm_device *dev, void *data, | |||
193 | * \return zero on success or a negative number on failure. | 193 | * \return zero on success or a negative number on failure. |
194 | * | 194 | * |
195 | * Verifies the AGP device is present and has been acquired, allocates the | 195 | * Verifies the AGP device is present and has been acquired, allocates the |
196 | * memory via alloc_agp() and creates a drm_agp_mem entry for it. | 196 | * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it. |
197 | */ | 197 | */ |
198 | int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) | 198 | int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) |
199 | { | 199 | { |
@@ -211,7 +211,7 @@ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) | |||
211 | 211 | ||
212 | pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; | 212 | pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; |
213 | type = (u32) request->type; | 213 | type = (u32) request->type; |
214 | if (!(memory = drm_alloc_agp(dev, pages, type))) { | 214 | if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) { |
215 | kfree(entry); | 215 | kfree(entry); |
216 | return -ENOMEM; | 216 | return -ENOMEM; |
217 | } | 217 | } |
@@ -423,38 +423,6 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev) | |||
423 | return head; | 423 | return head; |
424 | } | 424 | } |
425 | 425 | ||
426 | /** Calls agp_allocate_memory() */ | ||
427 | DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge, | ||
428 | size_t pages, u32 type) | ||
429 | { | ||
430 | return agp_allocate_memory(bridge, pages, type); | ||
431 | } | ||
432 | |||
433 | /** Calls agp_free_memory() */ | ||
434 | int drm_agp_free_memory(DRM_AGP_MEM * handle) | ||
435 | { | ||
436 | if (!handle) | ||
437 | return 0; | ||
438 | agp_free_memory(handle); | ||
439 | return 1; | ||
440 | } | ||
441 | |||
442 | /** Calls agp_bind_memory() */ | ||
443 | int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start) | ||
444 | { | ||
445 | if (!handle) | ||
446 | return -EINVAL; | ||
447 | return agp_bind_memory(handle, start); | ||
448 | } | ||
449 | |||
450 | /** Calls agp_unbind_memory() */ | ||
451 | int drm_agp_unbind_memory(DRM_AGP_MEM * handle) | ||
452 | { | ||
453 | if (!handle) | ||
454 | return -EINVAL; | ||
455 | return agp_unbind_memory(handle); | ||
456 | } | ||
457 | |||
458 | /** | 426 | /** |
459 | * Binds a collection of pages into AGP memory at the given offset, returning | 427 | * Binds a collection of pages into AGP memory at the given offset, returning |
460 | * the AGP memory structure containing them. | 428 | * the AGP memory structure containing them. |
@@ -474,7 +442,7 @@ drm_agp_bind_pages(struct drm_device *dev, | |||
474 | 442 | ||
475 | DRM_DEBUG("\n"); | 443 | DRM_DEBUG("\n"); |
476 | 444 | ||
477 | mem = drm_agp_allocate_memory(dev->agp->bridge, num_pages, | 445 | mem = agp_allocate_memory(dev->agp->bridge, num_pages, |
478 | type); | 446 | type); |
479 | if (mem == NULL) { | 447 | if (mem == NULL) { |
480 | DRM_ERROR("Failed to allocate memory for %ld pages\n", | 448 | DRM_ERROR("Failed to allocate memory for %ld pages\n", |
@@ -487,7 +455,7 @@ drm_agp_bind_pages(struct drm_device *dev, | |||
487 | mem->page_count = num_pages; | 455 | mem->page_count = num_pages; |
488 | 456 | ||
489 | mem->is_flushed = true; | 457 | mem->is_flushed = true; |
490 | ret = drm_agp_bind_memory(mem, gtt_offset / PAGE_SIZE); | 458 | ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE); |
491 | if (ret != 0) { | 459 | if (ret != 0) { |
492 | DRM_ERROR("Failed to bind AGP memory: %d\n", ret); | 460 | DRM_ERROR("Failed to bind AGP memory: %d\n", ret); |
493 | agp_free_memory(mem); | 461 | agp_free_memory(mem); |
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index 2607753a320b..6d440fb894cf 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c | |||
@@ -333,14 +333,6 @@ int drm_addctx(struct drm_device *dev, void *data, | |||
333 | return -ENOMEM; | 333 | return -ENOMEM; |
334 | } | 334 | } |
335 | 335 | ||
336 | if (ctx->handle != DRM_KERNEL_CONTEXT) { | ||
337 | if (dev->driver->context_ctor) | ||
338 | if (!dev->driver->context_ctor(dev, ctx->handle)) { | ||
339 | DRM_DEBUG("Running out of ctxs or memory.\n"); | ||
340 | return -ENOMEM; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL); | 336 | ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL); |
345 | if (!ctx_entry) { | 337 | if (!ctx_entry) { |
346 | DRM_DEBUG("out of memory\n"); | 338 | DRM_DEBUG("out of memory\n"); |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 37e0b4fa482a..6985cb1da72c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -1854,7 +1854,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
1854 | } | 1854 | } |
1855 | 1855 | ||
1856 | if (fb->funcs->dirty) { | 1856 | if (fb->funcs->dirty) { |
1857 | ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips); | 1857 | ret = fb->funcs->dirty(fb, file_priv, flags, r->color, |
1858 | clips, num_clips); | ||
1858 | } else { | 1859 | } else { |
1859 | ret = -ENOSYS; | 1860 | ret = -ENOSYS; |
1860 | goto out_err2; | 1861 | goto out_err2; |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 677b275fa721..9d8c892d07c9 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
@@ -48,7 +48,6 @@ static struct drm_info_list drm_debugfs_list[] = { | |||
48 | {"queues", drm_queues_info, 0}, | 48 | {"queues", drm_queues_info, 0}, |
49 | {"bufs", drm_bufs_info, 0}, | 49 | {"bufs", drm_bufs_info, 0}, |
50 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | 50 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
51 | {"gem_objects", drm_gem_object_info, DRIVER_GEM}, | ||
52 | #if DRM_DEBUG_CODE | 51 | #if DRM_DEBUG_CODE |
53 | {"vma", drm_vma_info, 0}, | 52 | {"vma", drm_vma_info, 0}, |
54 | #endif | 53 | #endif |
diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c deleted file mode 100644 index c53c9768cc11..000000000000 --- a/drivers/gpu/drm/drm_drawable.c +++ /dev/null | |||
@@ -1,198 +0,0 @@ | |||
1 | /** | ||
2 | * \file drm_drawable.c | ||
3 | * IOCTLs for drawables | ||
4 | * | ||
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | ||
6 | * \author Gareth Hughes <gareth@valinux.com> | ||
7 | * \author Michel Dänzer <michel@tungstengraphics.com> | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com | ||
12 | * | ||
13 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
14 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
15 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota. | ||
16 | * All Rights Reserved. | ||
17 | * | ||
18 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
19 | * copy of this software and associated documentation files (the "Software"), | ||
20 | * to deal in the Software without restriction, including without limitation | ||
21 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
22 | * and/or sell copies of the Software, and to permit persons to whom the | ||
23 | * Software is furnished to do so, subject to the following conditions: | ||
24 | * | ||
25 | * The above copyright notice and this permission notice (including the next | ||
26 | * paragraph) shall be included in all copies or substantial portions of the | ||
27 | * Software. | ||
28 | * | ||
29 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
30 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
31 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
32 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
33 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
34 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
35 | * OTHER DEALINGS IN THE SOFTWARE. | ||
36 | */ | ||
37 | |||
38 | #include "drmP.h" | ||
39 | |||
40 | /** | ||
41 | * Allocate drawable ID and memory to store information about it. | ||
42 | */ | ||
43 | int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
44 | { | ||
45 | unsigned long irqflags; | ||
46 | struct drm_draw *draw = data; | ||
47 | int new_id = 0; | ||
48 | int ret; | ||
49 | |||
50 | again: | ||
51 | if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) { | ||
52 | DRM_ERROR("Out of memory expanding drawable idr\n"); | ||
53 | return -ENOMEM; | ||
54 | } | ||
55 | |||
56 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
57 | ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id); | ||
58 | if (ret == -EAGAIN) { | ||
59 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
60 | goto again; | ||
61 | } | ||
62 | |||
63 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
64 | |||
65 | draw->handle = new_id; | ||
66 | |||
67 | DRM_DEBUG("%d\n", draw->handle); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * Free drawable ID and memory to store information about it. | ||
74 | */ | ||
75 | int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
76 | { | ||
77 | struct drm_draw *draw = data; | ||
78 | unsigned long irqflags; | ||
79 | struct drm_drawable_info *info; | ||
80 | |||
81 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
82 | |||
83 | info = drm_get_drawable_info(dev, draw->handle); | ||
84 | if (info == NULL) { | ||
85 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | kfree(info->rects); | ||
89 | kfree(info); | ||
90 | |||
91 | idr_remove(&dev->drw_idr, draw->handle); | ||
92 | |||
93 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
94 | DRM_DEBUG("%d\n", draw->handle); | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
99 | { | ||
100 | struct drm_update_draw *update = data; | ||
101 | unsigned long irqflags; | ||
102 | struct drm_clip_rect *rects; | ||
103 | struct drm_drawable_info *info; | ||
104 | int err; | ||
105 | |||
106 | info = idr_find(&dev->drw_idr, update->handle); | ||
107 | if (!info) { | ||
108 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
109 | if (!info) | ||
110 | return -ENOMEM; | ||
111 | if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) { | ||
112 | DRM_ERROR("No such drawable %d\n", update->handle); | ||
113 | kfree(info); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | switch (update->type) { | ||
119 | case DRM_DRAWABLE_CLIPRECTS: | ||
120 | if (update->num == 0) | ||
121 | rects = NULL; | ||
122 | else if (update->num != info->num_rects) { | ||
123 | rects = kmalloc(update->num * | ||
124 | sizeof(struct drm_clip_rect), | ||
125 | GFP_KERNEL); | ||
126 | } else | ||
127 | rects = info->rects; | ||
128 | |||
129 | if (update->num && !rects) { | ||
130 | DRM_ERROR("Failed to allocate cliprect memory\n"); | ||
131 | err = -ENOMEM; | ||
132 | goto error; | ||
133 | } | ||
134 | |||
135 | if (update->num && DRM_COPY_FROM_USER(rects, | ||
136 | (struct drm_clip_rect __user *) | ||
137 | (unsigned long)update->data, | ||
138 | update->num * | ||
139 | sizeof(*rects))) { | ||
140 | DRM_ERROR("Failed to copy cliprects from userspace\n"); | ||
141 | err = -EFAULT; | ||
142 | goto error; | ||
143 | } | ||
144 | |||
145 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
146 | |||
147 | if (rects != info->rects) { | ||
148 | kfree(info->rects); | ||
149 | } | ||
150 | |||
151 | info->rects = rects; | ||
152 | info->num_rects = update->num; | ||
153 | |||
154 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
155 | |||
156 | DRM_DEBUG("Updated %d cliprects for drawable %d\n", | ||
157 | info->num_rects, update->handle); | ||
158 | break; | ||
159 | default: | ||
160 | DRM_ERROR("Invalid update type %d\n", update->type); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | return 0; | ||
165 | |||
166 | error: | ||
167 | if (rects != info->rects) | ||
168 | kfree(rects); | ||
169 | |||
170 | return err; | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * Caller must hold the drawable spinlock! | ||
175 | */ | ||
176 | struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) | ||
177 | { | ||
178 | return idr_find(&dev->drw_idr, id); | ||
179 | } | ||
180 | EXPORT_SYMBOL(drm_get_drawable_info); | ||
181 | |||
182 | static int drm_drawable_free(int idr, void *p, void *data) | ||
183 | { | ||
184 | struct drm_drawable_info *info = p; | ||
185 | |||
186 | if (info) { | ||
187 | kfree(info->rects); | ||
188 | kfree(info); | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | void drm_drawable_free_all(struct drm_device *dev) | ||
195 | { | ||
196 | idr_for_each(&dev->drw_idr, drm_drawable_free, NULL); | ||
197 | idr_remove_all(&dev->drw_idr); | ||
198 | } | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 84da748555bc..5ff75a3a6b9d 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -91,8 +91,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
91 | DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 91 | DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
92 | DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), | 92 | DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), |
93 | 93 | ||
94 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 94 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
95 | DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 95 | DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
96 | 96 | ||
97 | DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), | 97 | DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), |
98 | DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), | 98 | DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), |
@@ -127,7 +127,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
127 | 127 | ||
128 | DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), | 128 | DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), |
129 | 129 | ||
130 | DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 130 | DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
131 | 131 | ||
132 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), | 132 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), |
133 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), | 133 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), |
@@ -180,10 +180,6 @@ int drm_lastclose(struct drm_device * dev) | |||
180 | 180 | ||
181 | mutex_lock(&dev->struct_mutex); | 181 | mutex_lock(&dev->struct_mutex); |
182 | 182 | ||
183 | /* Free drawable information memory */ | ||
184 | drm_drawable_free_all(dev); | ||
185 | del_timer(&dev->timer); | ||
186 | |||
187 | /* Clear AGP information */ | 183 | /* Clear AGP information */ |
188 | if (drm_core_has_AGP(dev) && dev->agp && | 184 | if (drm_core_has_AGP(dev) && dev->agp && |
189 | !drm_core_check_feature(dev, DRIVER_MODESET)) { | 185 | !drm_core_check_feature(dev, DRIVER_MODESET)) { |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 96e963108225..fd033ebbdf84 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/i2c-algo-bit.h> | ||
34 | #include "drmP.h" | 33 | #include "drmP.h" |
35 | #include "drm_edid.h" | 34 | #include "drm_edid.h" |
36 | #include "drm_edid_modes.h" | 35 | #include "drm_edid_modes.h" |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 6a5e403f9aa1..625a2d551d6a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -263,7 +263,8 @@ int drm_fb_helper_debug_enter(struct fb_info *info) | |||
263 | funcs->mode_set_base_atomic(mode_set->crtc, | 263 | funcs->mode_set_base_atomic(mode_set->crtc, |
264 | mode_set->fb, | 264 | mode_set->fb, |
265 | mode_set->x, | 265 | mode_set->x, |
266 | mode_set->y); | 266 | mode_set->y, |
267 | 1); | ||
267 | 268 | ||
268 | } | 269 | } |
269 | } | 270 | } |
@@ -309,7 +310,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) | |||
309 | } | 310 | } |
310 | 311 | ||
311 | funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, | 312 | funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, |
312 | crtc->y); | 313 | crtc->y, 0); |
313 | } | 314 | } |
314 | 315 | ||
315 | return 0; | 316 | return 0; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 5663d2719063..ea1c4b019ebf 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -92,12 +92,6 @@ drm_gem_init(struct drm_device *dev) | |||
92 | 92 | ||
93 | spin_lock_init(&dev->object_name_lock); | 93 | spin_lock_init(&dev->object_name_lock); |
94 | idr_init(&dev->object_name_idr); | 94 | idr_init(&dev->object_name_idr); |
95 | atomic_set(&dev->object_count, 0); | ||
96 | atomic_set(&dev->object_memory, 0); | ||
97 | atomic_set(&dev->pin_count, 0); | ||
98 | atomic_set(&dev->pin_memory, 0); | ||
99 | atomic_set(&dev->gtt_count, 0); | ||
100 | atomic_set(&dev->gtt_memory, 0); | ||
101 | 95 | ||
102 | mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL); | 96 | mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL); |
103 | if (!mm) { | 97 | if (!mm) { |
@@ -151,9 +145,6 @@ int drm_gem_object_init(struct drm_device *dev, | |||
151 | atomic_set(&obj->handle_count, 0); | 145 | atomic_set(&obj->handle_count, 0); |
152 | obj->size = size; | 146 | obj->size = size; |
153 | 147 | ||
154 | atomic_inc(&dev->object_count); | ||
155 | atomic_add(obj->size, &dev->object_memory); | ||
156 | |||
157 | return 0; | 148 | return 0; |
158 | } | 149 | } |
159 | EXPORT_SYMBOL(drm_gem_object_init); | 150 | EXPORT_SYMBOL(drm_gem_object_init); |
@@ -180,8 +171,6 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) | |||
180 | return obj; | 171 | return obj; |
181 | fput: | 172 | fput: |
182 | /* Object_init mangles the global counters - readjust them. */ | 173 | /* Object_init mangles the global counters - readjust them. */ |
183 | atomic_dec(&dev->object_count); | ||
184 | atomic_sub(obj->size, &dev->object_memory); | ||
185 | fput(obj->filp); | 174 | fput(obj->filp); |
186 | free: | 175 | free: |
187 | kfree(obj); | 176 | kfree(obj); |
@@ -436,10 +425,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private) | |||
436 | void | 425 | void |
437 | drm_gem_object_release(struct drm_gem_object *obj) | 426 | drm_gem_object_release(struct drm_gem_object *obj) |
438 | { | 427 | { |
439 | struct drm_device *dev = obj->dev; | ||
440 | fput(obj->filp); | 428 | fput(obj->filp); |
441 | atomic_dec(&dev->object_count); | ||
442 | atomic_sub(obj->size, &dev->object_memory); | ||
443 | } | 429 | } |
444 | EXPORT_SYMBOL(drm_gem_object_release); | 430 | EXPORT_SYMBOL(drm_gem_object_release); |
445 | 431 | ||
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 974e970ce3f8..3cdbaf379bb5 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
@@ -270,20 +270,6 @@ int drm_gem_name_info(struct seq_file *m, void *data) | |||
270 | return 0; | 270 | return 0; |
271 | } | 271 | } |
272 | 272 | ||
273 | int drm_gem_object_info(struct seq_file *m, void* data) | ||
274 | { | ||
275 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
276 | struct drm_device *dev = node->minor->dev; | ||
277 | |||
278 | seq_printf(m, "%d objects\n", atomic_read(&dev->object_count)); | ||
279 | seq_printf(m, "%d object bytes\n", atomic_read(&dev->object_memory)); | ||
280 | seq_printf(m, "%d pinned\n", atomic_read(&dev->pin_count)); | ||
281 | seq_printf(m, "%d pin bytes\n", atomic_read(&dev->pin_memory)); | ||
282 | seq_printf(m, "%d gtt bytes\n", atomic_read(&dev->gtt_memory)); | ||
283 | seq_printf(m, "%d gtt total\n", dev->gtt_total); | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | #if DRM_DEBUG_CODE | 273 | #if DRM_DEBUG_CODE |
288 | 274 | ||
289 | int drm_vma_info(struct seq_file *m, void *data) | 275 | int drm_vma_info(struct seq_file *m, void *data) |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 9bf93bc9a32c..632ae243ede0 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
@@ -37,6 +37,8 @@ | |||
37 | 37 | ||
38 | static int drm_notifier(void *priv); | 38 | static int drm_notifier(void *priv); |
39 | 39 | ||
40 | static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); | ||
41 | |||
40 | /** | 42 | /** |
41 | * Lock ioctl. | 43 | * Lock ioctl. |
42 | * | 44 | * |
@@ -124,9 +126,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
124 | block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); | 126 | block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); |
125 | } | 127 | } |
126 | 128 | ||
127 | if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY)) | ||
128 | dev->driver->dma_ready(dev); | ||
129 | |||
130 | if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT)) | 129 | if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT)) |
131 | { | 130 | { |
132 | if (dev->driver->dma_quiescent(dev)) { | 131 | if (dev->driver->dma_quiescent(dev)) { |
@@ -136,12 +135,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
136 | } | 135 | } |
137 | } | 136 | } |
138 | 137 | ||
139 | if (dev->driver->kernel_context_switch && | ||
140 | dev->last_context != lock->context) { | ||
141 | dev->driver->kernel_context_switch(dev, dev->last_context, | ||
142 | lock->context); | ||
143 | } | ||
144 | |||
145 | return 0; | 138 | return 0; |
146 | } | 139 | } |
147 | 140 | ||
@@ -169,15 +162,8 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
169 | 162 | ||
170 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); | 163 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); |
171 | 164 | ||
172 | /* kernel_context_switch isn't used by any of the x86 drm | 165 | if (drm_lock_free(&master->lock, lock->context)) { |
173 | * modules but is required by the Sparc driver. | 166 | /* FIXME: Should really bail out here. */ |
174 | */ | ||
175 | if (dev->driver->kernel_context_switch_unlock) | ||
176 | dev->driver->kernel_context_switch_unlock(dev); | ||
177 | else { | ||
178 | if (drm_lock_free(&master->lock, lock->context)) { | ||
179 | /* FIXME: Should really bail out here. */ | ||
180 | } | ||
181 | } | 167 | } |
182 | 168 | ||
183 | unblock_all_signals(); | 169 | unblock_all_signals(); |
@@ -193,6 +179,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
193 | * | 179 | * |
194 | * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction. | 180 | * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction. |
195 | */ | 181 | */ |
182 | static | ||
196 | int drm_lock_take(struct drm_lock_data *lock_data, | 183 | int drm_lock_take(struct drm_lock_data *lock_data, |
197 | unsigned int context) | 184 | unsigned int context) |
198 | { | 185 | { |
@@ -229,7 +216,6 @@ int drm_lock_take(struct drm_lock_data *lock_data, | |||
229 | } | 216 | } |
230 | return 0; | 217 | return 0; |
231 | } | 218 | } |
232 | EXPORT_SYMBOL(drm_lock_take); | ||
233 | 219 | ||
234 | /** | 220 | /** |
235 | * This takes a lock forcibly and hands it to context. Should ONLY be used | 221 | * This takes a lock forcibly and hands it to context. Should ONLY be used |
@@ -297,7 +283,6 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) | |||
297 | wake_up_interruptible(&lock_data->lock_queue); | 283 | wake_up_interruptible(&lock_data->lock_queue); |
298 | return 0; | 284 | return 0; |
299 | } | 285 | } |
300 | EXPORT_SYMBOL(drm_lock_free); | ||
301 | 286 | ||
302 | /** | 287 | /** |
303 | * If we get here, it means that the process has called DRM_IOCTL_LOCK | 288 | * If we get here, it means that the process has called DRM_IOCTL_LOCK |
@@ -360,7 +345,6 @@ void drm_idlelock_take(struct drm_lock_data *lock_data) | |||
360 | } | 345 | } |
361 | spin_unlock_bh(&lock_data->spinlock); | 346 | spin_unlock_bh(&lock_data->spinlock); |
362 | } | 347 | } |
363 | EXPORT_SYMBOL(drm_idlelock_take); | ||
364 | 348 | ||
365 | void drm_idlelock_release(struct drm_lock_data *lock_data) | 349 | void drm_idlelock_release(struct drm_lock_data *lock_data) |
366 | { | 350 | { |
@@ -380,8 +364,6 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) | |||
380 | } | 364 | } |
381 | spin_unlock_bh(&lock_data->spinlock); | 365 | spin_unlock_bh(&lock_data->spinlock); |
382 | } | 366 | } |
383 | EXPORT_SYMBOL(drm_idlelock_release); | ||
384 | |||
385 | 367 | ||
386 | int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) | 368 | int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) |
387 | { | 369 | { |
@@ -390,5 +372,3 @@ int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) | |||
390 | _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) && | 372 | _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) && |
391 | master->lock.file_priv == file_priv); | 373 | master->lock.file_priv == file_priv); |
392 | } | 374 | } |
393 | |||
394 | EXPORT_SYMBOL(drm_i_have_hw_lock); | ||
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index 7732268eced2..c9b805000a11 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c | |||
@@ -99,29 +99,23 @@ static void *agp_remap(unsigned long offset, unsigned long size, | |||
99 | return addr; | 99 | return addr; |
100 | } | 100 | } |
101 | 101 | ||
102 | /** Wrapper around agp_allocate_memory() */ | ||
103 | DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type) | ||
104 | { | ||
105 | return drm_agp_allocate_memory(dev->agp->bridge, pages, type); | ||
106 | } | ||
107 | |||
108 | /** Wrapper around agp_free_memory() */ | 102 | /** Wrapper around agp_free_memory() */ |
109 | int drm_free_agp(DRM_AGP_MEM * handle, int pages) | 103 | void drm_free_agp(DRM_AGP_MEM * handle, int pages) |
110 | { | 104 | { |
111 | return drm_agp_free_memory(handle) ? 0 : -EINVAL; | 105 | agp_free_memory(handle); |
112 | } | 106 | } |
113 | EXPORT_SYMBOL(drm_free_agp); | 107 | EXPORT_SYMBOL(drm_free_agp); |
114 | 108 | ||
115 | /** Wrapper around agp_bind_memory() */ | 109 | /** Wrapper around agp_bind_memory() */ |
116 | int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) | 110 | int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) |
117 | { | 111 | { |
118 | return drm_agp_bind_memory(handle, start); | 112 | return agp_bind_memory(handle, start); |
119 | } | 113 | } |
120 | 114 | ||
121 | /** Wrapper around agp_unbind_memory() */ | 115 | /** Wrapper around agp_unbind_memory() */ |
122 | int drm_unbind_agp(DRM_AGP_MEM * handle) | 116 | int drm_unbind_agp(DRM_AGP_MEM * handle) |
123 | { | 117 | { |
124 | return drm_agp_unbind_memory(handle); | 118 | return agp_unbind_memory(handle); |
125 | } | 119 | } |
126 | EXPORT_SYMBOL(drm_unbind_agp); | 120 | EXPORT_SYMBOL(drm_unbind_agp); |
127 | 121 | ||
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index a9ba6b69ad35..9e5b07efebb7 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c | |||
@@ -55,7 +55,6 @@ static struct drm_info_list drm_proc_list[] = { | |||
55 | {"queues", drm_queues_info, 0}, | 55 | {"queues", drm_queues_info, 0}, |
56 | {"bufs", drm_bufs_info, 0}, | 56 | {"bufs", drm_bufs_info, 0}, |
57 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | 57 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
58 | {"gem_objects", drm_gem_object_info, DRIVER_GEM}, | ||
59 | #if DRM_DEBUG_CODE | 58 | #if DRM_DEBUG_CODE |
60 | {"vma", drm_vma_info, 0}, | 59 | {"vma", drm_vma_info, 0}, |
61 | #endif | 60 | #endif |
@@ -151,7 +150,6 @@ fail: | |||
151 | int drm_proc_init(struct drm_minor *minor, int minor_id, | 150 | int drm_proc_init(struct drm_minor *minor, int minor_id, |
152 | struct proc_dir_entry *root) | 151 | struct proc_dir_entry *root) |
153 | { | 152 | { |
154 | struct drm_device *dev = minor->dev; | ||
155 | char name[64]; | 153 | char name[64]; |
156 | int ret; | 154 | int ret; |
157 | 155 | ||
@@ -172,14 +170,6 @@ int drm_proc_init(struct drm_minor *minor, int minor_id, | |||
172 | return ret; | 170 | return ret; |
173 | } | 171 | } |
174 | 172 | ||
175 | if (dev->driver->proc_init) { | ||
176 | ret = dev->driver->proc_init(minor); | ||
177 | if (ret) { | ||
178 | DRM_ERROR("DRM: Driver failed to initialize " | ||
179 | "/proc/dri.\n"); | ||
180 | return ret; | ||
181 | } | ||
182 | } | ||
183 | return 0; | 173 | return 0; |
184 | } | 174 | } |
185 | 175 | ||
@@ -216,15 +206,11 @@ int drm_proc_remove_files(struct drm_info_list *files, int count, | |||
216 | */ | 206 | */ |
217 | int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) | 207 | int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) |
218 | { | 208 | { |
219 | struct drm_device *dev = minor->dev; | ||
220 | char name[64]; | 209 | char name[64]; |
221 | 210 | ||
222 | if (!root || !minor->proc_root) | 211 | if (!root || !minor->proc_root) |
223 | return 0; | 212 | return 0; |
224 | 213 | ||
225 | if (dev->driver->proc_cleanup) | ||
226 | dev->driver->proc_cleanup(minor); | ||
227 | |||
228 | drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor); | 214 | drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor); |
229 | 215 | ||
230 | sprintf(name, "%d", minor->index); | 216 | sprintf(name, "%d", minor->index); |
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c index 9034c4c6100d..d15e09b0ae0b 100644 --- a/drivers/gpu/drm/drm_scatter.c +++ b/drivers/gpu/drm/drm_scatter.c | |||
@@ -184,8 +184,6 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) | |||
184 | drm_sg_cleanup(entry); | 184 | drm_sg_cleanup(entry); |
185 | return -ENOMEM; | 185 | return -ENOMEM; |
186 | } | 186 | } |
187 | EXPORT_SYMBOL(drm_sg_alloc); | ||
188 | |||
189 | 187 | ||
190 | int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, | 188 | int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, |
191 | struct drm_file *file_priv) | 189 | struct drm_file *file_priv) |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index d1ad57450df1..cdc89ee042cc 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
@@ -240,14 +240,10 @@ int drm_fill_in_dev(struct drm_device *dev, | |||
240 | INIT_LIST_HEAD(&dev->vblank_event_list); | 240 | INIT_LIST_HEAD(&dev->vblank_event_list); |
241 | 241 | ||
242 | spin_lock_init(&dev->count_lock); | 242 | spin_lock_init(&dev->count_lock); |
243 | spin_lock_init(&dev->drw_lock); | ||
244 | spin_lock_init(&dev->event_lock); | 243 | spin_lock_init(&dev->event_lock); |
245 | init_timer(&dev->timer); | ||
246 | mutex_init(&dev->struct_mutex); | 244 | mutex_init(&dev->struct_mutex); |
247 | mutex_init(&dev->ctxlist_mutex); | 245 | mutex_init(&dev->ctxlist_mutex); |
248 | 246 | ||
249 | idr_init(&dev->drw_idr); | ||
250 | |||
251 | if (drm_ht_create(&dev->map_hash, 12)) { | 247 | if (drm_ht_create(&dev->map_hash, 12)) { |
252 | return -ENOMEM; | 248 | return -ENOMEM; |
253 | } | 249 | } |
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 5df450683aab..2c3fcbdfd8ff 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c | |||
@@ -523,14 +523,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
526 | resource_size_t drm_core_get_map_ofs(struct drm_local_map * map) | 526 | static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) |
527 | { | ||
528 | return map->offset; | ||
529 | } | ||
530 | |||
531 | EXPORT_SYMBOL(drm_core_get_map_ofs); | ||
532 | |||
533 | resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) | ||
534 | { | 527 | { |
535 | #ifdef __alpha__ | 528 | #ifdef __alpha__ |
536 | return dev->hose->dense_mem_base - dev->hose->mem_space->start; | 529 | return dev->hose->dense_mem_base - dev->hose->mem_space->start; |
@@ -539,8 +532,6 @@ resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) | |||
539 | #endif | 532 | #endif |
540 | } | 533 | } |
541 | 534 | ||
542 | EXPORT_SYMBOL(drm_core_get_reg_ofs); | ||
543 | |||
544 | /** | 535 | /** |
545 | * mmap DMA memory. | 536 | * mmap DMA memory. |
546 | * | 537 | * |
@@ -627,7 +618,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) | |||
627 | #endif | 618 | #endif |
628 | case _DRM_FRAME_BUFFER: | 619 | case _DRM_FRAME_BUFFER: |
629 | case _DRM_REGISTERS: | 620 | case _DRM_REGISTERS: |
630 | offset = dev->driver->get_reg_ofs(dev); | 621 | offset = drm_core_get_reg_ofs(dev); |
631 | vma->vm_flags |= VM_IO; /* not in core dump */ | 622 | vma->vm_flags |= VM_IO; /* not in core dump */ |
632 | vma->vm_page_prot = drm_io_prot(map->type, vma); | 623 | vma->vm_page_prot = drm_io_prot(map->type, vma); |
633 | #if !defined(__arm__) | 624 | #if !defined(__arm__) |
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index b4250b2cac1f..1c73b0c43c1e 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c | |||
@@ -52,8 +52,6 @@ static struct drm_driver driver = { | |||
52 | .device_is_agp = i810_driver_device_is_agp, | 52 | .device_is_agp = i810_driver_device_is_agp, |
53 | .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, | 53 | .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, |
54 | .dma_quiescent = i810_driver_dma_quiescent, | 54 | .dma_quiescent = i810_driver_dma_quiescent, |
55 | .get_map_ofs = drm_core_get_map_ofs, | ||
56 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
57 | .ioctls = i810_ioctls, | 55 | .ioctls = i810_ioctls, |
58 | .fops = { | 56 | .fops = { |
59 | .owner = THIS_MODULE, | 57 | .owner = THIS_MODULE, |
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c index a5c66aa82f0c..7140ffc12eee 100644 --- a/drivers/gpu/drm/i830/i830_drv.c +++ b/drivers/gpu/drm/i830/i830_drv.c | |||
@@ -57,8 +57,6 @@ static struct drm_driver driver = { | |||
57 | .device_is_agp = i830_driver_device_is_agp, | 57 | .device_is_agp = i830_driver_device_is_agp, |
58 | .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked, | 58 | .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked, |
59 | .dma_quiescent = i830_driver_dma_quiescent, | 59 | .dma_quiescent = i830_driver_dma_quiescent, |
60 | .get_map_ofs = drm_core_get_map_ofs, | ||
61 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
62 | #if USE_IRQS | 60 | #if USE_IRQS |
63 | .irq_preinstall = i830_driver_irq_preinstall, | 61 | .irq_preinstall = i830_driver_irq_preinstall, |
64 | .irq_postinstall = i830_driver_irq_postinstall, | 62 | .irq_postinstall = i830_driver_irq_postinstall, |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5c8e53458edb..f6e98dd416c9 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -26,13 +26,13 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
26 | intel_dvo.o \ | 26 | intel_dvo.o \ |
27 | intel_ringbuffer.o \ | 27 | intel_ringbuffer.o \ |
28 | intel_overlay.o \ | 28 | intel_overlay.o \ |
29 | intel_opregion.o \ | ||
29 | dvo_ch7xxx.o \ | 30 | dvo_ch7xxx.o \ |
30 | dvo_ch7017.o \ | 31 | dvo_ch7017.o \ |
31 | dvo_ivch.o \ | 32 | dvo_ivch.o \ |
32 | dvo_tfp410.o \ | 33 | dvo_tfp410.o \ |
33 | dvo_sil164.o | 34 | dvo_sil164.o |
34 | 35 | ||
35 | i915-$(CONFIG_ACPI) += i915_opregion.o | ||
36 | i915-$(CONFIG_COMPAT) += i915_ioc32.o | 36 | i915-$(CONFIG_COMPAT) += i915_ioc32.o |
37 | 37 | ||
38 | obj-$(CONFIG_DRM_I915) += i915.o | 38 | obj-$(CONFIG_DRM_I915) += i915.o |
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index 14d59804acd7..af70337567ce 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c | |||
@@ -165,67 +165,44 @@ struct ch7017_priv { | |||
165 | static void ch7017_dump_regs(struct intel_dvo_device *dvo); | 165 | static void ch7017_dump_regs(struct intel_dvo_device *dvo); |
166 | static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); | 166 | static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); |
167 | 167 | ||
168 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | 168 | static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val) |
169 | { | 169 | { |
170 | struct i2c_adapter *adapter = dvo->i2c_bus; | ||
171 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
172 | u8 out_buf[2]; | ||
173 | u8 in_buf[2]; | ||
174 | |||
175 | struct i2c_msg msgs[] = { | 170 | struct i2c_msg msgs[] = { |
176 | { | 171 | { |
177 | .addr = dvo->slave_addr, | 172 | .addr = dvo->slave_addr, |
178 | .flags = 0, | 173 | .flags = 0, |
179 | .len = 1, | 174 | .len = 1, |
180 | .buf = out_buf, | 175 | .buf = &addr, |
181 | }, | 176 | }, |
182 | { | 177 | { |
183 | .addr = dvo->slave_addr, | 178 | .addr = dvo->slave_addr, |
184 | .flags = I2C_M_RD, | 179 | .flags = I2C_M_RD, |
185 | .len = 1, | 180 | .len = 1, |
186 | .buf = in_buf, | 181 | .buf = val, |
187 | } | 182 | } |
188 | }; | 183 | }; |
189 | 184 | return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2; | |
190 | out_buf[0] = addr; | ||
191 | out_buf[1] = 0; | ||
192 | |||
193 | if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { | ||
194 | *val= in_buf[0]; | ||
195 | return true; | ||
196 | }; | ||
197 | |||
198 | return false; | ||
199 | } | 185 | } |
200 | 186 | ||
201 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | 187 | static bool ch7017_write(struct intel_dvo_device *dvo, u8 addr, u8 val) |
202 | { | 188 | { |
203 | struct i2c_adapter *adapter = dvo->i2c_bus; | 189 | uint8_t buf[2] = { addr, val }; |
204 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
205 | uint8_t out_buf[2]; | ||
206 | struct i2c_msg msg = { | 190 | struct i2c_msg msg = { |
207 | .addr = dvo->slave_addr, | 191 | .addr = dvo->slave_addr, |
208 | .flags = 0, | 192 | .flags = 0, |
209 | .len = 2, | 193 | .len = 2, |
210 | .buf = out_buf, | 194 | .buf = buf, |
211 | }; | 195 | }; |
212 | 196 | return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1; | |
213 | out_buf[0] = addr; | ||
214 | out_buf[1] = val; | ||
215 | |||
216 | if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) | ||
217 | return true; | ||
218 | |||
219 | return false; | ||
220 | } | 197 | } |
221 | 198 | ||
222 | /** Probes for a CH7017 on the given bus and slave address. */ | 199 | /** Probes for a CH7017 on the given bus and slave address. */ |
223 | static bool ch7017_init(struct intel_dvo_device *dvo, | 200 | static bool ch7017_init(struct intel_dvo_device *dvo, |
224 | struct i2c_adapter *adapter) | 201 | struct i2c_adapter *adapter) |
225 | { | 202 | { |
226 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
227 | struct ch7017_priv *priv; | 203 | struct ch7017_priv *priv; |
228 | uint8_t val; | 204 | const char *str; |
205 | u8 val; | ||
229 | 206 | ||
230 | priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL); | 207 | priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL); |
231 | if (priv == NULL) | 208 | if (priv == NULL) |
@@ -237,16 +214,27 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
237 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) | 214 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) |
238 | goto fail; | 215 | goto fail; |
239 | 216 | ||
240 | if (val != CH7017_DEVICE_ID_VALUE && | 217 | switch (val) { |
241 | val != CH7018_DEVICE_ID_VALUE && | 218 | case CH7017_DEVICE_ID_VALUE: |
242 | val != CH7019_DEVICE_ID_VALUE) { | 219 | str = "ch7017"; |
220 | break; | ||
221 | case CH7018_DEVICE_ID_VALUE: | ||
222 | str = "ch7018"; | ||
223 | break; | ||
224 | case CH7019_DEVICE_ID_VALUE: | ||
225 | str = "ch7019"; | ||
226 | break; | ||
227 | default: | ||
243 | DRM_DEBUG_KMS("ch701x not detected, got %d: from %s " | 228 | DRM_DEBUG_KMS("ch701x not detected, got %d: from %s " |
244 | "Slave %d.\n", | 229 | "slave %d.\n", |
245 | val, i2cbus->adapter.name,dvo->slave_addr); | 230 | val, adapter->name,dvo->slave_addr); |
246 | goto fail; | 231 | goto fail; |
247 | } | 232 | } |
248 | 233 | ||
234 | DRM_DEBUG_KMS("%s detected on %s, addr %d\n", | ||
235 | str, adapter->name, dvo->slave_addr); | ||
249 | return true; | 236 | return true; |
237 | |||
250 | fail: | 238 | fail: |
251 | kfree(priv); | 239 | kfree(priv); |
252 | return false; | 240 | return false; |
@@ -368,7 +356,7 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode) | |||
368 | } | 356 | } |
369 | 357 | ||
370 | /* XXX: Should actually wait for update power status somehow */ | 358 | /* XXX: Should actually wait for update power status somehow */ |
371 | udelay(20000); | 359 | msleep(20); |
372 | } | 360 | } |
373 | 361 | ||
374 | static void ch7017_dump_regs(struct intel_dvo_device *dvo) | 362 | static void ch7017_dump_regs(struct intel_dvo_device *dvo) |
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 6f1944b24441..7eaa94e4ff06 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c | |||
@@ -113,7 +113,6 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
113 | { | 113 | { |
114 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; | 114 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; |
115 | struct i2c_adapter *adapter = dvo->i2c_bus; | 115 | struct i2c_adapter *adapter = dvo->i2c_bus; |
116 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
117 | u8 out_buf[2]; | 116 | u8 out_buf[2]; |
118 | u8 in_buf[2]; | 117 | u8 in_buf[2]; |
119 | 118 | ||
@@ -135,14 +134,14 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
135 | out_buf[0] = addr; | 134 | out_buf[0] = addr; |
136 | out_buf[1] = 0; | 135 | out_buf[1] = 0; |
137 | 136 | ||
138 | if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { | 137 | if (i2c_transfer(adapter, msgs, 2) == 2) { |
139 | *ch = in_buf[0]; | 138 | *ch = in_buf[0]; |
140 | return true; | 139 | return true; |
141 | }; | 140 | }; |
142 | 141 | ||
143 | if (!ch7xxx->quiet) { | 142 | if (!ch7xxx->quiet) { |
144 | DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", | 143 | DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", |
145 | addr, i2cbus->adapter.name, dvo->slave_addr); | 144 | addr, adapter->name, dvo->slave_addr); |
146 | } | 145 | } |
147 | return false; | 146 | return false; |
148 | } | 147 | } |
@@ -152,7 +151,6 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
152 | { | 151 | { |
153 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; | 152 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; |
154 | struct i2c_adapter *adapter = dvo->i2c_bus; | 153 | struct i2c_adapter *adapter = dvo->i2c_bus; |
155 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
156 | uint8_t out_buf[2]; | 154 | uint8_t out_buf[2]; |
157 | struct i2c_msg msg = { | 155 | struct i2c_msg msg = { |
158 | .addr = dvo->slave_addr, | 156 | .addr = dvo->slave_addr, |
@@ -164,12 +162,12 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
164 | out_buf[0] = addr; | 162 | out_buf[0] = addr; |
165 | out_buf[1] = ch; | 163 | out_buf[1] = ch; |
166 | 164 | ||
167 | if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) | 165 | if (i2c_transfer(adapter, &msg, 1) == 1) |
168 | return true; | 166 | return true; |
169 | 167 | ||
170 | if (!ch7xxx->quiet) { | 168 | if (!ch7xxx->quiet) { |
171 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", | 169 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", |
172 | addr, i2cbus->adapter.name, dvo->slave_addr); | 170 | addr, adapter->name, dvo->slave_addr); |
173 | } | 171 | } |
174 | 172 | ||
175 | return false; | 173 | return false; |
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index a2ec3f487202..a12ed9414cc7 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c | |||
@@ -167,7 +167,6 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
167 | { | 167 | { |
168 | struct ivch_priv *priv = dvo->dev_priv; | 168 | struct ivch_priv *priv = dvo->dev_priv; |
169 | struct i2c_adapter *adapter = dvo->i2c_bus; | 169 | struct i2c_adapter *adapter = dvo->i2c_bus; |
170 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
171 | u8 out_buf[1]; | 170 | u8 out_buf[1]; |
172 | u8 in_buf[2]; | 171 | u8 in_buf[2]; |
173 | 172 | ||
@@ -193,7 +192,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
193 | 192 | ||
194 | out_buf[0] = addr; | 193 | out_buf[0] = addr; |
195 | 194 | ||
196 | if (i2c_transfer(&i2cbus->adapter, msgs, 3) == 3) { | 195 | if (i2c_transfer(adapter, msgs, 3) == 3) { |
197 | *data = (in_buf[1] << 8) | in_buf[0]; | 196 | *data = (in_buf[1] << 8) | in_buf[0]; |
198 | return true; | 197 | return true; |
199 | }; | 198 | }; |
@@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
201 | if (!priv->quiet) { | 200 | if (!priv->quiet) { |
202 | DRM_DEBUG_KMS("Unable to read register 0x%02x from " | 201 | DRM_DEBUG_KMS("Unable to read register 0x%02x from " |
203 | "%s:%02x.\n", | 202 | "%s:%02x.\n", |
204 | addr, i2cbus->adapter.name, dvo->slave_addr); | 203 | addr, adapter->name, dvo->slave_addr); |
205 | } | 204 | } |
206 | return false; | 205 | return false; |
207 | } | 206 | } |
@@ -211,7 +210,6 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
211 | { | 210 | { |
212 | struct ivch_priv *priv = dvo->dev_priv; | 211 | struct ivch_priv *priv = dvo->dev_priv; |
213 | struct i2c_adapter *adapter = dvo->i2c_bus; | 212 | struct i2c_adapter *adapter = dvo->i2c_bus; |
214 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
215 | u8 out_buf[3]; | 213 | u8 out_buf[3]; |
216 | struct i2c_msg msg = { | 214 | struct i2c_msg msg = { |
217 | .addr = dvo->slave_addr, | 215 | .addr = dvo->slave_addr, |
@@ -224,12 +222,12 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
224 | out_buf[1] = data & 0xff; | 222 | out_buf[1] = data & 0xff; |
225 | out_buf[2] = data >> 8; | 223 | out_buf[2] = data >> 8; |
226 | 224 | ||
227 | if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) | 225 | if (i2c_transfer(adapter, &msg, 1) == 1) |
228 | return true; | 226 | return true; |
229 | 227 | ||
230 | if (!priv->quiet) { | 228 | if (!priv->quiet) { |
231 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", | 229 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", |
232 | addr, i2cbus->adapter.name, dvo->slave_addr); | 230 | addr, adapter->name, dvo->slave_addr); |
233 | } | 231 | } |
234 | 232 | ||
235 | return false; | 233 | return false; |
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index 9b8e6765cf26..e4b4091df942 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c | |||
@@ -69,7 +69,6 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
69 | { | 69 | { |
70 | struct sil164_priv *sil = dvo->dev_priv; | 70 | struct sil164_priv *sil = dvo->dev_priv; |
71 | struct i2c_adapter *adapter = dvo->i2c_bus; | 71 | struct i2c_adapter *adapter = dvo->i2c_bus; |
72 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
73 | u8 out_buf[2]; | 72 | u8 out_buf[2]; |
74 | u8 in_buf[2]; | 73 | u8 in_buf[2]; |
75 | 74 | ||
@@ -91,14 +90,14 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
91 | out_buf[0] = addr; | 90 | out_buf[0] = addr; |
92 | out_buf[1] = 0; | 91 | out_buf[1] = 0; |
93 | 92 | ||
94 | if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { | 93 | if (i2c_transfer(adapter, msgs, 2) == 2) { |
95 | *ch = in_buf[0]; | 94 | *ch = in_buf[0]; |
96 | return true; | 95 | return true; |
97 | }; | 96 | }; |
98 | 97 | ||
99 | if (!sil->quiet) { | 98 | if (!sil->quiet) { |
100 | DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", | 99 | DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", |
101 | addr, i2cbus->adapter.name, dvo->slave_addr); | 100 | addr, adapter->name, dvo->slave_addr); |
102 | } | 101 | } |
103 | return false; | 102 | return false; |
104 | } | 103 | } |
@@ -107,7 +106,6 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
107 | { | 106 | { |
108 | struct sil164_priv *sil= dvo->dev_priv; | 107 | struct sil164_priv *sil= dvo->dev_priv; |
109 | struct i2c_adapter *adapter = dvo->i2c_bus; | 108 | struct i2c_adapter *adapter = dvo->i2c_bus; |
110 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
111 | uint8_t out_buf[2]; | 109 | uint8_t out_buf[2]; |
112 | struct i2c_msg msg = { | 110 | struct i2c_msg msg = { |
113 | .addr = dvo->slave_addr, | 111 | .addr = dvo->slave_addr, |
@@ -119,12 +117,12 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
119 | out_buf[0] = addr; | 117 | out_buf[0] = addr; |
120 | out_buf[1] = ch; | 118 | out_buf[1] = ch; |
121 | 119 | ||
122 | if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) | 120 | if (i2c_transfer(adapter, &msg, 1) == 1) |
123 | return true; | 121 | return true; |
124 | 122 | ||
125 | if (!sil->quiet) { | 123 | if (!sil->quiet) { |
126 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", | 124 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", |
127 | addr, i2cbus->adapter.name, dvo->slave_addr); | 125 | addr, adapter->name, dvo->slave_addr); |
128 | } | 126 | } |
129 | 127 | ||
130 | return false; | 128 | return false; |
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 56f66426207f..8ab2855bb544 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c | |||
@@ -94,7 +94,6 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
94 | { | 94 | { |
95 | struct tfp410_priv *tfp = dvo->dev_priv; | 95 | struct tfp410_priv *tfp = dvo->dev_priv; |
96 | struct i2c_adapter *adapter = dvo->i2c_bus; | 96 | struct i2c_adapter *adapter = dvo->i2c_bus; |
97 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
98 | u8 out_buf[2]; | 97 | u8 out_buf[2]; |
99 | u8 in_buf[2]; | 98 | u8 in_buf[2]; |
100 | 99 | ||
@@ -116,14 +115,14 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
116 | out_buf[0] = addr; | 115 | out_buf[0] = addr; |
117 | out_buf[1] = 0; | 116 | out_buf[1] = 0; |
118 | 117 | ||
119 | if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { | 118 | if (i2c_transfer(adapter, msgs, 2) == 2) { |
120 | *ch = in_buf[0]; | 119 | *ch = in_buf[0]; |
121 | return true; | 120 | return true; |
122 | }; | 121 | }; |
123 | 122 | ||
124 | if (!tfp->quiet) { | 123 | if (!tfp->quiet) { |
125 | DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", | 124 | DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", |
126 | addr, i2cbus->adapter.name, dvo->slave_addr); | 125 | addr, adapter->name, dvo->slave_addr); |
127 | } | 126 | } |
128 | return false; | 127 | return false; |
129 | } | 128 | } |
@@ -132,7 +131,6 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
132 | { | 131 | { |
133 | struct tfp410_priv *tfp = dvo->dev_priv; | 132 | struct tfp410_priv *tfp = dvo->dev_priv; |
134 | struct i2c_adapter *adapter = dvo->i2c_bus; | 133 | struct i2c_adapter *adapter = dvo->i2c_bus; |
135 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
136 | uint8_t out_buf[2]; | 134 | uint8_t out_buf[2]; |
137 | struct i2c_msg msg = { | 135 | struct i2c_msg msg = { |
138 | .addr = dvo->slave_addr, | 136 | .addr = dvo->slave_addr, |
@@ -144,12 +142,12 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
144 | out_buf[0] = addr; | 142 | out_buf[0] = addr; |
145 | out_buf[1] = ch; | 143 | out_buf[1] = ch; |
146 | 144 | ||
147 | if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) | 145 | if (i2c_transfer(adapter, &msg, 1) == 1) |
148 | return true; | 146 | return true; |
149 | 147 | ||
150 | if (!tfp->quiet) { | 148 | if (!tfp->quiet) { |
151 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", | 149 | DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", |
152 | addr, i2cbus->adapter.name, dvo->slave_addr); | 150 | addr, adapter->name, dvo->slave_addr); |
153 | } | 151 | } |
154 | 152 | ||
155 | return false; | 153 | return false; |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5e43d7076789..d598070fb279 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -40,9 +40,51 @@ | |||
40 | 40 | ||
41 | #if defined(CONFIG_DEBUG_FS) | 41 | #if defined(CONFIG_DEBUG_FS) |
42 | 42 | ||
43 | #define ACTIVE_LIST 1 | 43 | enum { |
44 | #define FLUSHING_LIST 2 | 44 | RENDER_LIST, |
45 | #define INACTIVE_LIST 3 | 45 | BSD_LIST, |
46 | FLUSHING_LIST, | ||
47 | INACTIVE_LIST, | ||
48 | PINNED_LIST, | ||
49 | DEFERRED_FREE_LIST, | ||
50 | }; | ||
51 | |||
52 | static const char *yesno(int v) | ||
53 | { | ||
54 | return v ? "yes" : "no"; | ||
55 | } | ||
56 | |||
57 | static int i915_capabilities(struct seq_file *m, void *data) | ||
58 | { | ||
59 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
60 | struct drm_device *dev = node->minor->dev; | ||
61 | const struct intel_device_info *info = INTEL_INFO(dev); | ||
62 | |||
63 | seq_printf(m, "gen: %d\n", info->gen); | ||
64 | #define B(x) seq_printf(m, #x ": %s\n", yesno(info->x)) | ||
65 | B(is_mobile); | ||
66 | B(is_i85x); | ||
67 | B(is_i915g); | ||
68 | B(is_i945gm); | ||
69 | B(is_g33); | ||
70 | B(need_gfx_hws); | ||
71 | B(is_g4x); | ||
72 | B(is_pineview); | ||
73 | B(is_broadwater); | ||
74 | B(is_crestline); | ||
75 | B(is_ironlake); | ||
76 | B(has_fbc); | ||
77 | B(has_rc6); | ||
78 | B(has_pipe_cxsr); | ||
79 | B(has_hotplug); | ||
80 | B(cursor_needs_physical); | ||
81 | B(has_overlay); | ||
82 | B(overlay_needs_physical); | ||
83 | B(supports_tv); | ||
84 | #undef B | ||
85 | |||
86 | return 0; | ||
87 | } | ||
46 | 88 | ||
47 | static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv) | 89 | static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv) |
48 | { | 90 | { |
@@ -64,6 +106,27 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv) | |||
64 | } | 106 | } |
65 | } | 107 | } |
66 | 108 | ||
109 | static void | ||
110 | describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | ||
111 | { | ||
112 | seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s", | ||
113 | &obj->base, | ||
114 | get_pin_flag(obj), | ||
115 | get_tiling_flag(obj), | ||
116 | obj->base.size, | ||
117 | obj->base.read_domains, | ||
118 | obj->base.write_domain, | ||
119 | obj->last_rendering_seqno, | ||
120 | obj->dirty ? " dirty" : "", | ||
121 | obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); | ||
122 | if (obj->base.name) | ||
123 | seq_printf(m, " (name: %d)", obj->base.name); | ||
124 | if (obj->fence_reg != I915_FENCE_REG_NONE) | ||
125 | seq_printf(m, " (fence: %d)", obj->fence_reg); | ||
126 | if (obj->gtt_space != NULL) | ||
127 | seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset); | ||
128 | } | ||
129 | |||
67 | static int i915_gem_object_list_info(struct seq_file *m, void *data) | 130 | static int i915_gem_object_list_info(struct seq_file *m, void *data) |
68 | { | 131 | { |
69 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 132 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
@@ -72,56 +135,84 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
72 | struct drm_device *dev = node->minor->dev; | 135 | struct drm_device *dev = node->minor->dev; |
73 | drm_i915_private_t *dev_priv = dev->dev_private; | 136 | drm_i915_private_t *dev_priv = dev->dev_private; |
74 | struct drm_i915_gem_object *obj_priv; | 137 | struct drm_i915_gem_object *obj_priv; |
75 | spinlock_t *lock = NULL; | 138 | size_t total_obj_size, total_gtt_size; |
139 | int count, ret; | ||
140 | |||
141 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
142 | if (ret) | ||
143 | return ret; | ||
76 | 144 | ||
77 | switch (list) { | 145 | switch (list) { |
78 | case ACTIVE_LIST: | 146 | case RENDER_LIST: |
79 | seq_printf(m, "Active:\n"); | 147 | seq_printf(m, "Render:\n"); |
80 | lock = &dev_priv->mm.active_list_lock; | ||
81 | head = &dev_priv->render_ring.active_list; | 148 | head = &dev_priv->render_ring.active_list; |
82 | break; | 149 | break; |
150 | case BSD_LIST: | ||
151 | seq_printf(m, "BSD:\n"); | ||
152 | head = &dev_priv->bsd_ring.active_list; | ||
153 | break; | ||
83 | case INACTIVE_LIST: | 154 | case INACTIVE_LIST: |
84 | seq_printf(m, "Inactive:\n"); | 155 | seq_printf(m, "Inactive:\n"); |
85 | head = &dev_priv->mm.inactive_list; | 156 | head = &dev_priv->mm.inactive_list; |
86 | break; | 157 | break; |
158 | case PINNED_LIST: | ||
159 | seq_printf(m, "Pinned:\n"); | ||
160 | head = &dev_priv->mm.pinned_list; | ||
161 | break; | ||
87 | case FLUSHING_LIST: | 162 | case FLUSHING_LIST: |
88 | seq_printf(m, "Flushing:\n"); | 163 | seq_printf(m, "Flushing:\n"); |
89 | head = &dev_priv->mm.flushing_list; | 164 | head = &dev_priv->mm.flushing_list; |
90 | break; | 165 | break; |
166 | case DEFERRED_FREE_LIST: | ||
167 | seq_printf(m, "Deferred free:\n"); | ||
168 | head = &dev_priv->mm.deferred_free_list; | ||
169 | break; | ||
91 | default: | 170 | default: |
92 | DRM_INFO("Ooops, unexpected list\n"); | 171 | mutex_unlock(&dev->struct_mutex); |
93 | return 0; | 172 | return -EINVAL; |
94 | } | 173 | } |
95 | 174 | ||
96 | if (lock) | 175 | total_obj_size = total_gtt_size = count = 0; |
97 | spin_lock(lock); | 176 | list_for_each_entry(obj_priv, head, list) { |
98 | list_for_each_entry(obj_priv, head, list) | 177 | seq_printf(m, " "); |
99 | { | 178 | describe_obj(m, obj_priv); |
100 | seq_printf(m, " %p: %s %8zd %08x %08x %d%s%s", | ||
101 | &obj_priv->base, | ||
102 | get_pin_flag(obj_priv), | ||
103 | obj_priv->base.size, | ||
104 | obj_priv->base.read_domains, | ||
105 | obj_priv->base.write_domain, | ||
106 | obj_priv->last_rendering_seqno, | ||
107 | obj_priv->dirty ? " dirty" : "", | ||
108 | obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : ""); | ||
109 | |||
110 | if (obj_priv->base.name) | ||
111 | seq_printf(m, " (name: %d)", obj_priv->base.name); | ||
112 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | ||
113 | seq_printf(m, " (fence: %d)", obj_priv->fence_reg); | ||
114 | if (obj_priv->gtt_space != NULL) | ||
115 | seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset); | ||
116 | |||
117 | seq_printf(m, "\n"); | 179 | seq_printf(m, "\n"); |
180 | total_obj_size += obj_priv->base.size; | ||
181 | total_gtt_size += obj_priv->gtt_space->size; | ||
182 | count++; | ||
118 | } | 183 | } |
184 | mutex_unlock(&dev->struct_mutex); | ||
119 | 185 | ||
120 | if (lock) | 186 | seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n", |
121 | spin_unlock(lock); | 187 | count, total_obj_size, total_gtt_size); |
122 | return 0; | 188 | return 0; |
123 | } | 189 | } |
124 | 190 | ||
191 | static int i915_gem_object_info(struct seq_file *m, void* data) | ||
192 | { | ||
193 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
194 | struct drm_device *dev = node->minor->dev; | ||
195 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
196 | int ret; | ||
197 | |||
198 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
199 | if (ret) | ||
200 | return ret; | ||
201 | |||
202 | seq_printf(m, "%u objects\n", dev_priv->mm.object_count); | ||
203 | seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory); | ||
204 | seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count); | ||
205 | seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory); | ||
206 | seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count); | ||
207 | seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory); | ||
208 | seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total); | ||
209 | |||
210 | mutex_unlock(&dev->struct_mutex); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | |||
125 | static int i915_gem_pageflip_info(struct seq_file *m, void *data) | 216 | static int i915_gem_pageflip_info(struct seq_file *m, void *data) |
126 | { | 217 | { |
127 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 218 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
@@ -176,6 +267,11 @@ static int i915_gem_request_info(struct seq_file *m, void *data) | |||
176 | struct drm_device *dev = node->minor->dev; | 267 | struct drm_device *dev = node->minor->dev; |
177 | drm_i915_private_t *dev_priv = dev->dev_private; | 268 | drm_i915_private_t *dev_priv = dev->dev_private; |
178 | struct drm_i915_gem_request *gem_request; | 269 | struct drm_i915_gem_request *gem_request; |
270 | int ret; | ||
271 | |||
272 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
273 | if (ret) | ||
274 | return ret; | ||
179 | 275 | ||
180 | seq_printf(m, "Request:\n"); | 276 | seq_printf(m, "Request:\n"); |
181 | list_for_each_entry(gem_request, &dev_priv->render_ring.request_list, | 277 | list_for_each_entry(gem_request, &dev_priv->render_ring.request_list, |
@@ -184,6 +280,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data) | |||
184 | gem_request->seqno, | 280 | gem_request->seqno, |
185 | (int) (jiffies - gem_request->emitted_jiffies)); | 281 | (int) (jiffies - gem_request->emitted_jiffies)); |
186 | } | 282 | } |
283 | mutex_unlock(&dev->struct_mutex); | ||
284 | |||
187 | return 0; | 285 | return 0; |
188 | } | 286 | } |
189 | 287 | ||
@@ -192,16 +290,24 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) | |||
192 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 290 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
193 | struct drm_device *dev = node->minor->dev; | 291 | struct drm_device *dev = node->minor->dev; |
194 | drm_i915_private_t *dev_priv = dev->dev_private; | 292 | drm_i915_private_t *dev_priv = dev->dev_private; |
293 | int ret; | ||
294 | |||
295 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
296 | if (ret) | ||
297 | return ret; | ||
195 | 298 | ||
196 | if (dev_priv->render_ring.status_page.page_addr != NULL) { | 299 | if (dev_priv->render_ring.status_page.page_addr != NULL) { |
197 | seq_printf(m, "Current sequence: %d\n", | 300 | seq_printf(m, "Current sequence: %d\n", |
198 | i915_get_gem_seqno(dev, &dev_priv->render_ring)); | 301 | dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring)); |
199 | } else { | 302 | } else { |
200 | seq_printf(m, "Current sequence: hws uninitialized\n"); | 303 | seq_printf(m, "Current sequence: hws uninitialized\n"); |
201 | } | 304 | } |
202 | seq_printf(m, "Waiter sequence: %d\n", | 305 | seq_printf(m, "Waiter sequence: %d\n", |
203 | dev_priv->mm.waiting_gem_seqno); | 306 | dev_priv->mm.waiting_gem_seqno); |
204 | seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); | 307 | seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); |
308 | |||
309 | mutex_unlock(&dev->struct_mutex); | ||
310 | |||
205 | return 0; | 311 | return 0; |
206 | } | 312 | } |
207 | 313 | ||
@@ -211,6 +317,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
211 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 317 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
212 | struct drm_device *dev = node->minor->dev; | 318 | struct drm_device *dev = node->minor->dev; |
213 | drm_i915_private_t *dev_priv = dev->dev_private; | 319 | drm_i915_private_t *dev_priv = dev->dev_private; |
320 | int ret; | ||
321 | |||
322 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
323 | if (ret) | ||
324 | return ret; | ||
214 | 325 | ||
215 | if (!HAS_PCH_SPLIT(dev)) { | 326 | if (!HAS_PCH_SPLIT(dev)) { |
216 | seq_printf(m, "Interrupt enable: %08x\n", | 327 | seq_printf(m, "Interrupt enable: %08x\n", |
@@ -247,7 +358,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
247 | atomic_read(&dev_priv->irq_received)); | 358 | atomic_read(&dev_priv->irq_received)); |
248 | if (dev_priv->render_ring.status_page.page_addr != NULL) { | 359 | if (dev_priv->render_ring.status_page.page_addr != NULL) { |
249 | seq_printf(m, "Current sequence: %d\n", | 360 | seq_printf(m, "Current sequence: %d\n", |
250 | i915_get_gem_seqno(dev, &dev_priv->render_ring)); | 361 | dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring)); |
251 | } else { | 362 | } else { |
252 | seq_printf(m, "Current sequence: hws uninitialized\n"); | 363 | seq_printf(m, "Current sequence: hws uninitialized\n"); |
253 | } | 364 | } |
@@ -255,6 +366,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
255 | dev_priv->mm.waiting_gem_seqno); | 366 | dev_priv->mm.waiting_gem_seqno); |
256 | seq_printf(m, "IRQ sequence: %d\n", | 367 | seq_printf(m, "IRQ sequence: %d\n", |
257 | dev_priv->mm.irq_gem_seqno); | 368 | dev_priv->mm.irq_gem_seqno); |
369 | mutex_unlock(&dev->struct_mutex); | ||
370 | |||
258 | return 0; | 371 | return 0; |
259 | } | 372 | } |
260 | 373 | ||
@@ -263,7 +376,11 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) | |||
263 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 376 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
264 | struct drm_device *dev = node->minor->dev; | 377 | struct drm_device *dev = node->minor->dev; |
265 | drm_i915_private_t *dev_priv = dev->dev_private; | 378 | drm_i915_private_t *dev_priv = dev->dev_private; |
266 | int i; | 379 | int i, ret; |
380 | |||
381 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
382 | if (ret) | ||
383 | return ret; | ||
267 | 384 | ||
268 | seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); | 385 | seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); |
269 | seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); | 386 | seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); |
@@ -289,6 +406,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) | |||
289 | seq_printf(m, "\n"); | 406 | seq_printf(m, "\n"); |
290 | } | 407 | } |
291 | } | 408 | } |
409 | mutex_unlock(&dev->struct_mutex); | ||
292 | 410 | ||
293 | return 0; | 411 | return 0; |
294 | } | 412 | } |
@@ -313,16 +431,19 @@ static int i915_hws_info(struct seq_file *m, void *data) | |||
313 | return 0; | 431 | return 0; |
314 | } | 432 | } |
315 | 433 | ||
316 | static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_count) | 434 | static void i915_dump_object(struct seq_file *m, |
435 | struct io_mapping *mapping, | ||
436 | struct drm_i915_gem_object *obj_priv) | ||
317 | { | 437 | { |
318 | int page, i; | 438 | int page, page_count, i; |
319 | uint32_t *mem; | ||
320 | 439 | ||
440 | page_count = obj_priv->base.size / PAGE_SIZE; | ||
321 | for (page = 0; page < page_count; page++) { | 441 | for (page = 0; page < page_count; page++) { |
322 | mem = kmap_atomic(pages[page], KM_USER0); | 442 | u32 *mem = io_mapping_map_wc(mapping, |
443 | obj_priv->gtt_offset + page * PAGE_SIZE); | ||
323 | for (i = 0; i < PAGE_SIZE; i += 4) | 444 | for (i = 0; i < PAGE_SIZE; i += 4) |
324 | seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); | 445 | seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); |
325 | kunmap_atomic(mem, KM_USER0); | 446 | io_mapping_unmap(mem); |
326 | } | 447 | } |
327 | } | 448 | } |
328 | 449 | ||
@@ -335,27 +456,21 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data) | |||
335 | struct drm_i915_gem_object *obj_priv; | 456 | struct drm_i915_gem_object *obj_priv; |
336 | int ret; | 457 | int ret; |
337 | 458 | ||
338 | spin_lock(&dev_priv->mm.active_list_lock); | 459 | ret = mutex_lock_interruptible(&dev->struct_mutex); |
460 | if (ret) | ||
461 | return ret; | ||
339 | 462 | ||
340 | list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, | 463 | list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list, |
341 | list) { | 464 | list) { |
342 | obj = &obj_priv->base; | 465 | obj = &obj_priv->base; |
343 | if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { | 466 | if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { |
344 | ret = i915_gem_object_get_pages(obj, 0); | 467 | seq_printf(m, "--- gtt_offset = 0x%08x\n", |
345 | if (ret) { | 468 | obj_priv->gtt_offset); |
346 | DRM_ERROR("Failed to get pages: %d\n", ret); | 469 | i915_dump_object(m, dev_priv->mm.gtt_mapping, obj_priv); |
347 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | seq_printf(m, "--- gtt_offset = 0x%08x\n", obj_priv->gtt_offset); | ||
352 | i915_dump_pages(m, obj_priv->pages, obj->size / PAGE_SIZE); | ||
353 | |||
354 | i915_gem_object_put_pages(obj); | ||
355 | } | 470 | } |
356 | } | 471 | } |
357 | 472 | ||
358 | spin_unlock(&dev_priv->mm.active_list_lock); | 473 | mutex_unlock(&dev->struct_mutex); |
359 | 474 | ||
360 | return 0; | 475 | return 0; |
361 | } | 476 | } |
@@ -365,20 +480,24 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data) | |||
365 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 480 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
366 | struct drm_device *dev = node->minor->dev; | 481 | struct drm_device *dev = node->minor->dev; |
367 | drm_i915_private_t *dev_priv = dev->dev_private; | 482 | drm_i915_private_t *dev_priv = dev->dev_private; |
368 | u8 *virt; | 483 | int ret; |
369 | uint32_t *ptr, off; | 484 | |
485 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
486 | if (ret) | ||
487 | return ret; | ||
370 | 488 | ||
371 | if (!dev_priv->render_ring.gem_object) { | 489 | if (!dev_priv->render_ring.gem_object) { |
372 | seq_printf(m, "No ringbuffer setup\n"); | 490 | seq_printf(m, "No ringbuffer setup\n"); |
373 | return 0; | 491 | } else { |
374 | } | 492 | u8 *virt = dev_priv->render_ring.virtual_start; |
375 | 493 | uint32_t off; | |
376 | virt = dev_priv->render_ring.virtual_start; | ||
377 | 494 | ||
378 | for (off = 0; off < dev_priv->render_ring.size; off += 4) { | 495 | for (off = 0; off < dev_priv->render_ring.size; off += 4) { |
379 | ptr = (uint32_t *)(virt + off); | 496 | uint32_t *ptr = (uint32_t *)(virt + off); |
380 | seq_printf(m, "%08x : %08x\n", off, *ptr); | 497 | seq_printf(m, "%08x : %08x\n", off, *ptr); |
498 | } | ||
381 | } | 499 | } |
500 | mutex_unlock(&dev->struct_mutex); | ||
382 | 501 | ||
383 | return 0; | 502 | return 0; |
384 | } | 503 | } |
@@ -396,7 +515,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) | |||
396 | seq_printf(m, "RingHead : %08x\n", head); | 515 | seq_printf(m, "RingHead : %08x\n", head); |
397 | seq_printf(m, "RingTail : %08x\n", tail); | 516 | seq_printf(m, "RingTail : %08x\n", tail); |
398 | seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size); | 517 | seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size); |
399 | seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD)); | 518 | seq_printf(m, "Acthd : %08x\n", I915_READ(INTEL_INFO(dev)->gen >= 4 ? ACTHD_I965 : ACTHD)); |
400 | 519 | ||
401 | return 0; | 520 | return 0; |
402 | } | 521 | } |
@@ -458,7 +577,7 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
458 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); | 577 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); |
459 | seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); | 578 | seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); |
460 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); | 579 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); |
461 | if (IS_I965G(dev)) { | 580 | if (INTEL_INFO(dev)->gen >= 4) { |
462 | seq_printf(m, " INSTPS: 0x%08x\n", error->instps); | 581 | seq_printf(m, " INSTPS: 0x%08x\n", error->instps); |
463 | seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); | 582 | seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); |
464 | } | 583 | } |
@@ -642,6 +761,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused) | |||
642 | } else { | 761 | } else { |
643 | seq_printf(m, "FBC disabled: "); | 762 | seq_printf(m, "FBC disabled: "); |
644 | switch (dev_priv->no_fbc_reason) { | 763 | switch (dev_priv->no_fbc_reason) { |
764 | case FBC_NO_OUTPUT: | ||
765 | seq_printf(m, "no outputs"); | ||
766 | break; | ||
645 | case FBC_STOLEN_TOO_SMALL: | 767 | case FBC_STOLEN_TOO_SMALL: |
646 | seq_printf(m, "not enough stolen memory"); | 768 | seq_printf(m, "not enough stolen memory"); |
647 | break; | 769 | break; |
@@ -675,15 +797,17 @@ static int i915_sr_status(struct seq_file *m, void *unused) | |||
675 | drm_i915_private_t *dev_priv = dev->dev_private; | 797 | drm_i915_private_t *dev_priv = dev->dev_private; |
676 | bool sr_enabled = false; | 798 | bool sr_enabled = false; |
677 | 799 | ||
678 | if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev)) | 800 | if (IS_IRONLAKE(dev)) |
801 | sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN; | ||
802 | else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev)) | ||
679 | sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN; | 803 | sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN; |
680 | else if (IS_I915GM(dev)) | 804 | else if (IS_I915GM(dev)) |
681 | sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; | 805 | sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; |
682 | else if (IS_PINEVIEW(dev)) | 806 | else if (IS_PINEVIEW(dev)) |
683 | sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN; | 807 | sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN; |
684 | 808 | ||
685 | seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" : | 809 | seq_printf(m, "self-refresh: %s\n", |
686 | "disabled"); | 810 | sr_enabled ? "enabled" : "disabled"); |
687 | 811 | ||
688 | return 0; | 812 | return 0; |
689 | } | 813 | } |
@@ -694,10 +818,16 @@ static int i915_emon_status(struct seq_file *m, void *unused) | |||
694 | struct drm_device *dev = node->minor->dev; | 818 | struct drm_device *dev = node->minor->dev; |
695 | drm_i915_private_t *dev_priv = dev->dev_private; | 819 | drm_i915_private_t *dev_priv = dev->dev_private; |
696 | unsigned long temp, chipset, gfx; | 820 | unsigned long temp, chipset, gfx; |
821 | int ret; | ||
822 | |||
823 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
824 | if (ret) | ||
825 | return ret; | ||
697 | 826 | ||
698 | temp = i915_mch_val(dev_priv); | 827 | temp = i915_mch_val(dev_priv); |
699 | chipset = i915_chipset_val(dev_priv); | 828 | chipset = i915_chipset_val(dev_priv); |
700 | gfx = i915_gfx_val(dev_priv); | 829 | gfx = i915_gfx_val(dev_priv); |
830 | mutex_unlock(&dev->struct_mutex); | ||
701 | 831 | ||
702 | seq_printf(m, "GMCH temp: %ld\n", temp); | 832 | seq_printf(m, "GMCH temp: %ld\n", temp); |
703 | seq_printf(m, "Chipset power: %ld\n", chipset); | 833 | seq_printf(m, "Chipset power: %ld\n", chipset); |
@@ -718,6 +848,68 @@ static int i915_gfxec(struct seq_file *m, void *unused) | |||
718 | return 0; | 848 | return 0; |
719 | } | 849 | } |
720 | 850 | ||
851 | static int i915_opregion(struct seq_file *m, void *unused) | ||
852 | { | ||
853 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
854 | struct drm_device *dev = node->minor->dev; | ||
855 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
856 | struct intel_opregion *opregion = &dev_priv->opregion; | ||
857 | int ret; | ||
858 | |||
859 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
860 | if (ret) | ||
861 | return ret; | ||
862 | |||
863 | if (opregion->header) | ||
864 | seq_write(m, opregion->header, OPREGION_SIZE); | ||
865 | |||
866 | mutex_unlock(&dev->struct_mutex); | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static int i915_gem_framebuffer_info(struct seq_file *m, void *data) | ||
872 | { | ||
873 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
874 | struct drm_device *dev = node->minor->dev; | ||
875 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
876 | struct intel_fbdev *ifbdev; | ||
877 | struct intel_framebuffer *fb; | ||
878 | int ret; | ||
879 | |||
880 | ret = mutex_lock_interruptible(&dev->mode_config.mutex); | ||
881 | if (ret) | ||
882 | return ret; | ||
883 | |||
884 | ifbdev = dev_priv->fbdev; | ||
885 | fb = to_intel_framebuffer(ifbdev->helper.fb); | ||
886 | |||
887 | seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, obj ", | ||
888 | fb->base.width, | ||
889 | fb->base.height, | ||
890 | fb->base.depth, | ||
891 | fb->base.bits_per_pixel); | ||
892 | describe_obj(m, to_intel_bo(fb->obj)); | ||
893 | seq_printf(m, "\n"); | ||
894 | |||
895 | list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { | ||
896 | if (&fb->base == ifbdev->helper.fb) | ||
897 | continue; | ||
898 | |||
899 | seq_printf(m, "user size: %d x %d, depth %d, %d bpp, obj ", | ||
900 | fb->base.width, | ||
901 | fb->base.height, | ||
902 | fb->base.depth, | ||
903 | fb->base.bits_per_pixel); | ||
904 | describe_obj(m, to_intel_bo(fb->obj)); | ||
905 | seq_printf(m, "\n"); | ||
906 | } | ||
907 | |||
908 | mutex_unlock(&dev->mode_config.mutex); | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
721 | static int | 913 | static int |
722 | i915_wedged_open(struct inode *inode, | 914 | i915_wedged_open(struct inode *inode, |
723 | struct file *filp) | 915 | struct file *filp) |
@@ -741,6 +933,9 @@ i915_wedged_read(struct file *filp, | |||
741 | "wedged : %d\n", | 933 | "wedged : %d\n", |
742 | atomic_read(&dev_priv->mm.wedged)); | 934 | atomic_read(&dev_priv->mm.wedged)); |
743 | 935 | ||
936 | if (len > sizeof (buf)) | ||
937 | len = sizeof (buf); | ||
938 | |||
744 | return simple_read_from_buffer(ubuf, max, ppos, buf, len); | 939 | return simple_read_from_buffer(ubuf, max, ppos, buf, len); |
745 | } | 940 | } |
746 | 941 | ||
@@ -770,7 +965,7 @@ i915_wedged_write(struct file *filp, | |||
770 | 965 | ||
771 | atomic_set(&dev_priv->mm.wedged, val); | 966 | atomic_set(&dev_priv->mm.wedged, val); |
772 | if (val) { | 967 | if (val) { |
773 | DRM_WAKEUP(&dev_priv->irq_queue); | 968 | wake_up_all(&dev_priv->irq_queue); |
774 | queue_work(dev_priv->wq, &dev_priv->error_work); | 969 | queue_work(dev_priv->wq, &dev_priv->error_work); |
775 | } | 970 | } |
776 | 971 | ||
@@ -823,9 +1018,14 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) | |||
823 | } | 1018 | } |
824 | 1019 | ||
825 | static struct drm_info_list i915_debugfs_list[] = { | 1020 | static struct drm_info_list i915_debugfs_list[] = { |
826 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, | 1021 | {"i915_capabilities", i915_capabilities, 0, 0}, |
1022 | {"i915_gem_objects", i915_gem_object_info, 0}, | ||
1023 | {"i915_gem_render_active", i915_gem_object_list_info, 0, (void *) RENDER_LIST}, | ||
1024 | {"i915_gem_bsd_active", i915_gem_object_list_info, 0, (void *) BSD_LIST}, | ||
827 | {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, | 1025 | {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, |
828 | {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, | 1026 | {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, |
1027 | {"i915_gem_pinned", i915_gem_object_list_info, 0, (void *) PINNED_LIST}, | ||
1028 | {"i915_gem_deferred_free", i915_gem_object_list_info, 0, (void *) DEFERRED_FREE_LIST}, | ||
829 | {"i915_gem_pageflip", i915_gem_pageflip_info, 0}, | 1029 | {"i915_gem_pageflip", i915_gem_pageflip_info, 0}, |
830 | {"i915_gem_request", i915_gem_request_info, 0}, | 1030 | {"i915_gem_request", i915_gem_request_info, 0}, |
831 | {"i915_gem_seqno", i915_gem_seqno_info, 0}, | 1031 | {"i915_gem_seqno", i915_gem_seqno_info, 0}, |
@@ -845,6 +1045,8 @@ static struct drm_info_list i915_debugfs_list[] = { | |||
845 | {"i915_gfxec", i915_gfxec, 0}, | 1045 | {"i915_gfxec", i915_gfxec, 0}, |
846 | {"i915_fbc_status", i915_fbc_status, 0}, | 1046 | {"i915_fbc_status", i915_fbc_status, 0}, |
847 | {"i915_sr_status", i915_sr_status, 0}, | 1047 | {"i915_sr_status", i915_sr_status, 0}, |
1048 | {"i915_opregion", i915_opregion, 0}, | ||
1049 | {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, | ||
848 | }; | 1050 | }; |
849 | #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) | 1051 | #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) |
850 | 1052 | ||
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2dd2c93ebfa3..251987307ebe 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -40,8 +40,7 @@ | |||
40 | #include <linux/pnp.h> | 40 | #include <linux/pnp.h> |
41 | #include <linux/vga_switcheroo.h> | 41 | #include <linux/vga_switcheroo.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | 43 | #include <acpi/video.h> | |
44 | extern int intel_max_stolen; /* from AGP driver */ | ||
45 | 44 | ||
46 | /** | 45 | /** |
47 | * Sets up the hardware status page for devices that need a physical address | 46 | * Sets up the hardware status page for devices that need a physical address |
@@ -64,7 +63,7 @@ static int i915_init_phys_hws(struct drm_device *dev) | |||
64 | 63 | ||
65 | memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE); | 64 | memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE); |
66 | 65 | ||
67 | if (IS_I965G(dev)) | 66 | if (INTEL_INFO(dev)->gen >= 4) |
68 | dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & | 67 | dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & |
69 | 0xf0; | 68 | 0xf0; |
70 | 69 | ||
@@ -222,7 +221,7 @@ static int i915_dma_resume(struct drm_device * dev) | |||
222 | DRM_DEBUG_DRIVER("hw status page @ %p\n", | 221 | DRM_DEBUG_DRIVER("hw status page @ %p\n", |
223 | ring->status_page.page_addr); | 222 | ring->status_page.page_addr); |
224 | if (ring->status_page.gfx_addr != 0) | 223 | if (ring->status_page.gfx_addr != 0) |
225 | ring->setup_status_page(dev, ring); | 224 | intel_ring_setup_status_page(dev, ring); |
226 | else | 225 | else |
227 | I915_WRITE(HWS_PGA, dev_priv->dma_status_page); | 226 | I915_WRITE(HWS_PGA, dev_priv->dma_status_page); |
228 | 227 | ||
@@ -377,7 +376,7 @@ i915_emit_box(struct drm_device *dev, | |||
377 | return -EINVAL; | 376 | return -EINVAL; |
378 | } | 377 | } |
379 | 378 | ||
380 | if (IS_I965G(dev)) { | 379 | if (INTEL_INFO(dev)->gen >= 4) { |
381 | BEGIN_LP_RING(4); | 380 | BEGIN_LP_RING(4); |
382 | OUT_RING(GFX_OP_DRAWRECT_INFO_I965); | 381 | OUT_RING(GFX_OP_DRAWRECT_INFO_I965); |
383 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); | 382 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); |
@@ -481,7 +480,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, | |||
481 | 480 | ||
482 | if (!IS_I830(dev) && !IS_845G(dev)) { | 481 | if (!IS_I830(dev) && !IS_845G(dev)) { |
483 | BEGIN_LP_RING(2); | 482 | BEGIN_LP_RING(2); |
484 | if (IS_I965G(dev)) { | 483 | if (INTEL_INFO(dev)->gen >= 4) { |
485 | OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); | 484 | OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); |
486 | OUT_RING(batch->start); | 485 | OUT_RING(batch->start); |
487 | } else { | 486 | } else { |
@@ -888,12 +887,12 @@ static int | |||
888 | intel_alloc_mchbar_resource(struct drm_device *dev) | 887 | intel_alloc_mchbar_resource(struct drm_device *dev) |
889 | { | 888 | { |
890 | drm_i915_private_t *dev_priv = dev->dev_private; | 889 | drm_i915_private_t *dev_priv = dev->dev_private; |
891 | int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; | 890 | int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; |
892 | u32 temp_lo, temp_hi = 0; | 891 | u32 temp_lo, temp_hi = 0; |
893 | u64 mchbar_addr; | 892 | u64 mchbar_addr; |
894 | int ret; | 893 | int ret; |
895 | 894 | ||
896 | if (IS_I965G(dev)) | 895 | if (INTEL_INFO(dev)->gen >= 4) |
897 | pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); | 896 | pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); |
898 | pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); | 897 | pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); |
899 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; | 898 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; |
@@ -920,7 +919,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) | |||
920 | return ret; | 919 | return ret; |
921 | } | 920 | } |
922 | 921 | ||
923 | if (IS_I965G(dev)) | 922 | if (INTEL_INFO(dev)->gen >= 4) |
924 | pci_write_config_dword(dev_priv->bridge_dev, reg + 4, | 923 | pci_write_config_dword(dev_priv->bridge_dev, reg + 4, |
925 | upper_32_bits(dev_priv->mch_res.start)); | 924 | upper_32_bits(dev_priv->mch_res.start)); |
926 | 925 | ||
@@ -934,7 +933,7 @@ static void | |||
934 | intel_setup_mchbar(struct drm_device *dev) | 933 | intel_setup_mchbar(struct drm_device *dev) |
935 | { | 934 | { |
936 | drm_i915_private_t *dev_priv = dev->dev_private; | 935 | drm_i915_private_t *dev_priv = dev->dev_private; |
937 | int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; | 936 | int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; |
938 | u32 temp; | 937 | u32 temp; |
939 | bool enabled; | 938 | bool enabled; |
940 | 939 | ||
@@ -971,7 +970,7 @@ static void | |||
971 | intel_teardown_mchbar(struct drm_device *dev) | 970 | intel_teardown_mchbar(struct drm_device *dev) |
972 | { | 971 | { |
973 | drm_i915_private_t *dev_priv = dev->dev_private; | 972 | drm_i915_private_t *dev_priv = dev->dev_private; |
974 | int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; | 973 | int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; |
975 | u32 temp; | 974 | u32 temp; |
976 | 975 | ||
977 | if (dev_priv->mchbar_need_disable) { | 976 | if (dev_priv->mchbar_need_disable) { |
@@ -990,174 +989,6 @@ intel_teardown_mchbar(struct drm_device *dev) | |||
990 | release_resource(&dev_priv->mch_res); | 989 | release_resource(&dev_priv->mch_res); |
991 | } | 990 | } |
992 | 991 | ||
993 | /** | ||
994 | * i915_probe_agp - get AGP bootup configuration | ||
995 | * @pdev: PCI device | ||
996 | * @aperture_size: returns AGP aperture configured size | ||
997 | * @preallocated_size: returns size of BIOS preallocated AGP space | ||
998 | * | ||
999 | * Since Intel integrated graphics are UMA, the BIOS has to set aside | ||
1000 | * some RAM for the framebuffer at early boot. This code figures out | ||
1001 | * how much was set aside so we can use it for our own purposes. | ||
1002 | */ | ||
1003 | static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, | ||
1004 | uint32_t *preallocated_size, | ||
1005 | uint32_t *start) | ||
1006 | { | ||
1007 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1008 | u16 tmp = 0; | ||
1009 | unsigned long overhead; | ||
1010 | unsigned long stolen; | ||
1011 | |||
1012 | /* Get the fb aperture size and "stolen" memory amount. */ | ||
1013 | pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp); | ||
1014 | |||
1015 | *aperture_size = 1024 * 1024; | ||
1016 | *preallocated_size = 1024 * 1024; | ||
1017 | |||
1018 | switch (dev->pdev->device) { | ||
1019 | case PCI_DEVICE_ID_INTEL_82830_CGC: | ||
1020 | case PCI_DEVICE_ID_INTEL_82845G_IG: | ||
1021 | case PCI_DEVICE_ID_INTEL_82855GM_IG: | ||
1022 | case PCI_DEVICE_ID_INTEL_82865_IG: | ||
1023 | if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) | ||
1024 | *aperture_size *= 64; | ||
1025 | else | ||
1026 | *aperture_size *= 128; | ||
1027 | break; | ||
1028 | default: | ||
1029 | /* 9xx supports large sizes, just look at the length */ | ||
1030 | *aperture_size = pci_resource_len(dev->pdev, 2); | ||
1031 | break; | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * Some of the preallocated space is taken by the GTT | ||
1036 | * and popup. GTT is 1K per MB of aperture size, and popup is 4K. | ||
1037 | */ | ||
1038 | if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) | ||
1039 | overhead = 4096; | ||
1040 | else | ||
1041 | overhead = (*aperture_size / 1024) + 4096; | ||
1042 | |||
1043 | if (IS_GEN6(dev)) { | ||
1044 | /* SNB has memory control reg at 0x50.w */ | ||
1045 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &tmp); | ||
1046 | |||
1047 | switch (tmp & SNB_GMCH_GMS_STOLEN_MASK) { | ||
1048 | case INTEL_855_GMCH_GMS_DISABLED: | ||
1049 | DRM_ERROR("video memory is disabled\n"); | ||
1050 | return -1; | ||
1051 | case SNB_GMCH_GMS_STOLEN_32M: | ||
1052 | stolen = 32 * 1024 * 1024; | ||
1053 | break; | ||
1054 | case SNB_GMCH_GMS_STOLEN_64M: | ||
1055 | stolen = 64 * 1024 * 1024; | ||
1056 | break; | ||
1057 | case SNB_GMCH_GMS_STOLEN_96M: | ||
1058 | stolen = 96 * 1024 * 1024; | ||
1059 | break; | ||
1060 | case SNB_GMCH_GMS_STOLEN_128M: | ||
1061 | stolen = 128 * 1024 * 1024; | ||
1062 | break; | ||
1063 | case SNB_GMCH_GMS_STOLEN_160M: | ||
1064 | stolen = 160 * 1024 * 1024; | ||
1065 | break; | ||
1066 | case SNB_GMCH_GMS_STOLEN_192M: | ||
1067 | stolen = 192 * 1024 * 1024; | ||
1068 | break; | ||
1069 | case SNB_GMCH_GMS_STOLEN_224M: | ||
1070 | stolen = 224 * 1024 * 1024; | ||
1071 | break; | ||
1072 | case SNB_GMCH_GMS_STOLEN_256M: | ||
1073 | stolen = 256 * 1024 * 1024; | ||
1074 | break; | ||
1075 | case SNB_GMCH_GMS_STOLEN_288M: | ||
1076 | stolen = 288 * 1024 * 1024; | ||
1077 | break; | ||
1078 | case SNB_GMCH_GMS_STOLEN_320M: | ||
1079 | stolen = 320 * 1024 * 1024; | ||
1080 | break; | ||
1081 | case SNB_GMCH_GMS_STOLEN_352M: | ||
1082 | stolen = 352 * 1024 * 1024; | ||
1083 | break; | ||
1084 | case SNB_GMCH_GMS_STOLEN_384M: | ||
1085 | stolen = 384 * 1024 * 1024; | ||
1086 | break; | ||
1087 | case SNB_GMCH_GMS_STOLEN_416M: | ||
1088 | stolen = 416 * 1024 * 1024; | ||
1089 | break; | ||
1090 | case SNB_GMCH_GMS_STOLEN_448M: | ||
1091 | stolen = 448 * 1024 * 1024; | ||
1092 | break; | ||
1093 | case SNB_GMCH_GMS_STOLEN_480M: | ||
1094 | stolen = 480 * 1024 * 1024; | ||
1095 | break; | ||
1096 | case SNB_GMCH_GMS_STOLEN_512M: | ||
1097 | stolen = 512 * 1024 * 1024; | ||
1098 | break; | ||
1099 | default: | ||
1100 | DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", | ||
1101 | tmp & SNB_GMCH_GMS_STOLEN_MASK); | ||
1102 | return -1; | ||
1103 | } | ||
1104 | } else { | ||
1105 | switch (tmp & INTEL_GMCH_GMS_MASK) { | ||
1106 | case INTEL_855_GMCH_GMS_DISABLED: | ||
1107 | DRM_ERROR("video memory is disabled\n"); | ||
1108 | return -1; | ||
1109 | case INTEL_855_GMCH_GMS_STOLEN_1M: | ||
1110 | stolen = 1 * 1024 * 1024; | ||
1111 | break; | ||
1112 | case INTEL_855_GMCH_GMS_STOLEN_4M: | ||
1113 | stolen = 4 * 1024 * 1024; | ||
1114 | break; | ||
1115 | case INTEL_855_GMCH_GMS_STOLEN_8M: | ||
1116 | stolen = 8 * 1024 * 1024; | ||
1117 | break; | ||
1118 | case INTEL_855_GMCH_GMS_STOLEN_16M: | ||
1119 | stolen = 16 * 1024 * 1024; | ||
1120 | break; | ||
1121 | case INTEL_855_GMCH_GMS_STOLEN_32M: | ||
1122 | stolen = 32 * 1024 * 1024; | ||
1123 | break; | ||
1124 | case INTEL_915G_GMCH_GMS_STOLEN_48M: | ||
1125 | stolen = 48 * 1024 * 1024; | ||
1126 | break; | ||
1127 | case INTEL_915G_GMCH_GMS_STOLEN_64M: | ||
1128 | stolen = 64 * 1024 * 1024; | ||
1129 | break; | ||
1130 | case INTEL_GMCH_GMS_STOLEN_128M: | ||
1131 | stolen = 128 * 1024 * 1024; | ||
1132 | break; | ||
1133 | case INTEL_GMCH_GMS_STOLEN_256M: | ||
1134 | stolen = 256 * 1024 * 1024; | ||
1135 | break; | ||
1136 | case INTEL_GMCH_GMS_STOLEN_96M: | ||
1137 | stolen = 96 * 1024 * 1024; | ||
1138 | break; | ||
1139 | case INTEL_GMCH_GMS_STOLEN_160M: | ||
1140 | stolen = 160 * 1024 * 1024; | ||
1141 | break; | ||
1142 | case INTEL_GMCH_GMS_STOLEN_224M: | ||
1143 | stolen = 224 * 1024 * 1024; | ||
1144 | break; | ||
1145 | case INTEL_GMCH_GMS_STOLEN_352M: | ||
1146 | stolen = 352 * 1024 * 1024; | ||
1147 | break; | ||
1148 | default: | ||
1149 | DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", | ||
1150 | tmp & INTEL_GMCH_GMS_MASK); | ||
1151 | return -1; | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | *preallocated_size = stolen - overhead; | ||
1156 | *start = overhead; | ||
1157 | |||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | #define PTE_ADDRESS_MASK 0xfffff000 | 992 | #define PTE_ADDRESS_MASK 0xfffff000 |
1162 | #define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */ | 993 | #define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */ |
1163 | #define PTE_MAPPING_TYPE_UNCACHED (0 << 1) | 994 | #define PTE_MAPPING_TYPE_UNCACHED (0 << 1) |
@@ -1181,11 +1012,11 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, | |||
1181 | { | 1012 | { |
1182 | unsigned long *gtt; | 1013 | unsigned long *gtt; |
1183 | unsigned long entry, phys; | 1014 | unsigned long entry, phys; |
1184 | int gtt_bar = IS_I9XX(dev) ? 0 : 1; | 1015 | int gtt_bar = IS_GEN2(dev) ? 1 : 0; |
1185 | int gtt_offset, gtt_size; | 1016 | int gtt_offset, gtt_size; |
1186 | 1017 | ||
1187 | if (IS_I965G(dev)) { | 1018 | if (INTEL_INFO(dev)->gen >= 4) { |
1188 | if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) { | 1019 | if (IS_G4X(dev) || INTEL_INFO(dev)->gen > 4) { |
1189 | gtt_offset = 2*1024*1024; | 1020 | gtt_offset = 2*1024*1024; |
1190 | gtt_size = 2*1024*1024; | 1021 | gtt_size = 2*1024*1024; |
1191 | } else { | 1022 | } else { |
@@ -1210,10 +1041,8 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, | |||
1210 | DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); | 1041 | DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); |
1211 | 1042 | ||
1212 | /* Mask out these reserved bits on this hardware. */ | 1043 | /* Mask out these reserved bits on this hardware. */ |
1213 | if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) || | 1044 | if (INTEL_INFO(dev)->gen < 4 && !IS_G33(dev)) |
1214 | IS_I945G(dev) || IS_I945GM(dev)) { | ||
1215 | entry &= ~PTE_ADDRESS_MASK_HIGH; | 1045 | entry &= ~PTE_ADDRESS_MASK_HIGH; |
1216 | } | ||
1217 | 1046 | ||
1218 | /* If it's not a mapping type we know, then bail. */ | 1047 | /* If it's not a mapping type we know, then bail. */ |
1219 | if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED && | 1048 | if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED && |
@@ -1252,7 +1081,7 @@ static void i915_setup_compression(struct drm_device *dev, int size) | |||
1252 | unsigned long ll_base = 0; | 1081 | unsigned long ll_base = 0; |
1253 | 1082 | ||
1254 | /* Leave 1M for line length buffer & misc. */ | 1083 | /* Leave 1M for line length buffer & misc. */ |
1255 | compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0); | 1084 | compressed_fb = drm_mm_search_free(&dev_priv->mm.vram, size, 4096, 0); |
1256 | if (!compressed_fb) { | 1085 | if (!compressed_fb) { |
1257 | dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; | 1086 | dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; |
1258 | i915_warn_stolen(dev); | 1087 | i915_warn_stolen(dev); |
@@ -1273,7 +1102,7 @@ static void i915_setup_compression(struct drm_device *dev, int size) | |||
1273 | } | 1102 | } |
1274 | 1103 | ||
1275 | if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) { | 1104 | if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) { |
1276 | compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, | 1105 | compressed_llb = drm_mm_search_free(&dev_priv->mm.vram, 4096, |
1277 | 4096, 0); | 1106 | 4096, 0); |
1278 | if (!compressed_llb) { | 1107 | if (!compressed_llb) { |
1279 | i915_warn_stolen(dev); | 1108 | i915_warn_stolen(dev); |
@@ -1343,10 +1172,8 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ | |||
1343 | /* i915 resume handler doesn't set to D0 */ | 1172 | /* i915 resume handler doesn't set to D0 */ |
1344 | pci_set_power_state(dev->pdev, PCI_D0); | 1173 | pci_set_power_state(dev->pdev, PCI_D0); |
1345 | i915_resume(dev); | 1174 | i915_resume(dev); |
1346 | drm_kms_helper_poll_enable(dev); | ||
1347 | } else { | 1175 | } else { |
1348 | printk(KERN_ERR "i915: switched off\n"); | 1176 | printk(KERN_ERR "i915: switched off\n"); |
1349 | drm_kms_helper_poll_disable(dev); | ||
1350 | i915_suspend(dev, pmm); | 1177 | i915_suspend(dev, pmm); |
1351 | } | 1178 | } |
1352 | } | 1179 | } |
@@ -1363,20 +1190,14 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) | |||
1363 | } | 1190 | } |
1364 | 1191 | ||
1365 | static int i915_load_modeset_init(struct drm_device *dev, | 1192 | static int i915_load_modeset_init(struct drm_device *dev, |
1366 | unsigned long prealloc_start, | ||
1367 | unsigned long prealloc_size, | 1193 | unsigned long prealloc_size, |
1368 | unsigned long agp_size) | 1194 | unsigned long agp_size) |
1369 | { | 1195 | { |
1370 | struct drm_i915_private *dev_priv = dev->dev_private; | 1196 | struct drm_i915_private *dev_priv = dev->dev_private; |
1371 | int fb_bar = IS_I9XX(dev) ? 2 : 0; | ||
1372 | int ret = 0; | 1197 | int ret = 0; |
1373 | 1198 | ||
1374 | dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) & | 1199 | /* Basic memrange allocator for stolen space (aka mm.vram) */ |
1375 | 0xff000000; | 1200 | drm_mm_init(&dev_priv->mm.vram, 0, prealloc_size); |
1376 | |||
1377 | /* Basic memrange allocator for stolen space (aka vram) */ | ||
1378 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); | ||
1379 | DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024)); | ||
1380 | 1201 | ||
1381 | /* We're off and running w/KMS */ | 1202 | /* We're off and running w/KMS */ |
1382 | dev_priv->mm.suspended = 0; | 1203 | dev_priv->mm.suspended = 0; |
@@ -1443,12 +1264,6 @@ static int i915_load_modeset_init(struct drm_device *dev, | |||
1443 | /* FIXME: do pre/post-mode set stuff in core KMS code */ | 1264 | /* FIXME: do pre/post-mode set stuff in core KMS code */ |
1444 | dev->vblank_disable_allowed = 1; | 1265 | dev->vblank_disable_allowed = 1; |
1445 | 1266 | ||
1446 | /* | ||
1447 | * Initialize the hardware status page IRQ location. | ||
1448 | */ | ||
1449 | |||
1450 | I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); | ||
1451 | |||
1452 | ret = intel_fbdev_init(dev); | 1267 | ret = intel_fbdev_init(dev); |
1453 | if (ret) | 1268 | if (ret) |
1454 | goto cleanup_irq; | 1269 | goto cleanup_irq; |
@@ -1907,7 +1722,7 @@ static struct drm_i915_private *i915_mch_dev; | |||
1907 | * - dev_priv->fmax | 1722 | * - dev_priv->fmax |
1908 | * - dev_priv->gpu_busy | 1723 | * - dev_priv->gpu_busy |
1909 | */ | 1724 | */ |
1910 | DEFINE_SPINLOCK(mchdev_lock); | 1725 | static DEFINE_SPINLOCK(mchdev_lock); |
1911 | 1726 | ||
1912 | /** | 1727 | /** |
1913 | * i915_read_mch_val - return value for IPS use | 1728 | * i915_read_mch_val - return value for IPS use |
@@ -2062,7 +1877,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2062 | struct drm_i915_private *dev_priv; | 1877 | struct drm_i915_private *dev_priv; |
2063 | resource_size_t base, size; | 1878 | resource_size_t base, size; |
2064 | int ret = 0, mmio_bar; | 1879 | int ret = 0, mmio_bar; |
2065 | uint32_t agp_size, prealloc_size, prealloc_start; | 1880 | uint32_t agp_size, prealloc_size; |
2066 | /* i915 has 4 more counters */ | 1881 | /* i915 has 4 more counters */ |
2067 | dev->counters += 4; | 1882 | dev->counters += 4; |
2068 | dev->types[6] = _DRM_STAT_IRQ; | 1883 | dev->types[6] = _DRM_STAT_IRQ; |
@@ -2079,7 +1894,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2079 | dev_priv->info = (struct intel_device_info *) flags; | 1894 | dev_priv->info = (struct intel_device_info *) flags; |
2080 | 1895 | ||
2081 | /* Add register map (needed for suspend/resume) */ | 1896 | /* Add register map (needed for suspend/resume) */ |
2082 | mmio_bar = IS_I9XX(dev) ? 0 : 1; | 1897 | mmio_bar = IS_GEN2(dev) ? 1 : 0; |
2083 | base = pci_resource_start(dev->pdev, mmio_bar); | 1898 | base = pci_resource_start(dev->pdev, mmio_bar); |
2084 | size = pci_resource_len(dev->pdev, mmio_bar); | 1899 | size = pci_resource_len(dev->pdev, mmio_bar); |
2085 | 1900 | ||
@@ -2121,17 +1936,32 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2121 | "performance may suffer.\n"); | 1936 | "performance may suffer.\n"); |
2122 | } | 1937 | } |
2123 | 1938 | ||
2124 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size, &prealloc_start); | 1939 | dev_priv->mm.gtt = intel_gtt_get(); |
2125 | if (ret) | 1940 | if (!dev_priv->mm.gtt) { |
1941 | DRM_ERROR("Failed to initialize GTT\n"); | ||
1942 | ret = -ENODEV; | ||
2126 | goto out_iomapfree; | 1943 | goto out_iomapfree; |
2127 | |||
2128 | if (prealloc_size > intel_max_stolen) { | ||
2129 | DRM_INFO("detected %dM stolen memory, trimming to %dM\n", | ||
2130 | prealloc_size >> 20, intel_max_stolen >> 20); | ||
2131 | prealloc_size = intel_max_stolen; | ||
2132 | } | 1944 | } |
2133 | 1945 | ||
2134 | dev_priv->wq = create_singlethread_workqueue("i915"); | 1946 | prealloc_size = dev_priv->mm.gtt->gtt_stolen_entries << PAGE_SHIFT; |
1947 | agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; | ||
1948 | |||
1949 | /* The i915 workqueue is primarily used for batched retirement of | ||
1950 | * requests (and thus managing bo) once the task has been completed | ||
1951 | * by the GPU. i915_gem_retire_requests() is called directly when we | ||
1952 | * need high-priority retirement, such as waiting for an explicit | ||
1953 | * bo. | ||
1954 | * | ||
1955 | * It is also used for periodic low-priority events, such as | ||
1956 | * idle-timers and hangcheck. | ||
1957 | * | ||
1958 | * All tasks on the workqueue are expected to acquire the dev mutex | ||
1959 | * so there is no point in running more than one instance of the | ||
1960 | * workqueue at any time: max_active = 1 and NON_REENTRANT. | ||
1961 | */ | ||
1962 | dev_priv->wq = alloc_workqueue("i915", | ||
1963 | WQ_UNBOUND | WQ_NON_REENTRANT, | ||
1964 | 1); | ||
2135 | if (dev_priv->wq == NULL) { | 1965 | if (dev_priv->wq == NULL) { |
2136 | DRM_ERROR("Failed to create our workqueue.\n"); | 1966 | DRM_ERROR("Failed to create our workqueue.\n"); |
2137 | ret = -ENOMEM; | 1967 | ret = -ENOMEM; |
@@ -2166,6 +1996,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2166 | 1996 | ||
2167 | /* Try to make sure MCHBAR is enabled before poking at it */ | 1997 | /* Try to make sure MCHBAR is enabled before poking at it */ |
2168 | intel_setup_mchbar(dev); | 1998 | intel_setup_mchbar(dev); |
1999 | intel_setup_gmbus(dev); | ||
2000 | intel_opregion_setup(dev); | ||
2169 | 2001 | ||
2170 | i915_gem_load(dev); | 2002 | i915_gem_load(dev); |
2171 | 2003 | ||
@@ -2212,8 +2044,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2212 | intel_detect_pch(dev); | 2044 | intel_detect_pch(dev); |
2213 | 2045 | ||
2214 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 2046 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
2215 | ret = i915_load_modeset_init(dev, prealloc_start, | 2047 | ret = i915_load_modeset_init(dev, prealloc_size, agp_size); |
2216 | prealloc_size, agp_size); | ||
2217 | if (ret < 0) { | 2048 | if (ret < 0) { |
2218 | DRM_ERROR("failed to init modeset\n"); | 2049 | DRM_ERROR("failed to init modeset\n"); |
2219 | goto out_workqueue_free; | 2050 | goto out_workqueue_free; |
@@ -2221,7 +2052,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2221 | } | 2052 | } |
2222 | 2053 | ||
2223 | /* Must be done after probing outputs */ | 2054 | /* Must be done after probing outputs */ |
2224 | intel_opregion_init(dev, 0); | 2055 | intel_opregion_init(dev); |
2056 | acpi_video_register(); | ||
2225 | 2057 | ||
2226 | setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, | 2058 | setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, |
2227 | (unsigned long) dev); | 2059 | (unsigned long) dev); |
@@ -2252,15 +2084,20 @@ free_priv: | |||
2252 | int i915_driver_unload(struct drm_device *dev) | 2084 | int i915_driver_unload(struct drm_device *dev) |
2253 | { | 2085 | { |
2254 | struct drm_i915_private *dev_priv = dev->dev_private; | 2086 | struct drm_i915_private *dev_priv = dev->dev_private; |
2255 | 2087 | int ret; | |
2256 | i915_destroy_error_state(dev); | ||
2257 | 2088 | ||
2258 | spin_lock(&mchdev_lock); | 2089 | spin_lock(&mchdev_lock); |
2259 | i915_mch_dev = NULL; | 2090 | i915_mch_dev = NULL; |
2260 | spin_unlock(&mchdev_lock); | 2091 | spin_unlock(&mchdev_lock); |
2261 | 2092 | ||
2262 | destroy_workqueue(dev_priv->wq); | 2093 | mutex_lock(&dev->struct_mutex); |
2263 | del_timer_sync(&dev_priv->hangcheck_timer); | 2094 | ret = i915_gpu_idle(dev); |
2095 | if (ret) | ||
2096 | DRM_ERROR("failed to idle hardware: %d\n", ret); | ||
2097 | mutex_unlock(&dev->struct_mutex); | ||
2098 | |||
2099 | /* Cancel the retire work handler, which should be idle now. */ | ||
2100 | cancel_delayed_work_sync(&dev_priv->mm.retire_work); | ||
2264 | 2101 | ||
2265 | io_mapping_free(dev_priv->mm.gtt_mapping); | 2102 | io_mapping_free(dev_priv->mm.gtt_mapping); |
2266 | if (dev_priv->mm.gtt_mtrr >= 0) { | 2103 | if (dev_priv->mm.gtt_mtrr >= 0) { |
@@ -2269,7 +2106,10 @@ int i915_driver_unload(struct drm_device *dev) | |||
2269 | dev_priv->mm.gtt_mtrr = -1; | 2106 | dev_priv->mm.gtt_mtrr = -1; |
2270 | } | 2107 | } |
2271 | 2108 | ||
2109 | acpi_video_unregister(); | ||
2110 | |||
2272 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 2111 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
2112 | intel_fbdev_fini(dev); | ||
2273 | intel_modeset_cleanup(dev); | 2113 | intel_modeset_cleanup(dev); |
2274 | 2114 | ||
2275 | /* | 2115 | /* |
@@ -2281,20 +2121,28 @@ int i915_driver_unload(struct drm_device *dev) | |||
2281 | dev_priv->child_dev = NULL; | 2121 | dev_priv->child_dev = NULL; |
2282 | dev_priv->child_dev_num = 0; | 2122 | dev_priv->child_dev_num = 0; |
2283 | } | 2123 | } |
2284 | drm_irq_uninstall(dev); | 2124 | |
2285 | vga_switcheroo_unregister_client(dev->pdev); | 2125 | vga_switcheroo_unregister_client(dev->pdev); |
2286 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 2126 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
2287 | } | 2127 | } |
2288 | 2128 | ||
2129 | /* Free error state after interrupts are fully disabled. */ | ||
2130 | del_timer_sync(&dev_priv->hangcheck_timer); | ||
2131 | cancel_work_sync(&dev_priv->error_work); | ||
2132 | i915_destroy_error_state(dev); | ||
2133 | |||
2289 | if (dev->pdev->msi_enabled) | 2134 | if (dev->pdev->msi_enabled) |
2290 | pci_disable_msi(dev->pdev); | 2135 | pci_disable_msi(dev->pdev); |
2291 | 2136 | ||
2292 | if (dev_priv->regs != NULL) | 2137 | if (dev_priv->regs != NULL) |
2293 | iounmap(dev_priv->regs); | 2138 | iounmap(dev_priv->regs); |
2294 | 2139 | ||
2295 | intel_opregion_free(dev, 0); | 2140 | intel_opregion_fini(dev); |
2296 | 2141 | ||
2297 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 2142 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
2143 | /* Flush any outstanding unpin_work. */ | ||
2144 | flush_workqueue(dev_priv->wq); | ||
2145 | |||
2298 | i915_gem_free_all_phys_object(dev); | 2146 | i915_gem_free_all_phys_object(dev); |
2299 | 2147 | ||
2300 | mutex_lock(&dev->struct_mutex); | 2148 | mutex_lock(&dev->struct_mutex); |
@@ -2302,34 +2150,35 @@ int i915_driver_unload(struct drm_device *dev) | |||
2302 | mutex_unlock(&dev->struct_mutex); | 2150 | mutex_unlock(&dev->struct_mutex); |
2303 | if (I915_HAS_FBC(dev) && i915_powersave) | 2151 | if (I915_HAS_FBC(dev) && i915_powersave) |
2304 | i915_cleanup_compression(dev); | 2152 | i915_cleanup_compression(dev); |
2305 | drm_mm_takedown(&dev_priv->vram); | 2153 | drm_mm_takedown(&dev_priv->mm.vram); |
2306 | i915_gem_lastclose(dev); | ||
2307 | 2154 | ||
2308 | intel_cleanup_overlay(dev); | 2155 | intel_cleanup_overlay(dev); |
2309 | } | 2156 | } |
2310 | 2157 | ||
2158 | intel_teardown_gmbus(dev); | ||
2311 | intel_teardown_mchbar(dev); | 2159 | intel_teardown_mchbar(dev); |
2312 | 2160 | ||
2161 | destroy_workqueue(dev_priv->wq); | ||
2162 | |||
2313 | pci_dev_put(dev_priv->bridge_dev); | 2163 | pci_dev_put(dev_priv->bridge_dev); |
2314 | kfree(dev->dev_private); | 2164 | kfree(dev->dev_private); |
2315 | 2165 | ||
2316 | return 0; | 2166 | return 0; |
2317 | } | 2167 | } |
2318 | 2168 | ||
2319 | int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) | 2169 | int i915_driver_open(struct drm_device *dev, struct drm_file *file) |
2320 | { | 2170 | { |
2321 | struct drm_i915_file_private *i915_file_priv; | 2171 | struct drm_i915_file_private *file_priv; |
2322 | 2172 | ||
2323 | DRM_DEBUG_DRIVER("\n"); | 2173 | DRM_DEBUG_DRIVER("\n"); |
2324 | i915_file_priv = (struct drm_i915_file_private *) | 2174 | file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL); |
2325 | kmalloc(sizeof(*i915_file_priv), GFP_KERNEL); | 2175 | if (!file_priv) |
2326 | |||
2327 | if (!i915_file_priv) | ||
2328 | return -ENOMEM; | 2176 | return -ENOMEM; |
2329 | 2177 | ||
2330 | file_priv->driver_priv = i915_file_priv; | 2178 | file->driver_priv = file_priv; |
2331 | 2179 | ||
2332 | INIT_LIST_HEAD(&i915_file_priv->mm.request_list); | 2180 | spin_lock_init(&file_priv->mm.lock); |
2181 | INIT_LIST_HEAD(&file_priv->mm.request_list); | ||
2333 | 2182 | ||
2334 | return 0; | 2183 | return 0; |
2335 | } | 2184 | } |
@@ -2372,11 +2221,11 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) | |||
2372 | i915_mem_release(dev, file_priv, dev_priv->agp_heap); | 2221 | i915_mem_release(dev, file_priv, dev_priv->agp_heap); |
2373 | } | 2222 | } |
2374 | 2223 | ||
2375 | void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) | 2224 | void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) |
2376 | { | 2225 | { |
2377 | struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; | 2226 | struct drm_i915_file_private *file_priv = file->driver_priv; |
2378 | 2227 | ||
2379 | kfree(i915_file_priv); | 2228 | kfree(file_priv); |
2380 | } | 2229 | } |
2381 | 2230 | ||
2382 | struct drm_ioctl_desc i915_ioctls[] = { | 2231 | struct drm_ioctl_desc i915_ioctls[] = { |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6dbe14cc4f74..c3decb2fef4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "drm.h" | 32 | #include "drm.h" |
33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
34 | #include "i915_drv.h" | 34 | #include "i915_drv.h" |
35 | #include "intel_drv.h" | ||
35 | 36 | ||
36 | #include <linux/console.h> | 37 | #include <linux/console.h> |
37 | #include "drm_crtc_helper.h" | 38 | #include "drm_crtc_helper.h" |
@@ -61,86 +62,108 @@ extern int intel_agp_enabled; | |||
61 | .driver_data = (unsigned long) info } | 62 | .driver_data = (unsigned long) info } |
62 | 63 | ||
63 | static const struct intel_device_info intel_i830_info = { | 64 | static const struct intel_device_info intel_i830_info = { |
64 | .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, | 65 | .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, |
66 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | static const struct intel_device_info intel_845g_info = { | 69 | static const struct intel_device_info intel_845g_info = { |
68 | .gen = 2, .is_i8xx = 1, | 70 | .gen = 2, |
71 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
69 | }; | 72 | }; |
70 | 73 | ||
71 | static const struct intel_device_info intel_i85x_info = { | 74 | static const struct intel_device_info intel_i85x_info = { |
72 | .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, | 75 | .gen = 2, .is_i85x = 1, .is_mobile = 1, |
73 | .cursor_needs_physical = 1, | 76 | .cursor_needs_physical = 1, |
77 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
74 | }; | 78 | }; |
75 | 79 | ||
76 | static const struct intel_device_info intel_i865g_info = { | 80 | static const struct intel_device_info intel_i865g_info = { |
77 | .gen = 2, .is_i8xx = 1, | 81 | .gen = 2, |
82 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
78 | }; | 83 | }; |
79 | 84 | ||
80 | static const struct intel_device_info intel_i915g_info = { | 85 | static const struct intel_device_info intel_i915g_info = { |
81 | .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, | 86 | .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, |
87 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
82 | }; | 88 | }; |
83 | static const struct intel_device_info intel_i915gm_info = { | 89 | static const struct intel_device_info intel_i915gm_info = { |
84 | .gen = 3, .is_i9xx = 1, .is_mobile = 1, | 90 | .gen = 3, .is_mobile = 1, |
85 | .cursor_needs_physical = 1, | 91 | .cursor_needs_physical = 1, |
92 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
93 | .supports_tv = 1, | ||
86 | }; | 94 | }; |
87 | static const struct intel_device_info intel_i945g_info = { | 95 | static const struct intel_device_info intel_i945g_info = { |
88 | .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, | 96 | .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, |
97 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
89 | }; | 98 | }; |
90 | static const struct intel_device_info intel_i945gm_info = { | 99 | static const struct intel_device_info intel_i945gm_info = { |
91 | .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, | 100 | .gen = 3, .is_i945gm = 1, .is_mobile = 1, |
92 | .has_hotplug = 1, .cursor_needs_physical = 1, | 101 | .has_hotplug = 1, .cursor_needs_physical = 1, |
102 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
103 | .supports_tv = 1, | ||
93 | }; | 104 | }; |
94 | 105 | ||
95 | static const struct intel_device_info intel_i965g_info = { | 106 | static const struct intel_device_info intel_i965g_info = { |
96 | .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, | 107 | .gen = 4, .is_broadwater = 1, |
97 | .has_hotplug = 1, | 108 | .has_hotplug = 1, |
109 | .has_overlay = 1, | ||
98 | }; | 110 | }; |
99 | 111 | ||
100 | static const struct intel_device_info intel_i965gm_info = { | 112 | static const struct intel_device_info intel_i965gm_info = { |
101 | .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, | 113 | .gen = 4, .is_crestline = 1, |
102 | .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, | 114 | .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, |
115 | .has_overlay = 1, | ||
116 | .supports_tv = 1, | ||
103 | }; | 117 | }; |
104 | 118 | ||
105 | static const struct intel_device_info intel_g33_info = { | 119 | static const struct intel_device_info intel_g33_info = { |
106 | .gen = 3, .is_g33 = 1, .is_i9xx = 1, | 120 | .gen = 3, .is_g33 = 1, |
107 | .need_gfx_hws = 1, .has_hotplug = 1, | 121 | .need_gfx_hws = 1, .has_hotplug = 1, |
122 | .has_overlay = 1, | ||
108 | }; | 123 | }; |
109 | 124 | ||
110 | static const struct intel_device_info intel_g45_info = { | 125 | static const struct intel_device_info intel_g45_info = { |
111 | .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, | 126 | .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, |
112 | .has_pipe_cxsr = 1, .has_hotplug = 1, | 127 | .has_pipe_cxsr = 1, .has_hotplug = 1, |
128 | .has_bsd_ring = 1, | ||
113 | }; | 129 | }; |
114 | 130 | ||
115 | static const struct intel_device_info intel_gm45_info = { | 131 | static const struct intel_device_info intel_gm45_info = { |
116 | .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, | 132 | .gen = 4, .is_g4x = 1, |
117 | .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, | 133 | .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, |
118 | .has_pipe_cxsr = 1, .has_hotplug = 1, | 134 | .has_pipe_cxsr = 1, .has_hotplug = 1, |
135 | .supports_tv = 1, | ||
136 | .has_bsd_ring = 1, | ||
119 | }; | 137 | }; |
120 | 138 | ||
121 | static const struct intel_device_info intel_pineview_info = { | 139 | static const struct intel_device_info intel_pineview_info = { |
122 | .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, | 140 | .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, |
123 | .need_gfx_hws = 1, .has_hotplug = 1, | 141 | .need_gfx_hws = 1, .has_hotplug = 1, |
142 | .has_overlay = 1, | ||
124 | }; | 143 | }; |
125 | 144 | ||
126 | static const struct intel_device_info intel_ironlake_d_info = { | 145 | static const struct intel_device_info intel_ironlake_d_info = { |
127 | .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, | 146 | .gen = 5, .is_ironlake = 1, |
128 | .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, | 147 | .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, |
148 | .has_bsd_ring = 1, | ||
129 | }; | 149 | }; |
130 | 150 | ||
131 | static const struct intel_device_info intel_ironlake_m_info = { | 151 | static const struct intel_device_info intel_ironlake_m_info = { |
132 | .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, | 152 | .gen = 5, .is_ironlake = 1, .is_mobile = 1, |
133 | .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, | 153 | .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, |
154 | .has_bsd_ring = 1, | ||
134 | }; | 155 | }; |
135 | 156 | ||
136 | static const struct intel_device_info intel_sandybridge_d_info = { | 157 | static const struct intel_device_info intel_sandybridge_d_info = { |
137 | .gen = 6, .is_i965g = 1, .is_i9xx = 1, | 158 | .gen = 6, |
138 | .need_gfx_hws = 1, .has_hotplug = 1, | 159 | .need_gfx_hws = 1, .has_hotplug = 1, |
160 | .has_bsd_ring = 1, | ||
139 | }; | 161 | }; |
140 | 162 | ||
141 | static const struct intel_device_info intel_sandybridge_m_info = { | 163 | static const struct intel_device_info intel_sandybridge_m_info = { |
142 | .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, | 164 | .gen = 6, .is_mobile = 1, |
143 | .need_gfx_hws = 1, .has_hotplug = 1, | 165 | .need_gfx_hws = 1, .has_hotplug = 1, |
166 | .has_bsd_ring = 1, | ||
144 | }; | 167 | }; |
145 | 168 | ||
146 | static const struct pci_device_id pciidlist[] = { /* aka */ | 169 | static const struct pci_device_id pciidlist[] = { /* aka */ |
@@ -237,7 +260,7 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
237 | 260 | ||
238 | i915_save_state(dev); | 261 | i915_save_state(dev); |
239 | 262 | ||
240 | intel_opregion_free(dev, 1); | 263 | intel_opregion_fini(dev); |
241 | 264 | ||
242 | /* Modeset on resume, not lid events */ | 265 | /* Modeset on resume, not lid events */ |
243 | dev_priv->modeset_on_lid = 0; | 266 | dev_priv->modeset_on_lid = 0; |
@@ -258,6 +281,8 @@ int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
258 | if (state.event == PM_EVENT_PRETHAW) | 281 | if (state.event == PM_EVENT_PRETHAW) |
259 | return 0; | 282 | return 0; |
260 | 283 | ||
284 | drm_kms_helper_poll_disable(dev); | ||
285 | |||
261 | error = i915_drm_freeze(dev); | 286 | error = i915_drm_freeze(dev); |
262 | if (error) | 287 | if (error) |
263 | return error; | 288 | return error; |
@@ -277,8 +302,7 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
277 | int error = 0; | 302 | int error = 0; |
278 | 303 | ||
279 | i915_restore_state(dev); | 304 | i915_restore_state(dev); |
280 | 305 | intel_opregion_setup(dev); | |
281 | intel_opregion_init(dev, 1); | ||
282 | 306 | ||
283 | /* KMS EnterVT equivalent */ | 307 | /* KMS EnterVT equivalent */ |
284 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 308 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
@@ -294,6 +318,8 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
294 | drm_helper_resume_force_mode(dev); | 318 | drm_helper_resume_force_mode(dev); |
295 | } | 319 | } |
296 | 320 | ||
321 | intel_opregion_init(dev); | ||
322 | |||
297 | dev_priv->modeset_on_lid = 0; | 323 | dev_priv->modeset_on_lid = 0; |
298 | 324 | ||
299 | return error; | 325 | return error; |
@@ -301,12 +327,79 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
301 | 327 | ||
302 | int i915_resume(struct drm_device *dev) | 328 | int i915_resume(struct drm_device *dev) |
303 | { | 329 | { |
330 | int ret; | ||
331 | |||
304 | if (pci_enable_device(dev->pdev)) | 332 | if (pci_enable_device(dev->pdev)) |
305 | return -EIO; | 333 | return -EIO; |
306 | 334 | ||
307 | pci_set_master(dev->pdev); | 335 | pci_set_master(dev->pdev); |
308 | 336 | ||
309 | return i915_drm_thaw(dev); | 337 | ret = i915_drm_thaw(dev); |
338 | if (ret) | ||
339 | return ret; | ||
340 | |||
341 | drm_kms_helper_poll_enable(dev); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int i8xx_do_reset(struct drm_device *dev, u8 flags) | ||
346 | { | ||
347 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
348 | |||
349 | if (IS_I85X(dev)) | ||
350 | return -ENODEV; | ||
351 | |||
352 | I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830); | ||
353 | POSTING_READ(D_STATE); | ||
354 | |||
355 | if (IS_I830(dev) || IS_845G(dev)) { | ||
356 | I915_WRITE(DEBUG_RESET_I830, | ||
357 | DEBUG_RESET_DISPLAY | | ||
358 | DEBUG_RESET_RENDER | | ||
359 | DEBUG_RESET_FULL); | ||
360 | POSTING_READ(DEBUG_RESET_I830); | ||
361 | msleep(1); | ||
362 | |||
363 | I915_WRITE(DEBUG_RESET_I830, 0); | ||
364 | POSTING_READ(DEBUG_RESET_I830); | ||
365 | } | ||
366 | |||
367 | msleep(1); | ||
368 | |||
369 | I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830); | ||
370 | POSTING_READ(D_STATE); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static int i965_reset_complete(struct drm_device *dev) | ||
376 | { | ||
377 | u8 gdrst; | ||
378 | pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); | ||
379 | return gdrst & 0x1; | ||
380 | } | ||
381 | |||
382 | static int i965_do_reset(struct drm_device *dev, u8 flags) | ||
383 | { | ||
384 | u8 gdrst; | ||
385 | |||
386 | /* | ||
387 | * Set the domains we want to reset (GRDOM/bits 2 and 3) as | ||
388 | * well as the reset bit (GR/bit 0). Setting the GR bit | ||
389 | * triggers the reset; when done, the hardware will clear it. | ||
390 | */ | ||
391 | pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); | ||
392 | pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1); | ||
393 | |||
394 | return wait_for(i965_reset_complete(dev), 500); | ||
395 | } | ||
396 | |||
397 | static int ironlake_do_reset(struct drm_device *dev, u8 flags) | ||
398 | { | ||
399 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
400 | u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR); | ||
401 | I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1); | ||
402 | return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); | ||
310 | } | 403 | } |
311 | 404 | ||
312 | /** | 405 | /** |
@@ -325,54 +418,39 @@ int i915_resume(struct drm_device *dev) | |||
325 | * - re-init interrupt state | 418 | * - re-init interrupt state |
326 | * - re-init display | 419 | * - re-init display |
327 | */ | 420 | */ |
328 | int i965_reset(struct drm_device *dev, u8 flags) | 421 | int i915_reset(struct drm_device *dev, u8 flags) |
329 | { | 422 | { |
330 | drm_i915_private_t *dev_priv = dev->dev_private; | 423 | drm_i915_private_t *dev_priv = dev->dev_private; |
331 | unsigned long timeout; | ||
332 | u8 gdrst; | ||
333 | /* | 424 | /* |
334 | * We really should only reset the display subsystem if we actually | 425 | * We really should only reset the display subsystem if we actually |
335 | * need to | 426 | * need to |
336 | */ | 427 | */ |
337 | bool need_display = true; | 428 | bool need_display = true; |
429 | int ret; | ||
338 | 430 | ||
339 | mutex_lock(&dev->struct_mutex); | 431 | mutex_lock(&dev->struct_mutex); |
340 | 432 | ||
341 | /* | 433 | i915_gem_reset(dev); |
342 | * Clear request list | 434 | |
343 | */ | 435 | ret = -ENODEV; |
344 | i915_gem_retire_requests(dev); | 436 | if (get_seconds() - dev_priv->last_gpu_reset < 5) { |
345 | 437 | DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); | |
346 | if (need_display) | 438 | } else switch (INTEL_INFO(dev)->gen) { |
347 | i915_save_display(dev); | 439 | case 5: |
348 | 440 | ret = ironlake_do_reset(dev, flags); | |
349 | if (IS_I965G(dev) || IS_G4X(dev)) { | 441 | break; |
350 | /* | 442 | case 4: |
351 | * Set the domains we want to reset, then the reset bit (bit 0). | 443 | ret = i965_do_reset(dev, flags); |
352 | * Clear the reset bit after a while and wait for hardware status | 444 | break; |
353 | * bit (bit 1) to be set | 445 | case 2: |
354 | */ | 446 | ret = i8xx_do_reset(dev, flags); |
355 | pci_read_config_byte(dev->pdev, GDRST, &gdrst); | 447 | break; |
356 | pci_write_config_byte(dev->pdev, GDRST, gdrst | flags | ((flags == GDRST_FULL) ? 0x1 : 0x0)); | 448 | } |
357 | udelay(50); | 449 | dev_priv->last_gpu_reset = get_seconds(); |
358 | pci_write_config_byte(dev->pdev, GDRST, gdrst & 0xfe); | 450 | if (ret) { |
359 | 451 | DRM_ERROR("Failed to reset chip.\n"); | |
360 | /* ...we don't want to loop forever though, 500ms should be plenty */ | ||
361 | timeout = jiffies + msecs_to_jiffies(500); | ||
362 | do { | ||
363 | udelay(100); | ||
364 | pci_read_config_byte(dev->pdev, GDRST, &gdrst); | ||
365 | } while ((gdrst & 0x1) && time_after(timeout, jiffies)); | ||
366 | |||
367 | if (gdrst & 0x1) { | ||
368 | WARN(true, "i915: Failed to reset chip\n"); | ||
369 | mutex_unlock(&dev->struct_mutex); | ||
370 | return -EIO; | ||
371 | } | ||
372 | } else { | ||
373 | DRM_ERROR("Error occurred. Don't know how to reset this chip.\n"); | ||
374 | mutex_unlock(&dev->struct_mutex); | 452 | mutex_unlock(&dev->struct_mutex); |
375 | return -ENODEV; | 453 | return ret; |
376 | } | 454 | } |
377 | 455 | ||
378 | /* Ok, now get things going again... */ | 456 | /* Ok, now get things going again... */ |
@@ -400,13 +478,19 @@ int i965_reset(struct drm_device *dev, u8 flags) | |||
400 | mutex_lock(&dev->struct_mutex); | 478 | mutex_lock(&dev->struct_mutex); |
401 | } | 479 | } |
402 | 480 | ||
481 | mutex_unlock(&dev->struct_mutex); | ||
482 | |||
403 | /* | 483 | /* |
404 | * Display needs restore too... | 484 | * Perform a full modeset as on later generations, e.g. Ironlake, we may |
485 | * need to retrain the display link and cannot just restore the register | ||
486 | * values. | ||
405 | */ | 487 | */ |
406 | if (need_display) | 488 | if (need_display) { |
407 | i915_restore_display(dev); | 489 | mutex_lock(&dev->mode_config.mutex); |
490 | drm_helper_resume_force_mode(dev); | ||
491 | mutex_unlock(&dev->mode_config.mutex); | ||
492 | } | ||
408 | 493 | ||
409 | mutex_unlock(&dev->struct_mutex); | ||
410 | return 0; | 494 | return 0; |
411 | } | 495 | } |
412 | 496 | ||
@@ -524,8 +608,6 @@ static struct drm_driver driver = { | |||
524 | .irq_uninstall = i915_driver_irq_uninstall, | 608 | .irq_uninstall = i915_driver_irq_uninstall, |
525 | .irq_handler = i915_driver_irq_handler, | 609 | .irq_handler = i915_driver_irq_handler, |
526 | .reclaim_buffers = drm_core_reclaim_buffers, | 610 | .reclaim_buffers = drm_core_reclaim_buffers, |
527 | .get_map_ofs = drm_core_get_map_ofs, | ||
528 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
529 | .master_create = i915_master_create, | 611 | .master_create = i915_master_create, |
530 | .master_destroy = i915_master_destroy, | 612 | .master_destroy = i915_master_destroy, |
531 | #if defined(CONFIG_DEBUG_FS) | 613 | #if defined(CONFIG_DEBUG_FS) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index af4a263cf257..73ad8bff2c2a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "intel_bios.h" | 34 | #include "intel_bios.h" |
35 | #include "intel_ringbuffer.h" | 35 | #include "intel_ringbuffer.h" |
36 | #include <linux/io-mapping.h> | 36 | #include <linux/io-mapping.h> |
37 | #include <linux/i2c.h> | ||
38 | #include <drm/intel-gtt.h> | ||
37 | 39 | ||
38 | /* General customization: | 40 | /* General customization: |
39 | */ | 41 | */ |
@@ -73,11 +75,9 @@ enum plane { | |||
73 | #define DRIVER_PATCHLEVEL 0 | 75 | #define DRIVER_PATCHLEVEL 0 |
74 | 76 | ||
75 | #define WATCH_COHERENCY 0 | 77 | #define WATCH_COHERENCY 0 |
76 | #define WATCH_BUF 0 | ||
77 | #define WATCH_EXEC 0 | 78 | #define WATCH_EXEC 0 |
78 | #define WATCH_LRU 0 | ||
79 | #define WATCH_RELOC 0 | 79 | #define WATCH_RELOC 0 |
80 | #define WATCH_INACTIVE 0 | 80 | #define WATCH_LISTS 0 |
81 | #define WATCH_PWRITE 0 | 81 | #define WATCH_PWRITE 0 |
82 | 82 | ||
83 | #define I915_GEM_PHYS_CURSOR_0 1 | 83 | #define I915_GEM_PHYS_CURSOR_0 1 |
@@ -110,8 +110,9 @@ struct intel_opregion { | |||
110 | struct opregion_acpi *acpi; | 110 | struct opregion_acpi *acpi; |
111 | struct opregion_swsci *swsci; | 111 | struct opregion_swsci *swsci; |
112 | struct opregion_asle *asle; | 112 | struct opregion_asle *asle; |
113 | int enabled; | 113 | void *vbt; |
114 | }; | 114 | }; |
115 | #define OPREGION_SIZE (8*1024) | ||
115 | 116 | ||
116 | struct intel_overlay; | 117 | struct intel_overlay; |
117 | struct intel_overlay_error_state; | 118 | struct intel_overlay_error_state; |
@@ -125,13 +126,16 @@ struct drm_i915_master_private { | |||
125 | struct drm_i915_fence_reg { | 126 | struct drm_i915_fence_reg { |
126 | struct drm_gem_object *obj; | 127 | struct drm_gem_object *obj; |
127 | struct list_head lru_list; | 128 | struct list_head lru_list; |
129 | bool gpu; | ||
128 | }; | 130 | }; |
129 | 131 | ||
130 | struct sdvo_device_mapping { | 132 | struct sdvo_device_mapping { |
133 | u8 initialized; | ||
131 | u8 dvo_port; | 134 | u8 dvo_port; |
132 | u8 slave_addr; | 135 | u8 slave_addr; |
133 | u8 dvo_wiring; | 136 | u8 dvo_wiring; |
134 | u8 initialized; | 137 | u8 i2c_pin; |
138 | u8 i2c_speed; | ||
135 | u8 ddc_pin; | 139 | u8 ddc_pin; |
136 | }; | 140 | }; |
137 | 141 | ||
@@ -193,13 +197,9 @@ struct drm_i915_display_funcs { | |||
193 | struct intel_device_info { | 197 | struct intel_device_info { |
194 | u8 gen; | 198 | u8 gen; |
195 | u8 is_mobile : 1; | 199 | u8 is_mobile : 1; |
196 | u8 is_i8xx : 1; | ||
197 | u8 is_i85x : 1; | 200 | u8 is_i85x : 1; |
198 | u8 is_i915g : 1; | 201 | u8 is_i915g : 1; |
199 | u8 is_i9xx : 1; | ||
200 | u8 is_i945gm : 1; | 202 | u8 is_i945gm : 1; |
201 | u8 is_i965g : 1; | ||
202 | u8 is_i965gm : 1; | ||
203 | u8 is_g33 : 1; | 203 | u8 is_g33 : 1; |
204 | u8 need_gfx_hws : 1; | 204 | u8 need_gfx_hws : 1; |
205 | u8 is_g4x : 1; | 205 | u8 is_g4x : 1; |
@@ -212,9 +212,14 @@ struct intel_device_info { | |||
212 | u8 has_pipe_cxsr : 1; | 212 | u8 has_pipe_cxsr : 1; |
213 | u8 has_hotplug : 1; | 213 | u8 has_hotplug : 1; |
214 | u8 cursor_needs_physical : 1; | 214 | u8 cursor_needs_physical : 1; |
215 | u8 has_overlay : 1; | ||
216 | u8 overlay_needs_physical : 1; | ||
217 | u8 supports_tv : 1; | ||
218 | u8 has_bsd_ring : 1; | ||
215 | }; | 219 | }; |
216 | 220 | ||
217 | enum no_fbc_reason { | 221 | enum no_fbc_reason { |
222 | FBC_NO_OUTPUT, /* no outputs enabled to compress */ | ||
218 | FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ | 223 | FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ |
219 | FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */ | 224 | FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */ |
220 | FBC_MODE_TOO_LARGE, /* mode too large for compression */ | 225 | FBC_MODE_TOO_LARGE, /* mode too large for compression */ |
@@ -241,6 +246,12 @@ typedef struct drm_i915_private { | |||
241 | 246 | ||
242 | void __iomem *regs; | 247 | void __iomem *regs; |
243 | 248 | ||
249 | struct intel_gmbus { | ||
250 | struct i2c_adapter adapter; | ||
251 | struct i2c_adapter *force_bit; | ||
252 | u32 reg0; | ||
253 | } *gmbus; | ||
254 | |||
244 | struct pci_dev *bridge_dev; | 255 | struct pci_dev *bridge_dev; |
245 | struct intel_ring_buffer render_ring; | 256 | struct intel_ring_buffer render_ring; |
246 | struct intel_ring_buffer bsd_ring; | 257 | struct intel_ring_buffer bsd_ring; |
@@ -263,6 +274,9 @@ typedef struct drm_i915_private { | |||
263 | int front_offset; | 274 | int front_offset; |
264 | int current_page; | 275 | int current_page; |
265 | int page_flipping; | 276 | int page_flipping; |
277 | #define I915_DEBUG_READ (1<<0) | ||
278 | #define I915_DEBUG_WRITE (1<<1) | ||
279 | unsigned long debug_flags; | ||
266 | 280 | ||
267 | wait_queue_head_t irq_queue; | 281 | wait_queue_head_t irq_queue; |
268 | atomic_t irq_received; | 282 | atomic_t irq_received; |
@@ -289,24 +303,21 @@ typedef struct drm_i915_private { | |||
289 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; | 303 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; |
290 | int vblank_pipe; | 304 | int vblank_pipe; |
291 | int num_pipe; | 305 | int num_pipe; |
292 | u32 flush_rings; | ||
293 | #define FLUSH_RENDER_RING 0x1 | ||
294 | #define FLUSH_BSD_RING 0x2 | ||
295 | 306 | ||
296 | /* For hangcheck timer */ | 307 | /* For hangcheck timer */ |
297 | #define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */ | 308 | #define DRM_I915_HANGCHECK_PERIOD 250 /* in ms */ |
298 | struct timer_list hangcheck_timer; | 309 | struct timer_list hangcheck_timer; |
299 | int hangcheck_count; | 310 | int hangcheck_count; |
300 | uint32_t last_acthd; | 311 | uint32_t last_acthd; |
301 | uint32_t last_instdone; | 312 | uint32_t last_instdone; |
302 | uint32_t last_instdone1; | 313 | uint32_t last_instdone1; |
303 | 314 | ||
304 | struct drm_mm vram; | ||
305 | |||
306 | unsigned long cfb_size; | 315 | unsigned long cfb_size; |
307 | unsigned long cfb_pitch; | 316 | unsigned long cfb_pitch; |
317 | unsigned long cfb_offset; | ||
308 | int cfb_fence; | 318 | int cfb_fence; |
309 | int cfb_plane; | 319 | int cfb_plane; |
320 | int cfb_y; | ||
310 | 321 | ||
311 | int irq_enabled; | 322 | int irq_enabled; |
312 | 323 | ||
@@ -316,8 +327,7 @@ typedef struct drm_i915_private { | |||
316 | struct intel_overlay *overlay; | 327 | struct intel_overlay *overlay; |
317 | 328 | ||
318 | /* LVDS info */ | 329 | /* LVDS info */ |
319 | int backlight_duty_cycle; /* restore backlight to this value */ | 330 | int backlight_level; /* restore backlight to this value */ |
320 | bool panel_wants_dither; | ||
321 | struct drm_display_mode *panel_fixed_mode; | 331 | struct drm_display_mode *panel_fixed_mode; |
322 | struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ | 332 | struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ |
323 | struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ | 333 | struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ |
@@ -328,13 +338,22 @@ typedef struct drm_i915_private { | |||
328 | unsigned int lvds_vbt:1; | 338 | unsigned int lvds_vbt:1; |
329 | unsigned int int_crt_support:1; | 339 | unsigned int int_crt_support:1; |
330 | unsigned int lvds_use_ssc:1; | 340 | unsigned int lvds_use_ssc:1; |
331 | unsigned int edp_support:1; | ||
332 | int lvds_ssc_freq; | 341 | int lvds_ssc_freq; |
333 | int edp_bpp; | 342 | |
343 | struct { | ||
344 | u8 rate:4; | ||
345 | u8 lanes:4; | ||
346 | u8 preemphasis:4; | ||
347 | u8 vswing:4; | ||
348 | |||
349 | u8 initialized:1; | ||
350 | u8 support:1; | ||
351 | u8 bpp:6; | ||
352 | } edp; | ||
334 | 353 | ||
335 | struct notifier_block lid_notifier; | 354 | struct notifier_block lid_notifier; |
336 | 355 | ||
337 | int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */ | 356 | int crt_ddc_pin; |
338 | struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ | 357 | struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ |
339 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ | 358 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ |
340 | int num_fence_regs; /* 8 on pre-965, 16 otherwise */ | 359 | int num_fence_regs; /* 8 on pre-965, 16 otherwise */ |
@@ -344,6 +363,7 @@ typedef struct drm_i915_private { | |||
344 | spinlock_t error_lock; | 363 | spinlock_t error_lock; |
345 | struct drm_i915_error_state *first_error; | 364 | struct drm_i915_error_state *first_error; |
346 | struct work_struct error_work; | 365 | struct work_struct error_work; |
366 | struct completion error_completion; | ||
347 | struct workqueue_struct *wq; | 367 | struct workqueue_struct *wq; |
348 | 368 | ||
349 | /* Display functions */ | 369 | /* Display functions */ |
@@ -507,6 +527,11 @@ typedef struct drm_i915_private { | |||
507 | u32 saveMCHBAR_RENDER_STANDBY; | 527 | u32 saveMCHBAR_RENDER_STANDBY; |
508 | 528 | ||
509 | struct { | 529 | struct { |
530 | /** Bridge to intel-gtt-ko */ | ||
531 | struct intel_gtt *gtt; | ||
532 | /** Memory allocator for GTT stolen memory */ | ||
533 | struct drm_mm vram; | ||
534 | /** Memory allocator for GTT */ | ||
510 | struct drm_mm gtt_space; | 535 | struct drm_mm gtt_space; |
511 | 536 | ||
512 | struct io_mapping *gtt_mapping; | 537 | struct io_mapping *gtt_mapping; |
@@ -521,8 +546,6 @@ typedef struct drm_i915_private { | |||
521 | */ | 546 | */ |
522 | struct list_head shrink_list; | 547 | struct list_head shrink_list; |
523 | 548 | ||
524 | spinlock_t active_list_lock; | ||
525 | |||
526 | /** | 549 | /** |
527 | * List of objects which are not in the ringbuffer but which | 550 | * List of objects which are not in the ringbuffer but which |
528 | * still have a write_domain which needs to be flushed before | 551 | * still have a write_domain which needs to be flushed before |
@@ -555,6 +578,12 @@ typedef struct drm_i915_private { | |||
555 | */ | 578 | */ |
556 | struct list_head inactive_list; | 579 | struct list_head inactive_list; |
557 | 580 | ||
581 | /** | ||
582 | * LRU list of objects which are not in the ringbuffer but | ||
583 | * are still pinned in the GTT. | ||
584 | */ | ||
585 | struct list_head pinned_list; | ||
586 | |||
558 | /** LRU list of objects with fence regs on them. */ | 587 | /** LRU list of objects with fence regs on them. */ |
559 | struct list_head fence_list; | 588 | struct list_head fence_list; |
560 | 589 | ||
@@ -611,6 +640,17 @@ typedef struct drm_i915_private { | |||
611 | 640 | ||
612 | /* storage for physical objects */ | 641 | /* storage for physical objects */ |
613 | struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; | 642 | struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; |
643 | |||
644 | uint32_t flush_rings; | ||
645 | |||
646 | /* accounting, useful for userland debugging */ | ||
647 | size_t object_memory; | ||
648 | size_t pin_memory; | ||
649 | size_t gtt_memory; | ||
650 | size_t gtt_total; | ||
651 | u32 object_count; | ||
652 | u32 pin_count; | ||
653 | u32 gtt_count; | ||
614 | } mm; | 654 | } mm; |
615 | struct sdvo_device_mapping sdvo_mappings[2]; | 655 | struct sdvo_device_mapping sdvo_mappings[2]; |
616 | /* indicate whether the LVDS_BORDER should be enabled or not */ | 656 | /* indicate whether the LVDS_BORDER should be enabled or not */ |
@@ -626,8 +666,6 @@ typedef struct drm_i915_private { | |||
626 | /* Reclocking support */ | 666 | /* Reclocking support */ |
627 | bool render_reclock_avail; | 667 | bool render_reclock_avail; |
628 | bool lvds_downclock_avail; | 668 | bool lvds_downclock_avail; |
629 | /* indicate whether the LVDS EDID is OK */ | ||
630 | bool lvds_edid_good; | ||
631 | /* indicates the reduced downclock for LVDS*/ | 669 | /* indicates the reduced downclock for LVDS*/ |
632 | int lvds_downclock; | 670 | int lvds_downclock; |
633 | struct work_struct idle_work; | 671 | struct work_struct idle_work; |
@@ -661,6 +699,8 @@ typedef struct drm_i915_private { | |||
661 | struct drm_mm_node *compressed_fb; | 699 | struct drm_mm_node *compressed_fb; |
662 | struct drm_mm_node *compressed_llb; | 700 | struct drm_mm_node *compressed_llb; |
663 | 701 | ||
702 | unsigned long last_gpu_reset; | ||
703 | |||
664 | /* list of fbdev register on this device */ | 704 | /* list of fbdev register on this device */ |
665 | struct intel_fbdev *fbdev; | 705 | struct intel_fbdev *fbdev; |
666 | } drm_i915_private_t; | 706 | } drm_i915_private_t; |
@@ -816,12 +856,14 @@ struct drm_i915_gem_request { | |||
816 | /** global list entry for this request */ | 856 | /** global list entry for this request */ |
817 | struct list_head list; | 857 | struct list_head list; |
818 | 858 | ||
859 | struct drm_i915_file_private *file_priv; | ||
819 | /** file_priv list entry for this request */ | 860 | /** file_priv list entry for this request */ |
820 | struct list_head client_list; | 861 | struct list_head client_list; |
821 | }; | 862 | }; |
822 | 863 | ||
823 | struct drm_i915_file_private { | 864 | struct drm_i915_file_private { |
824 | struct { | 865 | struct { |
866 | struct spinlock lock; | ||
825 | struct list_head request_list; | 867 | struct list_head request_list; |
826 | } mm; | 868 | } mm; |
827 | }; | 869 | }; |
@@ -862,7 +904,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, | |||
862 | extern int i915_emit_box(struct drm_device *dev, | 904 | extern int i915_emit_box(struct drm_device *dev, |
863 | struct drm_clip_rect *boxes, | 905 | struct drm_clip_rect *boxes, |
864 | int i, int DR1, int DR4); | 906 | int i, int DR1, int DR4); |
865 | extern int i965_reset(struct drm_device *dev, u8 flags); | 907 | extern int i915_reset(struct drm_device *dev, u8 flags); |
866 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); | 908 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); |
867 | extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); | 909 | extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); |
868 | extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); | 910 | extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); |
@@ -871,7 +913,6 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); | |||
871 | 913 | ||
872 | /* i915_irq.c */ | 914 | /* i915_irq.c */ |
873 | void i915_hangcheck_elapsed(unsigned long data); | 915 | void i915_hangcheck_elapsed(unsigned long data); |
874 | void i915_destroy_error_state(struct drm_device *dev); | ||
875 | extern int i915_irq_emit(struct drm_device *dev, void *data, | 916 | extern int i915_irq_emit(struct drm_device *dev, void *data, |
876 | struct drm_file *file_priv); | 917 | struct drm_file *file_priv); |
877 | extern int i915_irq_wait(struct drm_device *dev, void *data, | 918 | extern int i915_irq_wait(struct drm_device *dev, void *data, |
@@ -908,6 +949,12 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); | |||
908 | 949 | ||
909 | void intel_enable_asle (struct drm_device *dev); | 950 | void intel_enable_asle (struct drm_device *dev); |
910 | 951 | ||
952 | #ifdef CONFIG_DEBUG_FS | ||
953 | extern void i915_destroy_error_state(struct drm_device *dev); | ||
954 | #else | ||
955 | #define i915_destroy_error_state(x) | ||
956 | #endif | ||
957 | |||
911 | 958 | ||
912 | /* i915_mem.c */ | 959 | /* i915_mem.c */ |
913 | extern int i915_mem_alloc(struct drm_device *dev, void *data, | 960 | extern int i915_mem_alloc(struct drm_device *dev, void *data, |
@@ -922,6 +969,7 @@ extern void i915_mem_takedown(struct mem_block **heap); | |||
922 | extern void i915_mem_release(struct drm_device * dev, | 969 | extern void i915_mem_release(struct drm_device * dev, |
923 | struct drm_file *file_priv, struct mem_block *heap); | 970 | struct drm_file *file_priv, struct mem_block *heap); |
924 | /* i915_gem.c */ | 971 | /* i915_gem.c */ |
972 | int i915_gem_check_is_wedged(struct drm_device *dev); | ||
925 | int i915_gem_init_ioctl(struct drm_device *dev, void *data, | 973 | int i915_gem_init_ioctl(struct drm_device *dev, void *data, |
926 | struct drm_file *file_priv); | 974 | struct drm_file *file_priv); |
927 | int i915_gem_create_ioctl(struct drm_device *dev, void *data, | 975 | int i915_gem_create_ioctl(struct drm_device *dev, void *data, |
@@ -972,13 +1020,22 @@ void i915_gem_object_unpin(struct drm_gem_object *obj); | |||
972 | int i915_gem_object_unbind(struct drm_gem_object *obj); | 1020 | int i915_gem_object_unbind(struct drm_gem_object *obj); |
973 | void i915_gem_release_mmap(struct drm_gem_object *obj); | 1021 | void i915_gem_release_mmap(struct drm_gem_object *obj); |
974 | void i915_gem_lastclose(struct drm_device *dev); | 1022 | void i915_gem_lastclose(struct drm_device *dev); |
975 | uint32_t i915_get_gem_seqno(struct drm_device *dev, | 1023 | |
976 | struct intel_ring_buffer *ring); | 1024 | /** |
977 | bool i915_seqno_passed(uint32_t seq1, uint32_t seq2); | 1025 | * Returns true if seq1 is later than seq2. |
978 | int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); | 1026 | */ |
979 | int i915_gem_object_put_fence_reg(struct drm_gem_object *obj); | 1027 | static inline bool |
1028 | i915_seqno_passed(uint32_t seq1, uint32_t seq2) | ||
1029 | { | ||
1030 | return (int32_t)(seq1 - seq2) >= 0; | ||
1031 | } | ||
1032 | |||
1033 | int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, | ||
1034 | bool interruptible); | ||
1035 | int i915_gem_object_put_fence_reg(struct drm_gem_object *obj, | ||
1036 | bool interruptible); | ||
980 | void i915_gem_retire_requests(struct drm_device *dev); | 1037 | void i915_gem_retire_requests(struct drm_device *dev); |
981 | void i915_gem_retire_work_handler(struct work_struct *work); | 1038 | void i915_gem_reset(struct drm_device *dev); |
982 | void i915_gem_clflush_object(struct drm_gem_object *obj); | 1039 | void i915_gem_clflush_object(struct drm_gem_object *obj); |
983 | int i915_gem_object_set_domain(struct drm_gem_object *obj, | 1040 | int i915_gem_object_set_domain(struct drm_gem_object *obj, |
984 | uint32_t read_domains, | 1041 | uint32_t read_domains, |
@@ -990,16 +1047,18 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start, | |||
990 | int i915_gpu_idle(struct drm_device *dev); | 1047 | int i915_gpu_idle(struct drm_device *dev); |
991 | int i915_gem_idle(struct drm_device *dev); | 1048 | int i915_gem_idle(struct drm_device *dev); |
992 | uint32_t i915_add_request(struct drm_device *dev, | 1049 | uint32_t i915_add_request(struct drm_device *dev, |
993 | struct drm_file *file_priv, | 1050 | struct drm_file *file_priv, |
994 | uint32_t flush_domains, | 1051 | struct drm_i915_gem_request *request, |
995 | struct intel_ring_buffer *ring); | 1052 | struct intel_ring_buffer *ring); |
996 | int i915_do_wait_request(struct drm_device *dev, | 1053 | int i915_do_wait_request(struct drm_device *dev, |
997 | uint32_t seqno, int interruptible, | 1054 | uint32_t seqno, |
998 | struct intel_ring_buffer *ring); | 1055 | bool interruptible, |
1056 | struct intel_ring_buffer *ring); | ||
999 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 1057 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
1000 | int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, | 1058 | int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, |
1001 | int write); | 1059 | int write); |
1002 | int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); | 1060 | int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, |
1061 | bool pipelined); | ||
1003 | int i915_gem_attach_phys_object(struct drm_device *dev, | 1062 | int i915_gem_attach_phys_object(struct drm_device *dev, |
1004 | struct drm_gem_object *obj, | 1063 | struct drm_gem_object *obj, |
1005 | int id, | 1064 | int id, |
@@ -1007,10 +1066,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev, | |||
1007 | void i915_gem_detach_phys_object(struct drm_device *dev, | 1066 | void i915_gem_detach_phys_object(struct drm_device *dev, |
1008 | struct drm_gem_object *obj); | 1067 | struct drm_gem_object *obj); |
1009 | void i915_gem_free_all_phys_object(struct drm_device *dev); | 1068 | void i915_gem_free_all_phys_object(struct drm_device *dev); |
1010 | int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); | ||
1011 | void i915_gem_object_put_pages(struct drm_gem_object *obj); | ||
1012 | void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); | 1069 | void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); |
1013 | int i915_gem_object_flush_write_domain(struct drm_gem_object *obj); | ||
1014 | 1070 | ||
1015 | void i915_gem_shrinker_init(void); | 1071 | void i915_gem_shrinker_init(void); |
1016 | void i915_gem_shrinker_exit(void); | 1072 | void i915_gem_shrinker_exit(void); |
@@ -1032,15 +1088,14 @@ bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, | |||
1032 | /* i915_gem_debug.c */ | 1088 | /* i915_gem_debug.c */ |
1033 | void i915_gem_dump_object(struct drm_gem_object *obj, int len, | 1089 | void i915_gem_dump_object(struct drm_gem_object *obj, int len, |
1034 | const char *where, uint32_t mark); | 1090 | const char *where, uint32_t mark); |
1035 | #if WATCH_INACTIVE | 1091 | #if WATCH_LISTS |
1036 | void i915_verify_inactive(struct drm_device *dev, char *file, int line); | 1092 | int i915_verify_lists(struct drm_device *dev); |
1037 | #else | 1093 | #else |
1038 | #define i915_verify_inactive(dev, file, line) | 1094 | #define i915_verify_lists(dev) 0 |
1039 | #endif | 1095 | #endif |
1040 | void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle); | 1096 | void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle); |
1041 | void i915_gem_dump_object(struct drm_gem_object *obj, int len, | 1097 | void i915_gem_dump_object(struct drm_gem_object *obj, int len, |
1042 | const char *where, uint32_t mark); | 1098 | const char *where, uint32_t mark); |
1043 | void i915_dump_lru(struct drm_device *dev, const char *where); | ||
1044 | 1099 | ||
1045 | /* i915_debugfs.c */ | 1100 | /* i915_debugfs.c */ |
1046 | int i915_debugfs_init(struct drm_minor *minor); | 1101 | int i915_debugfs_init(struct drm_minor *minor); |
@@ -1054,19 +1109,31 @@ extern int i915_restore_state(struct drm_device *dev); | |||
1054 | extern int i915_save_state(struct drm_device *dev); | 1109 | extern int i915_save_state(struct drm_device *dev); |
1055 | extern int i915_restore_state(struct drm_device *dev); | 1110 | extern int i915_restore_state(struct drm_device *dev); |
1056 | 1111 | ||
1112 | /* intel_i2c.c */ | ||
1113 | extern int intel_setup_gmbus(struct drm_device *dev); | ||
1114 | extern void intel_teardown_gmbus(struct drm_device *dev); | ||
1115 | extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); | ||
1116 | extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); | ||
1117 | extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) | ||
1118 | { | ||
1119 | return container_of(adapter, struct intel_gmbus, adapter)->force_bit; | ||
1120 | } | ||
1121 | extern void intel_i2c_reset(struct drm_device *dev); | ||
1122 | |||
1123 | /* intel_opregion.c */ | ||
1124 | extern int intel_opregion_setup(struct drm_device *dev); | ||
1057 | #ifdef CONFIG_ACPI | 1125 | #ifdef CONFIG_ACPI |
1058 | /* i915_opregion.c */ | 1126 | extern void intel_opregion_init(struct drm_device *dev); |
1059 | extern int intel_opregion_init(struct drm_device *dev, int resume); | 1127 | extern void intel_opregion_fini(struct drm_device *dev); |
1060 | extern void intel_opregion_free(struct drm_device *dev, int suspend); | 1128 | extern void intel_opregion_asle_intr(struct drm_device *dev); |
1061 | extern void opregion_asle_intr(struct drm_device *dev); | 1129 | extern void intel_opregion_gse_intr(struct drm_device *dev); |
1062 | extern void ironlake_opregion_gse_intr(struct drm_device *dev); | 1130 | extern void intel_opregion_enable_asle(struct drm_device *dev); |
1063 | extern void opregion_enable_asle(struct drm_device *dev); | ||
1064 | #else | 1131 | #else |
1065 | static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } | 1132 | static inline void intel_opregion_init(struct drm_device *dev) { return; } |
1066 | static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } | 1133 | static inline void intel_opregion_fini(struct drm_device *dev) { return; } |
1067 | static inline void opregion_asle_intr(struct drm_device *dev) { return; } | 1134 | static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; } |
1068 | static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; } | 1135 | static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; } |
1069 | static inline void opregion_enable_asle(struct drm_device *dev) { return; } | 1136 | static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; } |
1070 | #endif | 1137 | #endif |
1071 | 1138 | ||
1072 | /* modesetting */ | 1139 | /* modesetting */ |
@@ -1084,8 +1151,10 @@ extern void intel_detect_pch (struct drm_device *dev); | |||
1084 | extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); | 1151 | extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); |
1085 | 1152 | ||
1086 | /* overlay */ | 1153 | /* overlay */ |
1154 | #ifdef CONFIG_DEBUG_FS | ||
1087 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); | 1155 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); |
1088 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); | 1156 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); |
1157 | #endif | ||
1089 | 1158 | ||
1090 | /** | 1159 | /** |
1091 | * Lock test for when it's just for synchronization of ring access. | 1160 | * Lock test for when it's just for synchronization of ring access. |
@@ -1099,8 +1168,26 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove | |||
1099 | LOCK_TEST_WITH_RETURN(dev, file_priv); \ | 1168 | LOCK_TEST_WITH_RETURN(dev, file_priv); \ |
1100 | } while (0) | 1169 | } while (0) |
1101 | 1170 | ||
1102 | #define I915_READ(reg) readl(dev_priv->regs + (reg)) | 1171 | static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg) |
1103 | #define I915_WRITE(reg, val) writel(val, dev_priv->regs + (reg)) | 1172 | { |
1173 | u32 val; | ||
1174 | |||
1175 | val = readl(dev_priv->regs + reg); | ||
1176 | if (dev_priv->debug_flags & I915_DEBUG_READ) | ||
1177 | printk(KERN_ERR "read 0x%08x from 0x%08x\n", val, reg); | ||
1178 | return val; | ||
1179 | } | ||
1180 | |||
1181 | static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg, | ||
1182 | u32 val) | ||
1183 | { | ||
1184 | writel(val, dev_priv->regs + reg); | ||
1185 | if (dev_priv->debug_flags & I915_DEBUG_WRITE) | ||
1186 | printk(KERN_ERR "wrote 0x%08x to 0x%08x\n", val, reg); | ||
1187 | } | ||
1188 | |||
1189 | #define I915_READ(reg) i915_read(dev_priv, (reg)) | ||
1190 | #define I915_WRITE(reg, val) i915_write(dev_priv, (reg), (val)) | ||
1104 | #define I915_READ16(reg) readw(dev_priv->regs + (reg)) | 1191 | #define I915_READ16(reg) readw(dev_priv->regs + (reg)) |
1105 | #define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) | 1192 | #define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) |
1106 | #define I915_READ8(reg) readb(dev_priv->regs + (reg)) | 1193 | #define I915_READ8(reg) readb(dev_priv->regs + (reg)) |
@@ -1110,6 +1197,11 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove | |||
1110 | #define POSTING_READ(reg) (void)I915_READ(reg) | 1197 | #define POSTING_READ(reg) (void)I915_READ(reg) |
1111 | #define POSTING_READ16(reg) (void)I915_READ16(reg) | 1198 | #define POSTING_READ16(reg) (void)I915_READ16(reg) |
1112 | 1199 | ||
1200 | #define I915_DEBUG_ENABLE_IO() (dev_priv->debug_flags |= I915_DEBUG_READ | \ | ||
1201 | I915_DEBUG_WRITE) | ||
1202 | #define I915_DEBUG_DISABLE_IO() (dev_priv->debug_flags &= ~(I915_DEBUG_READ | \ | ||
1203 | I915_DEBUG_WRITE)) | ||
1204 | |||
1113 | #define I915_VERBOSE 0 | 1205 | #define I915_VERBOSE 0 |
1114 | 1206 | ||
1115 | #define BEGIN_LP_RING(n) do { \ | 1207 | #define BEGIN_LP_RING(n) do { \ |
@@ -1166,8 +1258,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove | |||
1166 | #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) | 1258 | #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) |
1167 | #define IS_I945G(dev) ((dev)->pci_device == 0x2772) | 1259 | #define IS_I945G(dev) ((dev)->pci_device == 0x2772) |
1168 | #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) | 1260 | #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) |
1169 | #define IS_I965G(dev) (INTEL_INFO(dev)->is_i965g) | ||
1170 | #define IS_I965GM(dev) (INTEL_INFO(dev)->is_i965gm) | ||
1171 | #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) | 1261 | #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) |
1172 | #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) | 1262 | #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) |
1173 | #define IS_GM45(dev) ((dev)->pci_device == 0x2A42) | 1263 | #define IS_GM45(dev) ((dev)->pci_device == 0x2A42) |
@@ -1179,7 +1269,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove | |||
1179 | #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) | 1269 | #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) |
1180 | #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) | 1270 | #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) |
1181 | #define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) | 1271 | #define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) |
1182 | #define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) | ||
1183 | #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) | 1272 | #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) |
1184 | 1273 | ||
1185 | #define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) | 1274 | #define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) |
@@ -1188,26 +1277,27 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove | |||
1188 | #define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) | 1277 | #define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) |
1189 | #define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) | 1278 | #define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) |
1190 | 1279 | ||
1191 | #define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) | 1280 | #define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) |
1192 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) | 1281 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) |
1193 | 1282 | ||
1283 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) | ||
1284 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) | ||
1285 | |||
1194 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte | 1286 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte |
1195 | * rows, which changed the alignment requirements and fence programming. | 1287 | * rows, which changed the alignment requirements and fence programming. |
1196 | */ | 1288 | */ |
1197 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ | 1289 | #define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \ |
1198 | IS_I915GM(dev))) | 1290 | IS_I915GM(dev))) |
1199 | #define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_PINEVIEW(dev)) | 1291 | #define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) |
1200 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) | 1292 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) |
1201 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) | 1293 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) |
1202 | #define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) | 1294 | #define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) |
1203 | #define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \ | 1295 | #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) |
1204 | !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev) && \ | ||
1205 | !IS_GEN6(dev)) | ||
1206 | #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) | 1296 | #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) |
1207 | /* dsparb controlled by hw only */ | 1297 | /* dsparb controlled by hw only */ |
1208 | #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) | 1298 | #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) |
1209 | 1299 | ||
1210 | #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev)) | 1300 | #define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2) |
1211 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) | 1301 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) |
1212 | #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) | 1302 | #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) |
1213 | #define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) | 1303 | #define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 90b1d6753b9d..100a7537980e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -37,7 +37,9 @@ | |||
37 | #include <linux/intel-gtt.h> | 37 | #include <linux/intel-gtt.h> |
38 | 38 | ||
39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); | 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); |
40 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); | 40 | |
41 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | ||
42 | bool pipelined); | ||
41 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 43 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
42 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 44 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
43 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, | 45 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, |
@@ -46,7 +48,8 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
46 | uint64_t offset, | 48 | uint64_t offset, |
47 | uint64_t size); | 49 | uint64_t size); |
48 | static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); | 50 | static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); |
49 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); | 51 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj, |
52 | bool interruptible); | ||
50 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, | 53 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, |
51 | unsigned alignment); | 54 | unsigned alignment); |
52 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); | 55 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); |
@@ -55,9 +58,111 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *o | |||
55 | struct drm_file *file_priv); | 58 | struct drm_file *file_priv); |
56 | static void i915_gem_free_object_tail(struct drm_gem_object *obj); | 59 | static void i915_gem_free_object_tail(struct drm_gem_object *obj); |
57 | 60 | ||
61 | static int | ||
62 | i915_gem_object_get_pages(struct drm_gem_object *obj, | ||
63 | gfp_t gfpmask); | ||
64 | |||
65 | static void | ||
66 | i915_gem_object_put_pages(struct drm_gem_object *obj); | ||
67 | |||
58 | static LIST_HEAD(shrink_list); | 68 | static LIST_HEAD(shrink_list); |
59 | static DEFINE_SPINLOCK(shrink_list_lock); | 69 | static DEFINE_SPINLOCK(shrink_list_lock); |
60 | 70 | ||
71 | /* some bookkeeping */ | ||
72 | static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, | ||
73 | size_t size) | ||
74 | { | ||
75 | dev_priv->mm.object_count++; | ||
76 | dev_priv->mm.object_memory += size; | ||
77 | } | ||
78 | |||
79 | static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, | ||
80 | size_t size) | ||
81 | { | ||
82 | dev_priv->mm.object_count--; | ||
83 | dev_priv->mm.object_memory -= size; | ||
84 | } | ||
85 | |||
86 | static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv, | ||
87 | size_t size) | ||
88 | { | ||
89 | dev_priv->mm.gtt_count++; | ||
90 | dev_priv->mm.gtt_memory += size; | ||
91 | } | ||
92 | |||
93 | static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv, | ||
94 | size_t size) | ||
95 | { | ||
96 | dev_priv->mm.gtt_count--; | ||
97 | dev_priv->mm.gtt_memory -= size; | ||
98 | } | ||
99 | |||
100 | static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv, | ||
101 | size_t size) | ||
102 | { | ||
103 | dev_priv->mm.pin_count++; | ||
104 | dev_priv->mm.pin_memory += size; | ||
105 | } | ||
106 | |||
107 | static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv, | ||
108 | size_t size) | ||
109 | { | ||
110 | dev_priv->mm.pin_count--; | ||
111 | dev_priv->mm.pin_memory -= size; | ||
112 | } | ||
113 | |||
114 | int | ||
115 | i915_gem_check_is_wedged(struct drm_device *dev) | ||
116 | { | ||
117 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
118 | struct completion *x = &dev_priv->error_completion; | ||
119 | unsigned long flags; | ||
120 | int ret; | ||
121 | |||
122 | if (!atomic_read(&dev_priv->mm.wedged)) | ||
123 | return 0; | ||
124 | |||
125 | ret = wait_for_completion_interruptible(x); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | /* Success, we reset the GPU! */ | ||
130 | if (!atomic_read(&dev_priv->mm.wedged)) | ||
131 | return 0; | ||
132 | |||
133 | /* GPU is hung, bump the completion count to account for | ||
134 | * the token we just consumed so that we never hit zero and | ||
135 | * end up waiting upon a subsequent completion event that | ||
136 | * will never happen. | ||
137 | */ | ||
138 | spin_lock_irqsave(&x->wait.lock, flags); | ||
139 | x->done++; | ||
140 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
141 | return -EIO; | ||
142 | } | ||
143 | |||
144 | static int i915_mutex_lock_interruptible(struct drm_device *dev) | ||
145 | { | ||
146 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
147 | int ret; | ||
148 | |||
149 | ret = i915_gem_check_is_wedged(dev); | ||
150 | if (ret) | ||
151 | return ret; | ||
152 | |||
153 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
154 | if (ret) | ||
155 | return ret; | ||
156 | |||
157 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
158 | mutex_unlock(&dev->struct_mutex); | ||
159 | return -EAGAIN; | ||
160 | } | ||
161 | |||
162 | WARN_ON(i915_verify_lists(dev)); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
61 | static inline bool | 166 | static inline bool |
62 | i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) | 167 | i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) |
63 | { | 168 | { |
@@ -66,7 +171,8 @@ i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) | |||
66 | obj_priv->pin_count == 0; | 171 | obj_priv->pin_count == 0; |
67 | } | 172 | } |
68 | 173 | ||
69 | int i915_gem_do_init(struct drm_device *dev, unsigned long start, | 174 | int i915_gem_do_init(struct drm_device *dev, |
175 | unsigned long start, | ||
70 | unsigned long end) | 176 | unsigned long end) |
71 | { | 177 | { |
72 | drm_i915_private_t *dev_priv = dev->dev_private; | 178 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -80,7 +186,7 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start, | |||
80 | drm_mm_init(&dev_priv->mm.gtt_space, start, | 186 | drm_mm_init(&dev_priv->mm.gtt_space, start, |
81 | end - start); | 187 | end - start); |
82 | 188 | ||
83 | dev->gtt_total = (uint32_t) (end - start); | 189 | dev_priv->mm.gtt_total = end - start; |
84 | 190 | ||
85 | return 0; | 191 | return 0; |
86 | } | 192 | } |
@@ -103,14 +209,16 @@ int | |||
103 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | 209 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, |
104 | struct drm_file *file_priv) | 210 | struct drm_file *file_priv) |
105 | { | 211 | { |
212 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
106 | struct drm_i915_gem_get_aperture *args = data; | 213 | struct drm_i915_gem_get_aperture *args = data; |
107 | 214 | ||
108 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 215 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
109 | return -ENODEV; | 216 | return -ENODEV; |
110 | 217 | ||
111 | args->aper_size = dev->gtt_total; | 218 | mutex_lock(&dev->struct_mutex); |
112 | args->aper_available_size = (args->aper_size - | 219 | args->aper_size = dev_priv->mm.gtt_total; |
113 | atomic_read(&dev->pin_memory)); | 220 | args->aper_available_size = args->aper_size - dev_priv->mm.pin_memory; |
221 | mutex_unlock(&dev->struct_mutex); | ||
114 | 222 | ||
115 | return 0; | 223 | return 0; |
116 | } | 224 | } |
@@ -263,7 +371,9 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
263 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 371 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
264 | remain = args->size; | 372 | remain = args->size; |
265 | 373 | ||
266 | mutex_lock(&dev->struct_mutex); | 374 | ret = i915_mutex_lock_interruptible(dev); |
375 | if (ret) | ||
376 | return ret; | ||
267 | 377 | ||
268 | ret = i915_gem_object_get_pages(obj, 0); | 378 | ret = i915_gem_object_get_pages(obj, 0); |
269 | if (ret != 0) | 379 | if (ret != 0) |
@@ -382,7 +492,9 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
382 | 492 | ||
383 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 493 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
384 | 494 | ||
385 | mutex_lock(&dev->struct_mutex); | 495 | ret = i915_mutex_lock_interruptible(dev); |
496 | if (ret) | ||
497 | goto fail_put_user_pages; | ||
386 | 498 | ||
387 | ret = i915_gem_object_get_pages_or_evict(obj); | 499 | ret = i915_gem_object_get_pages_or_evict(obj); |
388 | if (ret) | 500 | if (ret) |
@@ -462,7 +574,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
462 | struct drm_i915_gem_pread *args = data; | 574 | struct drm_i915_gem_pread *args = data; |
463 | struct drm_gem_object *obj; | 575 | struct drm_gem_object *obj; |
464 | struct drm_i915_gem_object *obj_priv; | 576 | struct drm_i915_gem_object *obj_priv; |
465 | int ret; | 577 | int ret = 0; |
466 | 578 | ||
467 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 579 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
468 | if (obj == NULL) | 580 | if (obj == NULL) |
@@ -472,14 +584,17 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
472 | /* Bounds check source. */ | 584 | /* Bounds check source. */ |
473 | if (args->offset > obj->size || args->size > obj->size - args->offset) { | 585 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
474 | ret = -EINVAL; | 586 | ret = -EINVAL; |
475 | goto err; | 587 | goto out; |
476 | } | 588 | } |
477 | 589 | ||
590 | if (args->size == 0) | ||
591 | goto out; | ||
592 | |||
478 | if (!access_ok(VERIFY_WRITE, | 593 | if (!access_ok(VERIFY_WRITE, |
479 | (char __user *)(uintptr_t)args->data_ptr, | 594 | (char __user *)(uintptr_t)args->data_ptr, |
480 | args->size)) { | 595 | args->size)) { |
481 | ret = -EFAULT; | 596 | ret = -EFAULT; |
482 | goto err; | 597 | goto out; |
483 | } | 598 | } |
484 | 599 | ||
485 | if (i915_gem_object_needs_bit17_swizzle(obj)) { | 600 | if (i915_gem_object_needs_bit17_swizzle(obj)) { |
@@ -491,7 +606,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
491 | file_priv); | 606 | file_priv); |
492 | } | 607 | } |
493 | 608 | ||
494 | err: | 609 | out: |
495 | drm_gem_object_unreference_unlocked(obj); | 610 | drm_gem_object_unreference_unlocked(obj); |
496 | return ret; | 611 | return ret; |
497 | } | 612 | } |
@@ -582,8 +697,10 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
582 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 697 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
583 | remain = args->size; | 698 | remain = args->size; |
584 | 699 | ||
700 | ret = i915_mutex_lock_interruptible(dev); | ||
701 | if (ret) | ||
702 | return ret; | ||
585 | 703 | ||
586 | mutex_lock(&dev->struct_mutex); | ||
587 | ret = i915_gem_object_pin(obj, 0); | 704 | ret = i915_gem_object_pin(obj, 0); |
588 | if (ret) { | 705 | if (ret) { |
589 | mutex_unlock(&dev->struct_mutex); | 706 | mutex_unlock(&dev->struct_mutex); |
@@ -678,7 +795,10 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
678 | goto out_unpin_pages; | 795 | goto out_unpin_pages; |
679 | } | 796 | } |
680 | 797 | ||
681 | mutex_lock(&dev->struct_mutex); | 798 | ret = i915_mutex_lock_interruptible(dev); |
799 | if (ret) | ||
800 | goto out_unpin_pages; | ||
801 | |||
682 | ret = i915_gem_object_pin(obj, 0); | 802 | ret = i915_gem_object_pin(obj, 0); |
683 | if (ret) | 803 | if (ret) |
684 | goto out_unlock; | 804 | goto out_unlock; |
@@ -752,7 +872,9 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
752 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 872 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
753 | remain = args->size; | 873 | remain = args->size; |
754 | 874 | ||
755 | mutex_lock(&dev->struct_mutex); | 875 | ret = i915_mutex_lock_interruptible(dev); |
876 | if (ret) | ||
877 | return ret; | ||
756 | 878 | ||
757 | ret = i915_gem_object_get_pages(obj, 0); | 879 | ret = i915_gem_object_get_pages(obj, 0); |
758 | if (ret != 0) | 880 | if (ret != 0) |
@@ -848,7 +970,9 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
848 | 970 | ||
849 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 971 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
850 | 972 | ||
851 | mutex_lock(&dev->struct_mutex); | 973 | ret = i915_mutex_lock_interruptible(dev); |
974 | if (ret) | ||
975 | goto fail_put_user_pages; | ||
852 | 976 | ||
853 | ret = i915_gem_object_get_pages_or_evict(obj); | 977 | ret = i915_gem_object_get_pages_or_evict(obj); |
854 | if (ret) | 978 | if (ret) |
@@ -936,14 +1060,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
936 | /* Bounds check destination. */ | 1060 | /* Bounds check destination. */ |
937 | if (args->offset > obj->size || args->size > obj->size - args->offset) { | 1061 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
938 | ret = -EINVAL; | 1062 | ret = -EINVAL; |
939 | goto err; | 1063 | goto out; |
940 | } | 1064 | } |
941 | 1065 | ||
1066 | if (args->size == 0) | ||
1067 | goto out; | ||
1068 | |||
942 | if (!access_ok(VERIFY_READ, | 1069 | if (!access_ok(VERIFY_READ, |
943 | (char __user *)(uintptr_t)args->data_ptr, | 1070 | (char __user *)(uintptr_t)args->data_ptr, |
944 | args->size)) { | 1071 | args->size)) { |
945 | ret = -EFAULT; | 1072 | ret = -EFAULT; |
946 | goto err; | 1073 | goto out; |
947 | } | 1074 | } |
948 | 1075 | ||
949 | /* We can only do the GTT pwrite on untiled buffers, as otherwise | 1076 | /* We can only do the GTT pwrite on untiled buffers, as otherwise |
@@ -955,7 +1082,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
955 | if (obj_priv->phys_obj) | 1082 | if (obj_priv->phys_obj) |
956 | ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); | 1083 | ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); |
957 | else if (obj_priv->tiling_mode == I915_TILING_NONE && | 1084 | else if (obj_priv->tiling_mode == I915_TILING_NONE && |
958 | dev->gtt_total != 0 && | 1085 | obj_priv->gtt_space && |
959 | obj->write_domain != I915_GEM_DOMAIN_CPU) { | 1086 | obj->write_domain != I915_GEM_DOMAIN_CPU) { |
960 | ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv); | 1087 | ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv); |
961 | if (ret == -EFAULT) { | 1088 | if (ret == -EFAULT) { |
@@ -977,7 +1104,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
977 | DRM_INFO("pwrite failed %d\n", ret); | 1104 | DRM_INFO("pwrite failed %d\n", ret); |
978 | #endif | 1105 | #endif |
979 | 1106 | ||
980 | err: | 1107 | out: |
981 | drm_gem_object_unreference_unlocked(obj); | 1108 | drm_gem_object_unreference_unlocked(obj); |
982 | return ret; | 1109 | return ret; |
983 | } | 1110 | } |
@@ -1019,14 +1146,14 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1019 | return -ENOENT; | 1146 | return -ENOENT; |
1020 | obj_priv = to_intel_bo(obj); | 1147 | obj_priv = to_intel_bo(obj); |
1021 | 1148 | ||
1022 | mutex_lock(&dev->struct_mutex); | 1149 | ret = i915_mutex_lock_interruptible(dev); |
1150 | if (ret) { | ||
1151 | drm_gem_object_unreference_unlocked(obj); | ||
1152 | return ret; | ||
1153 | } | ||
1023 | 1154 | ||
1024 | intel_mark_busy(dev, obj); | 1155 | intel_mark_busy(dev, obj); |
1025 | 1156 | ||
1026 | #if WATCH_BUF | ||
1027 | DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", | ||
1028 | obj, obj->size, read_domains, write_domain); | ||
1029 | #endif | ||
1030 | if (read_domains & I915_GEM_DOMAIN_GTT) { | 1157 | if (read_domains & I915_GEM_DOMAIN_GTT) { |
1031 | ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); | 1158 | ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); |
1032 | 1159 | ||
@@ -1050,7 +1177,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1050 | ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); | 1177 | ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); |
1051 | } | 1178 | } |
1052 | 1179 | ||
1053 | |||
1054 | /* Maintain LRU order of "inactive" objects */ | 1180 | /* Maintain LRU order of "inactive" objects */ |
1055 | if (ret == 0 && i915_gem_object_is_inactive(obj_priv)) | 1181 | if (ret == 0 && i915_gem_object_is_inactive(obj_priv)) |
1056 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 1182 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); |
@@ -1069,27 +1195,23 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1069 | { | 1195 | { |
1070 | struct drm_i915_gem_sw_finish *args = data; | 1196 | struct drm_i915_gem_sw_finish *args = data; |
1071 | struct drm_gem_object *obj; | 1197 | struct drm_gem_object *obj; |
1072 | struct drm_i915_gem_object *obj_priv; | ||
1073 | int ret = 0; | 1198 | int ret = 0; |
1074 | 1199 | ||
1075 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 1200 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
1076 | return -ENODEV; | 1201 | return -ENODEV; |
1077 | 1202 | ||
1078 | mutex_lock(&dev->struct_mutex); | ||
1079 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1203 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1080 | if (obj == NULL) { | 1204 | if (obj == NULL) |
1081 | mutex_unlock(&dev->struct_mutex); | ||
1082 | return -ENOENT; | 1205 | return -ENOENT; |
1083 | } | ||
1084 | 1206 | ||
1085 | #if WATCH_BUF | 1207 | ret = i915_mutex_lock_interruptible(dev); |
1086 | DRM_INFO("%s: sw_finish %d (%p %zd)\n", | 1208 | if (ret) { |
1087 | __func__, args->handle, obj, obj->size); | 1209 | drm_gem_object_unreference_unlocked(obj); |
1088 | #endif | 1210 | return ret; |
1089 | obj_priv = to_intel_bo(obj); | 1211 | } |
1090 | 1212 | ||
1091 | /* Pinned buffers may be scanout, so flush the cache */ | 1213 | /* Pinned buffers may be scanout, so flush the cache */ |
1092 | if (obj_priv->pin_count) | 1214 | if (to_intel_bo(obj)->pin_count) |
1093 | i915_gem_object_flush_cpu_write_domain(obj); | 1215 | i915_gem_object_flush_cpu_write_domain(obj); |
1094 | 1216 | ||
1095 | drm_gem_object_unreference(obj); | 1217 | drm_gem_object_unreference(obj); |
@@ -1181,7 +1303,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1181 | 1303 | ||
1182 | /* Need a new fence register? */ | 1304 | /* Need a new fence register? */ |
1183 | if (obj_priv->tiling_mode != I915_TILING_NONE) { | 1305 | if (obj_priv->tiling_mode != I915_TILING_NONE) { |
1184 | ret = i915_gem_object_get_fence_reg(obj); | 1306 | ret = i915_gem_object_get_fence_reg(obj, true); |
1185 | if (ret) | 1307 | if (ret) |
1186 | goto unlock; | 1308 | goto unlock; |
1187 | } | 1309 | } |
@@ -1246,7 +1368,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) | |||
1246 | obj->size / PAGE_SIZE, 0, 0); | 1368 | obj->size / PAGE_SIZE, 0, 0); |
1247 | if (!list->file_offset_node) { | 1369 | if (!list->file_offset_node) { |
1248 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); | 1370 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); |
1249 | ret = -ENOMEM; | 1371 | ret = -ENOSPC; |
1250 | goto out_free_list; | 1372 | goto out_free_list; |
1251 | } | 1373 | } |
1252 | 1374 | ||
@@ -1258,9 +1380,9 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) | |||
1258 | } | 1380 | } |
1259 | 1381 | ||
1260 | list->hash.key = list->file_offset_node->start; | 1382 | list->hash.key = list->file_offset_node->start; |
1261 | if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { | 1383 | ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); |
1384 | if (ret) { | ||
1262 | DRM_ERROR("failed to add to map hash\n"); | 1385 | DRM_ERROR("failed to add to map hash\n"); |
1263 | ret = -ENOMEM; | ||
1264 | goto out_free_mm; | 1386 | goto out_free_mm; |
1265 | } | 1387 | } |
1266 | 1388 | ||
@@ -1345,14 +1467,14 @@ i915_gem_get_gtt_alignment(struct drm_gem_object *obj) | |||
1345 | * Minimum alignment is 4k (GTT page size), but might be greater | 1467 | * Minimum alignment is 4k (GTT page size), but might be greater |
1346 | * if a fence register is needed for the object. | 1468 | * if a fence register is needed for the object. |
1347 | */ | 1469 | */ |
1348 | if (IS_I965G(dev) || obj_priv->tiling_mode == I915_TILING_NONE) | 1470 | if (INTEL_INFO(dev)->gen >= 4 || obj_priv->tiling_mode == I915_TILING_NONE) |
1349 | return 4096; | 1471 | return 4096; |
1350 | 1472 | ||
1351 | /* | 1473 | /* |
1352 | * Previous chips need to be aligned to the size of the smallest | 1474 | * Previous chips need to be aligned to the size of the smallest |
1353 | * fence register that can contain the object. | 1475 | * fence register that can contain the object. |
1354 | */ | 1476 | */ |
1355 | if (IS_I9XX(dev)) | 1477 | if (INTEL_INFO(dev)->gen == 3) |
1356 | start = 1024*1024; | 1478 | start = 1024*1024; |
1357 | else | 1479 | else |
1358 | start = 512*1024; | 1480 | start = 512*1024; |
@@ -1394,7 +1516,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1394 | if (obj == NULL) | 1516 | if (obj == NULL) |
1395 | return -ENOENT; | 1517 | return -ENOENT; |
1396 | 1518 | ||
1397 | mutex_lock(&dev->struct_mutex); | 1519 | ret = i915_mutex_lock_interruptible(dev); |
1520 | if (ret) { | ||
1521 | drm_gem_object_unreference_unlocked(obj); | ||
1522 | return ret; | ||
1523 | } | ||
1398 | 1524 | ||
1399 | obj_priv = to_intel_bo(obj); | 1525 | obj_priv = to_intel_bo(obj); |
1400 | 1526 | ||
@@ -1436,7 +1562,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1436 | return 0; | 1562 | return 0; |
1437 | } | 1563 | } |
1438 | 1564 | ||
1439 | void | 1565 | static void |
1440 | i915_gem_object_put_pages(struct drm_gem_object *obj) | 1566 | i915_gem_object_put_pages(struct drm_gem_object *obj) |
1441 | { | 1567 | { |
1442 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1568 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
@@ -1470,13 +1596,24 @@ i915_gem_object_put_pages(struct drm_gem_object *obj) | |||
1470 | obj_priv->pages = NULL; | 1596 | obj_priv->pages = NULL; |
1471 | } | 1597 | } |
1472 | 1598 | ||
1599 | static uint32_t | ||
1600 | i915_gem_next_request_seqno(struct drm_device *dev, | ||
1601 | struct intel_ring_buffer *ring) | ||
1602 | { | ||
1603 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1604 | |||
1605 | ring->outstanding_lazy_request = true; | ||
1606 | return dev_priv->next_seqno; | ||
1607 | } | ||
1608 | |||
1473 | static void | 1609 | static void |
1474 | i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno, | 1610 | i915_gem_object_move_to_active(struct drm_gem_object *obj, |
1475 | struct intel_ring_buffer *ring) | 1611 | struct intel_ring_buffer *ring) |
1476 | { | 1612 | { |
1477 | struct drm_device *dev = obj->dev; | 1613 | struct drm_device *dev = obj->dev; |
1478 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1479 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1614 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1615 | uint32_t seqno = i915_gem_next_request_seqno(dev, ring); | ||
1616 | |||
1480 | BUG_ON(ring == NULL); | 1617 | BUG_ON(ring == NULL); |
1481 | obj_priv->ring = ring; | 1618 | obj_priv->ring = ring; |
1482 | 1619 | ||
@@ -1485,10 +1622,9 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno, | |||
1485 | drm_gem_object_reference(obj); | 1622 | drm_gem_object_reference(obj); |
1486 | obj_priv->active = 1; | 1623 | obj_priv->active = 1; |
1487 | } | 1624 | } |
1625 | |||
1488 | /* Move from whatever list we were on to the tail of execution. */ | 1626 | /* Move from whatever list we were on to the tail of execution. */ |
1489 | spin_lock(&dev_priv->mm.active_list_lock); | ||
1490 | list_move_tail(&obj_priv->list, &ring->active_list); | 1627 | list_move_tail(&obj_priv->list, &ring->active_list); |
1491 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1492 | obj_priv->last_rendering_seqno = seqno; | 1628 | obj_priv->last_rendering_seqno = seqno; |
1493 | } | 1629 | } |
1494 | 1630 | ||
@@ -1538,9 +1674,8 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | |||
1538 | drm_i915_private_t *dev_priv = dev->dev_private; | 1674 | drm_i915_private_t *dev_priv = dev->dev_private; |
1539 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1675 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1540 | 1676 | ||
1541 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
1542 | if (obj_priv->pin_count != 0) | 1677 | if (obj_priv->pin_count != 0) |
1543 | list_del_init(&obj_priv->list); | 1678 | list_move_tail(&obj_priv->list, &dev_priv->mm.pinned_list); |
1544 | else | 1679 | else |
1545 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 1680 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); |
1546 | 1681 | ||
@@ -1552,12 +1687,12 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | |||
1552 | obj_priv->active = 0; | 1687 | obj_priv->active = 0; |
1553 | drm_gem_object_unreference(obj); | 1688 | drm_gem_object_unreference(obj); |
1554 | } | 1689 | } |
1555 | i915_verify_inactive(dev, __FILE__, __LINE__); | 1690 | WARN_ON(i915_verify_lists(dev)); |
1556 | } | 1691 | } |
1557 | 1692 | ||
1558 | static void | 1693 | static void |
1559 | i915_gem_process_flushing_list(struct drm_device *dev, | 1694 | i915_gem_process_flushing_list(struct drm_device *dev, |
1560 | uint32_t flush_domains, uint32_t seqno, | 1695 | uint32_t flush_domains, |
1561 | struct intel_ring_buffer *ring) | 1696 | struct intel_ring_buffer *ring) |
1562 | { | 1697 | { |
1563 | drm_i915_private_t *dev_priv = dev->dev_private; | 1698 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -1568,14 +1703,13 @@ i915_gem_process_flushing_list(struct drm_device *dev, | |||
1568 | gpu_write_list) { | 1703 | gpu_write_list) { |
1569 | struct drm_gem_object *obj = &obj_priv->base; | 1704 | struct drm_gem_object *obj = &obj_priv->base; |
1570 | 1705 | ||
1571 | if ((obj->write_domain & flush_domains) == | 1706 | if (obj->write_domain & flush_domains && |
1572 | obj->write_domain && | 1707 | obj_priv->ring == ring) { |
1573 | obj_priv->ring->ring_flag == ring->ring_flag) { | ||
1574 | uint32_t old_write_domain = obj->write_domain; | 1708 | uint32_t old_write_domain = obj->write_domain; |
1575 | 1709 | ||
1576 | obj->write_domain = 0; | 1710 | obj->write_domain = 0; |
1577 | list_del_init(&obj_priv->gpu_write_list); | 1711 | list_del_init(&obj_priv->gpu_write_list); |
1578 | i915_gem_object_move_to_active(obj, seqno, ring); | 1712 | i915_gem_object_move_to_active(obj, ring); |
1579 | 1713 | ||
1580 | /* update the fence lru list */ | 1714 | /* update the fence lru list */ |
1581 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { | 1715 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { |
@@ -1593,23 +1727,27 @@ i915_gem_process_flushing_list(struct drm_device *dev, | |||
1593 | } | 1727 | } |
1594 | 1728 | ||
1595 | uint32_t | 1729 | uint32_t |
1596 | i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | 1730 | i915_add_request(struct drm_device *dev, |
1597 | uint32_t flush_domains, struct intel_ring_buffer *ring) | 1731 | struct drm_file *file, |
1732 | struct drm_i915_gem_request *request, | ||
1733 | struct intel_ring_buffer *ring) | ||
1598 | { | 1734 | { |
1599 | drm_i915_private_t *dev_priv = dev->dev_private; | 1735 | drm_i915_private_t *dev_priv = dev->dev_private; |
1600 | struct drm_i915_file_private *i915_file_priv = NULL; | 1736 | struct drm_i915_file_private *file_priv = NULL; |
1601 | struct drm_i915_gem_request *request; | ||
1602 | uint32_t seqno; | 1737 | uint32_t seqno; |
1603 | int was_empty; | 1738 | int was_empty; |
1604 | 1739 | ||
1605 | if (file_priv != NULL) | 1740 | if (file != NULL) |
1606 | i915_file_priv = file_priv->driver_priv; | 1741 | file_priv = file->driver_priv; |
1607 | 1742 | ||
1608 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 1743 | if (request == NULL) { |
1609 | if (request == NULL) | 1744 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
1610 | return 0; | 1745 | if (request == NULL) |
1746 | return 0; | ||
1747 | } | ||
1611 | 1748 | ||
1612 | seqno = ring->add_request(dev, ring, file_priv, flush_domains); | 1749 | seqno = ring->add_request(dev, ring, 0); |
1750 | ring->outstanding_lazy_request = false; | ||
1613 | 1751 | ||
1614 | request->seqno = seqno; | 1752 | request->seqno = seqno; |
1615 | request->ring = ring; | 1753 | request->ring = ring; |
@@ -1617,23 +1755,20 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | |||
1617 | was_empty = list_empty(&ring->request_list); | 1755 | was_empty = list_empty(&ring->request_list); |
1618 | list_add_tail(&request->list, &ring->request_list); | 1756 | list_add_tail(&request->list, &ring->request_list); |
1619 | 1757 | ||
1620 | if (i915_file_priv) { | 1758 | if (file_priv) { |
1759 | spin_lock(&file_priv->mm.lock); | ||
1760 | request->file_priv = file_priv; | ||
1621 | list_add_tail(&request->client_list, | 1761 | list_add_tail(&request->client_list, |
1622 | &i915_file_priv->mm.request_list); | 1762 | &file_priv->mm.request_list); |
1623 | } else { | 1763 | spin_unlock(&file_priv->mm.lock); |
1624 | INIT_LIST_HEAD(&request->client_list); | ||
1625 | } | 1764 | } |
1626 | 1765 | ||
1627 | /* Associate any objects on the flushing list matching the write | ||
1628 | * domain we're flushing with our flush. | ||
1629 | */ | ||
1630 | if (flush_domains != 0) | ||
1631 | i915_gem_process_flushing_list(dev, flush_domains, seqno, ring); | ||
1632 | |||
1633 | if (!dev_priv->mm.suspended) { | 1766 | if (!dev_priv->mm.suspended) { |
1634 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 1767 | mod_timer(&dev_priv->hangcheck_timer, |
1768 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | ||
1635 | if (was_empty) | 1769 | if (was_empty) |
1636 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); | 1770 | queue_delayed_work(dev_priv->wq, |
1771 | &dev_priv->mm.retire_work, HZ); | ||
1637 | } | 1772 | } |
1638 | return seqno; | 1773 | return seqno; |
1639 | } | 1774 | } |
@@ -1644,91 +1779,105 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | |||
1644 | * Ensures that all commands in the ring are finished | 1779 | * Ensures that all commands in the ring are finished |
1645 | * before signalling the CPU | 1780 | * before signalling the CPU |
1646 | */ | 1781 | */ |
1647 | static uint32_t | 1782 | static void |
1648 | i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) | 1783 | i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) |
1649 | { | 1784 | { |
1650 | uint32_t flush_domains = 0; | 1785 | uint32_t flush_domains = 0; |
1651 | 1786 | ||
1652 | /* The sampler always gets flushed on i965 (sigh) */ | 1787 | /* The sampler always gets flushed on i965 (sigh) */ |
1653 | if (IS_I965G(dev)) | 1788 | if (INTEL_INFO(dev)->gen >= 4) |
1654 | flush_domains |= I915_GEM_DOMAIN_SAMPLER; | 1789 | flush_domains |= I915_GEM_DOMAIN_SAMPLER; |
1655 | 1790 | ||
1656 | ring->flush(dev, ring, | 1791 | ring->flush(dev, ring, |
1657 | I915_GEM_DOMAIN_COMMAND, flush_domains); | 1792 | I915_GEM_DOMAIN_COMMAND, flush_domains); |
1658 | return flush_domains; | ||
1659 | } | 1793 | } |
1660 | 1794 | ||
1661 | /** | 1795 | static inline void |
1662 | * Moves buffers associated only with the given active seqno from the active | 1796 | i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) |
1663 | * to inactive list, potentially freeing them. | ||
1664 | */ | ||
1665 | static void | ||
1666 | i915_gem_retire_request(struct drm_device *dev, | ||
1667 | struct drm_i915_gem_request *request) | ||
1668 | { | 1797 | { |
1669 | drm_i915_private_t *dev_priv = dev->dev_private; | 1798 | struct drm_i915_file_private *file_priv = request->file_priv; |
1670 | 1799 | ||
1671 | trace_i915_gem_request_retire(dev, request->seqno); | 1800 | if (!file_priv) |
1801 | return; | ||
1672 | 1802 | ||
1673 | /* Move any buffers on the active list that are no longer referenced | 1803 | spin_lock(&file_priv->mm.lock); |
1674 | * by the ringbuffer to the flushing/inactive lists as appropriate. | 1804 | list_del(&request->client_list); |
1675 | */ | 1805 | request->file_priv = NULL; |
1676 | spin_lock(&dev_priv->mm.active_list_lock); | 1806 | spin_unlock(&file_priv->mm.lock); |
1677 | while (!list_empty(&request->ring->active_list)) { | 1807 | } |
1678 | struct drm_gem_object *obj; | 1808 | |
1809 | static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, | ||
1810 | struct intel_ring_buffer *ring) | ||
1811 | { | ||
1812 | while (!list_empty(&ring->request_list)) { | ||
1813 | struct drm_i915_gem_request *request; | ||
1814 | |||
1815 | request = list_first_entry(&ring->request_list, | ||
1816 | struct drm_i915_gem_request, | ||
1817 | list); | ||
1818 | |||
1819 | list_del(&request->list); | ||
1820 | i915_gem_request_remove_from_client(request); | ||
1821 | kfree(request); | ||
1822 | } | ||
1823 | |||
1824 | while (!list_empty(&ring->active_list)) { | ||
1679 | struct drm_i915_gem_object *obj_priv; | 1825 | struct drm_i915_gem_object *obj_priv; |
1680 | 1826 | ||
1681 | obj_priv = list_first_entry(&request->ring->active_list, | 1827 | obj_priv = list_first_entry(&ring->active_list, |
1682 | struct drm_i915_gem_object, | 1828 | struct drm_i915_gem_object, |
1683 | list); | 1829 | list); |
1684 | obj = &obj_priv->base; | ||
1685 | |||
1686 | /* If the seqno being retired doesn't match the oldest in the | ||
1687 | * list, then the oldest in the list must still be newer than | ||
1688 | * this seqno. | ||
1689 | */ | ||
1690 | if (obj_priv->last_rendering_seqno != request->seqno) | ||
1691 | goto out; | ||
1692 | 1830 | ||
1693 | #if WATCH_LRU | 1831 | obj_priv->base.write_domain = 0; |
1694 | DRM_INFO("%s: retire %d moves to inactive list %p\n", | 1832 | list_del_init(&obj_priv->gpu_write_list); |
1695 | __func__, request->seqno, obj); | 1833 | i915_gem_object_move_to_inactive(&obj_priv->base); |
1696 | #endif | ||
1697 | |||
1698 | if (obj->write_domain != 0) | ||
1699 | i915_gem_object_move_to_flushing(obj); | ||
1700 | else { | ||
1701 | /* Take a reference on the object so it won't be | ||
1702 | * freed while the spinlock is held. The list | ||
1703 | * protection for this spinlock is safe when breaking | ||
1704 | * the lock like this since the next thing we do | ||
1705 | * is just get the head of the list again. | ||
1706 | */ | ||
1707 | drm_gem_object_reference(obj); | ||
1708 | i915_gem_object_move_to_inactive(obj); | ||
1709 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1710 | drm_gem_object_unreference(obj); | ||
1711 | spin_lock(&dev_priv->mm.active_list_lock); | ||
1712 | } | ||
1713 | } | 1834 | } |
1714 | out: | ||
1715 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1716 | } | 1835 | } |
1717 | 1836 | ||
1718 | /** | 1837 | void i915_gem_reset(struct drm_device *dev) |
1719 | * Returns true if seq1 is later than seq2. | ||
1720 | */ | ||
1721 | bool | ||
1722 | i915_seqno_passed(uint32_t seq1, uint32_t seq2) | ||
1723 | { | 1838 | { |
1724 | return (int32_t)(seq1 - seq2) >= 0; | 1839 | struct drm_i915_private *dev_priv = dev->dev_private; |
1725 | } | 1840 | struct drm_i915_gem_object *obj_priv; |
1841 | int i; | ||
1726 | 1842 | ||
1727 | uint32_t | 1843 | i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring); |
1728 | i915_get_gem_seqno(struct drm_device *dev, | 1844 | if (HAS_BSD(dev)) |
1729 | struct intel_ring_buffer *ring) | 1845 | i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring); |
1730 | { | 1846 | |
1731 | return ring->get_gem_seqno(dev, ring); | 1847 | /* Remove anything from the flushing lists. The GPU cache is likely |
1848 | * to be lost on reset along with the data, so simply move the | ||
1849 | * lost bo to the inactive list. | ||
1850 | */ | ||
1851 | while (!list_empty(&dev_priv->mm.flushing_list)) { | ||
1852 | obj_priv = list_first_entry(&dev_priv->mm.flushing_list, | ||
1853 | struct drm_i915_gem_object, | ||
1854 | list); | ||
1855 | |||
1856 | obj_priv->base.write_domain = 0; | ||
1857 | list_del_init(&obj_priv->gpu_write_list); | ||
1858 | i915_gem_object_move_to_inactive(&obj_priv->base); | ||
1859 | } | ||
1860 | |||
1861 | /* Move everything out of the GPU domains to ensure we do any | ||
1862 | * necessary invalidation upon reuse. | ||
1863 | */ | ||
1864 | list_for_each_entry(obj_priv, | ||
1865 | &dev_priv->mm.inactive_list, | ||
1866 | list) | ||
1867 | { | ||
1868 | obj_priv->base.read_domains &= ~I915_GEM_GPU_DOMAINS; | ||
1869 | } | ||
1870 | |||
1871 | /* The fence registers are invalidated so clear them out */ | ||
1872 | for (i = 0; i < 16; i++) { | ||
1873 | struct drm_i915_fence_reg *reg; | ||
1874 | |||
1875 | reg = &dev_priv->fence_regs[i]; | ||
1876 | if (!reg->obj) | ||
1877 | continue; | ||
1878 | |||
1879 | i915_gem_clear_fence_reg(reg->obj); | ||
1880 | } | ||
1732 | } | 1881 | } |
1733 | 1882 | ||
1734 | /** | 1883 | /** |
@@ -1741,38 +1890,58 @@ i915_gem_retire_requests_ring(struct drm_device *dev, | |||
1741 | drm_i915_private_t *dev_priv = dev->dev_private; | 1890 | drm_i915_private_t *dev_priv = dev->dev_private; |
1742 | uint32_t seqno; | 1891 | uint32_t seqno; |
1743 | 1892 | ||
1744 | if (!ring->status_page.page_addr | 1893 | if (!ring->status_page.page_addr || |
1745 | || list_empty(&ring->request_list)) | 1894 | list_empty(&ring->request_list)) |
1746 | return; | 1895 | return; |
1747 | 1896 | ||
1748 | seqno = i915_get_gem_seqno(dev, ring); | 1897 | WARN_ON(i915_verify_lists(dev)); |
1749 | 1898 | ||
1899 | seqno = ring->get_seqno(dev, ring); | ||
1750 | while (!list_empty(&ring->request_list)) { | 1900 | while (!list_empty(&ring->request_list)) { |
1751 | struct drm_i915_gem_request *request; | 1901 | struct drm_i915_gem_request *request; |
1752 | uint32_t retiring_seqno; | ||
1753 | 1902 | ||
1754 | request = list_first_entry(&ring->request_list, | 1903 | request = list_first_entry(&ring->request_list, |
1755 | struct drm_i915_gem_request, | 1904 | struct drm_i915_gem_request, |
1756 | list); | 1905 | list); |
1757 | retiring_seqno = request->seqno; | ||
1758 | 1906 | ||
1759 | if (i915_seqno_passed(seqno, retiring_seqno) || | 1907 | if (!i915_seqno_passed(seqno, request->seqno)) |
1760 | atomic_read(&dev_priv->mm.wedged)) { | 1908 | break; |
1761 | i915_gem_retire_request(dev, request); | 1909 | |
1910 | trace_i915_gem_request_retire(dev, request->seqno); | ||
1762 | 1911 | ||
1763 | list_del(&request->list); | 1912 | list_del(&request->list); |
1764 | list_del(&request->client_list); | 1913 | i915_gem_request_remove_from_client(request); |
1765 | kfree(request); | 1914 | kfree(request); |
1766 | } else | 1915 | } |
1916 | |||
1917 | /* Move any buffers on the active list that are no longer referenced | ||
1918 | * by the ringbuffer to the flushing/inactive lists as appropriate. | ||
1919 | */ | ||
1920 | while (!list_empty(&ring->active_list)) { | ||
1921 | struct drm_gem_object *obj; | ||
1922 | struct drm_i915_gem_object *obj_priv; | ||
1923 | |||
1924 | obj_priv = list_first_entry(&ring->active_list, | ||
1925 | struct drm_i915_gem_object, | ||
1926 | list); | ||
1927 | |||
1928 | if (!i915_seqno_passed(seqno, obj_priv->last_rendering_seqno)) | ||
1767 | break; | 1929 | break; |
1930 | |||
1931 | obj = &obj_priv->base; | ||
1932 | if (obj->write_domain != 0) | ||
1933 | i915_gem_object_move_to_flushing(obj); | ||
1934 | else | ||
1935 | i915_gem_object_move_to_inactive(obj); | ||
1768 | } | 1936 | } |
1769 | 1937 | ||
1770 | if (unlikely (dev_priv->trace_irq_seqno && | 1938 | if (unlikely (dev_priv->trace_irq_seqno && |
1771 | i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { | 1939 | i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { |
1772 | |||
1773 | ring->user_irq_put(dev, ring); | 1940 | ring->user_irq_put(dev, ring); |
1774 | dev_priv->trace_irq_seqno = 0; | 1941 | dev_priv->trace_irq_seqno = 0; |
1775 | } | 1942 | } |
1943 | |||
1944 | WARN_ON(i915_verify_lists(dev)); | ||
1776 | } | 1945 | } |
1777 | 1946 | ||
1778 | void | 1947 | void |
@@ -1799,7 +1968,7 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
1799 | i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); | 1968 | i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); |
1800 | } | 1969 | } |
1801 | 1970 | ||
1802 | void | 1971 | static void |
1803 | i915_gem_retire_work_handler(struct work_struct *work) | 1972 | i915_gem_retire_work_handler(struct work_struct *work) |
1804 | { | 1973 | { |
1805 | drm_i915_private_t *dev_priv; | 1974 | drm_i915_private_t *dev_priv; |
@@ -1809,7 +1978,12 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1809 | mm.retire_work.work); | 1978 | mm.retire_work.work); |
1810 | dev = dev_priv->dev; | 1979 | dev = dev_priv->dev; |
1811 | 1980 | ||
1812 | mutex_lock(&dev->struct_mutex); | 1981 | /* Come back later if the device is busy... */ |
1982 | if (!mutex_trylock(&dev->struct_mutex)) { | ||
1983 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); | ||
1984 | return; | ||
1985 | } | ||
1986 | |||
1813 | i915_gem_retire_requests(dev); | 1987 | i915_gem_retire_requests(dev); |
1814 | 1988 | ||
1815 | if (!dev_priv->mm.suspended && | 1989 | if (!dev_priv->mm.suspended && |
@@ -1822,7 +1996,7 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1822 | 1996 | ||
1823 | int | 1997 | int |
1824 | i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | 1998 | i915_do_wait_request(struct drm_device *dev, uint32_t seqno, |
1825 | int interruptible, struct intel_ring_buffer *ring) | 1999 | bool interruptible, struct intel_ring_buffer *ring) |
1826 | { | 2000 | { |
1827 | drm_i915_private_t *dev_priv = dev->dev_private; | 2001 | drm_i915_private_t *dev_priv = dev->dev_private; |
1828 | u32 ier; | 2002 | u32 ier; |
@@ -1831,9 +2005,16 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1831 | BUG_ON(seqno == 0); | 2005 | BUG_ON(seqno == 0); |
1832 | 2006 | ||
1833 | if (atomic_read(&dev_priv->mm.wedged)) | 2007 | if (atomic_read(&dev_priv->mm.wedged)) |
1834 | return -EIO; | 2008 | return -EAGAIN; |
2009 | |||
2010 | if (ring->outstanding_lazy_request) { | ||
2011 | seqno = i915_add_request(dev, NULL, NULL, ring); | ||
2012 | if (seqno == 0) | ||
2013 | return -ENOMEM; | ||
2014 | } | ||
2015 | BUG_ON(seqno == dev_priv->next_seqno); | ||
1835 | 2016 | ||
1836 | if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) { | 2017 | if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { |
1837 | if (HAS_PCH_SPLIT(dev)) | 2018 | if (HAS_PCH_SPLIT(dev)) |
1838 | ier = I915_READ(DEIER) | I915_READ(GTIER); | 2019 | ier = I915_READ(DEIER) | I915_READ(GTIER); |
1839 | else | 2020 | else |
@@ -1852,12 +2033,12 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1852 | if (interruptible) | 2033 | if (interruptible) |
1853 | ret = wait_event_interruptible(ring->irq_queue, | 2034 | ret = wait_event_interruptible(ring->irq_queue, |
1854 | i915_seqno_passed( | 2035 | i915_seqno_passed( |
1855 | ring->get_gem_seqno(dev, ring), seqno) | 2036 | ring->get_seqno(dev, ring), seqno) |
1856 | || atomic_read(&dev_priv->mm.wedged)); | 2037 | || atomic_read(&dev_priv->mm.wedged)); |
1857 | else | 2038 | else |
1858 | wait_event(ring->irq_queue, | 2039 | wait_event(ring->irq_queue, |
1859 | i915_seqno_passed( | 2040 | i915_seqno_passed( |
1860 | ring->get_gem_seqno(dev, ring), seqno) | 2041 | ring->get_seqno(dev, ring), seqno) |
1861 | || atomic_read(&dev_priv->mm.wedged)); | 2042 | || atomic_read(&dev_priv->mm.wedged)); |
1862 | 2043 | ||
1863 | ring->user_irq_put(dev, ring); | 2044 | ring->user_irq_put(dev, ring); |
@@ -1866,11 +2047,12 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1866 | trace_i915_gem_request_wait_end(dev, seqno); | 2047 | trace_i915_gem_request_wait_end(dev, seqno); |
1867 | } | 2048 | } |
1868 | if (atomic_read(&dev_priv->mm.wedged)) | 2049 | if (atomic_read(&dev_priv->mm.wedged)) |
1869 | ret = -EIO; | 2050 | ret = -EAGAIN; |
1870 | 2051 | ||
1871 | if (ret && ret != -ERESTARTSYS) | 2052 | if (ret && ret != -ERESTARTSYS) |
1872 | DRM_ERROR("%s returns %d (awaiting %d at %d)\n", | 2053 | DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n", |
1873 | __func__, ret, seqno, ring->get_gem_seqno(dev, ring)); | 2054 | __func__, ret, seqno, ring->get_seqno(dev, ring), |
2055 | dev_priv->next_seqno); | ||
1874 | 2056 | ||
1875 | /* Directly dispatch request retiring. While we have the work queue | 2057 | /* Directly dispatch request retiring. While we have the work queue |
1876 | * to handle this, the waiter on a request often wants an associated | 2058 | * to handle this, the waiter on a request often wants an associated |
@@ -1889,27 +2071,44 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1889 | */ | 2071 | */ |
1890 | static int | 2072 | static int |
1891 | i915_wait_request(struct drm_device *dev, uint32_t seqno, | 2073 | i915_wait_request(struct drm_device *dev, uint32_t seqno, |
1892 | struct intel_ring_buffer *ring) | 2074 | struct intel_ring_buffer *ring) |
1893 | { | 2075 | { |
1894 | return i915_do_wait_request(dev, seqno, 1, ring); | 2076 | return i915_do_wait_request(dev, seqno, 1, ring); |
1895 | } | 2077 | } |
1896 | 2078 | ||
1897 | static void | 2079 | static void |
2080 | i915_gem_flush_ring(struct drm_device *dev, | ||
2081 | struct drm_file *file_priv, | ||
2082 | struct intel_ring_buffer *ring, | ||
2083 | uint32_t invalidate_domains, | ||
2084 | uint32_t flush_domains) | ||
2085 | { | ||
2086 | ring->flush(dev, ring, invalidate_domains, flush_domains); | ||
2087 | i915_gem_process_flushing_list(dev, flush_domains, ring); | ||
2088 | } | ||
2089 | |||
2090 | static void | ||
1898 | i915_gem_flush(struct drm_device *dev, | 2091 | i915_gem_flush(struct drm_device *dev, |
2092 | struct drm_file *file_priv, | ||
1899 | uint32_t invalidate_domains, | 2093 | uint32_t invalidate_domains, |
1900 | uint32_t flush_domains) | 2094 | uint32_t flush_domains, |
2095 | uint32_t flush_rings) | ||
1901 | { | 2096 | { |
1902 | drm_i915_private_t *dev_priv = dev->dev_private; | 2097 | drm_i915_private_t *dev_priv = dev->dev_private; |
2098 | |||
1903 | if (flush_domains & I915_GEM_DOMAIN_CPU) | 2099 | if (flush_domains & I915_GEM_DOMAIN_CPU) |
1904 | drm_agp_chipset_flush(dev); | 2100 | drm_agp_chipset_flush(dev); |
1905 | dev_priv->render_ring.flush(dev, &dev_priv->render_ring, | ||
1906 | invalidate_domains, | ||
1907 | flush_domains); | ||
1908 | 2101 | ||
1909 | if (HAS_BSD(dev)) | 2102 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { |
1910 | dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring, | 2103 | if (flush_rings & RING_RENDER) |
1911 | invalidate_domains, | 2104 | i915_gem_flush_ring(dev, file_priv, |
1912 | flush_domains); | 2105 | &dev_priv->render_ring, |
2106 | invalidate_domains, flush_domains); | ||
2107 | if (flush_rings & RING_BSD) | ||
2108 | i915_gem_flush_ring(dev, file_priv, | ||
2109 | &dev_priv->bsd_ring, | ||
2110 | invalidate_domains, flush_domains); | ||
2111 | } | ||
1913 | } | 2112 | } |
1914 | 2113 | ||
1915 | /** | 2114 | /** |
@@ -1917,7 +2116,8 @@ i915_gem_flush(struct drm_device *dev, | |||
1917 | * safe to unbind from the GTT or access from the CPU. | 2116 | * safe to unbind from the GTT or access from the CPU. |
1918 | */ | 2117 | */ |
1919 | static int | 2118 | static int |
1920 | i915_gem_object_wait_rendering(struct drm_gem_object *obj) | 2119 | i915_gem_object_wait_rendering(struct drm_gem_object *obj, |
2120 | bool interruptible) | ||
1921 | { | 2121 | { |
1922 | struct drm_device *dev = obj->dev; | 2122 | struct drm_device *dev = obj->dev; |
1923 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2123 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
@@ -1932,13 +2132,11 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) | |||
1932 | * it. | 2132 | * it. |
1933 | */ | 2133 | */ |
1934 | if (obj_priv->active) { | 2134 | if (obj_priv->active) { |
1935 | #if WATCH_BUF | 2135 | ret = i915_do_wait_request(dev, |
1936 | DRM_INFO("%s: object %p wait for seqno %08x\n", | 2136 | obj_priv->last_rendering_seqno, |
1937 | __func__, obj, obj_priv->last_rendering_seqno); | 2137 | interruptible, |
1938 | #endif | 2138 | obj_priv->ring); |
1939 | ret = i915_wait_request(dev, | 2139 | if (ret) |
1940 | obj_priv->last_rendering_seqno, obj_priv->ring); | ||
1941 | if (ret != 0) | ||
1942 | return ret; | 2140 | return ret; |
1943 | } | 2141 | } |
1944 | 2142 | ||
@@ -1952,14 +2150,10 @@ int | |||
1952 | i915_gem_object_unbind(struct drm_gem_object *obj) | 2150 | i915_gem_object_unbind(struct drm_gem_object *obj) |
1953 | { | 2151 | { |
1954 | struct drm_device *dev = obj->dev; | 2152 | struct drm_device *dev = obj->dev; |
1955 | drm_i915_private_t *dev_priv = dev->dev_private; | 2153 | struct drm_i915_private *dev_priv = dev->dev_private; |
1956 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2154 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1957 | int ret = 0; | 2155 | int ret = 0; |
1958 | 2156 | ||
1959 | #if WATCH_BUF | ||
1960 | DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj); | ||
1961 | DRM_INFO("gtt_space %p\n", obj_priv->gtt_space); | ||
1962 | #endif | ||
1963 | if (obj_priv->gtt_space == NULL) | 2157 | if (obj_priv->gtt_space == NULL) |
1964 | return 0; | 2158 | return 0; |
1965 | 2159 | ||
@@ -1984,33 +2178,26 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
1984 | * should be safe and we need to cleanup or else we might | 2178 | * should be safe and we need to cleanup or else we might |
1985 | * cause memory corruption through use-after-free. | 2179 | * cause memory corruption through use-after-free. |
1986 | */ | 2180 | */ |
2181 | if (ret) { | ||
2182 | i915_gem_clflush_object(obj); | ||
2183 | obj->read_domains = obj->write_domain = I915_GEM_DOMAIN_CPU; | ||
2184 | } | ||
1987 | 2185 | ||
1988 | /* release the fence reg _after_ flushing */ | 2186 | /* release the fence reg _after_ flushing */ |
1989 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 2187 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
1990 | i915_gem_clear_fence_reg(obj); | 2188 | i915_gem_clear_fence_reg(obj); |
1991 | 2189 | ||
1992 | if (obj_priv->agp_mem != NULL) { | 2190 | drm_unbind_agp(obj_priv->agp_mem); |
1993 | drm_unbind_agp(obj_priv->agp_mem); | 2191 | drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); |
1994 | drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); | ||
1995 | obj_priv->agp_mem = NULL; | ||
1996 | } | ||
1997 | 2192 | ||
1998 | i915_gem_object_put_pages(obj); | 2193 | i915_gem_object_put_pages(obj); |
1999 | BUG_ON(obj_priv->pages_refcount); | 2194 | BUG_ON(obj_priv->pages_refcount); |
2000 | 2195 | ||
2001 | if (obj_priv->gtt_space) { | 2196 | i915_gem_info_remove_gtt(dev_priv, obj->size); |
2002 | atomic_dec(&dev->gtt_count); | 2197 | list_del_init(&obj_priv->list); |
2003 | atomic_sub(obj->size, &dev->gtt_memory); | ||
2004 | |||
2005 | drm_mm_put_block(obj_priv->gtt_space); | ||
2006 | obj_priv->gtt_space = NULL; | ||
2007 | } | ||
2008 | 2198 | ||
2009 | /* Remove ourselves from the LRU list if present. */ | 2199 | drm_mm_put_block(obj_priv->gtt_space); |
2010 | spin_lock(&dev_priv->mm.active_list_lock); | 2200 | obj_priv->gtt_space = NULL; |
2011 | if (!list_empty(&obj_priv->list)) | ||
2012 | list_del_init(&obj_priv->list); | ||
2013 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
2014 | 2201 | ||
2015 | if (i915_gem_object_is_purgeable(obj_priv)) | 2202 | if (i915_gem_object_is_purgeable(obj_priv)) |
2016 | i915_gem_object_truncate(obj); | 2203 | i915_gem_object_truncate(obj); |
@@ -2020,48 +2207,45 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
2020 | return ret; | 2207 | return ret; |
2021 | } | 2208 | } |
2022 | 2209 | ||
2210 | static int i915_ring_idle(struct drm_device *dev, | ||
2211 | struct intel_ring_buffer *ring) | ||
2212 | { | ||
2213 | i915_gem_flush_ring(dev, NULL, ring, | ||
2214 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | ||
2215 | return i915_wait_request(dev, | ||
2216 | i915_gem_next_request_seqno(dev, ring), | ||
2217 | ring); | ||
2218 | } | ||
2219 | |||
2023 | int | 2220 | int |
2024 | i915_gpu_idle(struct drm_device *dev) | 2221 | i915_gpu_idle(struct drm_device *dev) |
2025 | { | 2222 | { |
2026 | drm_i915_private_t *dev_priv = dev->dev_private; | 2223 | drm_i915_private_t *dev_priv = dev->dev_private; |
2027 | bool lists_empty; | 2224 | bool lists_empty; |
2028 | uint32_t seqno1, seqno2; | ||
2029 | int ret; | 2225 | int ret; |
2030 | 2226 | ||
2031 | spin_lock(&dev_priv->mm.active_list_lock); | ||
2032 | lists_empty = (list_empty(&dev_priv->mm.flushing_list) && | 2227 | lists_empty = (list_empty(&dev_priv->mm.flushing_list) && |
2033 | list_empty(&dev_priv->render_ring.active_list) && | 2228 | list_empty(&dev_priv->render_ring.active_list) && |
2034 | (!HAS_BSD(dev) || | 2229 | (!HAS_BSD(dev) || |
2035 | list_empty(&dev_priv->bsd_ring.active_list))); | 2230 | list_empty(&dev_priv->bsd_ring.active_list))); |
2036 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
2037 | |||
2038 | if (lists_empty) | 2231 | if (lists_empty) |
2039 | return 0; | 2232 | return 0; |
2040 | 2233 | ||
2041 | /* Flush everything onto the inactive list. */ | 2234 | /* Flush everything onto the inactive list. */ |
2042 | i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | 2235 | ret = i915_ring_idle(dev, &dev_priv->render_ring); |
2043 | seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, | 2236 | if (ret) |
2044 | &dev_priv->render_ring); | 2237 | return ret; |
2045 | if (seqno1 == 0) | ||
2046 | return -ENOMEM; | ||
2047 | ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring); | ||
2048 | 2238 | ||
2049 | if (HAS_BSD(dev)) { | 2239 | if (HAS_BSD(dev)) { |
2050 | seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, | 2240 | ret = i915_ring_idle(dev, &dev_priv->bsd_ring); |
2051 | &dev_priv->bsd_ring); | ||
2052 | if (seqno2 == 0) | ||
2053 | return -ENOMEM; | ||
2054 | |||
2055 | ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring); | ||
2056 | if (ret) | 2241 | if (ret) |
2057 | return ret; | 2242 | return ret; |
2058 | } | 2243 | } |
2059 | 2244 | ||
2060 | 2245 | return 0; | |
2061 | return ret; | ||
2062 | } | 2246 | } |
2063 | 2247 | ||
2064 | int | 2248 | static int |
2065 | i915_gem_object_get_pages(struct drm_gem_object *obj, | 2249 | i915_gem_object_get_pages(struct drm_gem_object *obj, |
2066 | gfp_t gfpmask) | 2250 | gfp_t gfpmask) |
2067 | { | 2251 | { |
@@ -2241,7 +2425,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
2241 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); | 2425 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); |
2242 | } | 2426 | } |
2243 | 2427 | ||
2244 | static int i915_find_fence_reg(struct drm_device *dev) | 2428 | static int i915_find_fence_reg(struct drm_device *dev, |
2429 | bool interruptible) | ||
2245 | { | 2430 | { |
2246 | struct drm_i915_fence_reg *reg = NULL; | 2431 | struct drm_i915_fence_reg *reg = NULL; |
2247 | struct drm_i915_gem_object *obj_priv = NULL; | 2432 | struct drm_i915_gem_object *obj_priv = NULL; |
@@ -2286,7 +2471,7 @@ static int i915_find_fence_reg(struct drm_device *dev) | |||
2286 | * private reference to obj like the other callers of put_fence_reg | 2471 | * private reference to obj like the other callers of put_fence_reg |
2287 | * (set_tiling ioctl) do. */ | 2472 | * (set_tiling ioctl) do. */ |
2288 | drm_gem_object_reference(obj); | 2473 | drm_gem_object_reference(obj); |
2289 | ret = i915_gem_object_put_fence_reg(obj); | 2474 | ret = i915_gem_object_put_fence_reg(obj, interruptible); |
2290 | drm_gem_object_unreference(obj); | 2475 | drm_gem_object_unreference(obj); |
2291 | if (ret != 0) | 2476 | if (ret != 0) |
2292 | return ret; | 2477 | return ret; |
@@ -2308,7 +2493,8 @@ static int i915_find_fence_reg(struct drm_device *dev) | |||
2308 | * and tiling format. | 2493 | * and tiling format. |
2309 | */ | 2494 | */ |
2310 | int | 2495 | int |
2311 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | 2496 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj, |
2497 | bool interruptible) | ||
2312 | { | 2498 | { |
2313 | struct drm_device *dev = obj->dev; | 2499 | struct drm_device *dev = obj->dev; |
2314 | struct drm_i915_private *dev_priv = dev->dev_private; | 2500 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -2343,7 +2529,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | |||
2343 | break; | 2529 | break; |
2344 | } | 2530 | } |
2345 | 2531 | ||
2346 | ret = i915_find_fence_reg(dev); | 2532 | ret = i915_find_fence_reg(dev, interruptible); |
2347 | if (ret < 0) | 2533 | if (ret < 0) |
2348 | return ret; | 2534 | return ret; |
2349 | 2535 | ||
@@ -2421,15 +2607,19 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) | |||
2421 | * i915_gem_object_put_fence_reg - waits on outstanding fenced access | 2607 | * i915_gem_object_put_fence_reg - waits on outstanding fenced access |
2422 | * to the buffer to finish, and then resets the fence register. | 2608 | * to the buffer to finish, and then resets the fence register. |
2423 | * @obj: tiled object holding a fence register. | 2609 | * @obj: tiled object holding a fence register. |
2610 | * @bool: whether the wait upon the fence is interruptible | ||
2424 | * | 2611 | * |
2425 | * Zeroes out the fence register itself and clears out the associated | 2612 | * Zeroes out the fence register itself and clears out the associated |
2426 | * data structures in dev_priv and obj_priv. | 2613 | * data structures in dev_priv and obj_priv. |
2427 | */ | 2614 | */ |
2428 | int | 2615 | int |
2429 | i915_gem_object_put_fence_reg(struct drm_gem_object *obj) | 2616 | i915_gem_object_put_fence_reg(struct drm_gem_object *obj, |
2617 | bool interruptible) | ||
2430 | { | 2618 | { |
2431 | struct drm_device *dev = obj->dev; | 2619 | struct drm_device *dev = obj->dev; |
2620 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2432 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2621 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2622 | struct drm_i915_fence_reg *reg; | ||
2433 | 2623 | ||
2434 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE) | 2624 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE) |
2435 | return 0; | 2625 | return 0; |
@@ -2444,20 +2634,23 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj) | |||
2444 | * therefore we must wait for any outstanding access to complete | 2634 | * therefore we must wait for any outstanding access to complete |
2445 | * before clearing the fence. | 2635 | * before clearing the fence. |
2446 | */ | 2636 | */ |
2447 | if (!IS_I965G(dev)) { | 2637 | reg = &dev_priv->fence_regs[obj_priv->fence_reg]; |
2638 | if (reg->gpu) { | ||
2448 | int ret; | 2639 | int ret; |
2449 | 2640 | ||
2450 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2641 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); |
2451 | if (ret != 0) | 2642 | if (ret) |
2452 | return ret; | 2643 | return ret; |
2453 | 2644 | ||
2454 | ret = i915_gem_object_wait_rendering(obj); | 2645 | ret = i915_gem_object_wait_rendering(obj, interruptible); |
2455 | if (ret != 0) | 2646 | if (ret) |
2456 | return ret; | 2647 | return ret; |
2648 | |||
2649 | reg->gpu = false; | ||
2457 | } | 2650 | } |
2458 | 2651 | ||
2459 | i915_gem_object_flush_gtt_write_domain(obj); | 2652 | i915_gem_object_flush_gtt_write_domain(obj); |
2460 | i915_gem_clear_fence_reg (obj); | 2653 | i915_gem_clear_fence_reg(obj); |
2461 | 2654 | ||
2462 | return 0; | 2655 | return 0; |
2463 | } | 2656 | } |
@@ -2490,7 +2683,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2490 | /* If the object is bigger than the entire aperture, reject it early | 2683 | /* If the object is bigger than the entire aperture, reject it early |
2491 | * before evicting everything in a vain attempt to find space. | 2684 | * before evicting everything in a vain attempt to find space. |
2492 | */ | 2685 | */ |
2493 | if (obj->size > dev->gtt_total) { | 2686 | if (obj->size > dev_priv->mm.gtt_total) { |
2494 | DRM_ERROR("Attempting to bind an object larger than the aperture\n"); | 2687 | DRM_ERROR("Attempting to bind an object larger than the aperture\n"); |
2495 | return -E2BIG; | 2688 | return -E2BIG; |
2496 | } | 2689 | } |
@@ -2508,9 +2701,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2508 | /* If the gtt is empty and we're still having trouble | 2701 | /* If the gtt is empty and we're still having trouble |
2509 | * fitting our object in, we're out of memory. | 2702 | * fitting our object in, we're out of memory. |
2510 | */ | 2703 | */ |
2511 | #if WATCH_LRU | ||
2512 | DRM_INFO("%s: GTT full, evicting something\n", __func__); | ||
2513 | #endif | ||
2514 | ret = i915_gem_evict_something(dev, obj->size, alignment); | 2704 | ret = i915_gem_evict_something(dev, obj->size, alignment); |
2515 | if (ret) | 2705 | if (ret) |
2516 | return ret; | 2706 | return ret; |
@@ -2518,10 +2708,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2518 | goto search_free; | 2708 | goto search_free; |
2519 | } | 2709 | } |
2520 | 2710 | ||
2521 | #if WATCH_BUF | ||
2522 | DRM_INFO("Binding object of size %zd at 0x%08x\n", | ||
2523 | obj->size, obj_priv->gtt_offset); | ||
2524 | #endif | ||
2525 | ret = i915_gem_object_get_pages(obj, gfpmask); | 2711 | ret = i915_gem_object_get_pages(obj, gfpmask); |
2526 | if (ret) { | 2712 | if (ret) { |
2527 | drm_mm_put_block(obj_priv->gtt_space); | 2713 | drm_mm_put_block(obj_priv->gtt_space); |
@@ -2566,11 +2752,10 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2566 | 2752 | ||
2567 | goto search_free; | 2753 | goto search_free; |
2568 | } | 2754 | } |
2569 | atomic_inc(&dev->gtt_count); | ||
2570 | atomic_add(obj->size, &dev->gtt_memory); | ||
2571 | 2755 | ||
2572 | /* keep track of bounds object by adding it to the inactive list */ | 2756 | /* keep track of bounds object by adding it to the inactive list */ |
2573 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 2757 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); |
2758 | i915_gem_info_add_gtt(dev_priv, obj->size); | ||
2574 | 2759 | ||
2575 | /* Assert that the object is not currently in any GPU domain. As it | 2760 | /* Assert that the object is not currently in any GPU domain. As it |
2576 | * wasn't in the GTT, there shouldn't be any way it could have been in | 2761 | * wasn't in the GTT, there shouldn't be any way it could have been in |
@@ -2603,25 +2788,30 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
2603 | 2788 | ||
2604 | /** Flushes any GPU write domain for the object if it's dirty. */ | 2789 | /** Flushes any GPU write domain for the object if it's dirty. */ |
2605 | static int | 2790 | static int |
2606 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) | 2791 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, |
2792 | bool pipelined) | ||
2607 | { | 2793 | { |
2608 | struct drm_device *dev = obj->dev; | 2794 | struct drm_device *dev = obj->dev; |
2609 | uint32_t old_write_domain; | 2795 | uint32_t old_write_domain; |
2610 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | ||
2611 | 2796 | ||
2612 | if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | 2797 | if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) |
2613 | return 0; | 2798 | return 0; |
2614 | 2799 | ||
2615 | /* Queue the GPU write cache flushing we need. */ | 2800 | /* Queue the GPU write cache flushing we need. */ |
2616 | old_write_domain = obj->write_domain; | 2801 | old_write_domain = obj->write_domain; |
2617 | i915_gem_flush(dev, 0, obj->write_domain); | 2802 | i915_gem_flush_ring(dev, NULL, |
2618 | if (i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring) == 0) | 2803 | to_intel_bo(obj)->ring, |
2619 | return -ENOMEM; | 2804 | 0, obj->write_domain); |
2805 | BUG_ON(obj->write_domain); | ||
2620 | 2806 | ||
2621 | trace_i915_gem_object_change_domain(obj, | 2807 | trace_i915_gem_object_change_domain(obj, |
2622 | obj->read_domains, | 2808 | obj->read_domains, |
2623 | old_write_domain); | 2809 | old_write_domain); |
2624 | return 0; | 2810 | |
2811 | if (pipelined) | ||
2812 | return 0; | ||
2813 | |||
2814 | return i915_gem_object_wait_rendering(obj, true); | ||
2625 | } | 2815 | } |
2626 | 2816 | ||
2627 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2817 | /** Flushes the GTT write domain for the object if it's dirty. */ |
@@ -2665,26 +2855,6 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) | |||
2665 | old_write_domain); | 2855 | old_write_domain); |
2666 | } | 2856 | } |
2667 | 2857 | ||
2668 | int | ||
2669 | i915_gem_object_flush_write_domain(struct drm_gem_object *obj) | ||
2670 | { | ||
2671 | int ret = 0; | ||
2672 | |||
2673 | switch (obj->write_domain) { | ||
2674 | case I915_GEM_DOMAIN_GTT: | ||
2675 | i915_gem_object_flush_gtt_write_domain(obj); | ||
2676 | break; | ||
2677 | case I915_GEM_DOMAIN_CPU: | ||
2678 | i915_gem_object_flush_cpu_write_domain(obj); | ||
2679 | break; | ||
2680 | default: | ||
2681 | ret = i915_gem_object_flush_gpu_write_domain(obj); | ||
2682 | break; | ||
2683 | } | ||
2684 | |||
2685 | return ret; | ||
2686 | } | ||
2687 | |||
2688 | /** | 2858 | /** |
2689 | * Moves a single object to the GTT read, and possibly write domain. | 2859 | * Moves a single object to the GTT read, and possibly write domain. |
2690 | * | 2860 | * |
@@ -2702,32 +2872,28 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2702 | if (obj_priv->gtt_space == NULL) | 2872 | if (obj_priv->gtt_space == NULL) |
2703 | return -EINVAL; | 2873 | return -EINVAL; |
2704 | 2874 | ||
2705 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2875 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); |
2706 | if (ret != 0) | 2876 | if (ret != 0) |
2707 | return ret; | 2877 | return ret; |
2708 | 2878 | ||
2709 | /* Wait on any GPU rendering and flushing to occur. */ | 2879 | i915_gem_object_flush_cpu_write_domain(obj); |
2710 | ret = i915_gem_object_wait_rendering(obj); | 2880 | |
2711 | if (ret != 0) | 2881 | if (write) { |
2712 | return ret; | 2882 | ret = i915_gem_object_wait_rendering(obj, true); |
2883 | if (ret) | ||
2884 | return ret; | ||
2885 | } | ||
2713 | 2886 | ||
2714 | old_write_domain = obj->write_domain; | 2887 | old_write_domain = obj->write_domain; |
2715 | old_read_domains = obj->read_domains; | 2888 | old_read_domains = obj->read_domains; |
2716 | 2889 | ||
2717 | /* If we're writing through the GTT domain, then CPU and GPU caches | ||
2718 | * will need to be invalidated at next use. | ||
2719 | */ | ||
2720 | if (write) | ||
2721 | obj->read_domains &= I915_GEM_DOMAIN_GTT; | ||
2722 | |||
2723 | i915_gem_object_flush_cpu_write_domain(obj); | ||
2724 | |||
2725 | /* It should now be out of any other write domains, and we can update | 2890 | /* It should now be out of any other write domains, and we can update |
2726 | * the domain values for our changes. | 2891 | * the domain values for our changes. |
2727 | */ | 2892 | */ |
2728 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); | 2893 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); |
2729 | obj->read_domains |= I915_GEM_DOMAIN_GTT; | 2894 | obj->read_domains |= I915_GEM_DOMAIN_GTT; |
2730 | if (write) { | 2895 | if (write) { |
2896 | obj->read_domains = I915_GEM_DOMAIN_GTT; | ||
2731 | obj->write_domain = I915_GEM_DOMAIN_GTT; | 2897 | obj->write_domain = I915_GEM_DOMAIN_GTT; |
2732 | obj_priv->dirty = 1; | 2898 | obj_priv->dirty = 1; |
2733 | } | 2899 | } |
@@ -2744,51 +2910,36 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2744 | * wait, as in modesetting process we're not supposed to be interrupted. | 2910 | * wait, as in modesetting process we're not supposed to be interrupted. |
2745 | */ | 2911 | */ |
2746 | int | 2912 | int |
2747 | i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) | 2913 | i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, |
2914 | bool pipelined) | ||
2748 | { | 2915 | { |
2749 | struct drm_device *dev = obj->dev; | ||
2750 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2916 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2751 | uint32_t old_write_domain, old_read_domains; | 2917 | uint32_t old_read_domains; |
2752 | int ret; | 2918 | int ret; |
2753 | 2919 | ||
2754 | /* Not valid to be called on unbound objects. */ | 2920 | /* Not valid to be called on unbound objects. */ |
2755 | if (obj_priv->gtt_space == NULL) | 2921 | if (obj_priv->gtt_space == NULL) |
2756 | return -EINVAL; | 2922 | return -EINVAL; |
2757 | 2923 | ||
2758 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2924 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); |
2759 | if (ret) | 2925 | if (ret) |
2760 | return ret; | 2926 | return ret; |
2761 | 2927 | ||
2762 | /* Wait on any GPU rendering and flushing to occur. */ | 2928 | /* Currently, we are always called from an non-interruptible context. */ |
2763 | if (obj_priv->active) { | 2929 | if (!pipelined) { |
2764 | #if WATCH_BUF | 2930 | ret = i915_gem_object_wait_rendering(obj, false); |
2765 | DRM_INFO("%s: object %p wait for seqno %08x\n", | 2931 | if (ret) |
2766 | __func__, obj, obj_priv->last_rendering_seqno); | ||
2767 | #endif | ||
2768 | ret = i915_do_wait_request(dev, | ||
2769 | obj_priv->last_rendering_seqno, | ||
2770 | 0, | ||
2771 | obj_priv->ring); | ||
2772 | if (ret != 0) | ||
2773 | return ret; | 2932 | return ret; |
2774 | } | 2933 | } |
2775 | 2934 | ||
2776 | i915_gem_object_flush_cpu_write_domain(obj); | 2935 | i915_gem_object_flush_cpu_write_domain(obj); |
2777 | 2936 | ||
2778 | old_write_domain = obj->write_domain; | ||
2779 | old_read_domains = obj->read_domains; | 2937 | old_read_domains = obj->read_domains; |
2780 | 2938 | obj->read_domains |= I915_GEM_DOMAIN_GTT; | |
2781 | /* It should now be out of any other write domains, and we can update | ||
2782 | * the domain values for our changes. | ||
2783 | */ | ||
2784 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); | ||
2785 | obj->read_domains = I915_GEM_DOMAIN_GTT; | ||
2786 | obj->write_domain = I915_GEM_DOMAIN_GTT; | ||
2787 | obj_priv->dirty = 1; | ||
2788 | 2939 | ||
2789 | trace_i915_gem_object_change_domain(obj, | 2940 | trace_i915_gem_object_change_domain(obj, |
2790 | old_read_domains, | 2941 | old_read_domains, |
2791 | old_write_domain); | 2942 | obj->write_domain); |
2792 | 2943 | ||
2793 | return 0; | 2944 | return 0; |
2794 | } | 2945 | } |
@@ -2805,12 +2956,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2805 | uint32_t old_write_domain, old_read_domains; | 2956 | uint32_t old_write_domain, old_read_domains; |
2806 | int ret; | 2957 | int ret; |
2807 | 2958 | ||
2808 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2959 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); |
2809 | if (ret) | ||
2810 | return ret; | ||
2811 | |||
2812 | /* Wait on any GPU rendering and flushing to occur. */ | ||
2813 | ret = i915_gem_object_wait_rendering(obj); | ||
2814 | if (ret != 0) | 2960 | if (ret != 0) |
2815 | return ret; | 2961 | return ret; |
2816 | 2962 | ||
@@ -2821,6 +2967,12 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2821 | */ | 2967 | */ |
2822 | i915_gem_object_set_to_full_cpu_read_domain(obj); | 2968 | i915_gem_object_set_to_full_cpu_read_domain(obj); |
2823 | 2969 | ||
2970 | if (write) { | ||
2971 | ret = i915_gem_object_wait_rendering(obj, true); | ||
2972 | if (ret) | ||
2973 | return ret; | ||
2974 | } | ||
2975 | |||
2824 | old_write_domain = obj->write_domain; | 2976 | old_write_domain = obj->write_domain; |
2825 | old_read_domains = obj->read_domains; | 2977 | old_read_domains = obj->read_domains; |
2826 | 2978 | ||
@@ -2840,7 +2992,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2840 | * need to be invalidated at next use. | 2992 | * need to be invalidated at next use. |
2841 | */ | 2993 | */ |
2842 | if (write) { | 2994 | if (write) { |
2843 | obj->read_domains &= I915_GEM_DOMAIN_CPU; | 2995 | obj->read_domains = I915_GEM_DOMAIN_CPU; |
2844 | obj->write_domain = I915_GEM_DOMAIN_CPU; | 2996 | obj->write_domain = I915_GEM_DOMAIN_CPU; |
2845 | } | 2997 | } |
2846 | 2998 | ||
@@ -2966,7 +3118,7 @@ static void | |||
2966 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | 3118 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) |
2967 | { | 3119 | { |
2968 | struct drm_device *dev = obj->dev; | 3120 | struct drm_device *dev = obj->dev; |
2969 | drm_i915_private_t *dev_priv = dev->dev_private; | 3121 | struct drm_i915_private *dev_priv = dev->dev_private; |
2970 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 3122 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2971 | uint32_t invalidate_domains = 0; | 3123 | uint32_t invalidate_domains = 0; |
2972 | uint32_t flush_domains = 0; | 3124 | uint32_t flush_domains = 0; |
@@ -2977,12 +3129,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
2977 | 3129 | ||
2978 | intel_mark_busy(dev, obj); | 3130 | intel_mark_busy(dev, obj); |
2979 | 3131 | ||
2980 | #if WATCH_BUF | ||
2981 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", | ||
2982 | __func__, obj, | ||
2983 | obj->read_domains, obj->pending_read_domains, | ||
2984 | obj->write_domain, obj->pending_write_domain); | ||
2985 | #endif | ||
2986 | /* | 3132 | /* |
2987 | * If the object isn't moving to a new write domain, | 3133 | * If the object isn't moving to a new write domain, |
2988 | * let the object stay in multiple read domains | 3134 | * let the object stay in multiple read domains |
@@ -3009,13 +3155,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
3009 | * stale data. That is, any new read domains. | 3155 | * stale data. That is, any new read domains. |
3010 | */ | 3156 | */ |
3011 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; | 3157 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; |
3012 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { | 3158 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) |
3013 | #if WATCH_BUF | ||
3014 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", | ||
3015 | __func__, flush_domains, invalidate_domains); | ||
3016 | #endif | ||
3017 | i915_gem_clflush_object(obj); | 3159 | i915_gem_clflush_object(obj); |
3018 | } | ||
3019 | 3160 | ||
3020 | old_read_domains = obj->read_domains; | 3161 | old_read_domains = obj->read_domains; |
3021 | 3162 | ||
@@ -3029,21 +3170,10 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
3029 | obj->pending_write_domain = obj->write_domain; | 3170 | obj->pending_write_domain = obj->write_domain; |
3030 | obj->read_domains = obj->pending_read_domains; | 3171 | obj->read_domains = obj->pending_read_domains; |
3031 | 3172 | ||
3032 | if (flush_domains & I915_GEM_GPU_DOMAINS) { | ||
3033 | if (obj_priv->ring == &dev_priv->render_ring) | ||
3034 | dev_priv->flush_rings |= FLUSH_RENDER_RING; | ||
3035 | else if (obj_priv->ring == &dev_priv->bsd_ring) | ||
3036 | dev_priv->flush_rings |= FLUSH_BSD_RING; | ||
3037 | } | ||
3038 | |||
3039 | dev->invalidate_domains |= invalidate_domains; | 3173 | dev->invalidate_domains |= invalidate_domains; |
3040 | dev->flush_domains |= flush_domains; | 3174 | dev->flush_domains |= flush_domains; |
3041 | #if WATCH_BUF | 3175 | if (obj_priv->ring) |
3042 | DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n", | 3176 | dev_priv->mm.flush_rings |= obj_priv->ring->id; |
3043 | __func__, | ||
3044 | obj->read_domains, obj->write_domain, | ||
3045 | dev->invalidate_domains, dev->flush_domains); | ||
3046 | #endif | ||
3047 | 3177 | ||
3048 | trace_i915_gem_object_change_domain(obj, | 3178 | trace_i915_gem_object_change_domain(obj, |
3049 | old_read_domains, | 3179 | old_read_domains, |
@@ -3106,12 +3236,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
3106 | if (offset == 0 && size == obj->size) | 3236 | if (offset == 0 && size == obj->size) |
3107 | return i915_gem_object_set_to_cpu_domain(obj, 0); | 3237 | return i915_gem_object_set_to_cpu_domain(obj, 0); |
3108 | 3238 | ||
3109 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 3239 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); |
3110 | if (ret) | ||
3111 | return ret; | ||
3112 | |||
3113 | /* Wait on any GPU rendering and flushing to occur. */ | ||
3114 | ret = i915_gem_object_wait_rendering(obj); | ||
3115 | if (ret != 0) | 3240 | if (ret != 0) |
3116 | return ret; | 3241 | return ret; |
3117 | i915_gem_object_flush_gtt_write_domain(obj); | 3242 | i915_gem_object_flush_gtt_write_domain(obj); |
@@ -3198,11 +3323,13 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3198 | * properly handle blits to/from tiled surfaces. | 3323 | * properly handle blits to/from tiled surfaces. |
3199 | */ | 3324 | */ |
3200 | if (need_fence) { | 3325 | if (need_fence) { |
3201 | ret = i915_gem_object_get_fence_reg(obj); | 3326 | ret = i915_gem_object_get_fence_reg(obj, true); |
3202 | if (ret != 0) { | 3327 | if (ret != 0) { |
3203 | i915_gem_object_unpin(obj); | 3328 | i915_gem_object_unpin(obj); |
3204 | return ret; | 3329 | return ret; |
3205 | } | 3330 | } |
3331 | |||
3332 | dev_priv->fence_regs[obj_priv->fence_reg].gpu = true; | ||
3206 | } | 3333 | } |
3207 | 3334 | ||
3208 | entry->offset = obj_priv->gtt_offset; | 3335 | entry->offset = obj_priv->gtt_offset; |
@@ -3337,7 +3464,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3337 | if (ret != 0) { | 3464 | if (ret != 0) { |
3338 | drm_gem_object_unreference(target_obj); | 3465 | drm_gem_object_unreference(target_obj); |
3339 | i915_gem_object_unpin(obj); | 3466 | i915_gem_object_unpin(obj); |
3340 | return -EINVAL; | 3467 | return ret; |
3341 | } | 3468 | } |
3342 | 3469 | ||
3343 | /* Map the page containing the relocation we're going to | 3470 | /* Map the page containing the relocation we're going to |
@@ -3352,11 +3479,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3352 | (reloc_offset & (PAGE_SIZE - 1))); | 3479 | (reloc_offset & (PAGE_SIZE - 1))); |
3353 | reloc_val = target_obj_priv->gtt_offset + reloc->delta; | 3480 | reloc_val = target_obj_priv->gtt_offset + reloc->delta; |
3354 | 3481 | ||
3355 | #if WATCH_BUF | ||
3356 | DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n", | ||
3357 | obj, (unsigned int) reloc->offset, | ||
3358 | readl(reloc_entry), reloc_val); | ||
3359 | #endif | ||
3360 | writel(reloc_val, reloc_entry); | 3482 | writel(reloc_val, reloc_entry); |
3361 | io_mapping_unmap_atomic(reloc_page, KM_USER0); | 3483 | io_mapping_unmap_atomic(reloc_page, KM_USER0); |
3362 | 3484 | ||
@@ -3368,10 +3490,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3368 | drm_gem_object_unreference(target_obj); | 3490 | drm_gem_object_unreference(target_obj); |
3369 | } | 3491 | } |
3370 | 3492 | ||
3371 | #if WATCH_BUF | ||
3372 | if (0) | ||
3373 | i915_gem_dump_object(obj, 128, __func__, ~0); | ||
3374 | #endif | ||
3375 | return 0; | 3493 | return 0; |
3376 | } | 3494 | } |
3377 | 3495 | ||
@@ -3386,28 +3504,48 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3386 | * relatively low latency when blocking on a particular request to finish. | 3504 | * relatively low latency when blocking on a particular request to finish. |
3387 | */ | 3505 | */ |
3388 | static int | 3506 | static int |
3389 | i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) | 3507 | i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) |
3390 | { | 3508 | { |
3391 | struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; | 3509 | struct drm_i915_private *dev_priv = dev->dev_private; |
3392 | int ret = 0; | 3510 | struct drm_i915_file_private *file_priv = file->driver_priv; |
3393 | unsigned long recent_enough = jiffies - msecs_to_jiffies(20); | 3511 | unsigned long recent_enough = jiffies - msecs_to_jiffies(20); |
3512 | struct drm_i915_gem_request *request; | ||
3513 | struct intel_ring_buffer *ring = NULL; | ||
3514 | u32 seqno = 0; | ||
3515 | int ret; | ||
3394 | 3516 | ||
3395 | mutex_lock(&dev->struct_mutex); | 3517 | spin_lock(&file_priv->mm.lock); |
3396 | while (!list_empty(&i915_file_priv->mm.request_list)) { | 3518 | list_for_each_entry(request, &file_priv->mm.request_list, client_list) { |
3397 | struct drm_i915_gem_request *request; | ||
3398 | |||
3399 | request = list_first_entry(&i915_file_priv->mm.request_list, | ||
3400 | struct drm_i915_gem_request, | ||
3401 | client_list); | ||
3402 | |||
3403 | if (time_after_eq(request->emitted_jiffies, recent_enough)) | 3519 | if (time_after_eq(request->emitted_jiffies, recent_enough)) |
3404 | break; | 3520 | break; |
3405 | 3521 | ||
3406 | ret = i915_wait_request(dev, request->seqno, request->ring); | 3522 | ring = request->ring; |
3407 | if (ret != 0) | 3523 | seqno = request->seqno; |
3408 | break; | ||
3409 | } | 3524 | } |
3410 | mutex_unlock(&dev->struct_mutex); | 3525 | spin_unlock(&file_priv->mm.lock); |
3526 | |||
3527 | if (seqno == 0) | ||
3528 | return 0; | ||
3529 | |||
3530 | ret = 0; | ||
3531 | if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { | ||
3532 | /* And wait for the seqno passing without holding any locks and | ||
3533 | * causing extra latency for others. This is safe as the irq | ||
3534 | * generation is designed to be run atomically and so is | ||
3535 | * lockless. | ||
3536 | */ | ||
3537 | ring->user_irq_get(dev, ring); | ||
3538 | ret = wait_event_interruptible(ring->irq_queue, | ||
3539 | i915_seqno_passed(ring->get_seqno(dev, ring), seqno) | ||
3540 | || atomic_read(&dev_priv->mm.wedged)); | ||
3541 | ring->user_irq_put(dev, ring); | ||
3542 | |||
3543 | if (ret == 0 && atomic_read(&dev_priv->mm.wedged)) | ||
3544 | ret = -EIO; | ||
3545 | } | ||
3546 | |||
3547 | if (ret == 0) | ||
3548 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); | ||
3411 | 3549 | ||
3412 | return ret; | 3550 | return ret; |
3413 | } | 3551 | } |
@@ -3543,8 +3681,7 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev, | |||
3543 | return ret; | 3681 | return ret; |
3544 | } | 3682 | } |
3545 | 3683 | ||
3546 | 3684 | static int | |
3547 | int | ||
3548 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, | 3685 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, |
3549 | struct drm_file *file_priv, | 3686 | struct drm_file *file_priv, |
3550 | struct drm_i915_gem_execbuffer2 *args, | 3687 | struct drm_i915_gem_execbuffer2 *args, |
@@ -3556,13 +3693,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3556 | struct drm_i915_gem_object *obj_priv; | 3693 | struct drm_i915_gem_object *obj_priv; |
3557 | struct drm_clip_rect *cliprects = NULL; | 3694 | struct drm_clip_rect *cliprects = NULL; |
3558 | struct drm_i915_gem_relocation_entry *relocs = NULL; | 3695 | struct drm_i915_gem_relocation_entry *relocs = NULL; |
3559 | int ret = 0, ret2, i, pinned = 0; | 3696 | struct drm_i915_gem_request *request = NULL; |
3697 | int ret, ret2, i, pinned = 0; | ||
3560 | uint64_t exec_offset; | 3698 | uint64_t exec_offset; |
3561 | uint32_t seqno, flush_domains, reloc_index; | 3699 | uint32_t reloc_index; |
3562 | int pin_tries, flips; | 3700 | int pin_tries, flips; |
3563 | 3701 | ||
3564 | struct intel_ring_buffer *ring = NULL; | 3702 | struct intel_ring_buffer *ring = NULL; |
3565 | 3703 | ||
3704 | ret = i915_gem_check_is_wedged(dev); | ||
3705 | if (ret) | ||
3706 | return ret; | ||
3707 | |||
3566 | #if WATCH_EXEC | 3708 | #if WATCH_EXEC |
3567 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | 3709 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", |
3568 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | 3710 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); |
@@ -3609,20 +3751,20 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3609 | } | 3751 | } |
3610 | } | 3752 | } |
3611 | 3753 | ||
3754 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
3755 | if (request == NULL) { | ||
3756 | ret = -ENOMEM; | ||
3757 | goto pre_mutex_err; | ||
3758 | } | ||
3759 | |||
3612 | ret = i915_gem_get_relocs_from_user(exec_list, args->buffer_count, | 3760 | ret = i915_gem_get_relocs_from_user(exec_list, args->buffer_count, |
3613 | &relocs); | 3761 | &relocs); |
3614 | if (ret != 0) | 3762 | if (ret != 0) |
3615 | goto pre_mutex_err; | 3763 | goto pre_mutex_err; |
3616 | 3764 | ||
3617 | mutex_lock(&dev->struct_mutex); | 3765 | ret = i915_mutex_lock_interruptible(dev); |
3618 | 3766 | if (ret) | |
3619 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3620 | |||
3621 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
3622 | mutex_unlock(&dev->struct_mutex); | ||
3623 | ret = -EIO; | ||
3624 | goto pre_mutex_err; | 3767 | goto pre_mutex_err; |
3625 | } | ||
3626 | 3768 | ||
3627 | if (dev_priv->mm.suspended) { | 3769 | if (dev_priv->mm.suspended) { |
3628 | mutex_unlock(&dev->struct_mutex); | 3770 | mutex_unlock(&dev->struct_mutex); |
@@ -3702,15 +3844,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3702 | pinned+1, args->buffer_count, | 3844 | pinned+1, args->buffer_count, |
3703 | total_size, num_fences, | 3845 | total_size, num_fences, |
3704 | ret); | 3846 | ret); |
3705 | DRM_ERROR("%d objects [%d pinned], " | 3847 | DRM_ERROR("%u objects [%u pinned, %u GTT], " |
3706 | "%d object bytes [%d pinned], " | 3848 | "%zu object bytes [%zu pinned], " |
3707 | "%d/%d gtt bytes\n", | 3849 | "%zu /%zu gtt bytes\n", |
3708 | atomic_read(&dev->object_count), | 3850 | dev_priv->mm.object_count, |
3709 | atomic_read(&dev->pin_count), | 3851 | dev_priv->mm.pin_count, |
3710 | atomic_read(&dev->object_memory), | 3852 | dev_priv->mm.gtt_count, |
3711 | atomic_read(&dev->pin_memory), | 3853 | dev_priv->mm.object_memory, |
3712 | atomic_read(&dev->gtt_memory), | 3854 | dev_priv->mm.pin_memory, |
3713 | dev->gtt_total); | 3855 | dev_priv->mm.gtt_memory, |
3856 | dev_priv->mm.gtt_total); | ||
3714 | } | 3857 | } |
3715 | goto err; | 3858 | goto err; |
3716 | } | 3859 | } |
@@ -3743,15 +3886,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3743 | goto err; | 3886 | goto err; |
3744 | } | 3887 | } |
3745 | 3888 | ||
3746 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3747 | |||
3748 | /* Zero the global flush/invalidate flags. These | 3889 | /* Zero the global flush/invalidate flags. These |
3749 | * will be modified as new domains are computed | 3890 | * will be modified as new domains are computed |
3750 | * for each object | 3891 | * for each object |
3751 | */ | 3892 | */ |
3752 | dev->invalidate_domains = 0; | 3893 | dev->invalidate_domains = 0; |
3753 | dev->flush_domains = 0; | 3894 | dev->flush_domains = 0; |
3754 | dev_priv->flush_rings = 0; | 3895 | dev_priv->mm.flush_rings = 0; |
3755 | 3896 | ||
3756 | for (i = 0; i < args->buffer_count; i++) { | 3897 | for (i = 0; i < args->buffer_count; i++) { |
3757 | struct drm_gem_object *obj = object_list[i]; | 3898 | struct drm_gem_object *obj = object_list[i]; |
@@ -3760,8 +3901,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3760 | i915_gem_object_set_to_gpu_domain(obj); | 3901 | i915_gem_object_set_to_gpu_domain(obj); |
3761 | } | 3902 | } |
3762 | 3903 | ||
3763 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3764 | |||
3765 | if (dev->invalidate_domains | dev->flush_domains) { | 3904 | if (dev->invalidate_domains | dev->flush_domains) { |
3766 | #if WATCH_EXEC | 3905 | #if WATCH_EXEC |
3767 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", | 3906 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", |
@@ -3769,17 +3908,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3769 | dev->invalidate_domains, | 3908 | dev->invalidate_domains, |
3770 | dev->flush_domains); | 3909 | dev->flush_domains); |
3771 | #endif | 3910 | #endif |
3772 | i915_gem_flush(dev, | 3911 | i915_gem_flush(dev, file_priv, |
3773 | dev->invalidate_domains, | 3912 | dev->invalidate_domains, |
3774 | dev->flush_domains); | 3913 | dev->flush_domains, |
3775 | if (dev_priv->flush_rings & FLUSH_RENDER_RING) | 3914 | dev_priv->mm.flush_rings); |
3776 | (void)i915_add_request(dev, file_priv, | ||
3777 | dev->flush_domains, | ||
3778 | &dev_priv->render_ring); | ||
3779 | if (dev_priv->flush_rings & FLUSH_BSD_RING) | ||
3780 | (void)i915_add_request(dev, file_priv, | ||
3781 | dev->flush_domains, | ||
3782 | &dev_priv->bsd_ring); | ||
3783 | } | 3915 | } |
3784 | 3916 | ||
3785 | for (i = 0; i < args->buffer_count; i++) { | 3917 | for (i = 0; i < args->buffer_count; i++) { |
@@ -3791,16 +3923,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3791 | if (obj->write_domain) | 3923 | if (obj->write_domain) |
3792 | list_move_tail(&obj_priv->gpu_write_list, | 3924 | list_move_tail(&obj_priv->gpu_write_list, |
3793 | &dev_priv->mm.gpu_write_list); | 3925 | &dev_priv->mm.gpu_write_list); |
3794 | else | ||
3795 | list_del_init(&obj_priv->gpu_write_list); | ||
3796 | 3926 | ||
3797 | trace_i915_gem_object_change_domain(obj, | 3927 | trace_i915_gem_object_change_domain(obj, |
3798 | obj->read_domains, | 3928 | obj->read_domains, |
3799 | old_write_domain); | 3929 | old_write_domain); |
3800 | } | 3930 | } |
3801 | 3931 | ||
3802 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3803 | |||
3804 | #if WATCH_COHERENCY | 3932 | #if WATCH_COHERENCY |
3805 | for (i = 0; i < args->buffer_count; i++) { | 3933 | for (i = 0; i < args->buffer_count; i++) { |
3806 | i915_gem_object_check_coherency(object_list[i], | 3934 | i915_gem_object_check_coherency(object_list[i], |
@@ -3827,33 +3955,17 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3827 | * Ensure that the commands in the batch buffer are | 3955 | * Ensure that the commands in the batch buffer are |
3828 | * finished before the interrupt fires | 3956 | * finished before the interrupt fires |
3829 | */ | 3957 | */ |
3830 | flush_domains = i915_retire_commands(dev, ring); | 3958 | i915_retire_commands(dev, ring); |
3831 | |||
3832 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3833 | 3959 | ||
3834 | /* | ||
3835 | * Get a seqno representing the execution of the current buffer, | ||
3836 | * which we can wait on. We would like to mitigate these interrupts, | ||
3837 | * likely by only creating seqnos occasionally (so that we have | ||
3838 | * *some* interrupts representing completion of buffers that we can | ||
3839 | * wait on when trying to clear up gtt space). | ||
3840 | */ | ||
3841 | seqno = i915_add_request(dev, file_priv, flush_domains, ring); | ||
3842 | BUG_ON(seqno == 0); | ||
3843 | for (i = 0; i < args->buffer_count; i++) { | 3960 | for (i = 0; i < args->buffer_count; i++) { |
3844 | struct drm_gem_object *obj = object_list[i]; | 3961 | struct drm_gem_object *obj = object_list[i]; |
3845 | obj_priv = to_intel_bo(obj); | 3962 | obj_priv = to_intel_bo(obj); |
3846 | 3963 | ||
3847 | i915_gem_object_move_to_active(obj, seqno, ring); | 3964 | i915_gem_object_move_to_active(obj, ring); |
3848 | #if WATCH_LRU | ||
3849 | DRM_INFO("%s: move to exec list %p\n", __func__, obj); | ||
3850 | #endif | ||
3851 | } | 3965 | } |
3852 | #if WATCH_LRU | ||
3853 | i915_dump_lru(dev, __func__); | ||
3854 | #endif | ||
3855 | 3966 | ||
3856 | i915_verify_inactive(dev, __FILE__, __LINE__); | 3967 | i915_add_request(dev, file_priv, request, ring); |
3968 | request = NULL; | ||
3857 | 3969 | ||
3858 | err: | 3970 | err: |
3859 | for (i = 0; i < pinned; i++) | 3971 | for (i = 0; i < pinned; i++) |
@@ -3886,6 +3998,7 @@ pre_mutex_err: | |||
3886 | 3998 | ||
3887 | drm_free_large(object_list); | 3999 | drm_free_large(object_list); |
3888 | kfree(cliprects); | 4000 | kfree(cliprects); |
4001 | kfree(request); | ||
3889 | 4002 | ||
3890 | return ret; | 4003 | return ret; |
3891 | } | 4004 | } |
@@ -3942,7 +4055,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3942 | exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; | 4055 | exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; |
3943 | exec2_list[i].alignment = exec_list[i].alignment; | 4056 | exec2_list[i].alignment = exec_list[i].alignment; |
3944 | exec2_list[i].offset = exec_list[i].offset; | 4057 | exec2_list[i].offset = exec_list[i].offset; |
3945 | if (!IS_I965G(dev)) | 4058 | if (INTEL_INFO(dev)->gen < 4) |
3946 | exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; | 4059 | exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; |
3947 | else | 4060 | else |
3948 | exec2_list[i].flags = 0; | 4061 | exec2_list[i].flags = 0; |
@@ -4039,12 +4152,12 @@ int | |||
4039 | i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | 4152 | i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) |
4040 | { | 4153 | { |
4041 | struct drm_device *dev = obj->dev; | 4154 | struct drm_device *dev = obj->dev; |
4155 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4042 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 4156 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
4043 | int ret; | 4157 | int ret; |
4044 | 4158 | ||
4045 | BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); | 4159 | BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); |
4046 | 4160 | WARN_ON(i915_verify_lists(dev)); | |
4047 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
4048 | 4161 | ||
4049 | if (obj_priv->gtt_space != NULL) { | 4162 | if (obj_priv->gtt_space != NULL) { |
4050 | if (alignment == 0) | 4163 | if (alignment == 0) |
@@ -4072,14 +4185,13 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
4072 | * remove it from the inactive list | 4185 | * remove it from the inactive list |
4073 | */ | 4186 | */ |
4074 | if (obj_priv->pin_count == 1) { | 4187 | if (obj_priv->pin_count == 1) { |
4075 | atomic_inc(&dev->pin_count); | 4188 | i915_gem_info_add_pin(dev_priv, obj->size); |
4076 | atomic_add(obj->size, &dev->pin_memory); | 4189 | if (!obj_priv->active) |
4077 | if (!obj_priv->active && | 4190 | list_move_tail(&obj_priv->list, |
4078 | (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | 4191 | &dev_priv->mm.pinned_list); |
4079 | list_del_init(&obj_priv->list); | ||
4080 | } | 4192 | } |
4081 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
4082 | 4193 | ||
4194 | WARN_ON(i915_verify_lists(dev)); | ||
4083 | return 0; | 4195 | return 0; |
4084 | } | 4196 | } |
4085 | 4197 | ||
@@ -4090,7 +4202,7 @@ i915_gem_object_unpin(struct drm_gem_object *obj) | |||
4090 | drm_i915_private_t *dev_priv = dev->dev_private; | 4202 | drm_i915_private_t *dev_priv = dev->dev_private; |
4091 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 4203 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
4092 | 4204 | ||
4093 | i915_verify_inactive(dev, __FILE__, __LINE__); | 4205 | WARN_ON(i915_verify_lists(dev)); |
4094 | obj_priv->pin_count--; | 4206 | obj_priv->pin_count--; |
4095 | BUG_ON(obj_priv->pin_count < 0); | 4207 | BUG_ON(obj_priv->pin_count < 0); |
4096 | BUG_ON(obj_priv->gtt_space == NULL); | 4208 | BUG_ON(obj_priv->gtt_space == NULL); |
@@ -4100,14 +4212,12 @@ i915_gem_object_unpin(struct drm_gem_object *obj) | |||
4100 | * the inactive list | 4212 | * the inactive list |
4101 | */ | 4213 | */ |
4102 | if (obj_priv->pin_count == 0) { | 4214 | if (obj_priv->pin_count == 0) { |
4103 | if (!obj_priv->active && | 4215 | if (!obj_priv->active) |
4104 | (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | ||
4105 | list_move_tail(&obj_priv->list, | 4216 | list_move_tail(&obj_priv->list, |
4106 | &dev_priv->mm.inactive_list); | 4217 | &dev_priv->mm.inactive_list); |
4107 | atomic_dec(&dev->pin_count); | 4218 | i915_gem_info_remove_pin(dev_priv, obj->size); |
4108 | atomic_sub(obj->size, &dev->pin_memory); | ||
4109 | } | 4219 | } |
4110 | i915_verify_inactive(dev, __FILE__, __LINE__); | 4220 | WARN_ON(i915_verify_lists(dev)); |
4111 | } | 4221 | } |
4112 | 4222 | ||
4113 | int | 4223 | int |
@@ -4119,17 +4229,20 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
4119 | struct drm_i915_gem_object *obj_priv; | 4229 | struct drm_i915_gem_object *obj_priv; |
4120 | int ret; | 4230 | int ret; |
4121 | 4231 | ||
4122 | mutex_lock(&dev->struct_mutex); | ||
4123 | |||
4124 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4232 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4125 | if (obj == NULL) { | 4233 | if (obj == NULL) { |
4126 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", | 4234 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", |
4127 | args->handle); | 4235 | args->handle); |
4128 | mutex_unlock(&dev->struct_mutex); | ||
4129 | return -ENOENT; | 4236 | return -ENOENT; |
4130 | } | 4237 | } |
4131 | obj_priv = to_intel_bo(obj); | 4238 | obj_priv = to_intel_bo(obj); |
4132 | 4239 | ||
4240 | ret = i915_mutex_lock_interruptible(dev); | ||
4241 | if (ret) { | ||
4242 | drm_gem_object_unreference_unlocked(obj); | ||
4243 | return ret; | ||
4244 | } | ||
4245 | |||
4133 | if (obj_priv->madv != I915_MADV_WILLNEED) { | 4246 | if (obj_priv->madv != I915_MADV_WILLNEED) { |
4134 | DRM_ERROR("Attempting to pin a purgeable buffer\n"); | 4247 | DRM_ERROR("Attempting to pin a purgeable buffer\n"); |
4135 | drm_gem_object_unreference(obj); | 4248 | drm_gem_object_unreference(obj); |
@@ -4174,18 +4287,23 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
4174 | struct drm_i915_gem_pin *args = data; | 4287 | struct drm_i915_gem_pin *args = data; |
4175 | struct drm_gem_object *obj; | 4288 | struct drm_gem_object *obj; |
4176 | struct drm_i915_gem_object *obj_priv; | 4289 | struct drm_i915_gem_object *obj_priv; |
4177 | 4290 | int ret; | |
4178 | mutex_lock(&dev->struct_mutex); | ||
4179 | 4291 | ||
4180 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4292 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4181 | if (obj == NULL) { | 4293 | if (obj == NULL) { |
4182 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", | 4294 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", |
4183 | args->handle); | 4295 | args->handle); |
4184 | mutex_unlock(&dev->struct_mutex); | ||
4185 | return -ENOENT; | 4296 | return -ENOENT; |
4186 | } | 4297 | } |
4187 | 4298 | ||
4188 | obj_priv = to_intel_bo(obj); | 4299 | obj_priv = to_intel_bo(obj); |
4300 | |||
4301 | ret = i915_mutex_lock_interruptible(dev); | ||
4302 | if (ret) { | ||
4303 | drm_gem_object_unreference_unlocked(obj); | ||
4304 | return ret; | ||
4305 | } | ||
4306 | |||
4189 | if (obj_priv->pin_filp != file_priv) { | 4307 | if (obj_priv->pin_filp != file_priv) { |
4190 | DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", | 4308 | DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", |
4191 | args->handle); | 4309 | args->handle); |
@@ -4211,6 +4329,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4211 | struct drm_i915_gem_busy *args = data; | 4329 | struct drm_i915_gem_busy *args = data; |
4212 | struct drm_gem_object *obj; | 4330 | struct drm_gem_object *obj; |
4213 | struct drm_i915_gem_object *obj_priv; | 4331 | struct drm_i915_gem_object *obj_priv; |
4332 | int ret; | ||
4214 | 4333 | ||
4215 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4334 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4216 | if (obj == NULL) { | 4335 | if (obj == NULL) { |
@@ -4219,7 +4338,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4219 | return -ENOENT; | 4338 | return -ENOENT; |
4220 | } | 4339 | } |
4221 | 4340 | ||
4222 | mutex_lock(&dev->struct_mutex); | 4341 | ret = i915_mutex_lock_interruptible(dev); |
4342 | if (ret) { | ||
4343 | drm_gem_object_unreference_unlocked(obj); | ||
4344 | return ret; | ||
4345 | } | ||
4223 | 4346 | ||
4224 | /* Count all active objects as busy, even if they are currently not used | 4347 | /* Count all active objects as busy, even if they are currently not used |
4225 | * by the gpu. Users of this interface expect objects to eventually | 4348 | * by the gpu. Users of this interface expect objects to eventually |
@@ -4234,10 +4357,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4234 | * use this buffer rather sooner than later, so issuing the required | 4357 | * use this buffer rather sooner than later, so issuing the required |
4235 | * flush earlier is beneficial. | 4358 | * flush earlier is beneficial. |
4236 | */ | 4359 | */ |
4237 | if (obj->write_domain) { | 4360 | if (obj->write_domain & I915_GEM_GPU_DOMAINS) |
4238 | i915_gem_flush(dev, 0, obj->write_domain); | 4361 | i915_gem_flush_ring(dev, file_priv, |
4239 | (void)i915_add_request(dev, file_priv, obj->write_domain, obj_priv->ring); | 4362 | obj_priv->ring, |
4240 | } | 4363 | 0, obj->write_domain); |
4241 | 4364 | ||
4242 | /* Update the active list for the hardware's current position. | 4365 | /* Update the active list for the hardware's current position. |
4243 | * Otherwise this only updates on a delayed timer or when irqs | 4366 | * Otherwise this only updates on a delayed timer or when irqs |
@@ -4268,6 +4391,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4268 | struct drm_i915_gem_madvise *args = data; | 4391 | struct drm_i915_gem_madvise *args = data; |
4269 | struct drm_gem_object *obj; | 4392 | struct drm_gem_object *obj; |
4270 | struct drm_i915_gem_object *obj_priv; | 4393 | struct drm_i915_gem_object *obj_priv; |
4394 | int ret; | ||
4271 | 4395 | ||
4272 | switch (args->madv) { | 4396 | switch (args->madv) { |
4273 | case I915_MADV_DONTNEED: | 4397 | case I915_MADV_DONTNEED: |
@@ -4283,10 +4407,14 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4283 | args->handle); | 4407 | args->handle); |
4284 | return -ENOENT; | 4408 | return -ENOENT; |
4285 | } | 4409 | } |
4286 | |||
4287 | mutex_lock(&dev->struct_mutex); | ||
4288 | obj_priv = to_intel_bo(obj); | 4410 | obj_priv = to_intel_bo(obj); |
4289 | 4411 | ||
4412 | ret = i915_mutex_lock_interruptible(dev); | ||
4413 | if (ret) { | ||
4414 | drm_gem_object_unreference_unlocked(obj); | ||
4415 | return ret; | ||
4416 | } | ||
4417 | |||
4290 | if (obj_priv->pin_count) { | 4418 | if (obj_priv->pin_count) { |
4291 | drm_gem_object_unreference(obj); | 4419 | drm_gem_object_unreference(obj); |
4292 | mutex_unlock(&dev->struct_mutex); | 4420 | mutex_unlock(&dev->struct_mutex); |
@@ -4314,6 +4442,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4314 | struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, | 4442 | struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, |
4315 | size_t size) | 4443 | size_t size) |
4316 | { | 4444 | { |
4445 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4317 | struct drm_i915_gem_object *obj; | 4446 | struct drm_i915_gem_object *obj; |
4318 | 4447 | ||
4319 | obj = kzalloc(sizeof(*obj), GFP_KERNEL); | 4448 | obj = kzalloc(sizeof(*obj), GFP_KERNEL); |
@@ -4325,6 +4454,8 @@ struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, | |||
4325 | return NULL; | 4454 | return NULL; |
4326 | } | 4455 | } |
4327 | 4456 | ||
4457 | i915_gem_info_add_obj(dev_priv, size); | ||
4458 | |||
4328 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; | 4459 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; |
4329 | obj->base.read_domains = I915_GEM_DOMAIN_CPU; | 4460 | obj->base.read_domains = I915_GEM_DOMAIN_CPU; |
4330 | 4461 | ||
@@ -4365,6 +4496,7 @@ static void i915_gem_free_object_tail(struct drm_gem_object *obj) | |||
4365 | i915_gem_free_mmap_offset(obj); | 4496 | i915_gem_free_mmap_offset(obj); |
4366 | 4497 | ||
4367 | drm_gem_object_release(obj); | 4498 | drm_gem_object_release(obj); |
4499 | i915_gem_info_remove_obj(dev_priv, obj->size); | ||
4368 | 4500 | ||
4369 | kfree(obj_priv->page_cpu_valid); | 4501 | kfree(obj_priv->page_cpu_valid); |
4370 | kfree(obj_priv->bit_17); | 4502 | kfree(obj_priv->bit_17); |
@@ -4423,7 +4555,7 @@ i915_gem_idle(struct drm_device *dev) | |||
4423 | * And not confound mm.suspended! | 4555 | * And not confound mm.suspended! |
4424 | */ | 4556 | */ |
4425 | dev_priv->mm.suspended = 1; | 4557 | dev_priv->mm.suspended = 1; |
4426 | del_timer(&dev_priv->hangcheck_timer); | 4558 | del_timer_sync(&dev_priv->hangcheck_timer); |
4427 | 4559 | ||
4428 | i915_kernel_lost_context(dev); | 4560 | i915_kernel_lost_context(dev); |
4429 | i915_gem_cleanup_ringbuffer(dev); | 4561 | i915_gem_cleanup_ringbuffer(dev); |
@@ -4503,28 +4635,18 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
4503 | drm_i915_private_t *dev_priv = dev->dev_private; | 4635 | drm_i915_private_t *dev_priv = dev->dev_private; |
4504 | int ret; | 4636 | int ret; |
4505 | 4637 | ||
4506 | dev_priv->render_ring = render_ring; | ||
4507 | |||
4508 | if (!I915_NEED_GFX_HWS(dev)) { | ||
4509 | dev_priv->render_ring.status_page.page_addr | ||
4510 | = dev_priv->status_page_dmah->vaddr; | ||
4511 | memset(dev_priv->render_ring.status_page.page_addr, | ||
4512 | 0, PAGE_SIZE); | ||
4513 | } | ||
4514 | |||
4515 | if (HAS_PIPE_CONTROL(dev)) { | 4638 | if (HAS_PIPE_CONTROL(dev)) { |
4516 | ret = i915_gem_init_pipe_control(dev); | 4639 | ret = i915_gem_init_pipe_control(dev); |
4517 | if (ret) | 4640 | if (ret) |
4518 | return ret; | 4641 | return ret; |
4519 | } | 4642 | } |
4520 | 4643 | ||
4521 | ret = intel_init_ring_buffer(dev, &dev_priv->render_ring); | 4644 | ret = intel_init_render_ring_buffer(dev); |
4522 | if (ret) | 4645 | if (ret) |
4523 | goto cleanup_pipe_control; | 4646 | goto cleanup_pipe_control; |
4524 | 4647 | ||
4525 | if (HAS_BSD(dev)) { | 4648 | if (HAS_BSD(dev)) { |
4526 | dev_priv->bsd_ring = bsd_ring; | 4649 | ret = intel_init_bsd_ring_buffer(dev); |
4527 | ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring); | ||
4528 | if (ret) | 4650 | if (ret) |
4529 | goto cleanup_render_ring; | 4651 | goto cleanup_render_ring; |
4530 | } | 4652 | } |
@@ -4577,11 +4699,8 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
4577 | return ret; | 4699 | return ret; |
4578 | } | 4700 | } |
4579 | 4701 | ||
4580 | spin_lock(&dev_priv->mm.active_list_lock); | ||
4581 | BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); | 4702 | BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); |
4582 | BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list)); | 4703 | BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list)); |
4583 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
4584 | |||
4585 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); | 4704 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); |
4586 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); | 4705 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); |
4587 | BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); | 4706 | BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); |
@@ -4633,10 +4752,10 @@ i915_gem_load(struct drm_device *dev) | |||
4633 | int i; | 4752 | int i; |
4634 | drm_i915_private_t *dev_priv = dev->dev_private; | 4753 | drm_i915_private_t *dev_priv = dev->dev_private; |
4635 | 4754 | ||
4636 | spin_lock_init(&dev_priv->mm.active_list_lock); | ||
4637 | INIT_LIST_HEAD(&dev_priv->mm.flushing_list); | 4755 | INIT_LIST_HEAD(&dev_priv->mm.flushing_list); |
4638 | INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); | 4756 | INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); |
4639 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); | 4757 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); |
4758 | INIT_LIST_HEAD(&dev_priv->mm.pinned_list); | ||
4640 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); | 4759 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); |
4641 | INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); | 4760 | INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); |
4642 | INIT_LIST_HEAD(&dev_priv->render_ring.active_list); | 4761 | INIT_LIST_HEAD(&dev_priv->render_ring.active_list); |
@@ -4649,6 +4768,7 @@ i915_gem_load(struct drm_device *dev) | |||
4649 | INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); | 4768 | INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); |
4650 | INIT_DELAYED_WORK(&dev_priv->mm.retire_work, | 4769 | INIT_DELAYED_WORK(&dev_priv->mm.retire_work, |
4651 | i915_gem_retire_work_handler); | 4770 | i915_gem_retire_work_handler); |
4771 | init_completion(&dev_priv->error_completion); | ||
4652 | spin_lock(&shrink_list_lock); | 4772 | spin_lock(&shrink_list_lock); |
4653 | list_add(&dev_priv->mm.shrink_list, &shrink_list); | 4773 | list_add(&dev_priv->mm.shrink_list, &shrink_list); |
4654 | spin_unlock(&shrink_list_lock); | 4774 | spin_unlock(&shrink_list_lock); |
@@ -4667,21 +4787,30 @@ i915_gem_load(struct drm_device *dev) | |||
4667 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 4787 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4668 | dev_priv->fence_reg_start = 3; | 4788 | dev_priv->fence_reg_start = 3; |
4669 | 4789 | ||
4670 | if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | 4790 | if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
4671 | dev_priv->num_fence_regs = 16; | 4791 | dev_priv->num_fence_regs = 16; |
4672 | else | 4792 | else |
4673 | dev_priv->num_fence_regs = 8; | 4793 | dev_priv->num_fence_regs = 8; |
4674 | 4794 | ||
4675 | /* Initialize fence registers to zero */ | 4795 | /* Initialize fence registers to zero */ |
4676 | if (IS_I965G(dev)) { | 4796 | switch (INTEL_INFO(dev)->gen) { |
4797 | case 6: | ||
4798 | for (i = 0; i < 16; i++) | ||
4799 | I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), 0); | ||
4800 | break; | ||
4801 | case 5: | ||
4802 | case 4: | ||
4677 | for (i = 0; i < 16; i++) | 4803 | for (i = 0; i < 16; i++) |
4678 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); | 4804 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); |
4679 | } else { | 4805 | break; |
4680 | for (i = 0; i < 8; i++) | 4806 | case 3: |
4681 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
4682 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | 4807 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
4683 | for (i = 0; i < 8; i++) | 4808 | for (i = 0; i < 8; i++) |
4684 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); | 4809 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); |
4810 | case 2: | ||
4811 | for (i = 0; i < 8; i++) | ||
4812 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
4813 | break; | ||
4685 | } | 4814 | } |
4686 | i915_gem_detect_bit_6_swizzle(dev); | 4815 | i915_gem_detect_bit_6_swizzle(dev); |
4687 | init_waitqueue_head(&dev_priv->pending_flip_queue); | 4816 | init_waitqueue_head(&dev_priv->pending_flip_queue); |
@@ -4691,8 +4820,8 @@ i915_gem_load(struct drm_device *dev) | |||
4691 | * Create a physically contiguous memory object for this object | 4820 | * Create a physically contiguous memory object for this object |
4692 | * e.g. for cursor + overlay regs | 4821 | * e.g. for cursor + overlay regs |
4693 | */ | 4822 | */ |
4694 | int i915_gem_init_phys_object(struct drm_device *dev, | 4823 | static int i915_gem_init_phys_object(struct drm_device *dev, |
4695 | int id, int size, int align) | 4824 | int id, int size, int align) |
4696 | { | 4825 | { |
4697 | drm_i915_private_t *dev_priv = dev->dev_private; | 4826 | drm_i915_private_t *dev_priv = dev->dev_private; |
4698 | struct drm_i915_gem_phys_object *phys_obj; | 4827 | struct drm_i915_gem_phys_object *phys_obj; |
@@ -4724,7 +4853,7 @@ kfree_obj: | |||
4724 | return ret; | 4853 | return ret; |
4725 | } | 4854 | } |
4726 | 4855 | ||
4727 | void i915_gem_free_phys_object(struct drm_device *dev, int id) | 4856 | static void i915_gem_free_phys_object(struct drm_device *dev, int id) |
4728 | { | 4857 | { |
4729 | drm_i915_private_t *dev_priv = dev->dev_private; | 4858 | drm_i915_private_t *dev_priv = dev->dev_private; |
4730 | struct drm_i915_gem_phys_object *phys_obj; | 4859 | struct drm_i915_gem_phys_object *phys_obj; |
@@ -4869,18 +4998,25 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
4869 | return 0; | 4998 | return 0; |
4870 | } | 4999 | } |
4871 | 5000 | ||
4872 | void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv) | 5001 | void i915_gem_release(struct drm_device *dev, struct drm_file *file) |
4873 | { | 5002 | { |
4874 | struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; | 5003 | struct drm_i915_file_private *file_priv = file->driver_priv; |
4875 | 5004 | ||
4876 | /* Clean up our request list when the client is going away, so that | 5005 | /* Clean up our request list when the client is going away, so that |
4877 | * later retire_requests won't dereference our soon-to-be-gone | 5006 | * later retire_requests won't dereference our soon-to-be-gone |
4878 | * file_priv. | 5007 | * file_priv. |
4879 | */ | 5008 | */ |
4880 | mutex_lock(&dev->struct_mutex); | 5009 | spin_lock(&file_priv->mm.lock); |
4881 | while (!list_empty(&i915_file_priv->mm.request_list)) | 5010 | while (!list_empty(&file_priv->mm.request_list)) { |
4882 | list_del_init(i915_file_priv->mm.request_list.next); | 5011 | struct drm_i915_gem_request *request; |
4883 | mutex_unlock(&dev->struct_mutex); | 5012 | |
5013 | request = list_first_entry(&file_priv->mm.request_list, | ||
5014 | struct drm_i915_gem_request, | ||
5015 | client_list); | ||
5016 | list_del(&request->client_list); | ||
5017 | request->file_priv = NULL; | ||
5018 | } | ||
5019 | spin_unlock(&file_priv->mm.lock); | ||
4884 | } | 5020 | } |
4885 | 5021 | ||
4886 | static int | 5022 | static int |
@@ -4889,12 +5025,10 @@ i915_gpu_is_active(struct drm_device *dev) | |||
4889 | drm_i915_private_t *dev_priv = dev->dev_private; | 5025 | drm_i915_private_t *dev_priv = dev->dev_private; |
4890 | int lists_empty; | 5026 | int lists_empty; |
4891 | 5027 | ||
4892 | spin_lock(&dev_priv->mm.active_list_lock); | ||
4893 | lists_empty = list_empty(&dev_priv->mm.flushing_list) && | 5028 | lists_empty = list_empty(&dev_priv->mm.flushing_list) && |
4894 | list_empty(&dev_priv->render_ring.active_list); | 5029 | list_empty(&dev_priv->render_ring.active_list); |
4895 | if (HAS_BSD(dev)) | 5030 | if (HAS_BSD(dev)) |
4896 | lists_empty &= list_empty(&dev_priv->bsd_ring.active_list); | 5031 | lists_empty &= list_empty(&dev_priv->bsd_ring.active_list); |
4897 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
4898 | 5032 | ||
4899 | return !lists_empty; | 5033 | return !lists_empty; |
4900 | } | 5034 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 80f380b1d951..48644b840a8d 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
@@ -30,29 +30,112 @@ | |||
30 | #include "i915_drm.h" | 30 | #include "i915_drm.h" |
31 | #include "i915_drv.h" | 31 | #include "i915_drv.h" |
32 | 32 | ||
33 | #if WATCH_INACTIVE | 33 | #if WATCH_LISTS |
34 | void | 34 | int |
35 | i915_verify_inactive(struct drm_device *dev, char *file, int line) | 35 | i915_verify_lists(struct drm_device *dev) |
36 | { | 36 | { |
37 | static int warned; | ||
37 | drm_i915_private_t *dev_priv = dev->dev_private; | 38 | drm_i915_private_t *dev_priv = dev->dev_private; |
38 | struct drm_gem_object *obj; | 39 | struct drm_i915_gem_object *obj; |
39 | struct drm_i915_gem_object *obj_priv; | 40 | int err = 0; |
40 | 41 | ||
41 | list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { | 42 | if (warned) |
42 | obj = &obj_priv->base; | 43 | return 0; |
43 | if (obj_priv->pin_count || obj_priv->active || | 44 | |
44 | (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | | 45 | list_for_each_entry(obj, &dev_priv->render_ring.active_list, list) { |
45 | I915_GEM_DOMAIN_GTT))) | 46 | if (obj->base.dev != dev || |
46 | DRM_ERROR("inactive %p (p %d a %d w %x) %s:%d\n", | 47 | !atomic_read(&obj->base.refcount.refcount)) { |
48 | DRM_ERROR("freed render active %p\n", obj); | ||
49 | err++; | ||
50 | break; | ||
51 | } else if (!obj->active || | ||
52 | (obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0) { | ||
53 | DRM_ERROR("invalid render active %p (a %d r %x)\n", | ||
54 | obj, | ||
55 | obj->active, | ||
56 | obj->base.read_domains); | ||
57 | err++; | ||
58 | } else if (obj->base.write_domain && list_empty(&obj->gpu_write_list)) { | ||
59 | DRM_ERROR("invalid render active %p (w %x, gwl %d)\n", | ||
60 | obj, | ||
61 | obj->base.write_domain, | ||
62 | !list_empty(&obj->gpu_write_list)); | ||
63 | err++; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | list_for_each_entry(obj, &dev_priv->mm.flushing_list, list) { | ||
68 | if (obj->base.dev != dev || | ||
69 | !atomic_read(&obj->base.refcount.refcount)) { | ||
70 | DRM_ERROR("freed flushing %p\n", obj); | ||
71 | err++; | ||
72 | break; | ||
73 | } else if (!obj->active || | ||
74 | (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 || | ||
75 | list_empty(&obj->gpu_write_list)){ | ||
76 | DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n", | ||
47 | obj, | 77 | obj, |
48 | obj_priv->pin_count, obj_priv->active, | 78 | obj->active, |
49 | obj->write_domain, file, line); | 79 | obj->base.write_domain, |
80 | !list_empty(&obj->gpu_write_list)); | ||
81 | err++; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | list_for_each_entry(obj, &dev_priv->mm.gpu_write_list, gpu_write_list) { | ||
86 | if (obj->base.dev != dev || | ||
87 | !atomic_read(&obj->base.refcount.refcount)) { | ||
88 | DRM_ERROR("freed gpu write %p\n", obj); | ||
89 | err++; | ||
90 | break; | ||
91 | } else if (!obj->active || | ||
92 | (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) { | ||
93 | DRM_ERROR("invalid gpu write %p (a %d w %x)\n", | ||
94 | obj, | ||
95 | obj->active, | ||
96 | obj->base.write_domain); | ||
97 | err++; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, list) { | ||
102 | if (obj->base.dev != dev || | ||
103 | !atomic_read(&obj->base.refcount.refcount)) { | ||
104 | DRM_ERROR("freed inactive %p\n", obj); | ||
105 | err++; | ||
106 | break; | ||
107 | } else if (obj->pin_count || obj->active || | ||
108 | (obj->base.write_domain & I915_GEM_GPU_DOMAINS)) { | ||
109 | DRM_ERROR("invalid inactive %p (p %d a %d w %x)\n", | ||
110 | obj, | ||
111 | obj->pin_count, obj->active, | ||
112 | obj->base.write_domain); | ||
113 | err++; | ||
114 | } | ||
50 | } | 115 | } |
116 | |||
117 | list_for_each_entry(obj, &dev_priv->mm.pinned_list, list) { | ||
118 | if (obj->base.dev != dev || | ||
119 | !atomic_read(&obj->base.refcount.refcount)) { | ||
120 | DRM_ERROR("freed pinned %p\n", obj); | ||
121 | err++; | ||
122 | break; | ||
123 | } else if (!obj->pin_count || obj->active || | ||
124 | (obj->base.write_domain & I915_GEM_GPU_DOMAINS)) { | ||
125 | DRM_ERROR("invalid pinned %p (p %d a %d w %x)\n", | ||
126 | obj, | ||
127 | obj->pin_count, obj->active, | ||
128 | obj->base.write_domain); | ||
129 | err++; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | return warned = err; | ||
51 | } | 134 | } |
52 | #endif /* WATCH_INACTIVE */ | 135 | #endif /* WATCH_INACTIVE */ |
53 | 136 | ||
54 | 137 | ||
55 | #if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE | 138 | #if WATCH_EXEC | WATCH_PWRITE |
56 | static void | 139 | static void |
57 | i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end, | 140 | i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end, |
58 | uint32_t bias, uint32_t mark) | 141 | uint32_t bias, uint32_t mark) |
@@ -97,41 +180,6 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len, | |||
97 | } | 180 | } |
98 | #endif | 181 | #endif |
99 | 182 | ||
100 | #if WATCH_LRU | ||
101 | void | ||
102 | i915_dump_lru(struct drm_device *dev, const char *where) | ||
103 | { | ||
104 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
105 | struct drm_i915_gem_object *obj_priv; | ||
106 | |||
107 | DRM_INFO("active list %s {\n", where); | ||
108 | spin_lock(&dev_priv->mm.active_list_lock); | ||
109 | list_for_each_entry(obj_priv, &dev_priv->mm.active_list, | ||
110 | list) | ||
111 | { | ||
112 | DRM_INFO(" %p: %08x\n", obj_priv, | ||
113 | obj_priv->last_rendering_seqno); | ||
114 | } | ||
115 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
116 | DRM_INFO("}\n"); | ||
117 | DRM_INFO("flushing list %s {\n", where); | ||
118 | list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, | ||
119 | list) | ||
120 | { | ||
121 | DRM_INFO(" %p: %08x\n", obj_priv, | ||
122 | obj_priv->last_rendering_seqno); | ||
123 | } | ||
124 | DRM_INFO("}\n"); | ||
125 | DRM_INFO("inactive %s {\n", where); | ||
126 | list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { | ||
127 | DRM_INFO(" %p: %08x\n", obj_priv, | ||
128 | obj_priv->last_rendering_seqno); | ||
129 | } | ||
130 | DRM_INFO("}\n"); | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | |||
135 | #if WATCH_COHERENCY | 183 | #if WATCH_COHERENCY |
136 | void | 184 | void |
137 | i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | 185 | i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 5c428fa3e0b3..3d7fbf32bb18 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
@@ -212,14 +212,11 @@ i915_gem_evict_everything(struct drm_device *dev) | |||
212 | int ret; | 212 | int ret; |
213 | bool lists_empty; | 213 | bool lists_empty; |
214 | 214 | ||
215 | spin_lock(&dev_priv->mm.active_list_lock); | ||
216 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && | 215 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && |
217 | list_empty(&dev_priv->mm.flushing_list) && | 216 | list_empty(&dev_priv->mm.flushing_list) && |
218 | list_empty(&dev_priv->render_ring.active_list) && | 217 | list_empty(&dev_priv->render_ring.active_list) && |
219 | (!HAS_BSD(dev) | 218 | (!HAS_BSD(dev) |
220 | || list_empty(&dev_priv->bsd_ring.active_list))); | 219 | || list_empty(&dev_priv->bsd_ring.active_list))); |
221 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
222 | |||
223 | if (lists_empty) | 220 | if (lists_empty) |
224 | return -ENOSPC; | 221 | return -ENOSPC; |
225 | 222 | ||
@@ -234,13 +231,11 @@ i915_gem_evict_everything(struct drm_device *dev) | |||
234 | if (ret) | 231 | if (ret) |
235 | return ret; | 232 | return ret; |
236 | 233 | ||
237 | spin_lock(&dev_priv->mm.active_list_lock); | ||
238 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && | 234 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && |
239 | list_empty(&dev_priv->mm.flushing_list) && | 235 | list_empty(&dev_priv->mm.flushing_list) && |
240 | list_empty(&dev_priv->render_ring.active_list) && | 236 | list_empty(&dev_priv->render_ring.active_list) && |
241 | (!HAS_BSD(dev) | 237 | (!HAS_BSD(dev) |
242 | || list_empty(&dev_priv->bsd_ring.active_list))); | 238 | || list_empty(&dev_priv->bsd_ring.active_list))); |
243 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
244 | BUG_ON(!lists_empty); | 239 | BUG_ON(!lists_empty); |
245 | 240 | ||
246 | return 0; | 241 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 710eca70b323..8c9ffc4768ee 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
@@ -98,7 +98,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) | |||
98 | */ | 98 | */ |
99 | swizzle_x = I915_BIT_6_SWIZZLE_9_10; | 99 | swizzle_x = I915_BIT_6_SWIZZLE_9_10; |
100 | swizzle_y = I915_BIT_6_SWIZZLE_9; | 100 | swizzle_y = I915_BIT_6_SWIZZLE_9; |
101 | } else if (!IS_I9XX(dev)) { | 101 | } else if (IS_GEN2(dev)) { |
102 | /* As far as we know, the 865 doesn't have these bit 6 | 102 | /* As far as we know, the 865 doesn't have these bit 6 |
103 | * swizzling issues. | 103 | * swizzling issues. |
104 | */ | 104 | */ |
@@ -190,19 +190,19 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
190 | if (tiling_mode == I915_TILING_NONE) | 190 | if (tiling_mode == I915_TILING_NONE) |
191 | return true; | 191 | return true; |
192 | 192 | ||
193 | if (!IS_I9XX(dev) || | 193 | if (IS_GEN2(dev) || |
194 | (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) | 194 | (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) |
195 | tile_width = 128; | 195 | tile_width = 128; |
196 | else | 196 | else |
197 | tile_width = 512; | 197 | tile_width = 512; |
198 | 198 | ||
199 | /* check maximum stride & object size */ | 199 | /* check maximum stride & object size */ |
200 | if (IS_I965G(dev)) { | 200 | if (INTEL_INFO(dev)->gen >= 4) { |
201 | /* i965 stores the end address of the gtt mapping in the fence | 201 | /* i965 stores the end address of the gtt mapping in the fence |
202 | * reg, so dont bother to check the size */ | 202 | * reg, so dont bother to check the size */ |
203 | if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) | 203 | if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) |
204 | return false; | 204 | return false; |
205 | } else if (IS_GEN3(dev) || IS_GEN2(dev)) { | 205 | } else { |
206 | if (stride > 8192) | 206 | if (stride > 8192) |
207 | return false; | 207 | return false; |
208 | 208 | ||
@@ -216,7 +216,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
216 | } | 216 | } |
217 | 217 | ||
218 | /* 965+ just needs multiples of tile width */ | 218 | /* 965+ just needs multiples of tile width */ |
219 | if (IS_I965G(dev)) { | 219 | if (INTEL_INFO(dev)->gen >= 4) { |
220 | if (stride & (tile_width - 1)) | 220 | if (stride & (tile_width - 1)) |
221 | return false; | 221 | return false; |
222 | return true; | 222 | return true; |
@@ -244,16 +244,18 @@ i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode) | |||
244 | if (tiling_mode == I915_TILING_NONE) | 244 | if (tiling_mode == I915_TILING_NONE) |
245 | return true; | 245 | return true; |
246 | 246 | ||
247 | if (!IS_I965G(dev)) { | 247 | if (INTEL_INFO(dev)->gen >= 4) |
248 | if (obj_priv->gtt_offset & (obj->size - 1)) | 248 | return true; |
249 | |||
250 | if (obj_priv->gtt_offset & (obj->size - 1)) | ||
251 | return false; | ||
252 | |||
253 | if (IS_GEN3(dev)) { | ||
254 | if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) | ||
255 | return false; | ||
256 | } else { | ||
257 | if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) | ||
249 | return false; | 258 | return false; |
250 | if (IS_I9XX(dev)) { | ||
251 | if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) | ||
252 | return false; | ||
253 | } else { | ||
254 | if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) | ||
255 | return false; | ||
256 | } | ||
257 | } | 259 | } |
258 | 260 | ||
259 | return true; | 261 | return true; |
@@ -271,7 +273,11 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
271 | drm_i915_private_t *dev_priv = dev->dev_private; | 273 | drm_i915_private_t *dev_priv = dev->dev_private; |
272 | struct drm_gem_object *obj; | 274 | struct drm_gem_object *obj; |
273 | struct drm_i915_gem_object *obj_priv; | 275 | struct drm_i915_gem_object *obj_priv; |
274 | int ret = 0; | 276 | int ret; |
277 | |||
278 | ret = i915_gem_check_is_wedged(dev); | ||
279 | if (ret) | ||
280 | return ret; | ||
275 | 281 | ||
276 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 282 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
277 | if (obj == NULL) | 283 | if (obj == NULL) |
@@ -328,7 +334,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
328 | if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode)) | 334 | if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode)) |
329 | ret = i915_gem_object_unbind(obj); | 335 | ret = i915_gem_object_unbind(obj); |
330 | else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 336 | else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
331 | ret = i915_gem_object_put_fence_reg(obj); | 337 | ret = i915_gem_object_put_fence_reg(obj, true); |
332 | else | 338 | else |
333 | i915_gem_release_mmap(obj); | 339 | i915_gem_release_mmap(obj); |
334 | 340 | ||
@@ -399,16 +405,14 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
399 | * bit 17 of its physical address and therefore being interpreted differently | 405 | * bit 17 of its physical address and therefore being interpreted differently |
400 | * by the GPU. | 406 | * by the GPU. |
401 | */ | 407 | */ |
402 | static int | 408 | static void |
403 | i915_gem_swizzle_page(struct page *page) | 409 | i915_gem_swizzle_page(struct page *page) |
404 | { | 410 | { |
411 | char temp[64]; | ||
405 | char *vaddr; | 412 | char *vaddr; |
406 | int i; | 413 | int i; |
407 | char temp[64]; | ||
408 | 414 | ||
409 | vaddr = kmap(page); | 415 | vaddr = kmap(page); |
410 | if (vaddr == NULL) | ||
411 | return -ENOMEM; | ||
412 | 416 | ||
413 | for (i = 0; i < PAGE_SIZE; i += 128) { | 417 | for (i = 0; i < PAGE_SIZE; i += 128) { |
414 | memcpy(temp, &vaddr[i], 64); | 418 | memcpy(temp, &vaddr[i], 64); |
@@ -417,8 +421,6 @@ i915_gem_swizzle_page(struct page *page) | |||
417 | } | 421 | } |
418 | 422 | ||
419 | kunmap(page); | 423 | kunmap(page); |
420 | |||
421 | return 0; | ||
422 | } | 424 | } |
423 | 425 | ||
424 | void | 426 | void |
@@ -440,11 +442,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj) | |||
440 | char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17; | 442 | char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17; |
441 | if ((new_bit_17 & 0x1) != | 443 | if ((new_bit_17 & 0x1) != |
442 | (test_bit(i, obj_priv->bit_17) != 0)) { | 444 | (test_bit(i, obj_priv->bit_17) != 0)) { |
443 | int ret = i915_gem_swizzle_page(obj_priv->pages[i]); | 445 | i915_gem_swizzle_page(obj_priv->pages[i]); |
444 | if (ret != 0) { | ||
445 | DRM_ERROR("Failed to swizzle page\n"); | ||
446 | return; | ||
447 | } | ||
448 | set_page_dirty(obj_priv->pages[i]); | 446 | set_page_dirty(obj_priv->pages[i]); |
449 | } | 447 | } |
450 | } | 448 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 744225ebb4b2..64c07c24e300 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -85,7 +85,7 @@ ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /* For display hotplug interrupt */ | 87 | /* For display hotplug interrupt */ |
88 | void | 88 | static void |
89 | ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | 89 | ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) |
90 | { | 90 | { |
91 | if ((dev_priv->irq_mask_reg & mask) != 0) { | 91 | if ((dev_priv->irq_mask_reg & mask) != 0) { |
@@ -172,7 +172,7 @@ void intel_enable_asle (struct drm_device *dev) | |||
172 | else { | 172 | else { |
173 | i915_enable_pipestat(dev_priv, 1, | 173 | i915_enable_pipestat(dev_priv, 1, |
174 | PIPE_LEGACY_BLC_EVENT_ENABLE); | 174 | PIPE_LEGACY_BLC_EVENT_ENABLE); |
175 | if (IS_I965G(dev)) | 175 | if (INTEL_INFO(dev)->gen >= 4) |
176 | i915_enable_pipestat(dev_priv, 0, | 176 | i915_enable_pipestat(dev_priv, 0, |
177 | PIPE_LEGACY_BLC_EVENT_ENABLE); | 177 | PIPE_LEGACY_BLC_EVENT_ENABLE); |
178 | } | 178 | } |
@@ -191,12 +191,7 @@ static int | |||
191 | i915_pipe_enabled(struct drm_device *dev, int pipe) | 191 | i915_pipe_enabled(struct drm_device *dev, int pipe) |
192 | { | 192 | { |
193 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 193 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
194 | unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; | 194 | return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE; |
195 | |||
196 | if (I915_READ(pipeconf) & PIPEACONF_ENABLE) | ||
197 | return 1; | ||
198 | |||
199 | return 0; | ||
200 | } | 195 | } |
201 | 196 | ||
202 | /* Called from drm generic code, passed a 'crtc', which | 197 | /* Called from drm generic code, passed a 'crtc', which |
@@ -207,10 +202,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
207 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 202 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
208 | unsigned long high_frame; | 203 | unsigned long high_frame; |
209 | unsigned long low_frame; | 204 | unsigned long low_frame; |
210 | u32 high1, high2, low, count; | 205 | u32 high1, high2, low; |
211 | |||
212 | high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; | ||
213 | low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; | ||
214 | 206 | ||
215 | if (!i915_pipe_enabled(dev, pipe)) { | 207 | if (!i915_pipe_enabled(dev, pipe)) { |
216 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " | 208 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " |
@@ -218,23 +210,23 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
218 | return 0; | 210 | return 0; |
219 | } | 211 | } |
220 | 212 | ||
213 | high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; | ||
214 | low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; | ||
215 | |||
221 | /* | 216 | /* |
222 | * High & low register fields aren't synchronized, so make sure | 217 | * High & low register fields aren't synchronized, so make sure |
223 | * we get a low value that's stable across two reads of the high | 218 | * we get a low value that's stable across two reads of the high |
224 | * register. | 219 | * register. |
225 | */ | 220 | */ |
226 | do { | 221 | do { |
227 | high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> | 222 | high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; |
228 | PIPE_FRAME_HIGH_SHIFT); | 223 | low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK; |
229 | low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> | 224 | high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; |
230 | PIPE_FRAME_LOW_SHIFT); | ||
231 | high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> | ||
232 | PIPE_FRAME_HIGH_SHIFT); | ||
233 | } while (high1 != high2); | 225 | } while (high1 != high2); |
234 | 226 | ||
235 | count = (high1 << 8) | low; | 227 | high1 >>= PIPE_FRAME_HIGH_SHIFT; |
236 | 228 | low >>= PIPE_FRAME_LOW_SHIFT; | |
237 | return count; | 229 | return (high1 << 8) | low; |
238 | } | 230 | } |
239 | 231 | ||
240 | u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) | 232 | u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) |
@@ -260,16 +252,12 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
260 | hotplug_work); | 252 | hotplug_work); |
261 | struct drm_device *dev = dev_priv->dev; | 253 | struct drm_device *dev = dev_priv->dev; |
262 | struct drm_mode_config *mode_config = &dev->mode_config; | 254 | struct drm_mode_config *mode_config = &dev->mode_config; |
263 | struct drm_encoder *encoder; | 255 | struct intel_encoder *encoder; |
264 | 256 | ||
265 | if (mode_config->num_encoder) { | 257 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) |
266 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | 258 | if (encoder->hot_plug) |
267 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 259 | encoder->hot_plug(encoder); |
268 | 260 | ||
269 | if (intel_encoder->hot_plug) | ||
270 | (*intel_encoder->hot_plug) (intel_encoder); | ||
271 | } | ||
272 | } | ||
273 | /* Just fire off a uevent and let userspace tell us what to do */ | 261 | /* Just fire off a uevent and let userspace tell us what to do */ |
274 | drm_helper_hpd_irq_event(dev); | 262 | drm_helper_hpd_irq_event(dev); |
275 | } | 263 | } |
@@ -305,13 +293,17 @@ static void i915_handle_rps_change(struct drm_device *dev) | |||
305 | return; | 293 | return; |
306 | } | 294 | } |
307 | 295 | ||
308 | irqreturn_t ironlake_irq_handler(struct drm_device *dev) | 296 | static irqreturn_t ironlake_irq_handler(struct drm_device *dev) |
309 | { | 297 | { |
310 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 298 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
311 | int ret = IRQ_NONE; | 299 | int ret = IRQ_NONE; |
312 | u32 de_iir, gt_iir, de_ier, pch_iir; | 300 | u32 de_iir, gt_iir, de_ier, pch_iir; |
313 | struct drm_i915_master_private *master_priv; | 301 | struct drm_i915_master_private *master_priv; |
314 | struct intel_ring_buffer *render_ring = &dev_priv->render_ring; | 302 | struct intel_ring_buffer *render_ring = &dev_priv->render_ring; |
303 | u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; | ||
304 | |||
305 | if (IS_GEN6(dev)) | ||
306 | bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; | ||
315 | 307 | ||
316 | /* disable master interrupt before clearing iir */ | 308 | /* disable master interrupt before clearing iir */ |
317 | de_ier = I915_READ(DEIER); | 309 | de_ier = I915_READ(DEIER); |
@@ -335,28 +327,28 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
335 | } | 327 | } |
336 | 328 | ||
337 | if (gt_iir & GT_PIPE_NOTIFY) { | 329 | if (gt_iir & GT_PIPE_NOTIFY) { |
338 | u32 seqno = render_ring->get_gem_seqno(dev, render_ring); | 330 | u32 seqno = render_ring->get_seqno(dev, render_ring); |
339 | render_ring->irq_gem_seqno = seqno; | 331 | render_ring->irq_gem_seqno = seqno; |
340 | trace_i915_gem_request_complete(dev, seqno); | 332 | trace_i915_gem_request_complete(dev, seqno); |
341 | DRM_WAKEUP(&dev_priv->render_ring.irq_queue); | 333 | wake_up_all(&dev_priv->render_ring.irq_queue); |
342 | dev_priv->hangcheck_count = 0; | 334 | dev_priv->hangcheck_count = 0; |
343 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 335 | mod_timer(&dev_priv->hangcheck_timer, |
336 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | ||
344 | } | 337 | } |
345 | if (gt_iir & GT_BSD_USER_INTERRUPT) | 338 | if (gt_iir & bsd_usr_interrupt) |
346 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | 339 | wake_up_all(&dev_priv->bsd_ring.irq_queue); |
347 | |||
348 | 340 | ||
349 | if (de_iir & DE_GSE) | 341 | if (de_iir & DE_GSE) |
350 | ironlake_opregion_gse_intr(dev); | 342 | intel_opregion_gse_intr(dev); |
351 | 343 | ||
352 | if (de_iir & DE_PLANEA_FLIP_DONE) { | 344 | if (de_iir & DE_PLANEA_FLIP_DONE) { |
353 | intel_prepare_page_flip(dev, 0); | 345 | intel_prepare_page_flip(dev, 0); |
354 | intel_finish_page_flip(dev, 0); | 346 | intel_finish_page_flip_plane(dev, 0); |
355 | } | 347 | } |
356 | 348 | ||
357 | if (de_iir & DE_PLANEB_FLIP_DONE) { | 349 | if (de_iir & DE_PLANEB_FLIP_DONE) { |
358 | intel_prepare_page_flip(dev, 1); | 350 | intel_prepare_page_flip(dev, 1); |
359 | intel_finish_page_flip(dev, 1); | 351 | intel_finish_page_flip_plane(dev, 1); |
360 | } | 352 | } |
361 | 353 | ||
362 | if (de_iir & DE_PIPEA_VBLANK) | 354 | if (de_iir & DE_PIPEA_VBLANK) |
@@ -404,23 +396,20 @@ static void i915_error_work_func(struct work_struct *work) | |||
404 | char *reset_event[] = { "RESET=1", NULL }; | 396 | char *reset_event[] = { "RESET=1", NULL }; |
405 | char *reset_done_event[] = { "ERROR=0", NULL }; | 397 | char *reset_done_event[] = { "ERROR=0", NULL }; |
406 | 398 | ||
407 | DRM_DEBUG_DRIVER("generating error event\n"); | ||
408 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); | 399 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); |
409 | 400 | ||
410 | if (atomic_read(&dev_priv->mm.wedged)) { | 401 | if (atomic_read(&dev_priv->mm.wedged)) { |
411 | if (IS_I965G(dev)) { | 402 | DRM_DEBUG_DRIVER("resetting chip\n"); |
412 | DRM_DEBUG_DRIVER("resetting chip\n"); | 403 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); |
413 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); | 404 | if (!i915_reset(dev, GRDOM_RENDER)) { |
414 | if (!i965_reset(dev, GDRST_RENDER)) { | 405 | atomic_set(&dev_priv->mm.wedged, 0); |
415 | atomic_set(&dev_priv->mm.wedged, 0); | 406 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); |
416 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); | ||
417 | } | ||
418 | } else { | ||
419 | DRM_DEBUG_DRIVER("reboot required\n"); | ||
420 | } | 407 | } |
408 | complete_all(&dev_priv->error_completion); | ||
421 | } | 409 | } |
422 | } | 410 | } |
423 | 411 | ||
412 | #ifdef CONFIG_DEBUG_FS | ||
424 | static struct drm_i915_error_object * | 413 | static struct drm_i915_error_object * |
425 | i915_error_object_create(struct drm_device *dev, | 414 | i915_error_object_create(struct drm_device *dev, |
426 | struct drm_gem_object *src) | 415 | struct drm_gem_object *src) |
@@ -511,7 +500,7 @@ i915_get_bbaddr(struct drm_device *dev, u32 *ring) | |||
511 | 500 | ||
512 | if (IS_I830(dev) || IS_845G(dev)) | 501 | if (IS_I830(dev) || IS_845G(dev)) |
513 | cmd = MI_BATCH_BUFFER; | 502 | cmd = MI_BATCH_BUFFER; |
514 | else if (IS_I965G(dev)) | 503 | else if (INTEL_INFO(dev)->gen >= 4) |
515 | cmd = (MI_BATCH_BUFFER_START | (2 << 6) | | 504 | cmd = (MI_BATCH_BUFFER_START | (2 << 6) | |
516 | MI_BATCH_NON_SECURE_I965); | 505 | MI_BATCH_NON_SECURE_I965); |
517 | else | 506 | else |
@@ -584,13 +573,16 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
584 | return; | 573 | return; |
585 | } | 574 | } |
586 | 575 | ||
587 | error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring); | 576 | DRM_DEBUG_DRIVER("generating error event\n"); |
577 | |||
578 | error->seqno = | ||
579 | dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring); | ||
588 | error->eir = I915_READ(EIR); | 580 | error->eir = I915_READ(EIR); |
589 | error->pgtbl_er = I915_READ(PGTBL_ER); | 581 | error->pgtbl_er = I915_READ(PGTBL_ER); |
590 | error->pipeastat = I915_READ(PIPEASTAT); | 582 | error->pipeastat = I915_READ(PIPEASTAT); |
591 | error->pipebstat = I915_READ(PIPEBSTAT); | 583 | error->pipebstat = I915_READ(PIPEBSTAT); |
592 | error->instpm = I915_READ(INSTPM); | 584 | error->instpm = I915_READ(INSTPM); |
593 | if (!IS_I965G(dev)) { | 585 | if (INTEL_INFO(dev)->gen < 4) { |
594 | error->ipeir = I915_READ(IPEIR); | 586 | error->ipeir = I915_READ(IPEIR); |
595 | error->ipehr = I915_READ(IPEHR); | 587 | error->ipehr = I915_READ(IPEHR); |
596 | error->instdone = I915_READ(INSTDONE); | 588 | error->instdone = I915_READ(INSTDONE); |
@@ -744,6 +736,9 @@ void i915_destroy_error_state(struct drm_device *dev) | |||
744 | if (error) | 736 | if (error) |
745 | i915_error_state_free(dev, error); | 737 | i915_error_state_free(dev, error); |
746 | } | 738 | } |
739 | #else | ||
740 | #define i915_capture_error_state(x) | ||
741 | #endif | ||
747 | 742 | ||
748 | static void i915_report_and_clear_eir(struct drm_device *dev) | 743 | static void i915_report_and_clear_eir(struct drm_device *dev) |
749 | { | 744 | { |
@@ -785,7 +780,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) | |||
785 | } | 780 | } |
786 | } | 781 | } |
787 | 782 | ||
788 | if (IS_I9XX(dev)) { | 783 | if (!IS_GEN2(dev)) { |
789 | if (eir & I915_ERROR_PAGE_TABLE) { | 784 | if (eir & I915_ERROR_PAGE_TABLE) { |
790 | u32 pgtbl_err = I915_READ(PGTBL_ER); | 785 | u32 pgtbl_err = I915_READ(PGTBL_ER); |
791 | printk(KERN_ERR "page table error\n"); | 786 | printk(KERN_ERR "page table error\n"); |
@@ -811,7 +806,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) | |||
811 | printk(KERN_ERR "instruction error\n"); | 806 | printk(KERN_ERR "instruction error\n"); |
812 | printk(KERN_ERR " INSTPM: 0x%08x\n", | 807 | printk(KERN_ERR " INSTPM: 0x%08x\n", |
813 | I915_READ(INSTPM)); | 808 | I915_READ(INSTPM)); |
814 | if (!IS_I965G(dev)) { | 809 | if (INTEL_INFO(dev)->gen < 4) { |
815 | u32 ipeir = I915_READ(IPEIR); | 810 | u32 ipeir = I915_READ(IPEIR); |
816 | 811 | ||
817 | printk(KERN_ERR " IPEIR: 0x%08x\n", | 812 | printk(KERN_ERR " IPEIR: 0x%08x\n", |
@@ -876,12 +871,15 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) | |||
876 | i915_report_and_clear_eir(dev); | 871 | i915_report_and_clear_eir(dev); |
877 | 872 | ||
878 | if (wedged) { | 873 | if (wedged) { |
874 | INIT_COMPLETION(dev_priv->error_completion); | ||
879 | atomic_set(&dev_priv->mm.wedged, 1); | 875 | atomic_set(&dev_priv->mm.wedged, 1); |
880 | 876 | ||
881 | /* | 877 | /* |
882 | * Wakeup waiting processes so they don't hang | 878 | * Wakeup waiting processes so they don't hang |
883 | */ | 879 | */ |
884 | DRM_WAKEUP(&dev_priv->render_ring.irq_queue); | 880 | wake_up_all(&dev_priv->render_ring.irq_queue); |
881 | if (HAS_BSD(dev)) | ||
882 | wake_up_all(&dev_priv->bsd_ring.irq_queue); | ||
885 | } | 883 | } |
886 | 884 | ||
887 | queue_work(dev_priv->wq, &dev_priv->error_work); | 885 | queue_work(dev_priv->wq, &dev_priv->error_work); |
@@ -912,7 +910,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) | |||
912 | 910 | ||
913 | /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ | 911 | /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ |
914 | obj_priv = to_intel_bo(work->pending_flip_obj); | 912 | obj_priv = to_intel_bo(work->pending_flip_obj); |
915 | if(IS_I965G(dev)) { | 913 | if (INTEL_INFO(dev)->gen >= 4) { |
916 | int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; | 914 | int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; |
917 | stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; | 915 | stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; |
918 | } else { | 916 | } else { |
@@ -951,7 +949,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
951 | 949 | ||
952 | iir = I915_READ(IIR); | 950 | iir = I915_READ(IIR); |
953 | 951 | ||
954 | if (IS_I965G(dev)) | 952 | if (INTEL_INFO(dev)->gen >= 4) |
955 | vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS; | 953 | vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS; |
956 | else | 954 | else |
957 | vblank_status = PIPE_VBLANK_INTERRUPT_STATUS; | 955 | vblank_status = PIPE_VBLANK_INTERRUPT_STATUS; |
@@ -1020,17 +1018,17 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
1020 | } | 1018 | } |
1021 | 1019 | ||
1022 | if (iir & I915_USER_INTERRUPT) { | 1020 | if (iir & I915_USER_INTERRUPT) { |
1023 | u32 seqno = | 1021 | u32 seqno = render_ring->get_seqno(dev, render_ring); |
1024 | render_ring->get_gem_seqno(dev, render_ring); | ||
1025 | render_ring->irq_gem_seqno = seqno; | 1022 | render_ring->irq_gem_seqno = seqno; |
1026 | trace_i915_gem_request_complete(dev, seqno); | 1023 | trace_i915_gem_request_complete(dev, seqno); |
1027 | DRM_WAKEUP(&dev_priv->render_ring.irq_queue); | 1024 | wake_up_all(&dev_priv->render_ring.irq_queue); |
1028 | dev_priv->hangcheck_count = 0; | 1025 | dev_priv->hangcheck_count = 0; |
1029 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 1026 | mod_timer(&dev_priv->hangcheck_timer, |
1027 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | ||
1030 | } | 1028 | } |
1031 | 1029 | ||
1032 | if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) | 1030 | if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) |
1033 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | 1031 | wake_up_all(&dev_priv->bsd_ring.irq_queue); |
1034 | 1032 | ||
1035 | if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { | 1033 | if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { |
1036 | intel_prepare_page_flip(dev, 0); | 1034 | intel_prepare_page_flip(dev, 0); |
@@ -1065,7 +1063,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
1065 | if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || | 1063 | if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || |
1066 | (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || | 1064 | (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || |
1067 | (iir & I915_ASLE_INTERRUPT)) | 1065 | (iir & I915_ASLE_INTERRUPT)) |
1068 | opregion_asle_intr(dev); | 1066 | intel_opregion_asle_intr(dev); |
1069 | 1067 | ||
1070 | /* With MSI, interrupts are only generated when iir | 1068 | /* With MSI, interrupts are only generated when iir |
1071 | * transitions from zero to nonzero. If another bit got | 1069 | * transitions from zero to nonzero. If another bit got |
@@ -1207,18 +1205,15 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) | |||
1207 | { | 1205 | { |
1208 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1206 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1209 | unsigned long irqflags; | 1207 | unsigned long irqflags; |
1210 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
1211 | u32 pipeconf; | ||
1212 | 1208 | ||
1213 | pipeconf = I915_READ(pipeconf_reg); | 1209 | if (!i915_pipe_enabled(dev, pipe)) |
1214 | if (!(pipeconf & PIPEACONF_ENABLE)) | ||
1215 | return -EINVAL; | 1210 | return -EINVAL; |
1216 | 1211 | ||
1217 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1212 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
1218 | if (HAS_PCH_SPLIT(dev)) | 1213 | if (HAS_PCH_SPLIT(dev)) |
1219 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? | 1214 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? |
1220 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | 1215 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); |
1221 | else if (IS_I965G(dev)) | 1216 | else if (INTEL_INFO(dev)->gen >= 4) |
1222 | i915_enable_pipestat(dev_priv, pipe, | 1217 | i915_enable_pipestat(dev_priv, pipe, |
1223 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 1218 | PIPE_START_VBLANK_INTERRUPT_ENABLE); |
1224 | else | 1219 | else |
@@ -1252,7 +1247,7 @@ void i915_enable_interrupt (struct drm_device *dev) | |||
1252 | struct drm_i915_private *dev_priv = dev->dev_private; | 1247 | struct drm_i915_private *dev_priv = dev->dev_private; |
1253 | 1248 | ||
1254 | if (!HAS_PCH_SPLIT(dev)) | 1249 | if (!HAS_PCH_SPLIT(dev)) |
1255 | opregion_enable_asle(dev); | 1250 | intel_opregion_enable_asle(dev); |
1256 | dev_priv->irq_enabled = 1; | 1251 | dev_priv->irq_enabled = 1; |
1257 | } | 1252 | } |
1258 | 1253 | ||
@@ -1311,7 +1306,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, | |||
1311 | return -EINVAL; | 1306 | return -EINVAL; |
1312 | } | 1307 | } |
1313 | 1308 | ||
1314 | struct drm_i915_gem_request * | 1309 | static struct drm_i915_gem_request * |
1315 | i915_get_tail_request(struct drm_device *dev) | 1310 | i915_get_tail_request(struct drm_device *dev) |
1316 | { | 1311 | { |
1317 | drm_i915_private_t *dev_priv = dev->dev_private; | 1312 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -1331,11 +1326,7 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1331 | drm_i915_private_t *dev_priv = dev->dev_private; | 1326 | drm_i915_private_t *dev_priv = dev->dev_private; |
1332 | uint32_t acthd, instdone, instdone1; | 1327 | uint32_t acthd, instdone, instdone1; |
1333 | 1328 | ||
1334 | /* No reset support on this chip yet. */ | 1329 | if (INTEL_INFO(dev)->gen < 4) { |
1335 | if (IS_GEN6(dev)) | ||
1336 | return; | ||
1337 | |||
1338 | if (!IS_I965G(dev)) { | ||
1339 | acthd = I915_READ(ACTHD); | 1330 | acthd = I915_READ(ACTHD); |
1340 | instdone = I915_READ(INSTDONE); | 1331 | instdone = I915_READ(INSTDONE); |
1341 | instdone1 = 0; | 1332 | instdone1 = 0; |
@@ -1347,9 +1338,8 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1347 | 1338 | ||
1348 | /* If all work is done then ACTHD clearly hasn't advanced. */ | 1339 | /* If all work is done then ACTHD clearly hasn't advanced. */ |
1349 | if (list_empty(&dev_priv->render_ring.request_list) || | 1340 | if (list_empty(&dev_priv->render_ring.request_list) || |
1350 | i915_seqno_passed(i915_get_gem_seqno(dev, | 1341 | i915_seqno_passed(dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring), |
1351 | &dev_priv->render_ring), | 1342 | i915_get_tail_request(dev)->seqno)) { |
1352 | i915_get_tail_request(dev)->seqno)) { | ||
1353 | bool missed_wakeup = false; | 1343 | bool missed_wakeup = false; |
1354 | 1344 | ||
1355 | dev_priv->hangcheck_count = 0; | 1345 | dev_priv->hangcheck_count = 0; |
@@ -1357,13 +1347,13 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1357 | /* Issue a wake-up to catch stuck h/w. */ | 1347 | /* Issue a wake-up to catch stuck h/w. */ |
1358 | if (dev_priv->render_ring.waiting_gem_seqno && | 1348 | if (dev_priv->render_ring.waiting_gem_seqno && |
1359 | waitqueue_active(&dev_priv->render_ring.irq_queue)) { | 1349 | waitqueue_active(&dev_priv->render_ring.irq_queue)) { |
1360 | DRM_WAKEUP(&dev_priv->render_ring.irq_queue); | 1350 | wake_up_all(&dev_priv->render_ring.irq_queue); |
1361 | missed_wakeup = true; | 1351 | missed_wakeup = true; |
1362 | } | 1352 | } |
1363 | 1353 | ||
1364 | if (dev_priv->bsd_ring.waiting_gem_seqno && | 1354 | if (dev_priv->bsd_ring.waiting_gem_seqno && |
1365 | waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { | 1355 | waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { |
1366 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | 1356 | wake_up_all(&dev_priv->bsd_ring.irq_queue); |
1367 | missed_wakeup = true; | 1357 | missed_wakeup = true; |
1368 | } | 1358 | } |
1369 | 1359 | ||
@@ -1377,6 +1367,21 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1377 | dev_priv->last_instdone1 == instdone1) { | 1367 | dev_priv->last_instdone1 == instdone1) { |
1378 | if (dev_priv->hangcheck_count++ > 1) { | 1368 | if (dev_priv->hangcheck_count++ > 1) { |
1379 | DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); | 1369 | DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); |
1370 | |||
1371 | if (!IS_GEN2(dev)) { | ||
1372 | /* Is the chip hanging on a WAIT_FOR_EVENT? | ||
1373 | * If so we can simply poke the RB_WAIT bit | ||
1374 | * and break the hang. This should work on | ||
1375 | * all but the second generation chipsets. | ||
1376 | */ | ||
1377 | u32 tmp = I915_READ(PRB0_CTL); | ||
1378 | if (tmp & RING_WAIT) { | ||
1379 | I915_WRITE(PRB0_CTL, tmp); | ||
1380 | POSTING_READ(PRB0_CTL); | ||
1381 | goto out; | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1380 | i915_handle_error(dev, true); | 1385 | i915_handle_error(dev, true); |
1381 | return; | 1386 | return; |
1382 | } | 1387 | } |
@@ -1388,8 +1393,10 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
1388 | dev_priv->last_instdone1 = instdone1; | 1393 | dev_priv->last_instdone1 = instdone1; |
1389 | } | 1394 | } |
1390 | 1395 | ||
1396 | out: | ||
1391 | /* Reset timer case chip hangs without another request being added */ | 1397 | /* Reset timer case chip hangs without another request being added */ |
1392 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 1398 | mod_timer(&dev_priv->hangcheck_timer, |
1399 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | ||
1393 | } | 1400 | } |
1394 | 1401 | ||
1395 | /* drm_dma.h hooks | 1402 | /* drm_dma.h hooks |
@@ -1436,17 +1443,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1436 | I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); | 1443 | I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); |
1437 | (void) I915_READ(DEIER); | 1444 | (void) I915_READ(DEIER); |
1438 | 1445 | ||
1439 | /* Gen6 only needs render pipe_control now */ | ||
1440 | if (IS_GEN6(dev)) | 1446 | if (IS_GEN6(dev)) |
1441 | render_mask = GT_PIPE_NOTIFY; | 1447 | render_mask = GT_PIPE_NOTIFY | GT_GEN6_BSD_USER_INTERRUPT; |
1442 | 1448 | ||
1443 | dev_priv->gt_irq_mask_reg = ~render_mask; | 1449 | dev_priv->gt_irq_mask_reg = ~render_mask; |
1444 | dev_priv->gt_irq_enable_reg = render_mask; | 1450 | dev_priv->gt_irq_enable_reg = render_mask; |
1445 | 1451 | ||
1446 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1452 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
1447 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); | 1453 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); |
1448 | if (IS_GEN6(dev)) | 1454 | if (IS_GEN6(dev)) { |
1449 | I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); | 1455 | I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); |
1456 | I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT); | ||
1457 | } | ||
1458 | |||
1450 | I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); | 1459 | I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); |
1451 | (void) I915_READ(GTIER); | 1460 | (void) I915_READ(GTIER); |
1452 | 1461 | ||
@@ -1578,7 +1587,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
1578 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); | 1587 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
1579 | } | 1588 | } |
1580 | 1589 | ||
1581 | opregion_enable_asle(dev); | 1590 | intel_opregion_enable_asle(dev); |
1582 | 1591 | ||
1583 | return 0; | 1592 | return 0; |
1584 | } | 1593 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4f5e15577e89..d02de212e6ad 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -25,52 +25,16 @@ | |||
25 | #ifndef _I915_REG_H_ | 25 | #ifndef _I915_REG_H_ |
26 | #define _I915_REG_H_ | 26 | #define _I915_REG_H_ |
27 | 27 | ||
28 | #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) | ||
29 | |||
28 | /* | 30 | /* |
29 | * The Bridge device's PCI config space has information about the | 31 | * The Bridge device's PCI config space has information about the |
30 | * fb aperture size and the amount of pre-reserved memory. | 32 | * fb aperture size and the amount of pre-reserved memory. |
33 | * This is all handled in the intel-gtt.ko module. i915.ko only | ||
34 | * cares about the vga bit for the vga rbiter. | ||
31 | */ | 35 | */ |
32 | #define INTEL_GMCH_CTRL 0x52 | 36 | #define INTEL_GMCH_CTRL 0x52 |
33 | #define INTEL_GMCH_VGA_DISABLE (1 << 1) | 37 | #define INTEL_GMCH_VGA_DISABLE (1 << 1) |
34 | #define INTEL_GMCH_ENABLED 0x4 | ||
35 | #define INTEL_GMCH_MEM_MASK 0x1 | ||
36 | #define INTEL_GMCH_MEM_64M 0x1 | ||
37 | #define INTEL_GMCH_MEM_128M 0 | ||
38 | |||
39 | #define INTEL_GMCH_GMS_MASK (0xf << 4) | ||
40 | #define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4) | ||
41 | #define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4) | ||
42 | #define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4) | ||
43 | #define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4) | ||
44 | #define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4) | ||
45 | #define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4) | ||
46 | |||
47 | #define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4) | ||
48 | #define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4) | ||
49 | #define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4) | ||
50 | #define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4) | ||
51 | #define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) | ||
52 | #define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) | ||
53 | #define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) | ||
54 | #define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) | ||
55 | |||
56 | #define SNB_GMCH_CTRL 0x50 | ||
57 | #define SNB_GMCH_GMS_STOLEN_MASK 0xF8 | ||
58 | #define SNB_GMCH_GMS_STOLEN_32M (1 << 3) | ||
59 | #define SNB_GMCH_GMS_STOLEN_64M (2 << 3) | ||
60 | #define SNB_GMCH_GMS_STOLEN_96M (3 << 3) | ||
61 | #define SNB_GMCH_GMS_STOLEN_128M (4 << 3) | ||
62 | #define SNB_GMCH_GMS_STOLEN_160M (5 << 3) | ||
63 | #define SNB_GMCH_GMS_STOLEN_192M (6 << 3) | ||
64 | #define SNB_GMCH_GMS_STOLEN_224M (7 << 3) | ||
65 | #define SNB_GMCH_GMS_STOLEN_256M (8 << 3) | ||
66 | #define SNB_GMCH_GMS_STOLEN_288M (9 << 3) | ||
67 | #define SNB_GMCH_GMS_STOLEN_320M (0xa << 3) | ||
68 | #define SNB_GMCH_GMS_STOLEN_352M (0xb << 3) | ||
69 | #define SNB_GMCH_GMS_STOLEN_384M (0xc << 3) | ||
70 | #define SNB_GMCH_GMS_STOLEN_416M (0xd << 3) | ||
71 | #define SNB_GMCH_GMS_STOLEN_448M (0xe << 3) | ||
72 | #define SNB_GMCH_GMS_STOLEN_480M (0xf << 3) | ||
73 | #define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3) | ||
74 | 38 | ||
75 | /* PCI config space */ | 39 | /* PCI config space */ |
76 | 40 | ||
@@ -106,10 +70,13 @@ | |||
106 | #define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0) | 70 | #define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0) |
107 | #define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0) | 71 | #define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0) |
108 | #define LBB 0xf4 | 72 | #define LBB 0xf4 |
109 | #define GDRST 0xc0 | 73 | |
110 | #define GDRST_FULL (0<<2) | 74 | /* Graphics reset regs */ |
111 | #define GDRST_RENDER (1<<2) | 75 | #define I965_GDRST 0xc0 /* PCI config register */ |
112 | #define GDRST_MEDIA (3<<2) | 76 | #define ILK_GDSR 0x2ca4 /* MCHBAR offset */ |
77 | #define GRDOM_FULL (0<<2) | ||
78 | #define GRDOM_RENDER (1<<2) | ||
79 | #define GRDOM_MEDIA (3<<2) | ||
113 | 80 | ||
114 | /* VGA stuff */ | 81 | /* VGA stuff */ |
115 | 82 | ||
@@ -192,11 +159,11 @@ | |||
192 | #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) | 159 | #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) |
193 | #define MI_STORE_DWORD_INDEX_SHIFT 2 | 160 | #define MI_STORE_DWORD_INDEX_SHIFT 2 |
194 | #define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) | 161 | #define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) |
162 | #define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */ | ||
195 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) | 163 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) |
196 | #define MI_BATCH_NON_SECURE (1) | 164 | #define MI_BATCH_NON_SECURE (1) |
197 | #define MI_BATCH_NON_SECURE_I965 (1<<8) | 165 | #define MI_BATCH_NON_SECURE_I965 (1<<8) |
198 | #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) | 166 | #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) |
199 | |||
200 | /* | 167 | /* |
201 | * 3D instructions used by the kernel | 168 | * 3D instructions used by the kernel |
202 | */ | 169 | */ |
@@ -249,6 +216,16 @@ | |||
249 | #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ | 216 | #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ |
250 | #define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */ | 217 | #define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */ |
251 | 218 | ||
219 | |||
220 | /* | ||
221 | * Reset registers | ||
222 | */ | ||
223 | #define DEBUG_RESET_I830 0x6070 | ||
224 | #define DEBUG_RESET_FULL (1<<7) | ||
225 | #define DEBUG_RESET_RENDER (1<<8) | ||
226 | #define DEBUG_RESET_DISPLAY (1<<9) | ||
227 | |||
228 | |||
252 | /* | 229 | /* |
253 | * Fence registers | 230 | * Fence registers |
254 | */ | 231 | */ |
@@ -283,6 +260,16 @@ | |||
283 | #define PRB0_HEAD 0x02034 | 260 | #define PRB0_HEAD 0x02034 |
284 | #define PRB0_START 0x02038 | 261 | #define PRB0_START 0x02038 |
285 | #define PRB0_CTL 0x0203c | 262 | #define PRB0_CTL 0x0203c |
263 | #define RENDER_RING_BASE 0x02000 | ||
264 | #define BSD_RING_BASE 0x04000 | ||
265 | #define GEN6_BSD_RING_BASE 0x12000 | ||
266 | #define RING_TAIL(base) ((base)+0x30) | ||
267 | #define RING_HEAD(base) ((base)+0x34) | ||
268 | #define RING_START(base) ((base)+0x38) | ||
269 | #define RING_CTL(base) ((base)+0x3c) | ||
270 | #define RING_HWS_PGA(base) ((base)+0x80) | ||
271 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) | ||
272 | #define RING_ACTHD(base) ((base)+0x74) | ||
286 | #define TAIL_ADDR 0x001FFFF8 | 273 | #define TAIL_ADDR 0x001FFFF8 |
287 | #define HEAD_WRAP_COUNT 0xFFE00000 | 274 | #define HEAD_WRAP_COUNT 0xFFE00000 |
288 | #define HEAD_WRAP_ONE 0x00200000 | 275 | #define HEAD_WRAP_ONE 0x00200000 |
@@ -295,6 +282,8 @@ | |||
295 | #define RING_VALID_MASK 0x00000001 | 282 | #define RING_VALID_MASK 0x00000001 |
296 | #define RING_VALID 0x00000001 | 283 | #define RING_VALID 0x00000001 |
297 | #define RING_INVALID 0x00000000 | 284 | #define RING_INVALID 0x00000000 |
285 | #define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */ | ||
286 | #define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ | ||
298 | #define PRB1_TAIL 0x02040 /* 915+ only */ | 287 | #define PRB1_TAIL 0x02040 /* 915+ only */ |
299 | #define PRB1_HEAD 0x02044 /* 915+ only */ | 288 | #define PRB1_HEAD 0x02044 /* 915+ only */ |
300 | #define PRB1_START 0x02048 /* 915+ only */ | 289 | #define PRB1_START 0x02048 /* 915+ only */ |
@@ -306,7 +295,6 @@ | |||
306 | #define INSTDONE1 0x0207c /* 965+ only */ | 295 | #define INSTDONE1 0x0207c /* 965+ only */ |
307 | #define ACTHD_I965 0x02074 | 296 | #define ACTHD_I965 0x02074 |
308 | #define HWS_PGA 0x02080 | 297 | #define HWS_PGA 0x02080 |
309 | #define HWS_PGA_GEN6 0x04080 | ||
310 | #define HWS_ADDRESS_MASK 0xfffff000 | 298 | #define HWS_ADDRESS_MASK 0xfffff000 |
311 | #define HWS_START_ADDRESS_SHIFT 4 | 299 | #define HWS_START_ADDRESS_SHIFT 4 |
312 | #define PWRCTXA 0x2088 /* 965GM+ only */ | 300 | #define PWRCTXA 0x2088 /* 965GM+ only */ |
@@ -464,17 +452,17 @@ | |||
464 | #define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) | 452 | #define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) |
465 | #define GEN6_BLITTER_SYNC_STATUS (1 << 24) | 453 | #define GEN6_BLITTER_SYNC_STATUS (1 << 24) |
466 | #define GEN6_BLITTER_USER_INTERRUPT (1 << 22) | 454 | #define GEN6_BLITTER_USER_INTERRUPT (1 << 22) |
467 | /* | ||
468 | * BSD (bit stream decoder instruction and interrupt control register defines | ||
469 | * (G4X and Ironlake only) | ||
470 | */ | ||
471 | 455 | ||
472 | #define BSD_RING_TAIL 0x04030 | 456 | #define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 |
473 | #define BSD_RING_HEAD 0x04034 | 457 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16) |
474 | #define BSD_RING_START 0x04038 | 458 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0) |
475 | #define BSD_RING_CTL 0x0403c | 459 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 |
476 | #define BSD_RING_ACTHD 0x04074 | 460 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) |
477 | #define BSD_HWS_PGA 0x04080 | 461 | |
462 | #define GEN6_BSD_IMR 0x120a8 | ||
463 | #define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12) | ||
464 | |||
465 | #define GEN6_BSD_RNCID 0x12198 | ||
478 | 466 | ||
479 | /* | 467 | /* |
480 | * Framebuffer compression (915+ only) | 468 | * Framebuffer compression (915+ only) |
@@ -579,12 +567,51 @@ | |||
579 | # define GPIO_DATA_VAL_IN (1 << 12) | 567 | # define GPIO_DATA_VAL_IN (1 << 12) |
580 | # define GPIO_DATA_PULLUP_DISABLE (1 << 13) | 568 | # define GPIO_DATA_PULLUP_DISABLE (1 << 13) |
581 | 569 | ||
582 | #define GMBUS0 0x5100 | 570 | #define GMBUS0 0x5100 /* clock/port select */ |
583 | #define GMBUS1 0x5104 | 571 | #define GMBUS_RATE_100KHZ (0<<8) |
584 | #define GMBUS2 0x5108 | 572 | #define GMBUS_RATE_50KHZ (1<<8) |
585 | #define GMBUS3 0x510c | 573 | #define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ |
586 | #define GMBUS4 0x5110 | 574 | #define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ |
587 | #define GMBUS5 0x5120 | 575 | #define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ |
576 | #define GMBUS_PORT_DISABLED 0 | ||
577 | #define GMBUS_PORT_SSC 1 | ||
578 | #define GMBUS_PORT_VGADDC 2 | ||
579 | #define GMBUS_PORT_PANEL 3 | ||
580 | #define GMBUS_PORT_DPC 4 /* HDMIC */ | ||
581 | #define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ | ||
582 | /* 6 reserved */ | ||
583 | #define GMBUS_PORT_DPD 7 /* HDMID */ | ||
584 | #define GMBUS_NUM_PORTS 8 | ||
585 | #define GMBUS1 0x5104 /* command/status */ | ||
586 | #define GMBUS_SW_CLR_INT (1<<31) | ||
587 | #define GMBUS_SW_RDY (1<<30) | ||
588 | #define GMBUS_ENT (1<<29) /* enable timeout */ | ||
589 | #define GMBUS_CYCLE_NONE (0<<25) | ||
590 | #define GMBUS_CYCLE_WAIT (1<<25) | ||
591 | #define GMBUS_CYCLE_INDEX (2<<25) | ||
592 | #define GMBUS_CYCLE_STOP (4<<25) | ||
593 | #define GMBUS_BYTE_COUNT_SHIFT 16 | ||
594 | #define GMBUS_SLAVE_INDEX_SHIFT 8 | ||
595 | #define GMBUS_SLAVE_ADDR_SHIFT 1 | ||
596 | #define GMBUS_SLAVE_READ (1<<0) | ||
597 | #define GMBUS_SLAVE_WRITE (0<<0) | ||
598 | #define GMBUS2 0x5108 /* status */ | ||
599 | #define GMBUS_INUSE (1<<15) | ||
600 | #define GMBUS_HW_WAIT_PHASE (1<<14) | ||
601 | #define GMBUS_STALL_TIMEOUT (1<<13) | ||
602 | #define GMBUS_INT (1<<12) | ||
603 | #define GMBUS_HW_RDY (1<<11) | ||
604 | #define GMBUS_SATOER (1<<10) | ||
605 | #define GMBUS_ACTIVE (1<<9) | ||
606 | #define GMBUS3 0x510c /* data buffer bytes 3-0 */ | ||
607 | #define GMBUS4 0x5110 /* interrupt mask (Pineview+) */ | ||
608 | #define GMBUS_SLAVE_TIMEOUT_EN (1<<4) | ||
609 | #define GMBUS_NAK_EN (1<<3) | ||
610 | #define GMBUS_IDLE_EN (1<<2) | ||
611 | #define GMBUS_HW_WAIT_EN (1<<1) | ||
612 | #define GMBUS_HW_RDY_EN (1<<0) | ||
613 | #define GMBUS5 0x5120 /* byte index */ | ||
614 | #define GMBUS_2BYTE_INDEX_EN (1<<31) | ||
588 | 615 | ||
589 | /* | 616 | /* |
590 | * Clock control & power management | 617 | * Clock control & power management |
@@ -603,6 +630,7 @@ | |||
603 | #define VGA1_PD_P1_MASK (0x1f << 8) | 630 | #define VGA1_PD_P1_MASK (0x1f << 8) |
604 | #define DPLL_A 0x06014 | 631 | #define DPLL_A 0x06014 |
605 | #define DPLL_B 0x06018 | 632 | #define DPLL_B 0x06018 |
633 | #define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B) | ||
606 | #define DPLL_VCO_ENABLE (1 << 31) | 634 | #define DPLL_VCO_ENABLE (1 << 31) |
607 | #define DPLL_DVO_HIGH_SPEED (1 << 30) | 635 | #define DPLL_DVO_HIGH_SPEED (1 << 30) |
608 | #define DPLL_SYNCLOCK_ENABLE (1 << 29) | 636 | #define DPLL_SYNCLOCK_ENABLE (1 << 29) |
@@ -640,24 +668,6 @@ | |||
640 | #define ADPA_DPMS_STANDBY (2<<10) | 668 | #define ADPA_DPMS_STANDBY (2<<10) |
641 | #define ADPA_DPMS_OFF (3<<10) | 669 | #define ADPA_DPMS_OFF (3<<10) |
642 | 670 | ||
643 | #define RING_TAIL 0x00 | ||
644 | #define TAIL_ADDR 0x001FFFF8 | ||
645 | #define RING_HEAD 0x04 | ||
646 | #define HEAD_WRAP_COUNT 0xFFE00000 | ||
647 | #define HEAD_WRAP_ONE 0x00200000 | ||
648 | #define HEAD_ADDR 0x001FFFFC | ||
649 | #define RING_START 0x08 | ||
650 | #define START_ADDR 0xFFFFF000 | ||
651 | #define RING_LEN 0x0C | ||
652 | #define RING_NR_PAGES 0x001FF000 | ||
653 | #define RING_REPORT_MASK 0x00000006 | ||
654 | #define RING_REPORT_64K 0x00000002 | ||
655 | #define RING_REPORT_128K 0x00000004 | ||
656 | #define RING_NO_REPORT 0x00000000 | ||
657 | #define RING_VALID_MASK 0x00000001 | ||
658 | #define RING_VALID 0x00000001 | ||
659 | #define RING_INVALID 0x00000000 | ||
660 | |||
661 | /* Scratch pad debug 0 reg: | 671 | /* Scratch pad debug 0 reg: |
662 | */ | 672 | */ |
663 | #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 | 673 | #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 |
@@ -736,10 +746,13 @@ | |||
736 | #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f | 746 | #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f |
737 | #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 | 747 | #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 |
738 | #define DPLL_B_MD 0x06020 /* 965+ only */ | 748 | #define DPLL_B_MD 0x06020 /* 965+ only */ |
749 | #define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD) | ||
739 | #define FPA0 0x06040 | 750 | #define FPA0 0x06040 |
740 | #define FPA1 0x06044 | 751 | #define FPA1 0x06044 |
741 | #define FPB0 0x06048 | 752 | #define FPB0 0x06048 |
742 | #define FPB1 0x0604c | 753 | #define FPB1 0x0604c |
754 | #define FP0(pipe) _PIPE(pipe, FPA0, FPB0) | ||
755 | #define FP1(pipe) _PIPE(pipe, FPA1, FPB1) | ||
743 | #define FP_N_DIV_MASK 0x003f0000 | 756 | #define FP_N_DIV_MASK 0x003f0000 |
744 | #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 | 757 | #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 |
745 | #define FP_N_DIV_SHIFT 16 | 758 | #define FP_N_DIV_SHIFT 16 |
@@ -760,6 +773,7 @@ | |||
760 | #define DPLLA_TEST_M_BYPASS (1 << 2) | 773 | #define DPLLA_TEST_M_BYPASS (1 << 2) |
761 | #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) | 774 | #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) |
762 | #define D_STATE 0x6104 | 775 | #define D_STATE 0x6104 |
776 | #define DSTATE_GFX_RESET_I830 (1<<6) | ||
763 | #define DSTATE_PLL_D3_OFF (1<<3) | 777 | #define DSTATE_PLL_D3_OFF (1<<3) |
764 | #define DSTATE_GFX_CLOCK_GATING (1<<1) | 778 | #define DSTATE_GFX_CLOCK_GATING (1<<1) |
765 | #define DSTATE_DOT_CLOCK_GATING (1<<0) | 779 | #define DSTATE_DOT_CLOCK_GATING (1<<0) |
@@ -926,6 +940,8 @@ | |||
926 | #define CLKCFG_MEM_800 (3 << 4) | 940 | #define CLKCFG_MEM_800 (3 << 4) |
927 | #define CLKCFG_MEM_MASK (7 << 4) | 941 | #define CLKCFG_MEM_MASK (7 << 4) |
928 | 942 | ||
943 | #define TSC1 0x11001 | ||
944 | #define TSE (1<<0) | ||
929 | #define TR1 0x11006 | 945 | #define TR1 0x11006 |
930 | #define TSFS 0x11020 | 946 | #define TSFS 0x11020 |
931 | #define TSFS_SLOPE_MASK 0x0000ff00 | 947 | #define TSFS_SLOPE_MASK 0x0000ff00 |
@@ -1070,6 +1086,8 @@ | |||
1070 | #define MEMSTAT_SRC_CTL_STDBY 3 | 1086 | #define MEMSTAT_SRC_CTL_STDBY 3 |
1071 | #define RCPREVBSYTUPAVG 0x113b8 | 1087 | #define RCPREVBSYTUPAVG 0x113b8 |
1072 | #define RCPREVBSYTDNAVG 0x113bc | 1088 | #define RCPREVBSYTDNAVG 0x113bc |
1089 | #define PMMISC 0x11214 | ||
1090 | #define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */ | ||
1073 | #define SDEW 0x1124c | 1091 | #define SDEW 0x1124c |
1074 | #define CSIEW0 0x11250 | 1092 | #define CSIEW0 0x11250 |
1075 | #define CSIEW1 0x11254 | 1093 | #define CSIEW1 0x11254 |
@@ -1150,6 +1168,15 @@ | |||
1150 | #define PIPEBSRC 0x6101c | 1168 | #define PIPEBSRC 0x6101c |
1151 | #define BCLRPAT_B 0x61020 | 1169 | #define BCLRPAT_B 0x61020 |
1152 | 1170 | ||
1171 | #define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B) | ||
1172 | #define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B) | ||
1173 | #define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B) | ||
1174 | #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) | ||
1175 | #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) | ||
1176 | #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) | ||
1177 | #define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) | ||
1178 | #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) | ||
1179 | |||
1153 | /* VGA port control */ | 1180 | /* VGA port control */ |
1154 | #define ADPA 0x61100 | 1181 | #define ADPA 0x61100 |
1155 | #define ADPA_DAC_ENABLE (1<<31) | 1182 | #define ADPA_DAC_ENABLE (1<<31) |
@@ -1481,6 +1508,7 @@ | |||
1481 | # define TV_TEST_MODE_MASK (7 << 0) | 1508 | # define TV_TEST_MODE_MASK (7 << 0) |
1482 | 1509 | ||
1483 | #define TV_DAC 0x68004 | 1510 | #define TV_DAC 0x68004 |
1511 | # define TV_DAC_SAVE 0x00ffff00 | ||
1484 | /** | 1512 | /** |
1485 | * Reports that DAC state change logic has reported change (RO). | 1513 | * Reports that DAC state change logic has reported change (RO). |
1486 | * | 1514 | * |
@@ -2075,29 +2103,35 @@ | |||
2075 | 2103 | ||
2076 | /* Display & cursor control */ | 2104 | /* Display & cursor control */ |
2077 | 2105 | ||
2078 | /* dithering flag on Ironlake */ | ||
2079 | #define PIPE_ENABLE_DITHER (1 << 4) | ||
2080 | #define PIPE_DITHER_TYPE_MASK (3 << 2) | ||
2081 | #define PIPE_DITHER_TYPE_SPATIAL (0 << 2) | ||
2082 | #define PIPE_DITHER_TYPE_ST01 (1 << 2) | ||
2083 | /* Pipe A */ | 2106 | /* Pipe A */ |
2084 | #define PIPEADSL 0x70000 | 2107 | #define PIPEADSL 0x70000 |
2085 | #define DSL_LINEMASK 0x00000fff | 2108 | #define DSL_LINEMASK 0x00000fff |
2086 | #define PIPEACONF 0x70008 | 2109 | #define PIPEACONF 0x70008 |
2087 | #define PIPEACONF_ENABLE (1<<31) | 2110 | #define PIPECONF_ENABLE (1<<31) |
2088 | #define PIPEACONF_DISABLE 0 | 2111 | #define PIPECONF_DISABLE 0 |
2089 | #define PIPEACONF_DOUBLE_WIDE (1<<30) | 2112 | #define PIPECONF_DOUBLE_WIDE (1<<30) |
2090 | #define I965_PIPECONF_ACTIVE (1<<30) | 2113 | #define I965_PIPECONF_ACTIVE (1<<30) |
2091 | #define PIPEACONF_SINGLE_WIDE 0 | 2114 | #define PIPECONF_SINGLE_WIDE 0 |
2092 | #define PIPEACONF_PIPE_UNLOCKED 0 | 2115 | #define PIPECONF_PIPE_UNLOCKED 0 |
2093 | #define PIPEACONF_PIPE_LOCKED (1<<25) | 2116 | #define PIPECONF_PIPE_LOCKED (1<<25) |
2094 | #define PIPEACONF_PALETTE 0 | 2117 | #define PIPECONF_PALETTE 0 |
2095 | #define PIPEACONF_GAMMA (1<<24) | 2118 | #define PIPECONF_GAMMA (1<<24) |
2096 | #define PIPECONF_FORCE_BORDER (1<<25) | 2119 | #define PIPECONF_FORCE_BORDER (1<<25) |
2097 | #define PIPECONF_PROGRESSIVE (0 << 21) | 2120 | #define PIPECONF_PROGRESSIVE (0 << 21) |
2098 | #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) | 2121 | #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) |
2099 | #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) | 2122 | #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) |
2100 | #define PIPECONF_CXSR_DOWNCLOCK (1<<16) | 2123 | #define PIPECONF_CXSR_DOWNCLOCK (1<<16) |
2124 | #define PIPECONF_BPP_MASK (0x000000e0) | ||
2125 | #define PIPECONF_BPP_8 (0<<5) | ||
2126 | #define PIPECONF_BPP_10 (1<<5) | ||
2127 | #define PIPECONF_BPP_6 (2<<5) | ||
2128 | #define PIPECONF_BPP_12 (3<<5) | ||
2129 | #define PIPECONF_DITHER_EN (1<<4) | ||
2130 | #define PIPECONF_DITHER_TYPE_MASK (0x0000000c) | ||
2131 | #define PIPECONF_DITHER_TYPE_SP (0<<2) | ||
2132 | #define PIPECONF_DITHER_TYPE_ST1 (1<<2) | ||
2133 | #define PIPECONF_DITHER_TYPE_ST2 (2<<2) | ||
2134 | #define PIPECONF_DITHER_TYPE_TEMP (3<<2) | ||
2101 | #define PIPEASTAT 0x70024 | 2135 | #define PIPEASTAT 0x70024 |
2102 | #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) | 2136 | #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) |
2103 | #define PIPE_CRC_ERROR_ENABLE (1UL<<29) | 2137 | #define PIPE_CRC_ERROR_ENABLE (1UL<<29) |
@@ -2128,12 +2162,15 @@ | |||
2128 | #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ | 2162 | #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ |
2129 | #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) | 2163 | #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) |
2130 | #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) | 2164 | #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) |
2131 | #define PIPE_BPC_MASK (7 << 5) /* Ironlake */ | 2165 | #define PIPE_BPC_MASK (7 << 5) /* Ironlake */ |
2132 | #define PIPE_8BPC (0 << 5) | 2166 | #define PIPE_8BPC (0 << 5) |
2133 | #define PIPE_10BPC (1 << 5) | 2167 | #define PIPE_10BPC (1 << 5) |
2134 | #define PIPE_6BPC (2 << 5) | 2168 | #define PIPE_6BPC (2 << 5) |
2135 | #define PIPE_12BPC (3 << 5) | 2169 | #define PIPE_12BPC (3 << 5) |
2136 | 2170 | ||
2171 | #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) | ||
2172 | #define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) | ||
2173 | |||
2137 | #define DSPARB 0x70030 | 2174 | #define DSPARB 0x70030 |
2138 | #define DSPARB_CSTART_MASK (0x7f << 7) | 2175 | #define DSPARB_CSTART_MASK (0x7f << 7) |
2139 | #define DSPARB_CSTART_SHIFT 7 | 2176 | #define DSPARB_CSTART_SHIFT 7 |
@@ -2206,8 +2243,8 @@ | |||
2206 | #define WM1_LP_SR_EN (1<<31) | 2243 | #define WM1_LP_SR_EN (1<<31) |
2207 | #define WM1_LP_LATENCY_SHIFT 24 | 2244 | #define WM1_LP_LATENCY_SHIFT 24 |
2208 | #define WM1_LP_LATENCY_MASK (0x7f<<24) | 2245 | #define WM1_LP_LATENCY_MASK (0x7f<<24) |
2209 | #define WM1_LP_FBC_LP1_MASK (0xf<<20) | 2246 | #define WM1_LP_FBC_MASK (0xf<<20) |
2210 | #define WM1_LP_FBC_LP1_SHIFT 20 | 2247 | #define WM1_LP_FBC_SHIFT 20 |
2211 | #define WM1_LP_SR_MASK (0x1ff<<8) | 2248 | #define WM1_LP_SR_MASK (0x1ff<<8) |
2212 | #define WM1_LP_SR_SHIFT 8 | 2249 | #define WM1_LP_SR_SHIFT 8 |
2213 | #define WM1_LP_CURSOR_MASK (0x3f) | 2250 | #define WM1_LP_CURSOR_MASK (0x3f) |
@@ -2333,6 +2370,14 @@ | |||
2333 | #define DSPASURF 0x7019C /* 965+ only */ | 2370 | #define DSPASURF 0x7019C /* 965+ only */ |
2334 | #define DSPATILEOFF 0x701A4 /* 965+ only */ | 2371 | #define DSPATILEOFF 0x701A4 /* 965+ only */ |
2335 | 2372 | ||
2373 | #define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR) | ||
2374 | #define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR) | ||
2375 | #define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE) | ||
2376 | #define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS) | ||
2377 | #define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE) | ||
2378 | #define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF) | ||
2379 | #define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF) | ||
2380 | |||
2336 | /* VBIOS flags */ | 2381 | /* VBIOS flags */ |
2337 | #define SWF00 0x71410 | 2382 | #define SWF00 0x71410 |
2338 | #define SWF01 0x71414 | 2383 | #define SWF01 0x71414 |
@@ -2397,6 +2442,7 @@ | |||
2397 | #define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 | 2442 | #define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 |
2398 | 2443 | ||
2399 | #define FDI_PLL_BIOS_0 0x46000 | 2444 | #define FDI_PLL_BIOS_0 0x46000 |
2445 | #define FDI_PLL_FB_CLOCK_MASK 0xff | ||
2400 | #define FDI_PLL_BIOS_1 0x46004 | 2446 | #define FDI_PLL_BIOS_1 0x46004 |
2401 | #define FDI_PLL_BIOS_2 0x46008 | 2447 | #define FDI_PLL_BIOS_2 0x46008 |
2402 | #define DISPLAY_PORT_PLL_BIOS_0 0x4600c | 2448 | #define DISPLAY_PORT_PLL_BIOS_0 0x4600c |
@@ -2420,46 +2466,47 @@ | |||
2420 | #define PIPEA_DATA_M1 0x60030 | 2466 | #define PIPEA_DATA_M1 0x60030 |
2421 | #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ | 2467 | #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ |
2422 | #define TU_SIZE_MASK 0x7e000000 | 2468 | #define TU_SIZE_MASK 0x7e000000 |
2423 | #define PIPEA_DATA_M1_OFFSET 0 | 2469 | #define PIPE_DATA_M1_OFFSET 0 |
2424 | #define PIPEA_DATA_N1 0x60034 | 2470 | #define PIPEA_DATA_N1 0x60034 |
2425 | #define PIPEA_DATA_N1_OFFSET 0 | 2471 | #define PIPE_DATA_N1_OFFSET 0 |
2426 | 2472 | ||
2427 | #define PIPEA_DATA_M2 0x60038 | 2473 | #define PIPEA_DATA_M2 0x60038 |
2428 | #define PIPEA_DATA_M2_OFFSET 0 | 2474 | #define PIPE_DATA_M2_OFFSET 0 |
2429 | #define PIPEA_DATA_N2 0x6003c | 2475 | #define PIPEA_DATA_N2 0x6003c |
2430 | #define PIPEA_DATA_N2_OFFSET 0 | 2476 | #define PIPE_DATA_N2_OFFSET 0 |
2431 | 2477 | ||
2432 | #define PIPEA_LINK_M1 0x60040 | 2478 | #define PIPEA_LINK_M1 0x60040 |
2433 | #define PIPEA_LINK_M1_OFFSET 0 | 2479 | #define PIPE_LINK_M1_OFFSET 0 |
2434 | #define PIPEA_LINK_N1 0x60044 | 2480 | #define PIPEA_LINK_N1 0x60044 |
2435 | #define PIPEA_LINK_N1_OFFSET 0 | 2481 | #define PIPE_LINK_N1_OFFSET 0 |
2436 | 2482 | ||
2437 | #define PIPEA_LINK_M2 0x60048 | 2483 | #define PIPEA_LINK_M2 0x60048 |
2438 | #define PIPEA_LINK_M2_OFFSET 0 | 2484 | #define PIPE_LINK_M2_OFFSET 0 |
2439 | #define PIPEA_LINK_N2 0x6004c | 2485 | #define PIPEA_LINK_N2 0x6004c |
2440 | #define PIPEA_LINK_N2_OFFSET 0 | 2486 | #define PIPE_LINK_N2_OFFSET 0 |
2441 | 2487 | ||
2442 | /* PIPEB timing regs are same start from 0x61000 */ | 2488 | /* PIPEB timing regs are same start from 0x61000 */ |
2443 | 2489 | ||
2444 | #define PIPEB_DATA_M1 0x61030 | 2490 | #define PIPEB_DATA_M1 0x61030 |
2445 | #define PIPEB_DATA_M1_OFFSET 0 | ||
2446 | #define PIPEB_DATA_N1 0x61034 | 2491 | #define PIPEB_DATA_N1 0x61034 |
2447 | #define PIPEB_DATA_N1_OFFSET 0 | ||
2448 | 2492 | ||
2449 | #define PIPEB_DATA_M2 0x61038 | 2493 | #define PIPEB_DATA_M2 0x61038 |
2450 | #define PIPEB_DATA_M2_OFFSET 0 | ||
2451 | #define PIPEB_DATA_N2 0x6103c | 2494 | #define PIPEB_DATA_N2 0x6103c |
2452 | #define PIPEB_DATA_N2_OFFSET 0 | ||
2453 | 2495 | ||
2454 | #define PIPEB_LINK_M1 0x61040 | 2496 | #define PIPEB_LINK_M1 0x61040 |
2455 | #define PIPEB_LINK_M1_OFFSET 0 | ||
2456 | #define PIPEB_LINK_N1 0x61044 | 2497 | #define PIPEB_LINK_N1 0x61044 |
2457 | #define PIPEB_LINK_N1_OFFSET 0 | ||
2458 | 2498 | ||
2459 | #define PIPEB_LINK_M2 0x61048 | 2499 | #define PIPEB_LINK_M2 0x61048 |
2460 | #define PIPEB_LINK_M2_OFFSET 0 | ||
2461 | #define PIPEB_LINK_N2 0x6104c | 2500 | #define PIPEB_LINK_N2 0x6104c |
2462 | #define PIPEB_LINK_N2_OFFSET 0 | 2501 | |
2502 | #define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1) | ||
2503 | #define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1) | ||
2504 | #define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2) | ||
2505 | #define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2) | ||
2506 | #define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1) | ||
2507 | #define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1) | ||
2508 | #define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2) | ||
2509 | #define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2) | ||
2463 | 2510 | ||
2464 | /* CPU panel fitter */ | 2511 | /* CPU panel fitter */ |
2465 | #define PFA_CTL_1 0x68080 | 2512 | #define PFA_CTL_1 0x68080 |
@@ -2516,7 +2563,7 @@ | |||
2516 | #define GT_SYNC_STATUS (1 << 2) | 2563 | #define GT_SYNC_STATUS (1 << 2) |
2517 | #define GT_USER_INTERRUPT (1 << 0) | 2564 | #define GT_USER_INTERRUPT (1 << 0) |
2518 | #define GT_BSD_USER_INTERRUPT (1 << 5) | 2565 | #define GT_BSD_USER_INTERRUPT (1 << 5) |
2519 | 2566 | #define GT_GEN6_BSD_USER_INTERRUPT (1 << 12) | |
2520 | 2567 | ||
2521 | #define GTISR 0x44010 | 2568 | #define GTISR 0x44010 |
2522 | #define GTIMR 0x44014 | 2569 | #define GTIMR 0x44014 |
@@ -2600,11 +2647,14 @@ | |||
2600 | 2647 | ||
2601 | #define PCH_DPLL_A 0xc6014 | 2648 | #define PCH_DPLL_A 0xc6014 |
2602 | #define PCH_DPLL_B 0xc6018 | 2649 | #define PCH_DPLL_B 0xc6018 |
2650 | #define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B) | ||
2603 | 2651 | ||
2604 | #define PCH_FPA0 0xc6040 | 2652 | #define PCH_FPA0 0xc6040 |
2605 | #define PCH_FPA1 0xc6044 | 2653 | #define PCH_FPA1 0xc6044 |
2606 | #define PCH_FPB0 0xc6048 | 2654 | #define PCH_FPB0 0xc6048 |
2607 | #define PCH_FPB1 0xc604c | 2655 | #define PCH_FPB1 0xc604c |
2656 | #define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0) | ||
2657 | #define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1) | ||
2608 | 2658 | ||
2609 | #define PCH_DPLL_TEST 0xc606c | 2659 | #define PCH_DPLL_TEST 0xc606c |
2610 | 2660 | ||
@@ -2690,6 +2740,13 @@ | |||
2690 | #define TRANS_VBLANK_B 0xe1010 | 2740 | #define TRANS_VBLANK_B 0xe1010 |
2691 | #define TRANS_VSYNC_B 0xe1014 | 2741 | #define TRANS_VSYNC_B 0xe1014 |
2692 | 2742 | ||
2743 | #define TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B) | ||
2744 | #define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B) | ||
2745 | #define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B) | ||
2746 | #define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B) | ||
2747 | #define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B) | ||
2748 | #define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B) | ||
2749 | |||
2693 | #define TRANSB_DATA_M1 0xe1030 | 2750 | #define TRANSB_DATA_M1 0xe1030 |
2694 | #define TRANSB_DATA_N1 0xe1034 | 2751 | #define TRANSB_DATA_N1 0xe1034 |
2695 | #define TRANSB_DATA_M2 0xe1038 | 2752 | #define TRANSB_DATA_M2 0xe1038 |
@@ -2701,6 +2758,7 @@ | |||
2701 | 2758 | ||
2702 | #define TRANSACONF 0xf0008 | 2759 | #define TRANSACONF 0xf0008 |
2703 | #define TRANSBCONF 0xf1008 | 2760 | #define TRANSBCONF 0xf1008 |
2761 | #define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF) | ||
2704 | #define TRANS_DISABLE (0<<31) | 2762 | #define TRANS_DISABLE (0<<31) |
2705 | #define TRANS_ENABLE (1<<31) | 2763 | #define TRANS_ENABLE (1<<31) |
2706 | #define TRANS_STATE_MASK (1<<30) | 2764 | #define TRANS_STATE_MASK (1<<30) |
@@ -2725,6 +2783,7 @@ | |||
2725 | /* CPU: FDI_TX */ | 2783 | /* CPU: FDI_TX */ |
2726 | #define FDI_TXA_CTL 0x60100 | 2784 | #define FDI_TXA_CTL 0x60100 |
2727 | #define FDI_TXB_CTL 0x61100 | 2785 | #define FDI_TXB_CTL 0x61100 |
2786 | #define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL) | ||
2728 | #define FDI_TX_DISABLE (0<<31) | 2787 | #define FDI_TX_DISABLE (0<<31) |
2729 | #define FDI_TX_ENABLE (1<<31) | 2788 | #define FDI_TX_ENABLE (1<<31) |
2730 | #define FDI_LINK_TRAIN_PATTERN_1 (0<<28) | 2789 | #define FDI_LINK_TRAIN_PATTERN_1 (0<<28) |
@@ -2766,8 +2825,8 @@ | |||
2766 | /* FDI_RX, FDI_X is hard-wired to Transcoder_X */ | 2825 | /* FDI_RX, FDI_X is hard-wired to Transcoder_X */ |
2767 | #define FDI_RXA_CTL 0xf000c | 2826 | #define FDI_RXA_CTL 0xf000c |
2768 | #define FDI_RXB_CTL 0xf100c | 2827 | #define FDI_RXB_CTL 0xf100c |
2828 | #define FDI_RX_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL) | ||
2769 | #define FDI_RX_ENABLE (1<<31) | 2829 | #define FDI_RX_ENABLE (1<<31) |
2770 | #define FDI_RX_DISABLE (0<<31) | ||
2771 | /* train, dp width same as FDI_TX */ | 2830 | /* train, dp width same as FDI_TX */ |
2772 | #define FDI_DP_PORT_WIDTH_X8 (7<<19) | 2831 | #define FDI_DP_PORT_WIDTH_X8 (7<<19) |
2773 | #define FDI_8BPC (0<<16) | 2832 | #define FDI_8BPC (0<<16) |
@@ -2782,8 +2841,7 @@ | |||
2782 | #define FDI_FS_ERR_REPORT_ENABLE (1<<9) | 2841 | #define FDI_FS_ERR_REPORT_ENABLE (1<<9) |
2783 | #define FDI_FE_ERR_REPORT_ENABLE (1<<8) | 2842 | #define FDI_FE_ERR_REPORT_ENABLE (1<<8) |
2784 | #define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6) | 2843 | #define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6) |
2785 | #define FDI_SEL_RAWCLK (0<<4) | 2844 | #define FDI_PCDCLK (1<<4) |
2786 | #define FDI_SEL_PCDCLK (1<<4) | ||
2787 | /* CPT */ | 2845 | /* CPT */ |
2788 | #define FDI_AUTO_TRAINING (1<<10) | 2846 | #define FDI_AUTO_TRAINING (1<<10) |
2789 | #define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8) | 2847 | #define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8) |
@@ -2798,6 +2856,9 @@ | |||
2798 | #define FDI_RXA_TUSIZE2 0xf0038 | 2856 | #define FDI_RXA_TUSIZE2 0xf0038 |
2799 | #define FDI_RXB_TUSIZE1 0xf1030 | 2857 | #define FDI_RXB_TUSIZE1 0xf1030 |
2800 | #define FDI_RXB_TUSIZE2 0xf1038 | 2858 | #define FDI_RXB_TUSIZE2 0xf1038 |
2859 | #define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC) | ||
2860 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1) | ||
2861 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2) | ||
2801 | 2862 | ||
2802 | /* FDI_RX interrupt register format */ | 2863 | /* FDI_RX interrupt register format */ |
2803 | #define FDI_RX_INTER_LANE_ALIGN (1<<10) | 2864 | #define FDI_RX_INTER_LANE_ALIGN (1<<10) |
@@ -2816,6 +2877,8 @@ | |||
2816 | #define FDI_RXA_IMR 0xf0018 | 2877 | #define FDI_RXA_IMR 0xf0018 |
2817 | #define FDI_RXB_IIR 0xf1014 | 2878 | #define FDI_RXB_IIR 0xf1014 |
2818 | #define FDI_RXB_IMR 0xf1018 | 2879 | #define FDI_RXB_IMR 0xf1018 |
2880 | #define FDI_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR) | ||
2881 | #define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR) | ||
2819 | 2882 | ||
2820 | #define FDI_PLL_CTL_1 0xfe000 | 2883 | #define FDI_PLL_CTL_1 0xfe000 |
2821 | #define FDI_PLL_CTL_2 0xfe004 | 2884 | #define FDI_PLL_CTL_2 0xfe004 |
@@ -2935,6 +2998,7 @@ | |||
2935 | #define TRANS_DP_CTL_A 0xe0300 | 2998 | #define TRANS_DP_CTL_A 0xe0300 |
2936 | #define TRANS_DP_CTL_B 0xe1300 | 2999 | #define TRANS_DP_CTL_B 0xe1300 |
2937 | #define TRANS_DP_CTL_C 0xe2300 | 3000 | #define TRANS_DP_CTL_C 0xe2300 |
3001 | #define TRANS_DP_CTL(pipe) (TRANS_DP_CTL_A + (pipe) * 0x01000) | ||
2938 | #define TRANS_DP_OUTPUT_ENABLE (1<<31) | 3002 | #define TRANS_DP_OUTPUT_ENABLE (1<<31) |
2939 | #define TRANS_DP_PORT_SEL_B (0<<29) | 3003 | #define TRANS_DP_PORT_SEL_B (0<<29) |
2940 | #define TRANS_DP_PORT_SEL_C (1<<29) | 3004 | #define TRANS_DP_PORT_SEL_C (1<<29) |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 31f08581e93a..989c19d2d959 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
@@ -256,7 +256,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
256 | dev_priv->saveFPA1 = I915_READ(FPA1); | 256 | dev_priv->saveFPA1 = I915_READ(FPA1); |
257 | dev_priv->saveDPLL_A = I915_READ(DPLL_A); | 257 | dev_priv->saveDPLL_A = I915_READ(DPLL_A); |
258 | } | 258 | } |
259 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) | 259 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) |
260 | dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); | 260 | dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); |
261 | dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); | 261 | dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); |
262 | dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); | 262 | dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); |
@@ -294,7 +294,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
294 | dev_priv->saveDSPASIZE = I915_READ(DSPASIZE); | 294 | dev_priv->saveDSPASIZE = I915_READ(DSPASIZE); |
295 | dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); | 295 | dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); |
296 | dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); | 296 | dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); |
297 | if (IS_I965G(dev)) { | 297 | if (INTEL_INFO(dev)->gen >= 4) { |
298 | dev_priv->saveDSPASURF = I915_READ(DSPASURF); | 298 | dev_priv->saveDSPASURF = I915_READ(DSPASURF); |
299 | dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); | 299 | dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); |
300 | } | 300 | } |
@@ -313,7 +313,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
313 | dev_priv->saveFPB1 = I915_READ(FPB1); | 313 | dev_priv->saveFPB1 = I915_READ(FPB1); |
314 | dev_priv->saveDPLL_B = I915_READ(DPLL_B); | 314 | dev_priv->saveDPLL_B = I915_READ(DPLL_B); |
315 | } | 315 | } |
316 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) | 316 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) |
317 | dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); | 317 | dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); |
318 | dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); | 318 | dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); |
319 | dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); | 319 | dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); |
@@ -351,7 +351,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
351 | dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); | 351 | dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); |
352 | dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); | 352 | dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); |
353 | dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); | 353 | dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); |
354 | if (IS_I965GM(dev) || IS_GM45(dev)) { | 354 | if (INTEL_INFO(dev)->gen >= 4) { |
355 | dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); | 355 | dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); |
356 | dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); | 356 | dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); |
357 | } | 357 | } |
@@ -404,7 +404,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
404 | I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); | 404 | I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); |
405 | POSTING_READ(dpll_a_reg); | 405 | POSTING_READ(dpll_a_reg); |
406 | udelay(150); | 406 | udelay(150); |
407 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { | 407 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
408 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); | 408 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); |
409 | POSTING_READ(DPLL_A_MD); | 409 | POSTING_READ(DPLL_A_MD); |
410 | } | 410 | } |
@@ -448,7 +448,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
448 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); | 448 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); |
449 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); | 449 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); |
450 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); | 450 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); |
451 | if (IS_I965G(dev)) { | 451 | if (INTEL_INFO(dev)->gen >= 4) { |
452 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); | 452 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); |
453 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); | 453 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); |
454 | } | 454 | } |
@@ -473,7 +473,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
473 | I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); | 473 | I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); |
474 | POSTING_READ(dpll_b_reg); | 474 | POSTING_READ(dpll_b_reg); |
475 | udelay(150); | 475 | udelay(150); |
476 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { | 476 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
477 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); | 477 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); |
478 | POSTING_READ(DPLL_B_MD); | 478 | POSTING_READ(DPLL_B_MD); |
479 | } | 479 | } |
@@ -517,7 +517,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
517 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); | 517 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); |
518 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); | 518 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); |
519 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); | 519 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); |
520 | if (IS_I965G(dev)) { | 520 | if (INTEL_INFO(dev)->gen >= 4) { |
521 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); | 521 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); |
522 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); | 522 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); |
523 | } | 523 | } |
@@ -550,7 +550,7 @@ void i915_save_display(struct drm_device *dev) | |||
550 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); | 550 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); |
551 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); | 551 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); |
552 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); | 552 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); |
553 | if (!IS_I9XX(dev)) | 553 | if (IS_GEN2(dev)) |
554 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); | 554 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); |
555 | 555 | ||
556 | /* CRT state */ | 556 | /* CRT state */ |
@@ -573,7 +573,7 @@ void i915_save_display(struct drm_device *dev) | |||
573 | dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); | 573 | dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); |
574 | dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); | 574 | dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); |
575 | dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); | 575 | dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); |
576 | if (IS_I965G(dev)) | 576 | if (INTEL_INFO(dev)->gen >= 4) |
577 | dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); | 577 | dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); |
578 | if (IS_MOBILE(dev) && !IS_I830(dev)) | 578 | if (IS_MOBILE(dev) && !IS_I830(dev)) |
579 | dev_priv->saveLVDS = I915_READ(LVDS); | 579 | dev_priv->saveLVDS = I915_READ(LVDS); |
@@ -664,7 +664,7 @@ void i915_restore_display(struct drm_device *dev) | |||
664 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); | 664 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); |
665 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); | 665 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); |
666 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); | 666 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); |
667 | if (!IS_I9XX(dev)) | 667 | if (IS_GEN2(dev)) |
668 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); | 668 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); |
669 | 669 | ||
670 | /* CRT state */ | 670 | /* CRT state */ |
@@ -674,7 +674,7 @@ void i915_restore_display(struct drm_device *dev) | |||
674 | I915_WRITE(ADPA, dev_priv->saveADPA); | 674 | I915_WRITE(ADPA, dev_priv->saveADPA); |
675 | 675 | ||
676 | /* LVDS state */ | 676 | /* LVDS state */ |
677 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) | 677 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) |
678 | I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); | 678 | I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); |
679 | 679 | ||
680 | if (HAS_PCH_SPLIT(dev)) { | 680 | if (HAS_PCH_SPLIT(dev)) { |
@@ -878,9 +878,7 @@ int i915_restore_state(struct drm_device *dev) | |||
878 | for (i = 0; i < 3; i++) | 878 | for (i = 0; i < 3; i++) |
879 | I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); | 879 | I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); |
880 | 880 | ||
881 | /* I2C state */ | 881 | intel_i2c_reset(dev); |
882 | intel_i2c_reset_gmbus(dev); | ||
883 | 882 | ||
884 | return 0; | 883 | return 0; |
885 | } | 884 | } |
886 | |||
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 96f75d7f6633..b1f73ac0f3fd 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -129,10 +129,6 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
129 | int i, temp_downclock; | 129 | int i, temp_downclock; |
130 | struct drm_display_mode *temp_mode; | 130 | struct drm_display_mode *temp_mode; |
131 | 131 | ||
132 | /* Defaults if we can't find VBT info */ | ||
133 | dev_priv->lvds_dither = 0; | ||
134 | dev_priv->lvds_vbt = 0; | ||
135 | |||
136 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); | 132 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); |
137 | if (!lvds_options) | 133 | if (!lvds_options) |
138 | return; | 134 | return; |
@@ -140,6 +136,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
140 | dev_priv->lvds_dither = lvds_options->pixel_dither; | 136 | dev_priv->lvds_dither = lvds_options->pixel_dither; |
141 | if (lvds_options->panel_type == 0xff) | 137 | if (lvds_options->panel_type == 0xff) |
142 | return; | 138 | return; |
139 | |||
143 | panel_type = lvds_options->panel_type; | 140 | panel_type = lvds_options->panel_type; |
144 | 141 | ||
145 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); | 142 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); |
@@ -169,6 +166,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
169 | ((unsigned char *)entry + dvo_timing_offset); | 166 | ((unsigned char *)entry + dvo_timing_offset); |
170 | 167 | ||
171 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 168 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
169 | if (!panel_fixed_mode) | ||
170 | return; | ||
172 | 171 | ||
173 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); | 172 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); |
174 | 173 | ||
@@ -230,8 +229,6 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, | |||
230 | struct lvds_dvo_timing *dvo_timing; | 229 | struct lvds_dvo_timing *dvo_timing; |
231 | struct drm_display_mode *panel_fixed_mode; | 230 | struct drm_display_mode *panel_fixed_mode; |
232 | 231 | ||
233 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
234 | |||
235 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | 232 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); |
236 | if (!sdvo_lvds_options) | 233 | if (!sdvo_lvds_options) |
237 | return; | 234 | return; |
@@ -260,10 +257,6 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
260 | struct drm_device *dev = dev_priv->dev; | 257 | struct drm_device *dev = dev_priv->dev; |
261 | struct bdb_general_features *general; | 258 | struct bdb_general_features *general; |
262 | 259 | ||
263 | /* Set sensible defaults in case we can't find the general block */ | ||
264 | dev_priv->int_tv_support = 1; | ||
265 | dev_priv->int_crt_support = 1; | ||
266 | |||
267 | general = find_section(bdb, BDB_GENERAL_FEATURES); | 260 | general = find_section(bdb, BDB_GENERAL_FEATURES); |
268 | if (general) { | 261 | if (general) { |
269 | dev_priv->int_tv_support = general->int_tv_support; | 262 | dev_priv->int_tv_support = general->int_tv_support; |
@@ -289,14 +282,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
289 | struct bdb_header *bdb) | 282 | struct bdb_header *bdb) |
290 | { | 283 | { |
291 | struct bdb_general_definitions *general; | 284 | struct bdb_general_definitions *general; |
292 | const int crt_bus_map_table[] = { | ||
293 | GPIOB, | ||
294 | GPIOA, | ||
295 | GPIOC, | ||
296 | GPIOD, | ||
297 | GPIOE, | ||
298 | GPIOF, | ||
299 | }; | ||
300 | 285 | ||
301 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 286 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
302 | if (general) { | 287 | if (general) { |
@@ -304,10 +289,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
304 | if (block_size >= sizeof(*general)) { | 289 | if (block_size >= sizeof(*general)) { |
305 | int bus_pin = general->crt_ddc_gmbus_pin; | 290 | int bus_pin = general->crt_ddc_gmbus_pin; |
306 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); | 291 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
307 | if ((bus_pin >= 1) && (bus_pin <= 6)) { | 292 | if (bus_pin >= 1 && bus_pin <= 6) |
308 | dev_priv->crt_ddc_bus = | 293 | dev_priv->crt_ddc_pin = bus_pin; |
309 | crt_bus_map_table[bus_pin-1]; | ||
310 | } | ||
311 | } else { | 294 | } else { |
312 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", | 295 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
313 | block_size); | 296 | block_size); |
@@ -317,7 +300,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
317 | 300 | ||
318 | static void | 301 | static void |
319 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | 302 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, |
320 | struct bdb_header *bdb) | 303 | struct bdb_header *bdb) |
321 | { | 304 | { |
322 | struct sdvo_device_mapping *p_mapping; | 305 | struct sdvo_device_mapping *p_mapping; |
323 | struct bdb_general_definitions *p_defs; | 306 | struct bdb_general_definitions *p_defs; |
@@ -327,7 +310,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
327 | 310 | ||
328 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 311 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
329 | if (!p_defs) { | 312 | if (!p_defs) { |
330 | DRM_DEBUG_KMS("No general definition block is found\n"); | 313 | DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); |
331 | return; | 314 | return; |
332 | } | 315 | } |
333 | /* judge whether the size of child device meets the requirements. | 316 | /* judge whether the size of child device meets the requirements. |
@@ -377,7 +360,16 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
377 | p_mapping->slave_addr = p_child->slave_addr; | 360 | p_mapping->slave_addr = p_child->slave_addr; |
378 | p_mapping->dvo_wiring = p_child->dvo_wiring; | 361 | p_mapping->dvo_wiring = p_child->dvo_wiring; |
379 | p_mapping->ddc_pin = p_child->ddc_pin; | 362 | p_mapping->ddc_pin = p_child->ddc_pin; |
363 | p_mapping->i2c_pin = p_child->i2c_pin; | ||
364 | p_mapping->i2c_speed = p_child->i2c_speed; | ||
380 | p_mapping->initialized = 1; | 365 | p_mapping->initialized = 1; |
366 | DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n", | ||
367 | p_mapping->dvo_port, | ||
368 | p_mapping->slave_addr, | ||
369 | p_mapping->dvo_wiring, | ||
370 | p_mapping->ddc_pin, | ||
371 | p_mapping->i2c_pin, | ||
372 | p_mapping->i2c_speed); | ||
381 | } else { | 373 | } else { |
382 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " | 374 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
383 | "two SDVO device.\n"); | 375 | "two SDVO device.\n"); |
@@ -409,14 +401,11 @@ parse_driver_features(struct drm_i915_private *dev_priv, | |||
409 | if (!driver) | 401 | if (!driver) |
410 | return; | 402 | return; |
411 | 403 | ||
412 | if (driver && SUPPORTS_EDP(dev) && | 404 | if (SUPPORTS_EDP(dev) && |
413 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { | 405 | driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
414 | dev_priv->edp_support = 1; | 406 | dev_priv->edp.support = 1; |
415 | } else { | ||
416 | dev_priv->edp_support = 0; | ||
417 | } | ||
418 | 407 | ||
419 | if (driver && driver->dual_frequency) | 408 | if (driver->dual_frequency) |
420 | dev_priv->render_reclock_avail = true; | 409 | dev_priv->render_reclock_avail = true; |
421 | } | 410 | } |
422 | 411 | ||
@@ -427,26 +416,40 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
427 | 416 | ||
428 | edp = find_section(bdb, BDB_EDP); | 417 | edp = find_section(bdb, BDB_EDP); |
429 | if (!edp) { | 418 | if (!edp) { |
430 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { | 419 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { |
431 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " | 420 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " |
432 | "supported, assume 18bpp panel color " | 421 | "supported, assume %dbpp panel color " |
433 | "depth.\n"); | 422 | "depth.\n", |
434 | dev_priv->edp_bpp = 18; | 423 | dev_priv->edp.bpp); |
435 | } | 424 | } |
436 | return; | 425 | return; |
437 | } | 426 | } |
438 | 427 | ||
439 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { | 428 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { |
440 | case EDP_18BPP: | 429 | case EDP_18BPP: |
441 | dev_priv->edp_bpp = 18; | 430 | dev_priv->edp.bpp = 18; |
442 | break; | 431 | break; |
443 | case EDP_24BPP: | 432 | case EDP_24BPP: |
444 | dev_priv->edp_bpp = 24; | 433 | dev_priv->edp.bpp = 24; |
445 | break; | 434 | break; |
446 | case EDP_30BPP: | 435 | case EDP_30BPP: |
447 | dev_priv->edp_bpp = 30; | 436 | dev_priv->edp.bpp = 30; |
448 | break; | 437 | break; |
449 | } | 438 | } |
439 | |||
440 | dev_priv->edp.rate = edp->link_params[panel_type].rate; | ||
441 | dev_priv->edp.lanes = edp->link_params[panel_type].lanes; | ||
442 | dev_priv->edp.preemphasis = edp->link_params[panel_type].preemphasis; | ||
443 | dev_priv->edp.vswing = edp->link_params[panel_type].vswing; | ||
444 | |||
445 | DRM_DEBUG_KMS("eDP vBIOS settings: bpp=%d, rate=%d, lanes=%d, preemphasis=%d, vswing=%d\n", | ||
446 | dev_priv->edp.bpp, | ||
447 | dev_priv->edp.rate, | ||
448 | dev_priv->edp.lanes, | ||
449 | dev_priv->edp.preemphasis, | ||
450 | dev_priv->edp.vswing); | ||
451 | |||
452 | dev_priv->edp.initialized = true; | ||
450 | } | 453 | } |
451 | 454 | ||
452 | static void | 455 | static void |
@@ -460,7 +463,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
460 | 463 | ||
461 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 464 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
462 | if (!p_defs) { | 465 | if (!p_defs) { |
463 | DRM_DEBUG_KMS("No general definition block is found\n"); | 466 | DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); |
464 | return; | 467 | return; |
465 | } | 468 | } |
466 | /* judge whether the size of child device meets the requirements. | 469 | /* judge whether the size of child device meets the requirements. |
@@ -513,6 +516,28 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
513 | } | 516 | } |
514 | return; | 517 | return; |
515 | } | 518 | } |
519 | |||
520 | static void | ||
521 | init_vbt_defaults(struct drm_i915_private *dev_priv) | ||
522 | { | ||
523 | dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; | ||
524 | |||
525 | /* LFP panel data */ | ||
526 | dev_priv->lvds_dither = 1; | ||
527 | dev_priv->lvds_vbt = 0; | ||
528 | |||
529 | /* SDVO panel data */ | ||
530 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
531 | |||
532 | /* general features */ | ||
533 | dev_priv->int_tv_support = 1; | ||
534 | dev_priv->int_crt_support = 1; | ||
535 | dev_priv->lvds_use_ssc = 0; | ||
536 | |||
537 | /* eDP data */ | ||
538 | dev_priv->edp.bpp = 18; | ||
539 | } | ||
540 | |||
516 | /** | 541 | /** |
517 | * intel_init_bios - initialize VBIOS settings & find VBT | 542 | * intel_init_bios - initialize VBIOS settings & find VBT |
518 | * @dev: DRM device | 543 | * @dev: DRM device |
@@ -520,11 +545,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
520 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers | 545 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers |
521 | * to appropriate values. | 546 | * to appropriate values. |
522 | * | 547 | * |
523 | * VBT existence is a sanity check that is relied on by other i830_bios.c code. | ||
524 | * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may | ||
525 | * feed an updated VBT back through that, compared to what we'll fetch using | ||
526 | * this method of groping around in the BIOS data. | ||
527 | * | ||
528 | * Returns 0 on success, nonzero on failure. | 548 | * Returns 0 on success, nonzero on failure. |
529 | */ | 549 | */ |
530 | bool | 550 | bool |
@@ -532,31 +552,47 @@ intel_init_bios(struct drm_device *dev) | |||
532 | { | 552 | { |
533 | struct drm_i915_private *dev_priv = dev->dev_private; | 553 | struct drm_i915_private *dev_priv = dev->dev_private; |
534 | struct pci_dev *pdev = dev->pdev; | 554 | struct pci_dev *pdev = dev->pdev; |
535 | struct vbt_header *vbt = NULL; | 555 | struct bdb_header *bdb = NULL; |
536 | struct bdb_header *bdb; | 556 | u8 __iomem *bios = NULL; |
537 | u8 __iomem *bios; | 557 | |
538 | size_t size; | 558 | init_vbt_defaults(dev_priv); |
539 | int i; | 559 | |
540 | 560 | /* XXX Should this validation be moved to intel_opregion.c? */ | |
541 | bios = pci_map_rom(pdev, &size); | 561 | if (dev_priv->opregion.vbt) { |
542 | if (!bios) | 562 | struct vbt_header *vbt = dev_priv->opregion.vbt; |
543 | return -1; | 563 | if (memcmp(vbt->signature, "$VBT", 4) == 0) { |
544 | 564 | DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n", | |
545 | /* Scour memory looking for the VBT signature */ | 565 | vbt->signature); |
546 | for (i = 0; i + 4 < size; i++) { | 566 | bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); |
547 | if (!memcmp(bios + i, "$VBT", 4)) { | 567 | } else |
548 | vbt = (struct vbt_header *)(bios + i); | 568 | dev_priv->opregion.vbt = NULL; |
549 | break; | ||
550 | } | ||
551 | } | 569 | } |
552 | 570 | ||
553 | if (!vbt) { | 571 | if (bdb == NULL) { |
554 | DRM_ERROR("VBT signature missing\n"); | 572 | struct vbt_header *vbt = NULL; |
555 | pci_unmap_rom(pdev, bios); | 573 | size_t size; |
556 | return -1; | 574 | int i; |
557 | } | 575 | |
576 | bios = pci_map_rom(pdev, &size); | ||
577 | if (!bios) | ||
578 | return -1; | ||
579 | |||
580 | /* Scour memory looking for the VBT signature */ | ||
581 | for (i = 0; i + 4 < size; i++) { | ||
582 | if (!memcmp(bios + i, "$VBT", 4)) { | ||
583 | vbt = (struct vbt_header *)(bios + i); | ||
584 | break; | ||
585 | } | ||
586 | } | ||
558 | 587 | ||
559 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | 588 | if (!vbt) { |
589 | DRM_ERROR("VBT signature missing\n"); | ||
590 | pci_unmap_rom(pdev, bios); | ||
591 | return -1; | ||
592 | } | ||
593 | |||
594 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | ||
595 | } | ||
560 | 596 | ||
561 | /* Grab useful general definitions */ | 597 | /* Grab useful general definitions */ |
562 | parse_general_features(dev_priv, bdb); | 598 | parse_general_features(dev_priv, bdb); |
@@ -568,7 +604,8 @@ intel_init_bios(struct drm_device *dev) | |||
568 | parse_driver_features(dev_priv, bdb); | 604 | parse_driver_features(dev_priv, bdb); |
569 | parse_edp(dev_priv, bdb); | 605 | parse_edp(dev_priv, bdb); |
570 | 606 | ||
571 | pci_unmap_rom(pdev, bios); | 607 | if (bios) |
608 | pci_unmap_rom(pdev, bios); | ||
572 | 609 | ||
573 | return 0; | 610 | return 0; |
574 | } | 611 | } |
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 4c18514f6f80..e1a598f2a966 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
@@ -197,7 +197,8 @@ struct bdb_general_features { | |||
197 | struct child_device_config { | 197 | struct child_device_config { |
198 | u16 handle; | 198 | u16 handle; |
199 | u16 device_type; | 199 | u16 device_type; |
200 | u8 device_id[10]; /* See DEVICE_TYPE_* above */ | 200 | u8 i2c_speed; |
201 | u8 rsvd[9]; | ||
201 | u16 addin_offset; | 202 | u16 addin_offset; |
202 | u8 dvo_port; /* See Device_PORT_* above */ | 203 | u8 dvo_port; /* See Device_PORT_* above */ |
203 | u8 i2c_pin; | 204 | u8 i2c_pin; |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 197d4f32585a..389fcd2aea1f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -79,7 +79,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector, | |||
79 | if (mode->clock < 25000) | 79 | if (mode->clock < 25000) |
80 | return MODE_CLOCK_LOW; | 80 | return MODE_CLOCK_LOW; |
81 | 81 | ||
82 | if (!IS_I9XX(dev)) | 82 | if (IS_GEN2(dev)) |
83 | max_clock = 350000; | 83 | max_clock = 350000; |
84 | else | 84 | else |
85 | max_clock = 400000; | 85 | max_clock = 400000; |
@@ -123,7 +123,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
123 | * Disable separate mode multiplier used when cloning SDVO to CRT | 123 | * Disable separate mode multiplier used when cloning SDVO to CRT |
124 | * XXX this needs to be adjusted when we really are cloning | 124 | * XXX this needs to be adjusted when we really are cloning |
125 | */ | 125 | */ |
126 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { | 126 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
127 | dpll_md = I915_READ(dpll_md_reg); | 127 | dpll_md = I915_READ(dpll_md_reg); |
128 | I915_WRITE(dpll_md_reg, | 128 | I915_WRITE(dpll_md_reg, |
129 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); | 129 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); |
@@ -187,7 +187,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | |||
187 | I915_WRITE(PCH_ADPA, adpa); | 187 | I915_WRITE(PCH_ADPA, adpa); |
188 | 188 | ||
189 | if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | 189 | if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, |
190 | 1000, 1)) | 190 | 1000)) |
191 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | 191 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); |
192 | 192 | ||
193 | if (turn_off_dac) { | 193 | if (turn_off_dac) { |
@@ -244,7 +244,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
244 | /* wait for FORCE_DETECT to go off */ | 244 | /* wait for FORCE_DETECT to go off */ |
245 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & | 245 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & |
246 | CRT_HOTPLUG_FORCE_DETECT) == 0, | 246 | CRT_HOTPLUG_FORCE_DETECT) == 0, |
247 | 1000, 1)) | 247 | 1000)) |
248 | DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); | 248 | DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); |
249 | } | 249 | } |
250 | 250 | ||
@@ -261,21 +261,47 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
261 | return ret; | 261 | return ret; |
262 | } | 262 | } |
263 | 263 | ||
264 | static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus) | ||
265 | { | ||
266 | u8 buf; | ||
267 | struct i2c_msg msgs[] = { | ||
268 | { | ||
269 | .addr = 0xA0, | ||
270 | .flags = 0, | ||
271 | .len = 1, | ||
272 | .buf = &buf, | ||
273 | }, | ||
274 | }; | ||
275 | /* DDC monitor detect: Does it ACK a write to 0xA0? */ | ||
276 | return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; | ||
277 | } | ||
278 | |||
264 | static bool intel_crt_detect_ddc(struct drm_encoder *encoder) | 279 | static bool intel_crt_detect_ddc(struct drm_encoder *encoder) |
265 | { | 280 | { |
266 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 281 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); |
282 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
267 | 283 | ||
268 | /* CRT should always be at 0, but check anyway */ | 284 | /* CRT should always be at 0, but check anyway */ |
269 | if (intel_encoder->type != INTEL_OUTPUT_ANALOG) | 285 | if (intel_encoder->type != INTEL_OUTPUT_ANALOG) |
270 | return false; | 286 | return false; |
271 | 287 | ||
272 | return intel_ddc_probe(intel_encoder); | 288 | if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) { |
289 | DRM_DEBUG_KMS("CRT detected via DDC:0xa0\n"); | ||
290 | return true; | ||
291 | } | ||
292 | |||
293 | if (intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin)) { | ||
294 | DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); | ||
295 | return true; | ||
296 | } | ||
297 | |||
298 | return false; | ||
273 | } | 299 | } |
274 | 300 | ||
275 | static enum drm_connector_status | 301 | static enum drm_connector_status |
276 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) | 302 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) |
277 | { | 303 | { |
278 | struct drm_encoder *encoder = &intel_encoder->enc; | 304 | struct drm_encoder *encoder = &intel_encoder->base; |
279 | struct drm_device *dev = encoder->dev; | 305 | struct drm_device *dev = encoder->dev; |
280 | struct drm_i915_private *dev_priv = dev->dev_private; | 306 | struct drm_i915_private *dev_priv = dev->dev_private; |
281 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 307 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
@@ -295,6 +321,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
295 | uint8_t st00; | 321 | uint8_t st00; |
296 | enum drm_connector_status status; | 322 | enum drm_connector_status status; |
297 | 323 | ||
324 | DRM_DEBUG_KMS("starting load-detect on CRT\n"); | ||
325 | |||
298 | if (pipe == 0) { | 326 | if (pipe == 0) { |
299 | bclrpat_reg = BCLRPAT_A; | 327 | bclrpat_reg = BCLRPAT_A; |
300 | vtotal_reg = VTOTAL_A; | 328 | vtotal_reg = VTOTAL_A; |
@@ -324,9 +352,10 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
324 | /* Set the border color to purple. */ | 352 | /* Set the border color to purple. */ |
325 | I915_WRITE(bclrpat_reg, 0x500050); | 353 | I915_WRITE(bclrpat_reg, 0x500050); |
326 | 354 | ||
327 | if (IS_I9XX(dev)) { | 355 | if (!IS_GEN2(dev)) { |
328 | uint32_t pipeconf = I915_READ(pipeconf_reg); | 356 | uint32_t pipeconf = I915_READ(pipeconf_reg); |
329 | I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); | 357 | I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); |
358 | POSTING_READ(pipeconf_reg); | ||
330 | /* Wait for next Vblank to substitue | 359 | /* Wait for next Vblank to substitue |
331 | * border color for Color info */ | 360 | * border color for Color info */ |
332 | intel_wait_for_vblank(dev, pipe); | 361 | intel_wait_for_vblank(dev, pipe); |
@@ -404,34 +433,37 @@ static enum drm_connector_status | |||
404 | intel_crt_detect(struct drm_connector *connector, bool force) | 433 | intel_crt_detect(struct drm_connector *connector, bool force) |
405 | { | 434 | { |
406 | struct drm_device *dev = connector->dev; | 435 | struct drm_device *dev = connector->dev; |
407 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 436 | struct intel_encoder *encoder = intel_attached_encoder(connector); |
408 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
409 | struct drm_crtc *crtc; | 437 | struct drm_crtc *crtc; |
410 | int dpms_mode; | 438 | int dpms_mode; |
411 | enum drm_connector_status status; | 439 | enum drm_connector_status status; |
412 | 440 | ||
413 | if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { | 441 | if (I915_HAS_HOTPLUG(dev)) { |
414 | if (intel_crt_detect_hotplug(connector)) | 442 | if (intel_crt_detect_hotplug(connector)) { |
443 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); | ||
415 | return connector_status_connected; | 444 | return connector_status_connected; |
416 | else | 445 | } else |
417 | return connector_status_disconnected; | 446 | return connector_status_disconnected; |
418 | } | 447 | } |
419 | 448 | ||
420 | if (intel_crt_detect_ddc(encoder)) | 449 | if (intel_crt_detect_ddc(&encoder->base)) |
421 | return connector_status_connected; | 450 | return connector_status_connected; |
422 | 451 | ||
423 | if (!force) | 452 | if (!force) |
424 | return connector->status; | 453 | return connector->status; |
425 | 454 | ||
426 | /* for pre-945g platforms use load detect */ | 455 | /* for pre-945g platforms use load detect */ |
427 | if (encoder->crtc && encoder->crtc->enabled) { | 456 | if (encoder->base.crtc && encoder->base.crtc->enabled) { |
428 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); | 457 | status = intel_crt_load_detect(encoder->base.crtc, encoder); |
429 | } else { | 458 | } else { |
430 | crtc = intel_get_load_detect_pipe(intel_encoder, connector, | 459 | crtc = intel_get_load_detect_pipe(encoder, connector, |
431 | NULL, &dpms_mode); | 460 | NULL, &dpms_mode); |
432 | if (crtc) { | 461 | if (crtc) { |
433 | status = intel_crt_load_detect(crtc, intel_encoder); | 462 | if (intel_crt_detect_ddc(&encoder->base)) |
434 | intel_release_load_detect_pipe(intel_encoder, | 463 | status = connector_status_connected; |
464 | else | ||
465 | status = intel_crt_load_detect(crtc, encoder); | ||
466 | intel_release_load_detect_pipe(encoder, | ||
435 | connector, dpms_mode); | 467 | connector, dpms_mode); |
436 | } else | 468 | } else |
437 | status = connector_status_unknown; | 469 | status = connector_status_unknown; |
@@ -449,32 +481,18 @@ static void intel_crt_destroy(struct drm_connector *connector) | |||
449 | 481 | ||
450 | static int intel_crt_get_modes(struct drm_connector *connector) | 482 | static int intel_crt_get_modes(struct drm_connector *connector) |
451 | { | 483 | { |
452 | int ret; | ||
453 | struct drm_encoder *encoder = intel_attached_encoder(connector); | ||
454 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
455 | struct i2c_adapter *ddc_bus; | ||
456 | struct drm_device *dev = connector->dev; | 484 | struct drm_device *dev = connector->dev; |
485 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
486 | int ret; | ||
457 | 487 | ||
458 | 488 | ret = intel_ddc_get_modes(connector, | |
459 | ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); | 489 | &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); |
460 | if (ret || !IS_G4X(dev)) | 490 | if (ret || !IS_G4X(dev)) |
461 | goto end; | 491 | return ret; |
462 | 492 | ||
463 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ | 493 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
464 | ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); | 494 | return intel_ddc_get_modes(connector, |
465 | 495 | &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); | |
466 | if (!ddc_bus) { | ||
467 | dev_printk(KERN_ERR, &connector->dev->pdev->dev, | ||
468 | "DDC bus registration failed for CRTDDC_D.\n"); | ||
469 | goto end; | ||
470 | } | ||
471 | /* Try to get modes by GPIOD port */ | ||
472 | ret = intel_ddc_get_modes(connector, ddc_bus); | ||
473 | intel_i2c_destroy(ddc_bus); | ||
474 | |||
475 | end: | ||
476 | return ret; | ||
477 | |||
478 | } | 496 | } |
479 | 497 | ||
480 | static int intel_crt_set_property(struct drm_connector *connector, | 498 | static int intel_crt_set_property(struct drm_connector *connector, |
@@ -507,7 +525,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = { | |||
507 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { | 525 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
508 | .mode_valid = intel_crt_mode_valid, | 526 | .mode_valid = intel_crt_mode_valid, |
509 | .get_modes = intel_crt_get_modes, | 527 | .get_modes = intel_crt_get_modes, |
510 | .best_encoder = intel_attached_encoder, | 528 | .best_encoder = intel_best_encoder, |
511 | }; | 529 | }; |
512 | 530 | ||
513 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { | 531 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { |
@@ -520,7 +538,6 @@ void intel_crt_init(struct drm_device *dev) | |||
520 | struct intel_encoder *intel_encoder; | 538 | struct intel_encoder *intel_encoder; |
521 | struct intel_connector *intel_connector; | 539 | struct intel_connector *intel_connector; |
522 | struct drm_i915_private *dev_priv = dev->dev_private; | 540 | struct drm_i915_private *dev_priv = dev->dev_private; |
523 | u32 i2c_reg; | ||
524 | 541 | ||
525 | intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); | 542 | intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); |
526 | if (!intel_encoder) | 543 | if (!intel_encoder) |
@@ -536,27 +553,10 @@ void intel_crt_init(struct drm_device *dev) | |||
536 | drm_connector_init(dev, &intel_connector->base, | 553 | drm_connector_init(dev, &intel_connector->base, |
537 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); | 554 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); |
538 | 555 | ||
539 | drm_encoder_init(dev, &intel_encoder->enc, &intel_crt_enc_funcs, | 556 | drm_encoder_init(dev, &intel_encoder->base, &intel_crt_enc_funcs, |
540 | DRM_MODE_ENCODER_DAC); | 557 | DRM_MODE_ENCODER_DAC); |
541 | 558 | ||
542 | drm_mode_connector_attach_encoder(&intel_connector->base, | 559 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
543 | &intel_encoder->enc); | ||
544 | |||
545 | /* Set up the DDC bus. */ | ||
546 | if (HAS_PCH_SPLIT(dev)) | ||
547 | i2c_reg = PCH_GPIOA; | ||
548 | else { | ||
549 | i2c_reg = GPIOA; | ||
550 | /* Use VBT information for CRT DDC if available */ | ||
551 | if (dev_priv->crt_ddc_bus != 0) | ||
552 | i2c_reg = dev_priv->crt_ddc_bus; | ||
553 | } | ||
554 | intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); | ||
555 | if (!intel_encoder->ddc_bus) { | ||
556 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | ||
557 | "failed.\n"); | ||
558 | return; | ||
559 | } | ||
560 | 560 | ||
561 | intel_encoder->type = INTEL_OUTPUT_ANALOG; | 561 | intel_encoder->type = INTEL_OUTPUT_ANALOG; |
562 | intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 562 | intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | |
@@ -566,7 +566,7 @@ void intel_crt_init(struct drm_device *dev) | |||
566 | connector->interlace_allowed = 1; | 566 | connector->interlace_allowed = 1; |
567 | connector->doublescan_allowed = 0; | 567 | connector->doublescan_allowed = 0; |
568 | 568 | ||
569 | drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs); | 569 | drm_encoder_helper_add(&intel_encoder->base, &intel_crt_helper_funcs); |
570 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 570 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); |
571 | 571 | ||
572 | drm_sysfs_connector_add(connector); | 572 | drm_sysfs_connector_add(connector); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 979228594599..9109c00f3ead 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -43,8 +43,8 @@ | |||
43 | 43 | ||
44 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | 44 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); |
45 | static void intel_update_watermarks(struct drm_device *dev); | 45 | static void intel_update_watermarks(struct drm_device *dev); |
46 | static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule); | 46 | static void intel_increase_pllclock(struct drm_crtc *crtc); |
47 | static void intel_crtc_update_cursor(struct drm_crtc *crtc); | 47 | static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); |
48 | 48 | ||
49 | typedef struct { | 49 | typedef struct { |
50 | /* given values */ | 50 | /* given values */ |
@@ -342,6 +342,13 @@ static bool | |||
342 | intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, | 342 | intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, |
343 | int target, int refclk, intel_clock_t *best_clock); | 343 | int target, int refclk, intel_clock_t *best_clock); |
344 | 344 | ||
345 | static inline u32 /* units of 100MHz */ | ||
346 | intel_fdi_link_freq(struct drm_device *dev) | ||
347 | { | ||
348 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
349 | return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2; | ||
350 | } | ||
351 | |||
345 | static const intel_limit_t intel_limits_i8xx_dvo = { | 352 | static const intel_limit_t intel_limits_i8xx_dvo = { |
346 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 353 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
347 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 354 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
@@ -701,16 +708,16 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
701 | limit = intel_ironlake_limit(crtc); | 708 | limit = intel_ironlake_limit(crtc); |
702 | else if (IS_G4X(dev)) { | 709 | else if (IS_G4X(dev)) { |
703 | limit = intel_g4x_limit(crtc); | 710 | limit = intel_g4x_limit(crtc); |
704 | } else if (IS_I9XX(dev) && !IS_PINEVIEW(dev)) { | ||
705 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | ||
706 | limit = &intel_limits_i9xx_lvds; | ||
707 | else | ||
708 | limit = &intel_limits_i9xx_sdvo; | ||
709 | } else if (IS_PINEVIEW(dev)) { | 711 | } else if (IS_PINEVIEW(dev)) { |
710 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 712 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
711 | limit = &intel_limits_pineview_lvds; | 713 | limit = &intel_limits_pineview_lvds; |
712 | else | 714 | else |
713 | limit = &intel_limits_pineview_sdvo; | 715 | limit = &intel_limits_pineview_sdvo; |
716 | } else if (!IS_GEN2(dev)) { | ||
717 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | ||
718 | limit = &intel_limits_i9xx_lvds; | ||
719 | else | ||
720 | limit = &intel_limits_i9xx_sdvo; | ||
714 | } else { | 721 | } else { |
715 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 722 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
716 | limit = &intel_limits_i8xx_lvds; | 723 | limit = &intel_limits_i8xx_lvds; |
@@ -744,20 +751,17 @@ static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock | |||
744 | /** | 751 | /** |
745 | * Returns whether any output on the specified pipe is of the specified type | 752 | * Returns whether any output on the specified pipe is of the specified type |
746 | */ | 753 | */ |
747 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type) | 754 | bool intel_pipe_has_type(struct drm_crtc *crtc, int type) |
748 | { | 755 | { |
749 | struct drm_device *dev = crtc->dev; | 756 | struct drm_device *dev = crtc->dev; |
750 | struct drm_mode_config *mode_config = &dev->mode_config; | 757 | struct drm_mode_config *mode_config = &dev->mode_config; |
751 | struct drm_encoder *l_entry; | 758 | struct intel_encoder *encoder; |
752 | 759 | ||
753 | list_for_each_entry(l_entry, &mode_config->encoder_list, head) { | 760 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) |
754 | if (l_entry && l_entry->crtc == crtc) { | 761 | if (encoder->base.crtc == crtc && encoder->type == type) |
755 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(l_entry); | 762 | return true; |
756 | if (intel_encoder->type == type) | 763 | |
757 | return true; | 764 | return false; |
758 | } | ||
759 | } | ||
760 | return false; | ||
761 | } | 765 | } |
762 | 766 | ||
763 | #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) | 767 | #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) |
@@ -955,26 +959,26 @@ static bool | |||
955 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | 959 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, |
956 | int target, int refclk, intel_clock_t *best_clock) | 960 | int target, int refclk, intel_clock_t *best_clock) |
957 | { | 961 | { |
958 | intel_clock_t clock; | 962 | intel_clock_t clock; |
959 | if (target < 200000) { | 963 | if (target < 200000) { |
960 | clock.p1 = 2; | 964 | clock.p1 = 2; |
961 | clock.p2 = 10; | 965 | clock.p2 = 10; |
962 | clock.n = 2; | 966 | clock.n = 2; |
963 | clock.m1 = 23; | 967 | clock.m1 = 23; |
964 | clock.m2 = 8; | 968 | clock.m2 = 8; |
965 | } else { | 969 | } else { |
966 | clock.p1 = 1; | 970 | clock.p1 = 1; |
967 | clock.p2 = 10; | 971 | clock.p2 = 10; |
968 | clock.n = 1; | 972 | clock.n = 1; |
969 | clock.m1 = 14; | 973 | clock.m1 = 14; |
970 | clock.m2 = 2; | 974 | clock.m2 = 2; |
971 | } | 975 | } |
972 | clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); | 976 | clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); |
973 | clock.p = (clock.p1 * clock.p2); | 977 | clock.p = (clock.p1 * clock.p2); |
974 | clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; | 978 | clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; |
975 | clock.vco = 0; | 979 | clock.vco = 0; |
976 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | 980 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); |
977 | return true; | 981 | return true; |
978 | } | 982 | } |
979 | 983 | ||
980 | /** | 984 | /** |
@@ -1007,9 +1011,9 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) | |||
1007 | I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS); | 1011 | I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS); |
1008 | 1012 | ||
1009 | /* Wait for vblank interrupt bit to set */ | 1013 | /* Wait for vblank interrupt bit to set */ |
1010 | if (wait_for((I915_READ(pipestat_reg) & | 1014 | if (wait_for(I915_READ(pipestat_reg) & |
1011 | PIPE_VBLANK_INTERRUPT_STATUS), | 1015 | PIPE_VBLANK_INTERRUPT_STATUS, |
1012 | 50, 0)) | 1016 | 50)) |
1013 | DRM_DEBUG_KMS("vblank wait timed out\n"); | 1017 | DRM_DEBUG_KMS("vblank wait timed out\n"); |
1014 | } | 1018 | } |
1015 | 1019 | ||
@@ -1028,36 +1032,35 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) | |||
1028 | * Otherwise: | 1032 | * Otherwise: |
1029 | * wait for the display line value to settle (it usually | 1033 | * wait for the display line value to settle (it usually |
1030 | * ends up stopping at the start of the next frame). | 1034 | * ends up stopping at the start of the next frame). |
1031 | * | 1035 | * |
1032 | */ | 1036 | */ |
1033 | static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) | 1037 | void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) |
1034 | { | 1038 | { |
1035 | struct drm_i915_private *dev_priv = dev->dev_private; | 1039 | struct drm_i915_private *dev_priv = dev->dev_private; |
1036 | 1040 | ||
1037 | if (INTEL_INFO(dev)->gen >= 4) { | 1041 | if (INTEL_INFO(dev)->gen >= 4) { |
1038 | int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF); | 1042 | int reg = PIPECONF(pipe); |
1039 | 1043 | ||
1040 | /* Wait for the Pipe State to go off */ | 1044 | /* Wait for the Pipe State to go off */ |
1041 | if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, | 1045 | if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, |
1042 | 100, 0)) | 1046 | 100)) |
1043 | DRM_DEBUG_KMS("pipe_off wait timed out\n"); | 1047 | DRM_DEBUG_KMS("pipe_off wait timed out\n"); |
1044 | } else { | 1048 | } else { |
1045 | u32 last_line; | 1049 | u32 last_line; |
1046 | int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); | 1050 | int reg = PIPEDSL(pipe); |
1047 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | 1051 | unsigned long timeout = jiffies + msecs_to_jiffies(100); |
1048 | 1052 | ||
1049 | /* Wait for the display line to settle */ | 1053 | /* Wait for the display line to settle */ |
1050 | do { | 1054 | do { |
1051 | last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; | 1055 | last_line = I915_READ(reg) & DSL_LINEMASK; |
1052 | mdelay(5); | 1056 | mdelay(5); |
1053 | } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && | 1057 | } while (((I915_READ(reg) & DSL_LINEMASK) != last_line) && |
1054 | time_after(timeout, jiffies)); | 1058 | time_after(timeout, jiffies)); |
1055 | if (time_after(jiffies, timeout)) | 1059 | if (time_after(jiffies, timeout)) |
1056 | DRM_DEBUG_KMS("pipe_off wait timed out\n"); | 1060 | DRM_DEBUG_KMS("pipe_off wait timed out\n"); |
1057 | } | 1061 | } |
1058 | } | 1062 | } |
1059 | 1063 | ||
1060 | /* Parameters have changed, update FBC info */ | ||
1061 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 1064 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
1062 | { | 1065 | { |
1063 | struct drm_device *dev = crtc->dev; | 1066 | struct drm_device *dev = crtc->dev; |
@@ -1069,6 +1072,14 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1069 | int plane, i; | 1072 | int plane, i; |
1070 | u32 fbc_ctl, fbc_ctl2; | 1073 | u32 fbc_ctl, fbc_ctl2; |
1071 | 1074 | ||
1075 | if (fb->pitch == dev_priv->cfb_pitch && | ||
1076 | obj_priv->fence_reg == dev_priv->cfb_fence && | ||
1077 | intel_crtc->plane == dev_priv->cfb_plane && | ||
1078 | I915_READ(FBC_CONTROL) & FBC_CTL_EN) | ||
1079 | return; | ||
1080 | |||
1081 | i8xx_disable_fbc(dev); | ||
1082 | |||
1072 | dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; | 1083 | dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; |
1073 | 1084 | ||
1074 | if (fb->pitch < dev_priv->cfb_pitch) | 1085 | if (fb->pitch < dev_priv->cfb_pitch) |
@@ -1102,7 +1113,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1102 | I915_WRITE(FBC_CONTROL, fbc_ctl); | 1113 | I915_WRITE(FBC_CONTROL, fbc_ctl); |
1103 | 1114 | ||
1104 | DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ", | 1115 | DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ", |
1105 | dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); | 1116 | dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane); |
1106 | } | 1117 | } |
1107 | 1118 | ||
1108 | void i8xx_disable_fbc(struct drm_device *dev) | 1119 | void i8xx_disable_fbc(struct drm_device *dev) |
@@ -1110,19 +1121,16 @@ void i8xx_disable_fbc(struct drm_device *dev) | |||
1110 | struct drm_i915_private *dev_priv = dev->dev_private; | 1121 | struct drm_i915_private *dev_priv = dev->dev_private; |
1111 | u32 fbc_ctl; | 1122 | u32 fbc_ctl; |
1112 | 1123 | ||
1113 | if (!I915_HAS_FBC(dev)) | ||
1114 | return; | ||
1115 | |||
1116 | if (!(I915_READ(FBC_CONTROL) & FBC_CTL_EN)) | ||
1117 | return; /* Already off, just return */ | ||
1118 | |||
1119 | /* Disable compression */ | 1124 | /* Disable compression */ |
1120 | fbc_ctl = I915_READ(FBC_CONTROL); | 1125 | fbc_ctl = I915_READ(FBC_CONTROL); |
1126 | if ((fbc_ctl & FBC_CTL_EN) == 0) | ||
1127 | return; | ||
1128 | |||
1121 | fbc_ctl &= ~FBC_CTL_EN; | 1129 | fbc_ctl &= ~FBC_CTL_EN; |
1122 | I915_WRITE(FBC_CONTROL, fbc_ctl); | 1130 | I915_WRITE(FBC_CONTROL, fbc_ctl); |
1123 | 1131 | ||
1124 | /* Wait for compressing bit to clear */ | 1132 | /* Wait for compressing bit to clear */ |
1125 | if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10, 0)) { | 1133 | if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { |
1126 | DRM_DEBUG_KMS("FBC idle timed out\n"); | 1134 | DRM_DEBUG_KMS("FBC idle timed out\n"); |
1127 | return; | 1135 | return; |
1128 | } | 1136 | } |
@@ -1145,14 +1153,27 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1145 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | 1153 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
1146 | struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); | 1154 | struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); |
1147 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1155 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1148 | int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : | 1156 | int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; |
1149 | DPFC_CTL_PLANEB); | ||
1150 | unsigned long stall_watermark = 200; | 1157 | unsigned long stall_watermark = 200; |
1151 | u32 dpfc_ctl; | 1158 | u32 dpfc_ctl; |
1152 | 1159 | ||
1160 | dpfc_ctl = I915_READ(DPFC_CONTROL); | ||
1161 | if (dpfc_ctl & DPFC_CTL_EN) { | ||
1162 | if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 && | ||
1163 | dev_priv->cfb_fence == obj_priv->fence_reg && | ||
1164 | dev_priv->cfb_plane == intel_crtc->plane && | ||
1165 | dev_priv->cfb_y == crtc->y) | ||
1166 | return; | ||
1167 | |||
1168 | I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN); | ||
1169 | POSTING_READ(DPFC_CONTROL); | ||
1170 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
1171 | } | ||
1172 | |||
1153 | dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; | 1173 | dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; |
1154 | dev_priv->cfb_fence = obj_priv->fence_reg; | 1174 | dev_priv->cfb_fence = obj_priv->fence_reg; |
1155 | dev_priv->cfb_plane = intel_crtc->plane; | 1175 | dev_priv->cfb_plane = intel_crtc->plane; |
1176 | dev_priv->cfb_y = crtc->y; | ||
1156 | 1177 | ||
1157 | dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; | 1178 | dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; |
1158 | if (obj_priv->tiling_mode != I915_TILING_NONE) { | 1179 | if (obj_priv->tiling_mode != I915_TILING_NONE) { |
@@ -1162,7 +1183,6 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1162 | I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY); | 1183 | I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY); |
1163 | } | 1184 | } |
1164 | 1185 | ||
1165 | I915_WRITE(DPFC_CONTROL, dpfc_ctl); | ||
1166 | I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | | 1186 | I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | |
1167 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | | 1187 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | |
1168 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); | 1188 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); |
@@ -1181,10 +1201,12 @@ void g4x_disable_fbc(struct drm_device *dev) | |||
1181 | 1201 | ||
1182 | /* Disable compression */ | 1202 | /* Disable compression */ |
1183 | dpfc_ctl = I915_READ(DPFC_CONTROL); | 1203 | dpfc_ctl = I915_READ(DPFC_CONTROL); |
1184 | dpfc_ctl &= ~DPFC_CTL_EN; | 1204 | if (dpfc_ctl & DPFC_CTL_EN) { |
1185 | I915_WRITE(DPFC_CONTROL, dpfc_ctl); | 1205 | dpfc_ctl &= ~DPFC_CTL_EN; |
1206 | I915_WRITE(DPFC_CONTROL, dpfc_ctl); | ||
1186 | 1207 | ||
1187 | DRM_DEBUG_KMS("disabled FBC\n"); | 1208 | DRM_DEBUG_KMS("disabled FBC\n"); |
1209 | } | ||
1188 | } | 1210 | } |
1189 | 1211 | ||
1190 | static bool g4x_fbc_enabled(struct drm_device *dev) | 1212 | static bool g4x_fbc_enabled(struct drm_device *dev) |
@@ -1202,16 +1224,30 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1202 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | 1224 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
1203 | struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); | 1225 | struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); |
1204 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1226 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1205 | int plane = (intel_crtc->plane == 0) ? DPFC_CTL_PLANEA : | 1227 | int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; |
1206 | DPFC_CTL_PLANEB; | ||
1207 | unsigned long stall_watermark = 200; | 1228 | unsigned long stall_watermark = 200; |
1208 | u32 dpfc_ctl; | 1229 | u32 dpfc_ctl; |
1209 | 1230 | ||
1231 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); | ||
1232 | if (dpfc_ctl & DPFC_CTL_EN) { | ||
1233 | if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 && | ||
1234 | dev_priv->cfb_fence == obj_priv->fence_reg && | ||
1235 | dev_priv->cfb_plane == intel_crtc->plane && | ||
1236 | dev_priv->cfb_offset == obj_priv->gtt_offset && | ||
1237 | dev_priv->cfb_y == crtc->y) | ||
1238 | return; | ||
1239 | |||
1240 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN); | ||
1241 | POSTING_READ(ILK_DPFC_CONTROL); | ||
1242 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
1243 | } | ||
1244 | |||
1210 | dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; | 1245 | dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; |
1211 | dev_priv->cfb_fence = obj_priv->fence_reg; | 1246 | dev_priv->cfb_fence = obj_priv->fence_reg; |
1212 | dev_priv->cfb_plane = intel_crtc->plane; | 1247 | dev_priv->cfb_plane = intel_crtc->plane; |
1248 | dev_priv->cfb_offset = obj_priv->gtt_offset; | ||
1249 | dev_priv->cfb_y = crtc->y; | ||
1213 | 1250 | ||
1214 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); | ||
1215 | dpfc_ctl &= DPFC_RESERVED; | 1251 | dpfc_ctl &= DPFC_RESERVED; |
1216 | dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); | 1252 | dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); |
1217 | if (obj_priv->tiling_mode != I915_TILING_NONE) { | 1253 | if (obj_priv->tiling_mode != I915_TILING_NONE) { |
@@ -1221,15 +1257,13 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
1221 | I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY); | 1257 | I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY); |
1222 | } | 1258 | } |
1223 | 1259 | ||
1224 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); | ||
1225 | I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | | 1260 | I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | |
1226 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | | 1261 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | |
1227 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); | 1262 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); |
1228 | I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); | 1263 | I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); |
1229 | I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID); | 1264 | I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID); |
1230 | /* enable it... */ | 1265 | /* enable it... */ |
1231 | I915_WRITE(ILK_DPFC_CONTROL, I915_READ(ILK_DPFC_CONTROL) | | 1266 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); |
1232 | DPFC_CTL_EN); | ||
1233 | 1267 | ||
1234 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); | 1268 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); |
1235 | } | 1269 | } |
@@ -1241,10 +1275,12 @@ void ironlake_disable_fbc(struct drm_device *dev) | |||
1241 | 1275 | ||
1242 | /* Disable compression */ | 1276 | /* Disable compression */ |
1243 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); | 1277 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); |
1244 | dpfc_ctl &= ~DPFC_CTL_EN; | 1278 | if (dpfc_ctl & DPFC_CTL_EN) { |
1245 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); | 1279 | dpfc_ctl &= ~DPFC_CTL_EN; |
1280 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); | ||
1246 | 1281 | ||
1247 | DRM_DEBUG_KMS("disabled FBC\n"); | 1282 | DRM_DEBUG_KMS("disabled FBC\n"); |
1283 | } | ||
1248 | } | 1284 | } |
1249 | 1285 | ||
1250 | static bool ironlake_fbc_enabled(struct drm_device *dev) | 1286 | static bool ironlake_fbc_enabled(struct drm_device *dev) |
@@ -1286,8 +1322,7 @@ void intel_disable_fbc(struct drm_device *dev) | |||
1286 | 1322 | ||
1287 | /** | 1323 | /** |
1288 | * intel_update_fbc - enable/disable FBC as needed | 1324 | * intel_update_fbc - enable/disable FBC as needed |
1289 | * @crtc: CRTC to point the compressor at | 1325 | * @dev: the drm_device |
1290 | * @mode: mode in use | ||
1291 | * | 1326 | * |
1292 | * Set up the framebuffer compression hardware at mode set time. We | 1327 | * Set up the framebuffer compression hardware at mode set time. We |
1293 | * enable it if possible: | 1328 | * enable it if possible: |
@@ -1304,18 +1339,14 @@ void intel_disable_fbc(struct drm_device *dev) | |||
1304 | * | 1339 | * |
1305 | * We need to enable/disable FBC on a global basis. | 1340 | * We need to enable/disable FBC on a global basis. |
1306 | */ | 1341 | */ |
1307 | static void intel_update_fbc(struct drm_crtc *crtc, | 1342 | static void intel_update_fbc(struct drm_device *dev) |
1308 | struct drm_display_mode *mode) | ||
1309 | { | 1343 | { |
1310 | struct drm_device *dev = crtc->dev; | ||
1311 | struct drm_i915_private *dev_priv = dev->dev_private; | 1344 | struct drm_i915_private *dev_priv = dev->dev_private; |
1312 | struct drm_framebuffer *fb = crtc->fb; | 1345 | struct drm_crtc *crtc = NULL, *tmp_crtc; |
1346 | struct intel_crtc *intel_crtc; | ||
1347 | struct drm_framebuffer *fb; | ||
1313 | struct intel_framebuffer *intel_fb; | 1348 | struct intel_framebuffer *intel_fb; |
1314 | struct drm_i915_gem_object *obj_priv; | 1349 | struct drm_i915_gem_object *obj_priv; |
1315 | struct drm_crtc *tmp_crtc; | ||
1316 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
1317 | int plane = intel_crtc->plane; | ||
1318 | int crtcs_enabled = 0; | ||
1319 | 1350 | ||
1320 | DRM_DEBUG_KMS("\n"); | 1351 | DRM_DEBUG_KMS("\n"); |
1321 | 1352 | ||
@@ -1325,12 +1356,6 @@ static void intel_update_fbc(struct drm_crtc *crtc, | |||
1325 | if (!I915_HAS_FBC(dev)) | 1356 | if (!I915_HAS_FBC(dev)) |
1326 | return; | 1357 | return; |
1327 | 1358 | ||
1328 | if (!crtc->fb) | ||
1329 | return; | ||
1330 | |||
1331 | intel_fb = to_intel_framebuffer(fb); | ||
1332 | obj_priv = to_intel_bo(intel_fb->obj); | ||
1333 | |||
1334 | /* | 1359 | /* |
1335 | * If FBC is already on, we just have to verify that we can | 1360 | * If FBC is already on, we just have to verify that we can |
1336 | * keep it that way... | 1361 | * keep it that way... |
@@ -1341,35 +1366,47 @@ static void intel_update_fbc(struct drm_crtc *crtc, | |||
1341 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 1366 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
1342 | */ | 1367 | */ |
1343 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 1368 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
1344 | if (tmp_crtc->enabled) | 1369 | if (tmp_crtc->enabled) { |
1345 | crtcs_enabled++; | 1370 | if (crtc) { |
1371 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | ||
1372 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | ||
1373 | goto out_disable; | ||
1374 | } | ||
1375 | crtc = tmp_crtc; | ||
1376 | } | ||
1346 | } | 1377 | } |
1347 | DRM_DEBUG_KMS("%d pipes active\n", crtcs_enabled); | 1378 | |
1348 | if (crtcs_enabled > 1) { | 1379 | if (!crtc || crtc->fb == NULL) { |
1349 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | 1380 | DRM_DEBUG_KMS("no output, disabling\n"); |
1350 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | 1381 | dev_priv->no_fbc_reason = FBC_NO_OUTPUT; |
1351 | goto out_disable; | 1382 | goto out_disable; |
1352 | } | 1383 | } |
1384 | |||
1385 | intel_crtc = to_intel_crtc(crtc); | ||
1386 | fb = crtc->fb; | ||
1387 | intel_fb = to_intel_framebuffer(fb); | ||
1388 | obj_priv = to_intel_bo(intel_fb->obj); | ||
1389 | |||
1353 | if (intel_fb->obj->size > dev_priv->cfb_size) { | 1390 | if (intel_fb->obj->size > dev_priv->cfb_size) { |
1354 | DRM_DEBUG_KMS("framebuffer too large, disabling " | 1391 | DRM_DEBUG_KMS("framebuffer too large, disabling " |
1355 | "compression\n"); | 1392 | "compression\n"); |
1356 | dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; | 1393 | dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; |
1357 | goto out_disable; | 1394 | goto out_disable; |
1358 | } | 1395 | } |
1359 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || | 1396 | if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || |
1360 | (mode->flags & DRM_MODE_FLAG_DBLSCAN)) { | 1397 | (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { |
1361 | DRM_DEBUG_KMS("mode incompatible with compression, " | 1398 | DRM_DEBUG_KMS("mode incompatible with compression, " |
1362 | "disabling\n"); | 1399 | "disabling\n"); |
1363 | dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; | 1400 | dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; |
1364 | goto out_disable; | 1401 | goto out_disable; |
1365 | } | 1402 | } |
1366 | if ((mode->hdisplay > 2048) || | 1403 | if ((crtc->mode.hdisplay > 2048) || |
1367 | (mode->vdisplay > 1536)) { | 1404 | (crtc->mode.vdisplay > 1536)) { |
1368 | DRM_DEBUG_KMS("mode too large for compression, disabling\n"); | 1405 | DRM_DEBUG_KMS("mode too large for compression, disabling\n"); |
1369 | dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; | 1406 | dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; |
1370 | goto out_disable; | 1407 | goto out_disable; |
1371 | } | 1408 | } |
1372 | if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) { | 1409 | if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) { |
1373 | DRM_DEBUG_KMS("plane not 0, disabling compression\n"); | 1410 | DRM_DEBUG_KMS("plane not 0, disabling compression\n"); |
1374 | dev_priv->no_fbc_reason = FBC_BAD_PLANE; | 1411 | dev_priv->no_fbc_reason = FBC_BAD_PLANE; |
1375 | goto out_disable; | 1412 | goto out_disable; |
@@ -1384,18 +1421,7 @@ static void intel_update_fbc(struct drm_crtc *crtc, | |||
1384 | if (in_dbg_master()) | 1421 | if (in_dbg_master()) |
1385 | goto out_disable; | 1422 | goto out_disable; |
1386 | 1423 | ||
1387 | if (intel_fbc_enabled(dev)) { | 1424 | intel_enable_fbc(crtc, 500); |
1388 | /* We can re-enable it in this case, but need to update pitch */ | ||
1389 | if ((fb->pitch > dev_priv->cfb_pitch) || | ||
1390 | (obj_priv->fence_reg != dev_priv->cfb_fence) || | ||
1391 | (plane != dev_priv->cfb_plane)) | ||
1392 | intel_disable_fbc(dev); | ||
1393 | } | ||
1394 | |||
1395 | /* Now try to turn it back on if possible */ | ||
1396 | if (!intel_fbc_enabled(dev)) | ||
1397 | intel_enable_fbc(crtc, 500); | ||
1398 | |||
1399 | return; | 1425 | return; |
1400 | 1426 | ||
1401 | out_disable: | 1427 | out_disable: |
@@ -1407,7 +1433,9 @@ out_disable: | |||
1407 | } | 1433 | } |
1408 | 1434 | ||
1409 | int | 1435 | int |
1410 | intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) | 1436 | intel_pin_and_fence_fb_obj(struct drm_device *dev, |
1437 | struct drm_gem_object *obj, | ||
1438 | bool pipelined) | ||
1411 | { | 1439 | { |
1412 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1440 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1413 | u32 alignment; | 1441 | u32 alignment; |
@@ -1417,7 +1445,7 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) | |||
1417 | case I915_TILING_NONE: | 1445 | case I915_TILING_NONE: |
1418 | if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) | 1446 | if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) |
1419 | alignment = 128 * 1024; | 1447 | alignment = 128 * 1024; |
1420 | else if (IS_I965G(dev)) | 1448 | else if (INTEL_INFO(dev)->gen >= 4) |
1421 | alignment = 4 * 1024; | 1449 | alignment = 4 * 1024; |
1422 | else | 1450 | else |
1423 | alignment = 64 * 1024; | 1451 | alignment = 64 * 1024; |
@@ -1435,9 +1463,13 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) | |||
1435 | } | 1463 | } |
1436 | 1464 | ||
1437 | ret = i915_gem_object_pin(obj, alignment); | 1465 | ret = i915_gem_object_pin(obj, alignment); |
1438 | if (ret != 0) | 1466 | if (ret) |
1439 | return ret; | 1467 | return ret; |
1440 | 1468 | ||
1469 | ret = i915_gem_object_set_to_display_plane(obj, pipelined); | ||
1470 | if (ret) | ||
1471 | goto err_unpin; | ||
1472 | |||
1441 | /* Install a fence for tiled scan-out. Pre-i965 always needs a | 1473 | /* Install a fence for tiled scan-out. Pre-i965 always needs a |
1442 | * fence, whereas 965+ only requires a fence if using | 1474 | * fence, whereas 965+ only requires a fence if using |
1443 | * framebuffer compression. For simplicity, we always install | 1475 | * framebuffer compression. For simplicity, we always install |
@@ -1445,20 +1477,22 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) | |||
1445 | */ | 1477 | */ |
1446 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE && | 1478 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE && |
1447 | obj_priv->tiling_mode != I915_TILING_NONE) { | 1479 | obj_priv->tiling_mode != I915_TILING_NONE) { |
1448 | ret = i915_gem_object_get_fence_reg(obj); | 1480 | ret = i915_gem_object_get_fence_reg(obj, false); |
1449 | if (ret != 0) { | 1481 | if (ret) |
1450 | i915_gem_object_unpin(obj); | 1482 | goto err_unpin; |
1451 | return ret; | ||
1452 | } | ||
1453 | } | 1483 | } |
1454 | 1484 | ||
1455 | return 0; | 1485 | return 0; |
1486 | |||
1487 | err_unpin: | ||
1488 | i915_gem_object_unpin(obj); | ||
1489 | return ret; | ||
1456 | } | 1490 | } |
1457 | 1491 | ||
1458 | /* Assume fb object is pinned & idle & fenced and just update base pointers */ | 1492 | /* Assume fb object is pinned & idle & fenced and just update base pointers */ |
1459 | static int | 1493 | static int |
1460 | intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 1494 | intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
1461 | int x, int y) | 1495 | int x, int y, int enter) |
1462 | { | 1496 | { |
1463 | struct drm_device *dev = crtc->dev; | 1497 | struct drm_device *dev = crtc->dev; |
1464 | struct drm_i915_private *dev_priv = dev->dev_private; | 1498 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -1468,12 +1502,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
1468 | struct drm_gem_object *obj; | 1502 | struct drm_gem_object *obj; |
1469 | int plane = intel_crtc->plane; | 1503 | int plane = intel_crtc->plane; |
1470 | unsigned long Start, Offset; | 1504 | unsigned long Start, Offset; |
1471 | int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR); | ||
1472 | int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); | ||
1473 | int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
1474 | int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); | ||
1475 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | ||
1476 | u32 dspcntr; | 1505 | u32 dspcntr; |
1506 | u32 reg; | ||
1477 | 1507 | ||
1478 | switch (plane) { | 1508 | switch (plane) { |
1479 | case 0: | 1509 | case 0: |
@@ -1488,7 +1518,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
1488 | obj = intel_fb->obj; | 1518 | obj = intel_fb->obj; |
1489 | obj_priv = to_intel_bo(obj); | 1519 | obj_priv = to_intel_bo(obj); |
1490 | 1520 | ||
1491 | dspcntr = I915_READ(dspcntr_reg); | 1521 | reg = DSPCNTR(plane); |
1522 | dspcntr = I915_READ(reg); | ||
1492 | /* Mask out pixel format bits in case we change it */ | 1523 | /* Mask out pixel format bits in case we change it */ |
1493 | dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; | 1524 | dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; |
1494 | switch (fb->bits_per_pixel) { | 1525 | switch (fb->bits_per_pixel) { |
@@ -1509,7 +1540,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
1509 | DRM_ERROR("Unknown color depth\n"); | 1540 | DRM_ERROR("Unknown color depth\n"); |
1510 | return -EINVAL; | 1541 | return -EINVAL; |
1511 | } | 1542 | } |
1512 | if (IS_I965G(dev)) { | 1543 | if (INTEL_INFO(dev)->gen >= 4) { |
1513 | if (obj_priv->tiling_mode != I915_TILING_NONE) | 1544 | if (obj_priv->tiling_mode != I915_TILING_NONE) |
1514 | dspcntr |= DISPPLANE_TILED; | 1545 | dspcntr |= DISPPLANE_TILED; |
1515 | else | 1546 | else |
@@ -1520,28 +1551,24 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
1520 | /* must disable */ | 1551 | /* must disable */ |
1521 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; | 1552 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; |
1522 | 1553 | ||
1523 | I915_WRITE(dspcntr_reg, dspcntr); | 1554 | I915_WRITE(reg, dspcntr); |
1524 | 1555 | ||
1525 | Start = obj_priv->gtt_offset; | 1556 | Start = obj_priv->gtt_offset; |
1526 | Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); | 1557 | Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); |
1527 | 1558 | ||
1528 | DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", | 1559 | DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", |
1529 | Start, Offset, x, y, fb->pitch); | 1560 | Start, Offset, x, y, fb->pitch); |
1530 | I915_WRITE(dspstride, fb->pitch); | 1561 | I915_WRITE(DSPSTRIDE(plane), fb->pitch); |
1531 | if (IS_I965G(dev)) { | 1562 | if (INTEL_INFO(dev)->gen >= 4) { |
1532 | I915_WRITE(dspsurf, Start); | 1563 | I915_WRITE(DSPSURF(plane), Start); |
1533 | I915_WRITE(dsptileoff, (y << 16) | x); | 1564 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
1534 | I915_WRITE(dspbase, Offset); | 1565 | I915_WRITE(DSPADDR(plane), Offset); |
1535 | } else { | 1566 | } else |
1536 | I915_WRITE(dspbase, Start + Offset); | 1567 | I915_WRITE(DSPADDR(plane), Start + Offset); |
1537 | } | 1568 | POSTING_READ(reg); |
1538 | POSTING_READ(dspbase); | ||
1539 | |||
1540 | if (IS_I965G(dev) || plane == 0) | ||
1541 | intel_update_fbc(crtc, &crtc->mode); | ||
1542 | 1569 | ||
1543 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 1570 | intel_update_fbc(dev); |
1544 | intel_increase_pllclock(crtc, true); | 1571 | intel_increase_pllclock(crtc); |
1545 | 1572 | ||
1546 | return 0; | 1573 | return 0; |
1547 | } | 1574 | } |
@@ -1553,11 +1580,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1553 | struct drm_device *dev = crtc->dev; | 1580 | struct drm_device *dev = crtc->dev; |
1554 | struct drm_i915_master_private *master_priv; | 1581 | struct drm_i915_master_private *master_priv; |
1555 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1582 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1556 | struct intel_framebuffer *intel_fb; | ||
1557 | struct drm_i915_gem_object *obj_priv; | ||
1558 | struct drm_gem_object *obj; | ||
1559 | int pipe = intel_crtc->pipe; | ||
1560 | int plane = intel_crtc->plane; | ||
1561 | int ret; | 1583 | int ret; |
1562 | 1584 | ||
1563 | /* no fb bound */ | 1585 | /* no fb bound */ |
@@ -1566,45 +1588,41 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1566 | return 0; | 1588 | return 0; |
1567 | } | 1589 | } |
1568 | 1590 | ||
1569 | switch (plane) { | 1591 | switch (intel_crtc->plane) { |
1570 | case 0: | 1592 | case 0: |
1571 | case 1: | 1593 | case 1: |
1572 | break; | 1594 | break; |
1573 | default: | 1595 | default: |
1574 | DRM_ERROR("Can't update plane %d in SAREA\n", plane); | ||
1575 | return -EINVAL; | 1596 | return -EINVAL; |
1576 | } | 1597 | } |
1577 | 1598 | ||
1578 | intel_fb = to_intel_framebuffer(crtc->fb); | ||
1579 | obj = intel_fb->obj; | ||
1580 | obj_priv = to_intel_bo(obj); | ||
1581 | |||
1582 | mutex_lock(&dev->struct_mutex); | 1599 | mutex_lock(&dev->struct_mutex); |
1583 | ret = intel_pin_and_fence_fb_obj(dev, obj); | 1600 | ret = intel_pin_and_fence_fb_obj(dev, |
1601 | to_intel_framebuffer(crtc->fb)->obj, | ||
1602 | false); | ||
1584 | if (ret != 0) { | 1603 | if (ret != 0) { |
1585 | mutex_unlock(&dev->struct_mutex); | 1604 | mutex_unlock(&dev->struct_mutex); |
1586 | return ret; | 1605 | return ret; |
1587 | } | 1606 | } |
1588 | 1607 | ||
1589 | ret = i915_gem_object_set_to_display_plane(obj); | 1608 | if (old_fb) { |
1590 | if (ret != 0) { | 1609 | struct drm_i915_private *dev_priv = dev->dev_private; |
1591 | i915_gem_object_unpin(obj); | 1610 | struct drm_gem_object *obj = to_intel_framebuffer(old_fb)->obj; |
1592 | mutex_unlock(&dev->struct_mutex); | 1611 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1593 | return ret; | 1612 | |
1613 | wait_event(dev_priv->pending_flip_queue, | ||
1614 | atomic_read(&obj_priv->pending_flip) == 0); | ||
1594 | } | 1615 | } |
1595 | 1616 | ||
1596 | ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); | 1617 | ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, 0); |
1597 | if (ret) { | 1618 | if (ret) { |
1598 | i915_gem_object_unpin(obj); | 1619 | i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); |
1599 | mutex_unlock(&dev->struct_mutex); | 1620 | mutex_unlock(&dev->struct_mutex); |
1600 | return ret; | 1621 | return ret; |
1601 | } | 1622 | } |
1602 | 1623 | ||
1603 | if (old_fb) { | 1624 | if (old_fb) |
1604 | intel_fb = to_intel_framebuffer(old_fb); | 1625 | i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj); |
1605 | obj_priv = to_intel_bo(intel_fb->obj); | ||
1606 | i915_gem_object_unpin(intel_fb->obj); | ||
1607 | } | ||
1608 | 1626 | ||
1609 | mutex_unlock(&dev->struct_mutex); | 1627 | mutex_unlock(&dev->struct_mutex); |
1610 | 1628 | ||
@@ -1615,7 +1633,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1615 | if (!master_priv->sarea_priv) | 1633 | if (!master_priv->sarea_priv) |
1616 | return 0; | 1634 | return 0; |
1617 | 1635 | ||
1618 | if (pipe) { | 1636 | if (intel_crtc->pipe) { |
1619 | master_priv->sarea_priv->pipeB_x = x; | 1637 | master_priv->sarea_priv->pipeB_x = x; |
1620 | master_priv->sarea_priv->pipeB_y = y; | 1638 | master_priv->sarea_priv->pipeB_y = y; |
1621 | } else { | 1639 | } else { |
@@ -1626,7 +1644,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1626 | return 0; | 1644 | return 0; |
1627 | } | 1645 | } |
1628 | 1646 | ||
1629 | static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) | 1647 | static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) |
1630 | { | 1648 | { |
1631 | struct drm_device *dev = crtc->dev; | 1649 | struct drm_device *dev = crtc->dev; |
1632 | struct drm_i915_private *dev_priv = dev->dev_private; | 1650 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -1659,6 +1677,7 @@ static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) | |||
1659 | } | 1677 | } |
1660 | I915_WRITE(DP_A, dpa_ctl); | 1678 | I915_WRITE(DP_A, dpa_ctl); |
1661 | 1679 | ||
1680 | POSTING_READ(DP_A); | ||
1662 | udelay(500); | 1681 | udelay(500); |
1663 | } | 1682 | } |
1664 | 1683 | ||
@@ -1669,84 +1688,84 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) | |||
1669 | struct drm_i915_private *dev_priv = dev->dev_private; | 1688 | struct drm_i915_private *dev_priv = dev->dev_private; |
1670 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1689 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1671 | int pipe = intel_crtc->pipe; | 1690 | int pipe = intel_crtc->pipe; |
1672 | int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; | 1691 | u32 reg, temp, tries; |
1673 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | ||
1674 | int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR; | ||
1675 | int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR; | ||
1676 | u32 temp, tries = 0; | ||
1677 | 1692 | ||
1678 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit | 1693 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit |
1679 | for train result */ | 1694 | for train result */ |
1680 | temp = I915_READ(fdi_rx_imr_reg); | 1695 | reg = FDI_RX_IMR(pipe); |
1696 | temp = I915_READ(reg); | ||
1681 | temp &= ~FDI_RX_SYMBOL_LOCK; | 1697 | temp &= ~FDI_RX_SYMBOL_LOCK; |
1682 | temp &= ~FDI_RX_BIT_LOCK; | 1698 | temp &= ~FDI_RX_BIT_LOCK; |
1683 | I915_WRITE(fdi_rx_imr_reg, temp); | 1699 | I915_WRITE(reg, temp); |
1684 | I915_READ(fdi_rx_imr_reg); | 1700 | I915_READ(reg); |
1685 | udelay(150); | 1701 | udelay(150); |
1686 | 1702 | ||
1687 | /* enable CPU FDI TX and PCH FDI RX */ | 1703 | /* enable CPU FDI TX and PCH FDI RX */ |
1688 | temp = I915_READ(fdi_tx_reg); | 1704 | reg = FDI_TX_CTL(pipe); |
1689 | temp |= FDI_TX_ENABLE; | 1705 | temp = I915_READ(reg); |
1690 | temp &= ~(7 << 19); | 1706 | temp &= ~(7 << 19); |
1691 | temp |= (intel_crtc->fdi_lanes - 1) << 19; | 1707 | temp |= (intel_crtc->fdi_lanes - 1) << 19; |
1692 | temp &= ~FDI_LINK_TRAIN_NONE; | 1708 | temp &= ~FDI_LINK_TRAIN_NONE; |
1693 | temp |= FDI_LINK_TRAIN_PATTERN_1; | 1709 | temp |= FDI_LINK_TRAIN_PATTERN_1; |
1694 | I915_WRITE(fdi_tx_reg, temp); | 1710 | I915_WRITE(reg, temp | FDI_TX_ENABLE); |
1695 | I915_READ(fdi_tx_reg); | ||
1696 | 1711 | ||
1697 | temp = I915_READ(fdi_rx_reg); | 1712 | reg = FDI_RX_CTL(pipe); |
1713 | temp = I915_READ(reg); | ||
1698 | temp &= ~FDI_LINK_TRAIN_NONE; | 1714 | temp &= ~FDI_LINK_TRAIN_NONE; |
1699 | temp |= FDI_LINK_TRAIN_PATTERN_1; | 1715 | temp |= FDI_LINK_TRAIN_PATTERN_1; |
1700 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); | 1716 | I915_WRITE(reg, temp | FDI_RX_ENABLE); |
1701 | I915_READ(fdi_rx_reg); | 1717 | |
1718 | POSTING_READ(reg); | ||
1702 | udelay(150); | 1719 | udelay(150); |
1703 | 1720 | ||
1721 | reg = FDI_RX_IIR(pipe); | ||
1704 | for (tries = 0; tries < 5; tries++) { | 1722 | for (tries = 0; tries < 5; tries++) { |
1705 | temp = I915_READ(fdi_rx_iir_reg); | 1723 | temp = I915_READ(reg); |
1706 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | 1724 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); |
1707 | 1725 | ||
1708 | if ((temp & FDI_RX_BIT_LOCK)) { | 1726 | if ((temp & FDI_RX_BIT_LOCK)) { |
1709 | DRM_DEBUG_KMS("FDI train 1 done.\n"); | 1727 | DRM_DEBUG_KMS("FDI train 1 done.\n"); |
1710 | I915_WRITE(fdi_rx_iir_reg, | 1728 | I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); |
1711 | temp | FDI_RX_BIT_LOCK); | ||
1712 | break; | 1729 | break; |
1713 | } | 1730 | } |
1714 | } | 1731 | } |
1715 | if (tries == 5) | 1732 | if (tries == 5) |
1716 | DRM_DEBUG_KMS("FDI train 1 fail!\n"); | 1733 | DRM_ERROR("FDI train 1 fail!\n"); |
1717 | 1734 | ||
1718 | /* Train 2 */ | 1735 | /* Train 2 */ |
1719 | temp = I915_READ(fdi_tx_reg); | 1736 | reg = FDI_TX_CTL(pipe); |
1737 | temp = I915_READ(reg); | ||
1720 | temp &= ~FDI_LINK_TRAIN_NONE; | 1738 | temp &= ~FDI_LINK_TRAIN_NONE; |
1721 | temp |= FDI_LINK_TRAIN_PATTERN_2; | 1739 | temp |= FDI_LINK_TRAIN_PATTERN_2; |
1722 | I915_WRITE(fdi_tx_reg, temp); | 1740 | I915_WRITE(reg, temp); |
1723 | 1741 | ||
1724 | temp = I915_READ(fdi_rx_reg); | 1742 | reg = FDI_RX_CTL(pipe); |
1743 | temp = I915_READ(reg); | ||
1725 | temp &= ~FDI_LINK_TRAIN_NONE; | 1744 | temp &= ~FDI_LINK_TRAIN_NONE; |
1726 | temp |= FDI_LINK_TRAIN_PATTERN_2; | 1745 | temp |= FDI_LINK_TRAIN_PATTERN_2; |
1727 | I915_WRITE(fdi_rx_reg, temp); | 1746 | I915_WRITE(reg, temp); |
1728 | udelay(150); | ||
1729 | 1747 | ||
1730 | tries = 0; | 1748 | POSTING_READ(reg); |
1749 | udelay(150); | ||
1731 | 1750 | ||
1751 | reg = FDI_RX_IIR(pipe); | ||
1732 | for (tries = 0; tries < 5; tries++) { | 1752 | for (tries = 0; tries < 5; tries++) { |
1733 | temp = I915_READ(fdi_rx_iir_reg); | 1753 | temp = I915_READ(reg); |
1734 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | 1754 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); |
1735 | 1755 | ||
1736 | if (temp & FDI_RX_SYMBOL_LOCK) { | 1756 | if (temp & FDI_RX_SYMBOL_LOCK) { |
1737 | I915_WRITE(fdi_rx_iir_reg, | 1757 | I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); |
1738 | temp | FDI_RX_SYMBOL_LOCK); | ||
1739 | DRM_DEBUG_KMS("FDI train 2 done.\n"); | 1758 | DRM_DEBUG_KMS("FDI train 2 done.\n"); |
1740 | break; | 1759 | break; |
1741 | } | 1760 | } |
1742 | } | 1761 | } |
1743 | if (tries == 5) | 1762 | if (tries == 5) |
1744 | DRM_DEBUG_KMS("FDI train 2 fail!\n"); | 1763 | DRM_ERROR("FDI train 2 fail!\n"); |
1745 | 1764 | ||
1746 | DRM_DEBUG_KMS("FDI train done\n"); | 1765 | DRM_DEBUG_KMS("FDI train done\n"); |
1747 | } | 1766 | } |
1748 | 1767 | ||
1749 | static int snb_b_fdi_train_param [] = { | 1768 | static const int const snb_b_fdi_train_param [] = { |
1750 | FDI_LINK_TRAIN_400MV_0DB_SNB_B, | 1769 | FDI_LINK_TRAIN_400MV_0DB_SNB_B, |
1751 | FDI_LINK_TRAIN_400MV_6DB_SNB_B, | 1770 | FDI_LINK_TRAIN_400MV_6DB_SNB_B, |
1752 | FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, | 1771 | FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, |
@@ -1760,24 +1779,22 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
1760 | struct drm_i915_private *dev_priv = dev->dev_private; | 1779 | struct drm_i915_private *dev_priv = dev->dev_private; |
1761 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1780 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1762 | int pipe = intel_crtc->pipe; | 1781 | int pipe = intel_crtc->pipe; |
1763 | int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; | 1782 | u32 reg, temp, i; |
1764 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | ||
1765 | int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR; | ||
1766 | int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR; | ||
1767 | u32 temp, i; | ||
1768 | 1783 | ||
1769 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit | 1784 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit |
1770 | for train result */ | 1785 | for train result */ |
1771 | temp = I915_READ(fdi_rx_imr_reg); | 1786 | reg = FDI_RX_IMR(pipe); |
1787 | temp = I915_READ(reg); | ||
1772 | temp &= ~FDI_RX_SYMBOL_LOCK; | 1788 | temp &= ~FDI_RX_SYMBOL_LOCK; |
1773 | temp &= ~FDI_RX_BIT_LOCK; | 1789 | temp &= ~FDI_RX_BIT_LOCK; |
1774 | I915_WRITE(fdi_rx_imr_reg, temp); | 1790 | I915_WRITE(reg, temp); |
1775 | I915_READ(fdi_rx_imr_reg); | 1791 | |
1792 | POSTING_READ(reg); | ||
1776 | udelay(150); | 1793 | udelay(150); |
1777 | 1794 | ||
1778 | /* enable CPU FDI TX and PCH FDI RX */ | 1795 | /* enable CPU FDI TX and PCH FDI RX */ |
1779 | temp = I915_READ(fdi_tx_reg); | 1796 | reg = FDI_TX_CTL(pipe); |
1780 | temp |= FDI_TX_ENABLE; | 1797 | temp = I915_READ(reg); |
1781 | temp &= ~(7 << 19); | 1798 | temp &= ~(7 << 19); |
1782 | temp |= (intel_crtc->fdi_lanes - 1) << 19; | 1799 | temp |= (intel_crtc->fdi_lanes - 1) << 19; |
1783 | temp &= ~FDI_LINK_TRAIN_NONE; | 1800 | temp &= ~FDI_LINK_TRAIN_NONE; |
@@ -1785,10 +1802,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
1785 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 1802 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; |
1786 | /* SNB-B */ | 1803 | /* SNB-B */ |
1787 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; | 1804 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; |
1788 | I915_WRITE(fdi_tx_reg, temp); | 1805 | I915_WRITE(reg, temp | FDI_TX_ENABLE); |
1789 | I915_READ(fdi_tx_reg); | ||
1790 | 1806 | ||
1791 | temp = I915_READ(fdi_rx_reg); | 1807 | reg = FDI_RX_CTL(pipe); |
1808 | temp = I915_READ(reg); | ||
1792 | if (HAS_PCH_CPT(dev)) { | 1809 | if (HAS_PCH_CPT(dev)) { |
1793 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 1810 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; |
1794 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | 1811 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; |
@@ -1796,32 +1813,37 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
1796 | temp &= ~FDI_LINK_TRAIN_NONE; | 1813 | temp &= ~FDI_LINK_TRAIN_NONE; |
1797 | temp |= FDI_LINK_TRAIN_PATTERN_1; | 1814 | temp |= FDI_LINK_TRAIN_PATTERN_1; |
1798 | } | 1815 | } |
1799 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE); | 1816 | I915_WRITE(reg, temp | FDI_RX_ENABLE); |
1800 | I915_READ(fdi_rx_reg); | 1817 | |
1818 | POSTING_READ(reg); | ||
1801 | udelay(150); | 1819 | udelay(150); |
1802 | 1820 | ||
1803 | for (i = 0; i < 4; i++ ) { | 1821 | for (i = 0; i < 4; i++ ) { |
1804 | temp = I915_READ(fdi_tx_reg); | 1822 | reg = FDI_TX_CTL(pipe); |
1823 | temp = I915_READ(reg); | ||
1805 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 1824 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; |
1806 | temp |= snb_b_fdi_train_param[i]; | 1825 | temp |= snb_b_fdi_train_param[i]; |
1807 | I915_WRITE(fdi_tx_reg, temp); | 1826 | I915_WRITE(reg, temp); |
1827 | |||
1828 | POSTING_READ(reg); | ||
1808 | udelay(500); | 1829 | udelay(500); |
1809 | 1830 | ||
1810 | temp = I915_READ(fdi_rx_iir_reg); | 1831 | reg = FDI_RX_IIR(pipe); |
1832 | temp = I915_READ(reg); | ||
1811 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | 1833 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); |
1812 | 1834 | ||
1813 | if (temp & FDI_RX_BIT_LOCK) { | 1835 | if (temp & FDI_RX_BIT_LOCK) { |
1814 | I915_WRITE(fdi_rx_iir_reg, | 1836 | I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); |
1815 | temp | FDI_RX_BIT_LOCK); | ||
1816 | DRM_DEBUG_KMS("FDI train 1 done.\n"); | 1837 | DRM_DEBUG_KMS("FDI train 1 done.\n"); |
1817 | break; | 1838 | break; |
1818 | } | 1839 | } |
1819 | } | 1840 | } |
1820 | if (i == 4) | 1841 | if (i == 4) |
1821 | DRM_DEBUG_KMS("FDI train 1 fail!\n"); | 1842 | DRM_ERROR("FDI train 1 fail!\n"); |
1822 | 1843 | ||
1823 | /* Train 2 */ | 1844 | /* Train 2 */ |
1824 | temp = I915_READ(fdi_tx_reg); | 1845 | reg = FDI_TX_CTL(pipe); |
1846 | temp = I915_READ(reg); | ||
1825 | temp &= ~FDI_LINK_TRAIN_NONE; | 1847 | temp &= ~FDI_LINK_TRAIN_NONE; |
1826 | temp |= FDI_LINK_TRAIN_PATTERN_2; | 1848 | temp |= FDI_LINK_TRAIN_PATTERN_2; |
1827 | if (IS_GEN6(dev)) { | 1849 | if (IS_GEN6(dev)) { |
@@ -1829,9 +1851,10 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
1829 | /* SNB-B */ | 1851 | /* SNB-B */ |
1830 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; | 1852 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; |
1831 | } | 1853 | } |
1832 | I915_WRITE(fdi_tx_reg, temp); | 1854 | I915_WRITE(reg, temp); |
1833 | 1855 | ||
1834 | temp = I915_READ(fdi_rx_reg); | 1856 | reg = FDI_RX_CTL(pipe); |
1857 | temp = I915_READ(reg); | ||
1835 | if (HAS_PCH_CPT(dev)) { | 1858 | if (HAS_PCH_CPT(dev)) { |
1836 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 1859 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; |
1837 | temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; | 1860 | temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; |
@@ -1839,535 +1862,611 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
1839 | temp &= ~FDI_LINK_TRAIN_NONE; | 1862 | temp &= ~FDI_LINK_TRAIN_NONE; |
1840 | temp |= FDI_LINK_TRAIN_PATTERN_2; | 1863 | temp |= FDI_LINK_TRAIN_PATTERN_2; |
1841 | } | 1864 | } |
1842 | I915_WRITE(fdi_rx_reg, temp); | 1865 | I915_WRITE(reg, temp); |
1866 | |||
1867 | POSTING_READ(reg); | ||
1843 | udelay(150); | 1868 | udelay(150); |
1844 | 1869 | ||
1845 | for (i = 0; i < 4; i++ ) { | 1870 | for (i = 0; i < 4; i++ ) { |
1846 | temp = I915_READ(fdi_tx_reg); | 1871 | reg = FDI_TX_CTL(pipe); |
1872 | temp = I915_READ(reg); | ||
1847 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 1873 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; |
1848 | temp |= snb_b_fdi_train_param[i]; | 1874 | temp |= snb_b_fdi_train_param[i]; |
1849 | I915_WRITE(fdi_tx_reg, temp); | 1875 | I915_WRITE(reg, temp); |
1876 | |||
1877 | POSTING_READ(reg); | ||
1850 | udelay(500); | 1878 | udelay(500); |
1851 | 1879 | ||
1852 | temp = I915_READ(fdi_rx_iir_reg); | 1880 | reg = FDI_RX_IIR(pipe); |
1881 | temp = I915_READ(reg); | ||
1853 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | 1882 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); |
1854 | 1883 | ||
1855 | if (temp & FDI_RX_SYMBOL_LOCK) { | 1884 | if (temp & FDI_RX_SYMBOL_LOCK) { |
1856 | I915_WRITE(fdi_rx_iir_reg, | 1885 | I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); |
1857 | temp | FDI_RX_SYMBOL_LOCK); | ||
1858 | DRM_DEBUG_KMS("FDI train 2 done.\n"); | 1886 | DRM_DEBUG_KMS("FDI train 2 done.\n"); |
1859 | break; | 1887 | break; |
1860 | } | 1888 | } |
1861 | } | 1889 | } |
1862 | if (i == 4) | 1890 | if (i == 4) |
1863 | DRM_DEBUG_KMS("FDI train 2 fail!\n"); | 1891 | DRM_ERROR("FDI train 2 fail!\n"); |
1864 | 1892 | ||
1865 | DRM_DEBUG_KMS("FDI train done.\n"); | 1893 | DRM_DEBUG_KMS("FDI train done.\n"); |
1866 | } | 1894 | } |
1867 | 1895 | ||
1868 | static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | 1896 | static void ironlake_fdi_enable(struct drm_crtc *crtc) |
1869 | { | 1897 | { |
1870 | struct drm_device *dev = crtc->dev; | 1898 | struct drm_device *dev = crtc->dev; |
1871 | struct drm_i915_private *dev_priv = dev->dev_private; | 1899 | struct drm_i915_private *dev_priv = dev->dev_private; |
1872 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1900 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1873 | int pipe = intel_crtc->pipe; | 1901 | int pipe = intel_crtc->pipe; |
1874 | int plane = intel_crtc->plane; | 1902 | u32 reg, temp; |
1875 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | ||
1876 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
1877 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | ||
1878 | int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; | ||
1879 | int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; | ||
1880 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | ||
1881 | int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF; | ||
1882 | int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
1883 | int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
1884 | int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
1885 | int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
1886 | int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
1887 | int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
1888 | int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B; | ||
1889 | int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B; | ||
1890 | int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B; | ||
1891 | int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B; | ||
1892 | int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B; | ||
1893 | int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B; | ||
1894 | int trans_dpll_sel = (pipe == 0) ? 0 : 1; | ||
1895 | u32 temp; | ||
1896 | u32 pipe_bpc; | ||
1897 | |||
1898 | temp = I915_READ(pipeconf_reg); | ||
1899 | pipe_bpc = temp & PIPE_BPC_MASK; | ||
1900 | 1903 | ||
1901 | /* XXX: When our outputs are all unaware of DPMS modes other than off | 1904 | /* Write the TU size bits so error detection works */ |
1902 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | 1905 | I915_WRITE(FDI_RX_TUSIZE1(pipe), |
1903 | */ | 1906 | I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); |
1904 | switch (mode) { | ||
1905 | case DRM_MODE_DPMS_ON: | ||
1906 | case DRM_MODE_DPMS_STANDBY: | ||
1907 | case DRM_MODE_DPMS_SUSPEND: | ||
1908 | DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane); | ||
1909 | 1907 | ||
1910 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | 1908 | /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ |
1911 | temp = I915_READ(PCH_LVDS); | 1909 | reg = FDI_RX_CTL(pipe); |
1912 | if ((temp & LVDS_PORT_EN) == 0) { | 1910 | temp = I915_READ(reg); |
1913 | I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); | 1911 | temp &= ~((0x7 << 19) | (0x7 << 16)); |
1914 | POSTING_READ(PCH_LVDS); | 1912 | temp |= (intel_crtc->fdi_lanes - 1) << 19; |
1915 | } | 1913 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; |
1916 | } | 1914 | I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE); |
1917 | 1915 | ||
1918 | if (!HAS_eDP) { | 1916 | POSTING_READ(reg); |
1917 | udelay(200); | ||
1919 | 1918 | ||
1920 | /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ | 1919 | /* Switch from Rawclk to PCDclk */ |
1921 | temp = I915_READ(fdi_rx_reg); | 1920 | temp = I915_READ(reg); |
1922 | /* | 1921 | I915_WRITE(reg, temp | FDI_PCDCLK); |
1923 | * make the BPC in FDI Rx be consistent with that in | ||
1924 | * pipeconf reg. | ||
1925 | */ | ||
1926 | temp &= ~(0x7 << 16); | ||
1927 | temp |= (pipe_bpc << 11); | ||
1928 | temp &= ~(7 << 19); | ||
1929 | temp |= (intel_crtc->fdi_lanes - 1) << 19; | ||
1930 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); | ||
1931 | I915_READ(fdi_rx_reg); | ||
1932 | udelay(200); | ||
1933 | 1922 | ||
1934 | /* Switch from Rawclk to PCDclk */ | 1923 | POSTING_READ(reg); |
1935 | temp = I915_READ(fdi_rx_reg); | 1924 | udelay(200); |
1936 | I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK); | ||
1937 | I915_READ(fdi_rx_reg); | ||
1938 | udelay(200); | ||
1939 | 1925 | ||
1940 | /* Enable CPU FDI TX PLL, always on for Ironlake */ | 1926 | /* Enable CPU FDI TX PLL, always on for Ironlake */ |
1941 | temp = I915_READ(fdi_tx_reg); | 1927 | reg = FDI_TX_CTL(pipe); |
1942 | if ((temp & FDI_TX_PLL_ENABLE) == 0) { | 1928 | temp = I915_READ(reg); |
1943 | I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); | 1929 | if ((temp & FDI_TX_PLL_ENABLE) == 0) { |
1944 | I915_READ(fdi_tx_reg); | 1930 | I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE); |
1945 | udelay(100); | ||
1946 | } | ||
1947 | } | ||
1948 | 1931 | ||
1949 | /* Enable panel fitting for LVDS */ | 1932 | POSTING_READ(reg); |
1950 | if (dev_priv->pch_pf_size && | 1933 | udelay(100); |
1951 | (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) | 1934 | } |
1952 | || HAS_eDP || intel_pch_has_edp(crtc))) { | 1935 | } |
1953 | /* Force use of hard-coded filter coefficients | ||
1954 | * as some pre-programmed values are broken, | ||
1955 | * e.g. x201. | ||
1956 | */ | ||
1957 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, | ||
1958 | PF_ENABLE | PF_FILTER_MED_3x3); | ||
1959 | I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, | ||
1960 | dev_priv->pch_pf_pos); | ||
1961 | I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, | ||
1962 | dev_priv->pch_pf_size); | ||
1963 | } | ||
1964 | 1936 | ||
1965 | /* Enable CPU pipe */ | 1937 | static void intel_flush_display_plane(struct drm_device *dev, |
1966 | temp = I915_READ(pipeconf_reg); | 1938 | int plane) |
1967 | if ((temp & PIPEACONF_ENABLE) == 0) { | 1939 | { |
1968 | I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | 1940 | struct drm_i915_private *dev_priv = dev->dev_private; |
1969 | I915_READ(pipeconf_reg); | 1941 | u32 reg = DSPADDR(plane); |
1970 | udelay(100); | 1942 | I915_WRITE(reg, I915_READ(reg)); |
1971 | } | 1943 | } |
1972 | 1944 | ||
1973 | /* configure and enable CPU plane */ | 1945 | /* |
1974 | temp = I915_READ(dspcntr_reg); | 1946 | * When we disable a pipe, we need to clear any pending scanline wait events |
1975 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | 1947 | * to avoid hanging the ring, which we assume we are waiting on. |
1976 | I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | 1948 | */ |
1977 | /* Flush the plane changes */ | 1949 | static void intel_clear_scanline_wait(struct drm_device *dev) |
1978 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | 1950 | { |
1979 | } | 1951 | struct drm_i915_private *dev_priv = dev->dev_private; |
1952 | u32 tmp; | ||
1980 | 1953 | ||
1981 | if (!HAS_eDP) { | 1954 | if (IS_GEN2(dev)) |
1982 | /* For PCH output, training FDI link */ | 1955 | /* Can't break the hang on i8xx */ |
1983 | if (IS_GEN6(dev)) | 1956 | return; |
1984 | gen6_fdi_link_train(crtc); | ||
1985 | else | ||
1986 | ironlake_fdi_link_train(crtc); | ||
1987 | 1957 | ||
1988 | /* enable PCH DPLL */ | 1958 | tmp = I915_READ(PRB0_CTL); |
1989 | temp = I915_READ(pch_dpll_reg); | 1959 | if (tmp & RING_WAIT) { |
1990 | if ((temp & DPLL_VCO_ENABLE) == 0) { | 1960 | I915_WRITE(PRB0_CTL, tmp); |
1991 | I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE); | 1961 | POSTING_READ(PRB0_CTL); |
1992 | I915_READ(pch_dpll_reg); | 1962 | } |
1993 | } | 1963 | } |
1994 | udelay(200); | ||
1995 | 1964 | ||
1996 | if (HAS_PCH_CPT(dev)) { | 1965 | static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) |
1997 | /* Be sure PCH DPLL SEL is set */ | 1966 | { |
1998 | temp = I915_READ(PCH_DPLL_SEL); | 1967 | struct drm_i915_gem_object *obj_priv; |
1999 | if (trans_dpll_sel == 0 && | 1968 | struct drm_i915_private *dev_priv; |
2000 | (temp & TRANSA_DPLL_ENABLE) == 0) | ||
2001 | temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); | ||
2002 | else if (trans_dpll_sel == 1 && | ||
2003 | (temp & TRANSB_DPLL_ENABLE) == 0) | ||
2004 | temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); | ||
2005 | I915_WRITE(PCH_DPLL_SEL, temp); | ||
2006 | I915_READ(PCH_DPLL_SEL); | ||
2007 | } | ||
2008 | 1969 | ||
2009 | /* set transcoder timing */ | 1970 | if (crtc->fb == NULL) |
2010 | I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg)); | 1971 | return; |
2011 | I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg)); | ||
2012 | I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg)); | ||
2013 | |||
2014 | I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg)); | ||
2015 | I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg)); | ||
2016 | I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg)); | ||
2017 | |||
2018 | /* enable normal train */ | ||
2019 | temp = I915_READ(fdi_tx_reg); | ||
2020 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2021 | I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE | | ||
2022 | FDI_TX_ENHANCE_FRAME_ENABLE); | ||
2023 | I915_READ(fdi_tx_reg); | ||
2024 | |||
2025 | temp = I915_READ(fdi_rx_reg); | ||
2026 | if (HAS_PCH_CPT(dev)) { | ||
2027 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2028 | temp |= FDI_LINK_TRAIN_NORMAL_CPT; | ||
2029 | } else { | ||
2030 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2031 | temp |= FDI_LINK_TRAIN_NONE; | ||
2032 | } | ||
2033 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); | ||
2034 | I915_READ(fdi_rx_reg); | ||
2035 | 1972 | ||
2036 | /* wait one idle pattern time */ | 1973 | obj_priv = to_intel_bo(to_intel_framebuffer(crtc->fb)->obj); |
2037 | udelay(100); | 1974 | dev_priv = crtc->dev->dev_private; |
1975 | wait_event(dev_priv->pending_flip_queue, | ||
1976 | atomic_read(&obj_priv->pending_flip) == 0); | ||
1977 | } | ||
2038 | 1978 | ||
2039 | /* For PCH DP, enable TRANS_DP_CTL */ | 1979 | static void ironlake_crtc_enable(struct drm_crtc *crtc) |
2040 | if (HAS_PCH_CPT(dev) && | 1980 | { |
2041 | intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | 1981 | struct drm_device *dev = crtc->dev; |
2042 | int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; | 1982 | struct drm_i915_private *dev_priv = dev->dev_private; |
2043 | int reg; | 1983 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2044 | 1984 | int pipe = intel_crtc->pipe; | |
2045 | reg = I915_READ(trans_dp_ctl); | 1985 | int plane = intel_crtc->plane; |
2046 | reg &= ~(TRANS_DP_PORT_SEL_MASK | | 1986 | u32 reg, temp; |
2047 | TRANS_DP_SYNC_MASK); | ||
2048 | reg |= (TRANS_DP_OUTPUT_ENABLE | | ||
2049 | TRANS_DP_ENH_FRAMING); | ||
2050 | |||
2051 | if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) | ||
2052 | reg |= TRANS_DP_HSYNC_ACTIVE_HIGH; | ||
2053 | if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) | ||
2054 | reg |= TRANS_DP_VSYNC_ACTIVE_HIGH; | ||
2055 | |||
2056 | switch (intel_trans_dp_port_sel(crtc)) { | ||
2057 | case PCH_DP_B: | ||
2058 | reg |= TRANS_DP_PORT_SEL_B; | ||
2059 | break; | ||
2060 | case PCH_DP_C: | ||
2061 | reg |= TRANS_DP_PORT_SEL_C; | ||
2062 | break; | ||
2063 | case PCH_DP_D: | ||
2064 | reg |= TRANS_DP_PORT_SEL_D; | ||
2065 | break; | ||
2066 | default: | ||
2067 | DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n"); | ||
2068 | reg |= TRANS_DP_PORT_SEL_B; | ||
2069 | break; | ||
2070 | } | ||
2071 | 1987 | ||
2072 | I915_WRITE(trans_dp_ctl, reg); | 1988 | if (intel_crtc->active) |
2073 | POSTING_READ(trans_dp_ctl); | 1989 | return; |
2074 | } | ||
2075 | 1990 | ||
2076 | /* enable PCH transcoder */ | 1991 | intel_crtc->active = true; |
2077 | temp = I915_READ(transconf_reg); | 1992 | intel_update_watermarks(dev); |
2078 | /* | ||
2079 | * make the BPC in transcoder be consistent with | ||
2080 | * that in pipeconf reg. | ||
2081 | */ | ||
2082 | temp &= ~PIPE_BPC_MASK; | ||
2083 | temp |= pipe_bpc; | ||
2084 | I915_WRITE(transconf_reg, temp | TRANS_ENABLE); | ||
2085 | I915_READ(transconf_reg); | ||
2086 | 1993 | ||
2087 | if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1)) | 1994 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { |
2088 | DRM_ERROR("failed to enable transcoder\n"); | 1995 | temp = I915_READ(PCH_LVDS); |
2089 | } | 1996 | if ((temp & LVDS_PORT_EN) == 0) |
1997 | I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); | ||
1998 | } | ||
2090 | 1999 | ||
2091 | intel_crtc_load_lut(crtc); | 2000 | ironlake_fdi_enable(crtc); |
2092 | 2001 | ||
2093 | intel_update_fbc(crtc, &crtc->mode); | 2002 | /* Enable panel fitting for LVDS */ |
2094 | break; | 2003 | if (dev_priv->pch_pf_size && |
2004 | (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) | ||
2005 | || HAS_eDP || intel_pch_has_edp(crtc))) { | ||
2006 | /* Force use of hard-coded filter coefficients | ||
2007 | * as some pre-programmed values are broken, | ||
2008 | * e.g. x201. | ||
2009 | */ | ||
2010 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, | ||
2011 | PF_ENABLE | PF_FILTER_MED_3x3); | ||
2012 | I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, | ||
2013 | dev_priv->pch_pf_pos); | ||
2014 | I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, | ||
2015 | dev_priv->pch_pf_size); | ||
2016 | } | ||
2017 | |||
2018 | /* Enable CPU pipe */ | ||
2019 | reg = PIPECONF(pipe); | ||
2020 | temp = I915_READ(reg); | ||
2021 | if ((temp & PIPECONF_ENABLE) == 0) { | ||
2022 | I915_WRITE(reg, temp | PIPECONF_ENABLE); | ||
2023 | POSTING_READ(reg); | ||
2024 | udelay(100); | ||
2025 | } | ||
2095 | 2026 | ||
2096 | case DRM_MODE_DPMS_OFF: | 2027 | /* configure and enable CPU plane */ |
2097 | DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane); | 2028 | reg = DSPCNTR(plane); |
2029 | temp = I915_READ(reg); | ||
2030 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2031 | I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); | ||
2032 | intel_flush_display_plane(dev, plane); | ||
2033 | } | ||
2034 | |||
2035 | /* For PCH output, training FDI link */ | ||
2036 | if (IS_GEN6(dev)) | ||
2037 | gen6_fdi_link_train(crtc); | ||
2038 | else | ||
2039 | ironlake_fdi_link_train(crtc); | ||
2040 | |||
2041 | /* enable PCH DPLL */ | ||
2042 | reg = PCH_DPLL(pipe); | ||
2043 | temp = I915_READ(reg); | ||
2044 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
2045 | I915_WRITE(reg, temp | DPLL_VCO_ENABLE); | ||
2046 | POSTING_READ(reg); | ||
2047 | udelay(200); | ||
2048 | } | ||
2049 | |||
2050 | if (HAS_PCH_CPT(dev)) { | ||
2051 | /* Be sure PCH DPLL SEL is set */ | ||
2052 | temp = I915_READ(PCH_DPLL_SEL); | ||
2053 | if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0) | ||
2054 | temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); | ||
2055 | else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0) | ||
2056 | temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); | ||
2057 | I915_WRITE(PCH_DPLL_SEL, temp); | ||
2058 | } | ||
2059 | |||
2060 | /* set transcoder timing */ | ||
2061 | I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe))); | ||
2062 | I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe))); | ||
2063 | I915_WRITE(TRANS_HSYNC(pipe), I915_READ(HSYNC(pipe))); | ||
2064 | |||
2065 | I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe))); | ||
2066 | I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe))); | ||
2067 | I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe))); | ||
2098 | 2068 | ||
2099 | drm_vblank_off(dev, pipe); | 2069 | /* enable normal train */ |
2100 | /* Disable display plane */ | 2070 | reg = FDI_TX_CTL(pipe); |
2101 | temp = I915_READ(dspcntr_reg); | 2071 | temp = I915_READ(reg); |
2102 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | 2072 | temp &= ~FDI_LINK_TRAIN_NONE; |
2103 | I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | 2073 | temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; |
2104 | /* Flush the plane changes */ | 2074 | I915_WRITE(reg, temp); |
2105 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | 2075 | |
2106 | I915_READ(dspbase_reg); | 2076 | reg = FDI_RX_CTL(pipe); |
2077 | temp = I915_READ(reg); | ||
2078 | if (HAS_PCH_CPT(dev)) { | ||
2079 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2080 | temp |= FDI_LINK_TRAIN_NORMAL_CPT; | ||
2081 | } else { | ||
2082 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2083 | temp |= FDI_LINK_TRAIN_NONE; | ||
2084 | } | ||
2085 | I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); | ||
2086 | |||
2087 | /* wait one idle pattern time */ | ||
2088 | POSTING_READ(reg); | ||
2089 | udelay(100); | ||
2090 | |||
2091 | /* For PCH DP, enable TRANS_DP_CTL */ | ||
2092 | if (HAS_PCH_CPT(dev) && | ||
2093 | intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
2094 | reg = TRANS_DP_CTL(pipe); | ||
2095 | temp = I915_READ(reg); | ||
2096 | temp &= ~(TRANS_DP_PORT_SEL_MASK | | ||
2097 | TRANS_DP_SYNC_MASK); | ||
2098 | temp |= (TRANS_DP_OUTPUT_ENABLE | | ||
2099 | TRANS_DP_ENH_FRAMING); | ||
2100 | |||
2101 | if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) | ||
2102 | temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; | ||
2103 | if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) | ||
2104 | temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; | ||
2105 | |||
2106 | switch (intel_trans_dp_port_sel(crtc)) { | ||
2107 | case PCH_DP_B: | ||
2108 | temp |= TRANS_DP_PORT_SEL_B; | ||
2109 | break; | ||
2110 | case PCH_DP_C: | ||
2111 | temp |= TRANS_DP_PORT_SEL_C; | ||
2112 | break; | ||
2113 | case PCH_DP_D: | ||
2114 | temp |= TRANS_DP_PORT_SEL_D; | ||
2115 | break; | ||
2116 | default: | ||
2117 | DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n"); | ||
2118 | temp |= TRANS_DP_PORT_SEL_B; | ||
2119 | break; | ||
2107 | } | 2120 | } |
2108 | 2121 | ||
2109 | if (dev_priv->cfb_plane == plane && | 2122 | I915_WRITE(reg, temp); |
2110 | dev_priv->display.disable_fbc) | 2123 | } |
2111 | dev_priv->display.disable_fbc(dev); | ||
2112 | 2124 | ||
2113 | /* disable cpu pipe, disable after all planes disabled */ | 2125 | /* enable PCH transcoder */ |
2114 | temp = I915_READ(pipeconf_reg); | 2126 | reg = TRANSCONF(pipe); |
2115 | if ((temp & PIPEACONF_ENABLE) != 0) { | 2127 | temp = I915_READ(reg); |
2116 | I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | 2128 | /* |
2129 | * make the BPC in transcoder be consistent with | ||
2130 | * that in pipeconf reg. | ||
2131 | */ | ||
2132 | temp &= ~PIPE_BPC_MASK; | ||
2133 | temp |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK; | ||
2134 | I915_WRITE(reg, temp | TRANS_ENABLE); | ||
2135 | if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) | ||
2136 | DRM_ERROR("failed to enable transcoder\n"); | ||
2117 | 2137 | ||
2118 | /* wait for cpu pipe off, pipe state */ | 2138 | intel_crtc_load_lut(crtc); |
2119 | if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, 50, 1)) | 2139 | intel_update_fbc(dev); |
2120 | DRM_ERROR("failed to turn off cpu pipe\n"); | 2140 | intel_crtc_update_cursor(crtc, true); |
2121 | } else | 2141 | } |
2122 | DRM_DEBUG_KMS("crtc %d is disabled\n", pipe); | ||
2123 | 2142 | ||
2124 | udelay(100); | 2143 | static void ironlake_crtc_disable(struct drm_crtc *crtc) |
2144 | { | ||
2145 | struct drm_device *dev = crtc->dev; | ||
2146 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2147 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
2148 | int pipe = intel_crtc->pipe; | ||
2149 | int plane = intel_crtc->plane; | ||
2150 | u32 reg, temp; | ||
2125 | 2151 | ||
2126 | /* Disable PF */ | 2152 | if (!intel_crtc->active) |
2127 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); | 2153 | return; |
2128 | I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); | ||
2129 | 2154 | ||
2130 | /* disable CPU FDI tx and PCH FDI rx */ | 2155 | intel_crtc_wait_for_pending_flips(crtc); |
2131 | temp = I915_READ(fdi_tx_reg); | 2156 | drm_vblank_off(dev, pipe); |
2132 | I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE); | 2157 | intel_crtc_update_cursor(crtc, false); |
2133 | I915_READ(fdi_tx_reg); | ||
2134 | 2158 | ||
2135 | temp = I915_READ(fdi_rx_reg); | 2159 | /* Disable display plane */ |
2136 | /* BPC in FDI rx is consistent with that in pipeconf */ | 2160 | reg = DSPCNTR(plane); |
2137 | temp &= ~(0x07 << 16); | 2161 | temp = I915_READ(reg); |
2138 | temp |= (pipe_bpc << 11); | 2162 | if (temp & DISPLAY_PLANE_ENABLE) { |
2139 | I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); | 2163 | I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); |
2140 | I915_READ(fdi_rx_reg); | 2164 | intel_flush_display_plane(dev, plane); |
2165 | } | ||
2141 | 2166 | ||
2142 | udelay(100); | 2167 | if (dev_priv->cfb_plane == plane && |
2168 | dev_priv->display.disable_fbc) | ||
2169 | dev_priv->display.disable_fbc(dev); | ||
2143 | 2170 | ||
2144 | /* still set train pattern 1 */ | 2171 | /* disable cpu pipe, disable after all planes disabled */ |
2145 | temp = I915_READ(fdi_tx_reg); | 2172 | reg = PIPECONF(pipe); |
2173 | temp = I915_READ(reg); | ||
2174 | if (temp & PIPECONF_ENABLE) { | ||
2175 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | ||
2176 | /* wait for cpu pipe off, pipe state */ | ||
2177 | if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, 50)) | ||
2178 | DRM_ERROR("failed to turn off cpu pipe\n"); | ||
2179 | } | ||
2180 | |||
2181 | /* Disable PF */ | ||
2182 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); | ||
2183 | I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); | ||
2184 | |||
2185 | /* disable CPU FDI tx and PCH FDI rx */ | ||
2186 | reg = FDI_TX_CTL(pipe); | ||
2187 | temp = I915_READ(reg); | ||
2188 | I915_WRITE(reg, temp & ~FDI_TX_ENABLE); | ||
2189 | POSTING_READ(reg); | ||
2190 | |||
2191 | reg = FDI_RX_CTL(pipe); | ||
2192 | temp = I915_READ(reg); | ||
2193 | temp &= ~(0x7 << 16); | ||
2194 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2195 | I915_WRITE(reg, temp & ~FDI_RX_ENABLE); | ||
2196 | |||
2197 | POSTING_READ(reg); | ||
2198 | udelay(100); | ||
2199 | |||
2200 | /* still set train pattern 1 */ | ||
2201 | reg = FDI_TX_CTL(pipe); | ||
2202 | temp = I915_READ(reg); | ||
2203 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2204 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2205 | I915_WRITE(reg, temp); | ||
2206 | |||
2207 | reg = FDI_RX_CTL(pipe); | ||
2208 | temp = I915_READ(reg); | ||
2209 | if (HAS_PCH_CPT(dev)) { | ||
2210 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2211 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
2212 | } else { | ||
2146 | temp &= ~FDI_LINK_TRAIN_NONE; | 2213 | temp &= ~FDI_LINK_TRAIN_NONE; |
2147 | temp |= FDI_LINK_TRAIN_PATTERN_1; | 2214 | temp |= FDI_LINK_TRAIN_PATTERN_1; |
2148 | I915_WRITE(fdi_tx_reg, temp); | 2215 | } |
2149 | POSTING_READ(fdi_tx_reg); | 2216 | /* BPC in FDI rx is consistent with that in PIPECONF */ |
2150 | 2217 | temp &= ~(0x07 << 16); | |
2151 | temp = I915_READ(fdi_rx_reg); | 2218 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; |
2152 | if (HAS_PCH_CPT(dev)) { | 2219 | I915_WRITE(reg, temp); |
2153 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2154 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
2155 | } else { | ||
2156 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2157 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2158 | } | ||
2159 | I915_WRITE(fdi_rx_reg, temp); | ||
2160 | POSTING_READ(fdi_rx_reg); | ||
2161 | 2220 | ||
2162 | udelay(100); | 2221 | POSTING_READ(reg); |
2222 | udelay(100); | ||
2163 | 2223 | ||
2164 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | 2224 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { |
2165 | temp = I915_READ(PCH_LVDS); | 2225 | temp = I915_READ(PCH_LVDS); |
2226 | if (temp & LVDS_PORT_EN) { | ||
2166 | I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); | 2227 | I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); |
2167 | I915_READ(PCH_LVDS); | 2228 | POSTING_READ(PCH_LVDS); |
2168 | udelay(100); | 2229 | udelay(100); |
2169 | } | 2230 | } |
2231 | } | ||
2170 | 2232 | ||
2171 | /* disable PCH transcoder */ | 2233 | /* disable PCH transcoder */ |
2172 | temp = I915_READ(transconf_reg); | 2234 | reg = TRANSCONF(plane); |
2173 | if ((temp & TRANS_ENABLE) != 0) { | 2235 | temp = I915_READ(reg); |
2174 | I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE); | 2236 | if (temp & TRANS_ENABLE) { |
2237 | I915_WRITE(reg, temp & ~TRANS_ENABLE); | ||
2238 | /* wait for PCH transcoder off, transcoder state */ | ||
2239 | if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) | ||
2240 | DRM_ERROR("failed to disable transcoder\n"); | ||
2241 | } | ||
2175 | 2242 | ||
2176 | /* wait for PCH transcoder off, transcoder state */ | 2243 | if (HAS_PCH_CPT(dev)) { |
2177 | if (wait_for((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0, 50, 1)) | 2244 | /* disable TRANS_DP_CTL */ |
2178 | DRM_ERROR("failed to disable transcoder\n"); | 2245 | reg = TRANS_DP_CTL(pipe); |
2179 | } | 2246 | temp = I915_READ(reg); |
2247 | temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); | ||
2248 | I915_WRITE(reg, temp); | ||
2180 | 2249 | ||
2181 | temp = I915_READ(transconf_reg); | 2250 | /* disable DPLL_SEL */ |
2182 | /* BPC in transcoder is consistent with that in pipeconf */ | 2251 | temp = I915_READ(PCH_DPLL_SEL); |
2183 | temp &= ~PIPE_BPC_MASK; | 2252 | if (pipe == 0) |
2184 | temp |= pipe_bpc; | 2253 | temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); |
2185 | I915_WRITE(transconf_reg, temp); | 2254 | else |
2186 | I915_READ(transconf_reg); | 2255 | temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); |
2187 | udelay(100); | 2256 | I915_WRITE(PCH_DPLL_SEL, temp); |
2257 | } | ||
2188 | 2258 | ||
2189 | if (HAS_PCH_CPT(dev)) { | 2259 | /* disable PCH DPLL */ |
2190 | /* disable TRANS_DP_CTL */ | 2260 | reg = PCH_DPLL(pipe); |
2191 | int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B; | 2261 | temp = I915_READ(reg); |
2192 | int reg; | 2262 | I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE); |
2193 | 2263 | ||
2194 | reg = I915_READ(trans_dp_ctl); | 2264 | /* Switch from PCDclk to Rawclk */ |
2195 | reg &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); | 2265 | reg = FDI_RX_CTL(pipe); |
2196 | I915_WRITE(trans_dp_ctl, reg); | 2266 | temp = I915_READ(reg); |
2197 | POSTING_READ(trans_dp_ctl); | 2267 | I915_WRITE(reg, temp & ~FDI_PCDCLK); |
2198 | 2268 | ||
2199 | /* disable DPLL_SEL */ | 2269 | /* Disable CPU FDI TX PLL */ |
2200 | temp = I915_READ(PCH_DPLL_SEL); | 2270 | reg = FDI_TX_CTL(pipe); |
2201 | if (trans_dpll_sel == 0) | 2271 | temp = I915_READ(reg); |
2202 | temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); | 2272 | I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE); |
2203 | else | ||
2204 | temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); | ||
2205 | I915_WRITE(PCH_DPLL_SEL, temp); | ||
2206 | I915_READ(PCH_DPLL_SEL); | ||
2207 | 2273 | ||
2208 | } | 2274 | POSTING_READ(reg); |
2275 | udelay(100); | ||
2209 | 2276 | ||
2210 | /* disable PCH DPLL */ | 2277 | reg = FDI_RX_CTL(pipe); |
2211 | temp = I915_READ(pch_dpll_reg); | 2278 | temp = I915_READ(reg); |
2212 | I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); | 2279 | I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE); |
2213 | I915_READ(pch_dpll_reg); | ||
2214 | |||
2215 | /* Switch from PCDclk to Rawclk */ | ||
2216 | temp = I915_READ(fdi_rx_reg); | ||
2217 | temp &= ~FDI_SEL_PCDCLK; | ||
2218 | I915_WRITE(fdi_rx_reg, temp); | ||
2219 | I915_READ(fdi_rx_reg); | ||
2220 | |||
2221 | /* Disable CPU FDI TX PLL */ | ||
2222 | temp = I915_READ(fdi_tx_reg); | ||
2223 | I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE); | ||
2224 | I915_READ(fdi_tx_reg); | ||
2225 | udelay(100); | ||
2226 | 2280 | ||
2227 | temp = I915_READ(fdi_rx_reg); | 2281 | /* Wait for the clocks to turn off. */ |
2228 | temp &= ~FDI_RX_PLL_ENABLE; | 2282 | POSTING_READ(reg); |
2229 | I915_WRITE(fdi_rx_reg, temp); | 2283 | udelay(100); |
2230 | I915_READ(fdi_rx_reg); | ||
2231 | 2284 | ||
2232 | /* Wait for the clocks to turn off. */ | 2285 | intel_crtc->active = false; |
2233 | udelay(100); | 2286 | intel_update_watermarks(dev); |
2287 | intel_update_fbc(dev); | ||
2288 | intel_clear_scanline_wait(dev); | ||
2289 | } | ||
2290 | |||
2291 | static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
2292 | { | ||
2293 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
2294 | int pipe = intel_crtc->pipe; | ||
2295 | int plane = intel_crtc->plane; | ||
2296 | |||
2297 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
2298 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
2299 | */ | ||
2300 | switch (mode) { | ||
2301 | case DRM_MODE_DPMS_ON: | ||
2302 | case DRM_MODE_DPMS_STANDBY: | ||
2303 | case DRM_MODE_DPMS_SUSPEND: | ||
2304 | DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane); | ||
2305 | ironlake_crtc_enable(crtc); | ||
2306 | break; | ||
2307 | |||
2308 | case DRM_MODE_DPMS_OFF: | ||
2309 | DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane); | ||
2310 | ironlake_crtc_disable(crtc); | ||
2234 | break; | 2311 | break; |
2235 | } | 2312 | } |
2236 | } | 2313 | } |
2237 | 2314 | ||
2238 | static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) | 2315 | static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) |
2239 | { | 2316 | { |
2240 | struct intel_overlay *overlay; | ||
2241 | int ret; | ||
2242 | |||
2243 | if (!enable && intel_crtc->overlay) { | 2317 | if (!enable && intel_crtc->overlay) { |
2244 | overlay = intel_crtc->overlay; | 2318 | struct drm_device *dev = intel_crtc->base.dev; |
2245 | mutex_lock(&overlay->dev->struct_mutex); | ||
2246 | for (;;) { | ||
2247 | ret = intel_overlay_switch_off(overlay); | ||
2248 | if (ret == 0) | ||
2249 | break; | ||
2250 | 2319 | ||
2251 | ret = intel_overlay_recover_from_interrupt(overlay, 0); | 2320 | mutex_lock(&dev->struct_mutex); |
2252 | if (ret != 0) { | 2321 | (void) intel_overlay_switch_off(intel_crtc->overlay, false); |
2253 | /* overlay doesn't react anymore. Usually | 2322 | mutex_unlock(&dev->struct_mutex); |
2254 | * results in a black screen and an unkillable | ||
2255 | * X server. */ | ||
2256 | BUG(); | ||
2257 | overlay->hw_wedged = HW_WEDGED; | ||
2258 | break; | ||
2259 | } | ||
2260 | } | ||
2261 | mutex_unlock(&overlay->dev->struct_mutex); | ||
2262 | } | 2323 | } |
2263 | /* Let userspace switch the overlay on again. In most cases userspace | ||
2264 | * has to recompute where to put it anyway. */ | ||
2265 | 2324 | ||
2266 | return; | 2325 | /* Let userspace switch the overlay on again. In most cases userspace |
2326 | * has to recompute where to put it anyway. | ||
2327 | */ | ||
2267 | } | 2328 | } |
2268 | 2329 | ||
2269 | static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | 2330 | static void i9xx_crtc_enable(struct drm_crtc *crtc) |
2270 | { | 2331 | { |
2271 | struct drm_device *dev = crtc->dev; | 2332 | struct drm_device *dev = crtc->dev; |
2272 | struct drm_i915_private *dev_priv = dev->dev_private; | 2333 | struct drm_i915_private *dev_priv = dev->dev_private; |
2273 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2334 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2274 | int pipe = intel_crtc->pipe; | 2335 | int pipe = intel_crtc->pipe; |
2275 | int plane = intel_crtc->plane; | 2336 | int plane = intel_crtc->plane; |
2276 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | 2337 | u32 reg, temp; |
2277 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | ||
2278 | int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR; | ||
2279 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
2280 | u32 temp; | ||
2281 | 2338 | ||
2282 | /* XXX: When our outputs are all unaware of DPMS modes other than off | 2339 | if (intel_crtc->active) |
2283 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | 2340 | return; |
2284 | */ | ||
2285 | switch (mode) { | ||
2286 | case DRM_MODE_DPMS_ON: | ||
2287 | case DRM_MODE_DPMS_STANDBY: | ||
2288 | case DRM_MODE_DPMS_SUSPEND: | ||
2289 | /* Enable the DPLL */ | ||
2290 | temp = I915_READ(dpll_reg); | ||
2291 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
2292 | I915_WRITE(dpll_reg, temp); | ||
2293 | I915_READ(dpll_reg); | ||
2294 | /* Wait for the clocks to stabilize. */ | ||
2295 | udelay(150); | ||
2296 | I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
2297 | I915_READ(dpll_reg); | ||
2298 | /* Wait for the clocks to stabilize. */ | ||
2299 | udelay(150); | ||
2300 | I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
2301 | I915_READ(dpll_reg); | ||
2302 | /* Wait for the clocks to stabilize. */ | ||
2303 | udelay(150); | ||
2304 | } | ||
2305 | 2341 | ||
2306 | /* Enable the pipe */ | 2342 | intel_crtc->active = true; |
2307 | temp = I915_READ(pipeconf_reg); | 2343 | intel_update_watermarks(dev); |
2308 | if ((temp & PIPEACONF_ENABLE) == 0) | ||
2309 | I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | ||
2310 | |||
2311 | /* Enable the plane */ | ||
2312 | temp = I915_READ(dspcntr_reg); | ||
2313 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2314 | I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | ||
2315 | /* Flush the plane changes */ | ||
2316 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | ||
2317 | } | ||
2318 | 2344 | ||
2319 | intel_crtc_load_lut(crtc); | 2345 | /* Enable the DPLL */ |
2346 | reg = DPLL(pipe); | ||
2347 | temp = I915_READ(reg); | ||
2348 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
2349 | I915_WRITE(reg, temp); | ||
2320 | 2350 | ||
2321 | if ((IS_I965G(dev) || plane == 0)) | 2351 | /* Wait for the clocks to stabilize. */ |
2322 | intel_update_fbc(crtc, &crtc->mode); | 2352 | POSTING_READ(reg); |
2353 | udelay(150); | ||
2323 | 2354 | ||
2324 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | 2355 | I915_WRITE(reg, temp | DPLL_VCO_ENABLE); |
2325 | intel_crtc_dpms_overlay(intel_crtc, true); | 2356 | |
2326 | break; | 2357 | /* Wait for the clocks to stabilize. */ |
2327 | case DRM_MODE_DPMS_OFF: | 2358 | POSTING_READ(reg); |
2328 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | 2359 | udelay(150); |
2329 | intel_crtc_dpms_overlay(intel_crtc, false); | 2360 | |
2330 | drm_vblank_off(dev, pipe); | 2361 | I915_WRITE(reg, temp | DPLL_VCO_ENABLE); |
2331 | 2362 | ||
2332 | if (dev_priv->cfb_plane == plane && | 2363 | /* Wait for the clocks to stabilize. */ |
2333 | dev_priv->display.disable_fbc) | 2364 | POSTING_READ(reg); |
2334 | dev_priv->display.disable_fbc(dev); | 2365 | udelay(150); |
2335 | 2366 | } | |
2336 | /* Disable display plane */ | 2367 | |
2337 | temp = I915_READ(dspcntr_reg); | 2368 | /* Enable the pipe */ |
2338 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | 2369 | reg = PIPECONF(pipe); |
2339 | I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | 2370 | temp = I915_READ(reg); |
2340 | /* Flush the plane changes */ | 2371 | if ((temp & PIPECONF_ENABLE) == 0) |
2341 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | 2372 | I915_WRITE(reg, temp | PIPECONF_ENABLE); |
2342 | I915_READ(dspbase_reg); | 2373 | |
2343 | } | 2374 | /* Enable the plane */ |
2375 | reg = DSPCNTR(plane); | ||
2376 | temp = I915_READ(reg); | ||
2377 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2378 | I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); | ||
2379 | intel_flush_display_plane(dev, plane); | ||
2380 | } | ||
2381 | |||
2382 | intel_crtc_load_lut(crtc); | ||
2383 | intel_update_fbc(dev); | ||
2384 | |||
2385 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | ||
2386 | intel_crtc_dpms_overlay(intel_crtc, true); | ||
2387 | intel_crtc_update_cursor(crtc, true); | ||
2388 | } | ||
2389 | |||
2390 | static void i9xx_crtc_disable(struct drm_crtc *crtc) | ||
2391 | { | ||
2392 | struct drm_device *dev = crtc->dev; | ||
2393 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2394 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
2395 | int pipe = intel_crtc->pipe; | ||
2396 | int plane = intel_crtc->plane; | ||
2397 | u32 reg, temp; | ||
2398 | |||
2399 | if (!intel_crtc->active) | ||
2400 | return; | ||
2401 | |||
2402 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | ||
2403 | intel_crtc_wait_for_pending_flips(crtc); | ||
2404 | drm_vblank_off(dev, pipe); | ||
2405 | intel_crtc_dpms_overlay(intel_crtc, false); | ||
2406 | intel_crtc_update_cursor(crtc, false); | ||
2407 | |||
2408 | if (dev_priv->cfb_plane == plane && | ||
2409 | dev_priv->display.disable_fbc) | ||
2410 | dev_priv->display.disable_fbc(dev); | ||
2411 | |||
2412 | /* Disable display plane */ | ||
2413 | reg = DSPCNTR(plane); | ||
2414 | temp = I915_READ(reg); | ||
2415 | if (temp & DISPLAY_PLANE_ENABLE) { | ||
2416 | I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2417 | /* Flush the plane changes */ | ||
2418 | intel_flush_display_plane(dev, plane); | ||
2344 | 2419 | ||
2345 | /* Don't disable pipe A or pipe A PLLs if needed */ | 2420 | /* Wait for vblank for the disable to take effect */ |
2346 | if (pipeconf_reg == PIPEACONF && | 2421 | if (IS_GEN2(dev)) |
2347 | (dev_priv->quirks & QUIRK_PIPEA_FORCE)) { | ||
2348 | /* Wait for vblank for the disable to take effect */ | ||
2349 | intel_wait_for_vblank(dev, pipe); | 2422 | intel_wait_for_vblank(dev, pipe); |
2350 | goto skip_pipe_off; | 2423 | } |
2351 | } | ||
2352 | 2424 | ||
2353 | /* Next, disable display pipes */ | 2425 | /* Don't disable pipe A or pipe A PLLs if needed */ |
2354 | temp = I915_READ(pipeconf_reg); | 2426 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) |
2355 | if ((temp & PIPEACONF_ENABLE) != 0) { | 2427 | goto done; |
2356 | I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | 2428 | |
2357 | I915_READ(pipeconf_reg); | 2429 | /* Next, disable display pipes */ |
2358 | } | 2430 | reg = PIPECONF(pipe); |
2431 | temp = I915_READ(reg); | ||
2432 | if (temp & PIPECONF_ENABLE) { | ||
2433 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | ||
2359 | 2434 | ||
2360 | /* Wait for the pipe to turn off */ | 2435 | /* Wait for the pipe to turn off */ |
2436 | POSTING_READ(reg); | ||
2361 | intel_wait_for_pipe_off(dev, pipe); | 2437 | intel_wait_for_pipe_off(dev, pipe); |
2438 | } | ||
2439 | |||
2440 | reg = DPLL(pipe); | ||
2441 | temp = I915_READ(reg); | ||
2442 | if (temp & DPLL_VCO_ENABLE) { | ||
2443 | I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE); | ||
2362 | 2444 | ||
2363 | temp = I915_READ(dpll_reg); | ||
2364 | if ((temp & DPLL_VCO_ENABLE) != 0) { | ||
2365 | I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | ||
2366 | I915_READ(dpll_reg); | ||
2367 | } | ||
2368 | skip_pipe_off: | ||
2369 | /* Wait for the clocks to turn off. */ | 2445 | /* Wait for the clocks to turn off. */ |
2446 | POSTING_READ(reg); | ||
2370 | udelay(150); | 2447 | udelay(150); |
2448 | } | ||
2449 | |||
2450 | done: | ||
2451 | intel_crtc->active = false; | ||
2452 | intel_update_fbc(dev); | ||
2453 | intel_update_watermarks(dev); | ||
2454 | intel_clear_scanline_wait(dev); | ||
2455 | } | ||
2456 | |||
2457 | static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
2458 | { | ||
2459 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
2460 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
2461 | */ | ||
2462 | switch (mode) { | ||
2463 | case DRM_MODE_DPMS_ON: | ||
2464 | case DRM_MODE_DPMS_STANDBY: | ||
2465 | case DRM_MODE_DPMS_SUSPEND: | ||
2466 | i9xx_crtc_enable(crtc); | ||
2467 | break; | ||
2468 | case DRM_MODE_DPMS_OFF: | ||
2469 | i9xx_crtc_disable(crtc); | ||
2371 | break; | 2470 | break; |
2372 | } | 2471 | } |
2373 | } | 2472 | } |
@@ -2388,26 +2487,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2388 | return; | 2487 | return; |
2389 | 2488 | ||
2390 | intel_crtc->dpms_mode = mode; | 2489 | intel_crtc->dpms_mode = mode; |
2391 | intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON; | ||
2392 | |||
2393 | /* When switching on the display, ensure that SR is disabled | ||
2394 | * with multiple pipes prior to enabling to new pipe. | ||
2395 | * | ||
2396 | * When switching off the display, make sure the cursor is | ||
2397 | * properly hidden prior to disabling the pipe. | ||
2398 | */ | ||
2399 | if (mode == DRM_MODE_DPMS_ON) | ||
2400 | intel_update_watermarks(dev); | ||
2401 | else | ||
2402 | intel_crtc_update_cursor(crtc); | ||
2403 | 2490 | ||
2404 | dev_priv->display.dpms(crtc, mode); | 2491 | dev_priv->display.dpms(crtc, mode); |
2405 | 2492 | ||
2406 | if (mode == DRM_MODE_DPMS_ON) | ||
2407 | intel_crtc_update_cursor(crtc); | ||
2408 | else | ||
2409 | intel_update_watermarks(dev); | ||
2410 | |||
2411 | if (!dev->primary->master) | 2493 | if (!dev->primary->master) |
2412 | return; | 2494 | return; |
2413 | 2495 | ||
@@ -2432,16 +2514,46 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2432 | } | 2514 | } |
2433 | } | 2515 | } |
2434 | 2516 | ||
2435 | static void intel_crtc_prepare (struct drm_crtc *crtc) | 2517 | static void intel_crtc_disable(struct drm_crtc *crtc) |
2436 | { | 2518 | { |
2437 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | 2519 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
2520 | struct drm_device *dev = crtc->dev; | ||
2521 | |||
2438 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | 2522 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); |
2523 | |||
2524 | if (crtc->fb) { | ||
2525 | mutex_lock(&dev->struct_mutex); | ||
2526 | i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); | ||
2527 | mutex_unlock(&dev->struct_mutex); | ||
2528 | } | ||
2529 | } | ||
2530 | |||
2531 | /* Prepare for a mode set. | ||
2532 | * | ||
2533 | * Note we could be a lot smarter here. We need to figure out which outputs | ||
2534 | * will be enabled, which disabled (in short, how the config will changes) | ||
2535 | * and perform the minimum necessary steps to accomplish that, e.g. updating | ||
2536 | * watermarks, FBC configuration, making sure PLLs are programmed correctly, | ||
2537 | * panel fitting is in the proper state, etc. | ||
2538 | */ | ||
2539 | static void i9xx_crtc_prepare(struct drm_crtc *crtc) | ||
2540 | { | ||
2541 | i9xx_crtc_disable(crtc); | ||
2439 | } | 2542 | } |
2440 | 2543 | ||
2441 | static void intel_crtc_commit (struct drm_crtc *crtc) | 2544 | static void i9xx_crtc_commit(struct drm_crtc *crtc) |
2442 | { | 2545 | { |
2443 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | 2546 | i9xx_crtc_enable(crtc); |
2444 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | 2547 | } |
2548 | |||
2549 | static void ironlake_crtc_prepare(struct drm_crtc *crtc) | ||
2550 | { | ||
2551 | ironlake_crtc_disable(crtc); | ||
2552 | } | ||
2553 | |||
2554 | static void ironlake_crtc_commit(struct drm_crtc *crtc) | ||
2555 | { | ||
2556 | ironlake_crtc_enable(crtc); | ||
2445 | } | 2557 | } |
2446 | 2558 | ||
2447 | void intel_encoder_prepare (struct drm_encoder *encoder) | 2559 | void intel_encoder_prepare (struct drm_encoder *encoder) |
@@ -2460,13 +2572,7 @@ void intel_encoder_commit (struct drm_encoder *encoder) | |||
2460 | 2572 | ||
2461 | void intel_encoder_destroy(struct drm_encoder *encoder) | 2573 | void intel_encoder_destroy(struct drm_encoder *encoder) |
2462 | { | 2574 | { |
2463 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 2575 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); |
2464 | |||
2465 | if (intel_encoder->ddc_bus) | ||
2466 | intel_i2c_destroy(intel_encoder->ddc_bus); | ||
2467 | |||
2468 | if (intel_encoder->i2c_bus) | ||
2469 | intel_i2c_destroy(intel_encoder->i2c_bus); | ||
2470 | 2576 | ||
2471 | drm_encoder_cleanup(encoder); | 2577 | drm_encoder_cleanup(encoder); |
2472 | kfree(intel_encoder); | 2578 | kfree(intel_encoder); |
@@ -2557,33 +2663,6 @@ static int i830_get_display_clock_speed(struct drm_device *dev) | |||
2557 | return 133000; | 2663 | return 133000; |
2558 | } | 2664 | } |
2559 | 2665 | ||
2560 | /** | ||
2561 | * Return the pipe currently connected to the panel fitter, | ||
2562 | * or -1 if the panel fitter is not present or not in use | ||
2563 | */ | ||
2564 | int intel_panel_fitter_pipe (struct drm_device *dev) | ||
2565 | { | ||
2566 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2567 | u32 pfit_control; | ||
2568 | |||
2569 | /* i830 doesn't have a panel fitter */ | ||
2570 | if (IS_I830(dev)) | ||
2571 | return -1; | ||
2572 | |||
2573 | pfit_control = I915_READ(PFIT_CONTROL); | ||
2574 | |||
2575 | /* See if the panel fitter is in use */ | ||
2576 | if ((pfit_control & PFIT_ENABLE) == 0) | ||
2577 | return -1; | ||
2578 | |||
2579 | /* 965 can place panel fitter on either pipe */ | ||
2580 | if (IS_I965G(dev)) | ||
2581 | return (pfit_control >> 29) & 0x3; | ||
2582 | |||
2583 | /* older chips can only use pipe 1 */ | ||
2584 | return 1; | ||
2585 | } | ||
2586 | |||
2587 | struct fdi_m_n { | 2666 | struct fdi_m_n { |
2588 | u32 tu; | 2667 | u32 tu; |
2589 | u32 gmch_m; | 2668 | u32 gmch_m; |
@@ -2902,7 +2981,7 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane) | |||
2902 | size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; | 2981 | size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; |
2903 | 2982 | ||
2904 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | 2983 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
2905 | plane ? "B" : "A", size); | 2984 | plane ? "B" : "A", size); |
2906 | 2985 | ||
2907 | return size; | 2986 | return size; |
2908 | } | 2987 | } |
@@ -2919,7 +2998,7 @@ static int i85x_get_fifo_size(struct drm_device *dev, int plane) | |||
2919 | size >>= 1; /* Convert to cachelines */ | 2998 | size >>= 1; /* Convert to cachelines */ |
2920 | 2999 | ||
2921 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | 3000 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
2922 | plane ? "B" : "A", size); | 3001 | plane ? "B" : "A", size); |
2923 | 3002 | ||
2924 | return size; | 3003 | return size; |
2925 | } | 3004 | } |
@@ -2934,8 +3013,8 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane) | |||
2934 | size >>= 2; /* Convert to cachelines */ | 3013 | size >>= 2; /* Convert to cachelines */ |
2935 | 3014 | ||
2936 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | 3015 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
2937 | plane ? "B" : "A", | 3016 | plane ? "B" : "A", |
2938 | size); | 3017 | size); |
2939 | 3018 | ||
2940 | return size; | 3019 | return size; |
2941 | } | 3020 | } |
@@ -2950,14 +3029,14 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) | |||
2950 | size >>= 1; /* Convert to cachelines */ | 3029 | size >>= 1; /* Convert to cachelines */ |
2951 | 3030 | ||
2952 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | 3031 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
2953 | plane ? "B" : "A", size); | 3032 | plane ? "B" : "A", size); |
2954 | 3033 | ||
2955 | return size; | 3034 | return size; |
2956 | } | 3035 | } |
2957 | 3036 | ||
2958 | static void pineview_update_wm(struct drm_device *dev, int planea_clock, | 3037 | static void pineview_update_wm(struct drm_device *dev, int planea_clock, |
2959 | int planeb_clock, int sr_hdisplay, int unused, | 3038 | int planeb_clock, int sr_hdisplay, int unused, |
2960 | int pixel_size) | 3039 | int pixel_size) |
2961 | { | 3040 | { |
2962 | struct drm_i915_private *dev_priv = dev->dev_private; | 3041 | struct drm_i915_private *dev_priv = dev->dev_private; |
2963 | const struct cxsr_latency *latency; | 3042 | const struct cxsr_latency *latency; |
@@ -3069,13 +3148,13 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, | |||
3069 | 3148 | ||
3070 | /* Use ns/us then divide to preserve precision */ | 3149 | /* Use ns/us then divide to preserve precision */ |
3071 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3150 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3072 | pixel_size * sr_hdisplay; | 3151 | pixel_size * sr_hdisplay; |
3073 | sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); | 3152 | sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); |
3074 | 3153 | ||
3075 | entries_required = (((sr_latency_ns / line_time_us) + | 3154 | entries_required = (((sr_latency_ns / line_time_us) + |
3076 | 1000) / 1000) * pixel_size * 64; | 3155 | 1000) / 1000) * pixel_size * 64; |
3077 | entries_required = DIV_ROUND_UP(entries_required, | 3156 | entries_required = DIV_ROUND_UP(entries_required, |
3078 | g4x_cursor_wm_info.cacheline_size); | 3157 | g4x_cursor_wm_info.cacheline_size); |
3079 | cursor_sr = entries_required + g4x_cursor_wm_info.guard_size; | 3158 | cursor_sr = entries_required + g4x_cursor_wm_info.guard_size; |
3080 | 3159 | ||
3081 | if (cursor_sr > g4x_cursor_wm_info.max_wm) | 3160 | if (cursor_sr > g4x_cursor_wm_info.max_wm) |
@@ -3087,7 +3166,7 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, | |||
3087 | } else { | 3166 | } else { |
3088 | /* Turn off self refresh if both pipes are enabled */ | 3167 | /* Turn off self refresh if both pipes are enabled */ |
3089 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | 3168 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) |
3090 | & ~FW_BLC_SELF_EN); | 3169 | & ~FW_BLC_SELF_EN); |
3091 | } | 3170 | } |
3092 | 3171 | ||
3093 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", | 3172 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", |
@@ -3125,7 +3204,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, | |||
3125 | 3204 | ||
3126 | /* Use ns/us then divide to preserve precision */ | 3205 | /* Use ns/us then divide to preserve precision */ |
3127 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3206 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3128 | pixel_size * sr_hdisplay; | 3207 | pixel_size * sr_hdisplay; |
3129 | sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE); | 3208 | sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE); |
3130 | DRM_DEBUG("self-refresh entries: %d\n", sr_entries); | 3209 | DRM_DEBUG("self-refresh entries: %d\n", sr_entries); |
3131 | srwm = I965_FIFO_SIZE - sr_entries; | 3210 | srwm = I965_FIFO_SIZE - sr_entries; |
@@ -3134,11 +3213,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, | |||
3134 | srwm &= 0x1ff; | 3213 | srwm &= 0x1ff; |
3135 | 3214 | ||
3136 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3215 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3137 | pixel_size * 64; | 3216 | pixel_size * 64; |
3138 | sr_entries = DIV_ROUND_UP(sr_entries, | 3217 | sr_entries = DIV_ROUND_UP(sr_entries, |
3139 | i965_cursor_wm_info.cacheline_size); | 3218 | i965_cursor_wm_info.cacheline_size); |
3140 | cursor_sr = i965_cursor_wm_info.fifo_size - | 3219 | cursor_sr = i965_cursor_wm_info.fifo_size - |
3141 | (sr_entries + i965_cursor_wm_info.guard_size); | 3220 | (sr_entries + i965_cursor_wm_info.guard_size); |
3142 | 3221 | ||
3143 | if (cursor_sr > i965_cursor_wm_info.max_wm) | 3222 | if (cursor_sr > i965_cursor_wm_info.max_wm) |
3144 | cursor_sr = i965_cursor_wm_info.max_wm; | 3223 | cursor_sr = i965_cursor_wm_info.max_wm; |
@@ -3146,11 +3225,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, | |||
3146 | DRM_DEBUG_KMS("self-refresh watermark: display plane %d " | 3225 | DRM_DEBUG_KMS("self-refresh watermark: display plane %d " |
3147 | "cursor %d\n", srwm, cursor_sr); | 3226 | "cursor %d\n", srwm, cursor_sr); |
3148 | 3227 | ||
3149 | if (IS_I965GM(dev)) | 3228 | if (IS_CRESTLINE(dev)) |
3150 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | 3229 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); |
3151 | } else { | 3230 | } else { |
3152 | /* Turn off self refresh if both pipes are enabled */ | 3231 | /* Turn off self refresh if both pipes are enabled */ |
3153 | if (IS_I965GM(dev)) | 3232 | if (IS_CRESTLINE(dev)) |
3154 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | 3233 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) |
3155 | & ~FW_BLC_SELF_EN); | 3234 | & ~FW_BLC_SELF_EN); |
3156 | } | 3235 | } |
@@ -3180,9 +3259,9 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | |||
3180 | int sr_clock, sr_entries = 0; | 3259 | int sr_clock, sr_entries = 0; |
3181 | 3260 | ||
3182 | /* Create copies of the base settings for each pipe */ | 3261 | /* Create copies of the base settings for each pipe */ |
3183 | if (IS_I965GM(dev) || IS_I945GM(dev)) | 3262 | if (IS_CRESTLINE(dev) || IS_I945GM(dev)) |
3184 | planea_params = planeb_params = i945_wm_info; | 3263 | planea_params = planeb_params = i945_wm_info; |
3185 | else if (IS_I9XX(dev)) | 3264 | else if (!IS_GEN2(dev)) |
3186 | planea_params = planeb_params = i915_wm_info; | 3265 | planea_params = planeb_params = i915_wm_info; |
3187 | else | 3266 | else |
3188 | planea_params = planeb_params = i855_wm_info; | 3267 | planea_params = planeb_params = i855_wm_info; |
@@ -3217,7 +3296,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | |||
3217 | 3296 | ||
3218 | /* Use ns/us then divide to preserve precision */ | 3297 | /* Use ns/us then divide to preserve precision */ |
3219 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3298 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3220 | pixel_size * sr_hdisplay; | 3299 | pixel_size * sr_hdisplay; |
3221 | sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); | 3300 | sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); |
3222 | DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); | 3301 | DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); |
3223 | srwm = total_size - sr_entries; | 3302 | srwm = total_size - sr_entries; |
@@ -3242,7 +3321,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | |||
3242 | } | 3321 | } |
3243 | 3322 | ||
3244 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", | 3323 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", |
3245 | planea_wm, planeb_wm, cwm, srwm); | 3324 | planea_wm, planeb_wm, cwm, srwm); |
3246 | 3325 | ||
3247 | fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f); | 3326 | fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f); |
3248 | fwater_hi = (cwm & 0x1f); | 3327 | fwater_hi = (cwm & 0x1f); |
@@ -3276,146 +3355,130 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, | |||
3276 | #define ILK_LP0_PLANE_LATENCY 700 | 3355 | #define ILK_LP0_PLANE_LATENCY 700 |
3277 | #define ILK_LP0_CURSOR_LATENCY 1300 | 3356 | #define ILK_LP0_CURSOR_LATENCY 1300 |
3278 | 3357 | ||
3279 | static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | 3358 | static bool ironlake_compute_wm0(struct drm_device *dev, |
3280 | int planeb_clock, int sr_hdisplay, int sr_htotal, | 3359 | int pipe, |
3281 | int pixel_size) | 3360 | int *plane_wm, |
3361 | int *cursor_wm) | ||
3282 | { | 3362 | { |
3283 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3284 | int planea_wm, planeb_wm, cursora_wm, cursorb_wm; | ||
3285 | int sr_wm, cursor_wm; | ||
3286 | unsigned long line_time_us; | ||
3287 | int sr_clock, entries_required; | ||
3288 | u32 reg_value; | ||
3289 | int line_count; | ||
3290 | int planea_htotal = 0, planeb_htotal = 0; | ||
3291 | struct drm_crtc *crtc; | 3363 | struct drm_crtc *crtc; |
3364 | int htotal, hdisplay, clock, pixel_size = 0; | ||
3365 | int line_time_us, line_count, entries; | ||
3292 | 3366 | ||
3293 | /* Need htotal for all active display plane */ | 3367 | crtc = intel_get_crtc_for_pipe(dev, pipe); |
3294 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 3368 | if (crtc->fb == NULL || !crtc->enabled) |
3295 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 3369 | return false; |
3296 | if (intel_crtc->dpms_mode == DRM_MODE_DPMS_ON) { | ||
3297 | if (intel_crtc->plane == 0) | ||
3298 | planea_htotal = crtc->mode.htotal; | ||
3299 | else | ||
3300 | planeb_htotal = crtc->mode.htotal; | ||
3301 | } | ||
3302 | } | ||
3303 | |||
3304 | /* Calculate and update the watermark for plane A */ | ||
3305 | if (planea_clock) { | ||
3306 | entries_required = ((planea_clock / 1000) * pixel_size * | ||
3307 | ILK_LP0_PLANE_LATENCY) / 1000; | ||
3308 | entries_required = DIV_ROUND_UP(entries_required, | ||
3309 | ironlake_display_wm_info.cacheline_size); | ||
3310 | planea_wm = entries_required + | ||
3311 | ironlake_display_wm_info.guard_size; | ||
3312 | |||
3313 | if (planea_wm > (int)ironlake_display_wm_info.max_wm) | ||
3314 | planea_wm = ironlake_display_wm_info.max_wm; | ||
3315 | |||
3316 | /* Use the large buffer method to calculate cursor watermark */ | ||
3317 | line_time_us = (planea_htotal * 1000) / planea_clock; | ||
3318 | |||
3319 | /* Use ns/us then divide to preserve precision */ | ||
3320 | line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; | ||
3321 | |||
3322 | /* calculate the cursor watermark for cursor A */ | ||
3323 | entries_required = line_count * 64 * pixel_size; | ||
3324 | entries_required = DIV_ROUND_UP(entries_required, | ||
3325 | ironlake_cursor_wm_info.cacheline_size); | ||
3326 | cursora_wm = entries_required + ironlake_cursor_wm_info.guard_size; | ||
3327 | if (cursora_wm > ironlake_cursor_wm_info.max_wm) | ||
3328 | cursora_wm = ironlake_cursor_wm_info.max_wm; | ||
3329 | |||
3330 | reg_value = I915_READ(WM0_PIPEA_ILK); | ||
3331 | reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
3332 | reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) | | ||
3333 | (cursora_wm & WM0_PIPE_CURSOR_MASK); | ||
3334 | I915_WRITE(WM0_PIPEA_ILK, reg_value); | ||
3335 | DRM_DEBUG_KMS("FIFO watermarks For pipe A - plane %d, " | ||
3336 | "cursor: %d\n", planea_wm, cursora_wm); | ||
3337 | } | ||
3338 | /* Calculate and update the watermark for plane B */ | ||
3339 | if (planeb_clock) { | ||
3340 | entries_required = ((planeb_clock / 1000) * pixel_size * | ||
3341 | ILK_LP0_PLANE_LATENCY) / 1000; | ||
3342 | entries_required = DIV_ROUND_UP(entries_required, | ||
3343 | ironlake_display_wm_info.cacheline_size); | ||
3344 | planeb_wm = entries_required + | ||
3345 | ironlake_display_wm_info.guard_size; | ||
3346 | |||
3347 | if (planeb_wm > (int)ironlake_display_wm_info.max_wm) | ||
3348 | planeb_wm = ironlake_display_wm_info.max_wm; | ||
3349 | 3370 | ||
3350 | /* Use the large buffer method to calculate cursor watermark */ | 3371 | htotal = crtc->mode.htotal; |
3351 | line_time_us = (planeb_htotal * 1000) / planeb_clock; | 3372 | hdisplay = crtc->mode.hdisplay; |
3373 | clock = crtc->mode.clock; | ||
3374 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
3375 | |||
3376 | /* Use the small buffer method to calculate plane watermark */ | ||
3377 | entries = ((clock * pixel_size / 1000) * ILK_LP0_PLANE_LATENCY) / 1000; | ||
3378 | entries = DIV_ROUND_UP(entries, | ||
3379 | ironlake_display_wm_info.cacheline_size); | ||
3380 | *plane_wm = entries + ironlake_display_wm_info.guard_size; | ||
3381 | if (*plane_wm > (int)ironlake_display_wm_info.max_wm) | ||
3382 | *plane_wm = ironlake_display_wm_info.max_wm; | ||
3383 | |||
3384 | /* Use the large buffer method to calculate cursor watermark */ | ||
3385 | line_time_us = ((htotal * 1000) / clock); | ||
3386 | line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; | ||
3387 | entries = line_count * 64 * pixel_size; | ||
3388 | entries = DIV_ROUND_UP(entries, | ||
3389 | ironlake_cursor_wm_info.cacheline_size); | ||
3390 | *cursor_wm = entries + ironlake_cursor_wm_info.guard_size; | ||
3391 | if (*cursor_wm > ironlake_cursor_wm_info.max_wm) | ||
3392 | *cursor_wm = ironlake_cursor_wm_info.max_wm; | ||
3352 | 3393 | ||
3353 | /* Use ns/us then divide to preserve precision */ | 3394 | return true; |
3354 | line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; | 3395 | } |
3355 | 3396 | ||
3356 | /* calculate the cursor watermark for cursor B */ | 3397 | static void ironlake_update_wm(struct drm_device *dev, |
3357 | entries_required = line_count * 64 * pixel_size; | 3398 | int planea_clock, int planeb_clock, |
3358 | entries_required = DIV_ROUND_UP(entries_required, | 3399 | int sr_hdisplay, int sr_htotal, |
3359 | ironlake_cursor_wm_info.cacheline_size); | 3400 | int pixel_size) |
3360 | cursorb_wm = entries_required + ironlake_cursor_wm_info.guard_size; | 3401 | { |
3361 | if (cursorb_wm > ironlake_cursor_wm_info.max_wm) | 3402 | struct drm_i915_private *dev_priv = dev->dev_private; |
3362 | cursorb_wm = ironlake_cursor_wm_info.max_wm; | 3403 | int plane_wm, cursor_wm, enabled; |
3404 | int tmp; | ||
3405 | |||
3406 | enabled = 0; | ||
3407 | if (ironlake_compute_wm0(dev, 0, &plane_wm, &cursor_wm)) { | ||
3408 | I915_WRITE(WM0_PIPEA_ILK, | ||
3409 | (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); | ||
3410 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | ||
3411 | " plane %d, " "cursor: %d\n", | ||
3412 | plane_wm, cursor_wm); | ||
3413 | enabled++; | ||
3414 | } | ||
3363 | 3415 | ||
3364 | reg_value = I915_READ(WM0_PIPEB_ILK); | 3416 | if (ironlake_compute_wm0(dev, 1, &plane_wm, &cursor_wm)) { |
3365 | reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | 3417 | I915_WRITE(WM0_PIPEB_ILK, |
3366 | reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) | | 3418 | (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); |
3367 | (cursorb_wm & WM0_PIPE_CURSOR_MASK); | 3419 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" |
3368 | I915_WRITE(WM0_PIPEB_ILK, reg_value); | 3420 | " plane %d, cursor: %d\n", |
3369 | DRM_DEBUG_KMS("FIFO watermarks For pipe B - plane %d, " | 3421 | plane_wm, cursor_wm); |
3370 | "cursor: %d\n", planeb_wm, cursorb_wm); | 3422 | enabled++; |
3371 | } | 3423 | } |
3372 | 3424 | ||
3373 | /* | 3425 | /* |
3374 | * Calculate and update the self-refresh watermark only when one | 3426 | * Calculate and update the self-refresh watermark only when one |
3375 | * display plane is used. | 3427 | * display plane is used. |
3376 | */ | 3428 | */ |
3377 | if (!planea_clock || !planeb_clock) { | 3429 | tmp = 0; |
3378 | 3430 | if (enabled == 1 && /* XXX disabled due to buggy implmentation? */ 0) { | |
3431 | unsigned long line_time_us; | ||
3432 | int small, large, plane_fbc; | ||
3433 | int sr_clock, entries; | ||
3434 | int line_count, line_size; | ||
3379 | /* Read the self-refresh latency. The unit is 0.5us */ | 3435 | /* Read the self-refresh latency. The unit is 0.5us */ |
3380 | int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; | 3436 | int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; |
3381 | 3437 | ||
3382 | sr_clock = planea_clock ? planea_clock : planeb_clock; | 3438 | sr_clock = planea_clock ? planea_clock : planeb_clock; |
3383 | line_time_us = ((sr_htotal * 1000) / sr_clock); | 3439 | line_time_us = (sr_htotal * 1000) / sr_clock; |
3384 | 3440 | ||
3385 | /* Use ns/us then divide to preserve precision */ | 3441 | /* Use ns/us then divide to preserve precision */ |
3386 | line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) | 3442 | line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) |
3387 | / 1000; | 3443 | / 1000; |
3444 | line_size = sr_hdisplay * pixel_size; | ||
3388 | 3445 | ||
3389 | /* calculate the self-refresh watermark for display plane */ | 3446 | /* Use the minimum of the small and large buffer method for primary */ |
3390 | entries_required = line_count * sr_hdisplay * pixel_size; | 3447 | small = ((sr_clock * pixel_size / 1000) * (ilk_sr_latency * 500)) / 1000; |
3391 | entries_required = DIV_ROUND_UP(entries_required, | 3448 | large = line_count * line_size; |
3392 | ironlake_display_srwm_info.cacheline_size); | ||
3393 | sr_wm = entries_required + | ||
3394 | ironlake_display_srwm_info.guard_size; | ||
3395 | 3449 | ||
3396 | /* calculate the self-refresh watermark for display cursor */ | 3450 | entries = DIV_ROUND_UP(min(small, large), |
3397 | entries_required = line_count * pixel_size * 64; | 3451 | ironlake_display_srwm_info.cacheline_size); |
3398 | entries_required = DIV_ROUND_UP(entries_required, | ||
3399 | ironlake_cursor_srwm_info.cacheline_size); | ||
3400 | cursor_wm = entries_required + | ||
3401 | ironlake_cursor_srwm_info.guard_size; | ||
3402 | 3452 | ||
3403 | /* configure watermark and enable self-refresh */ | 3453 | plane_fbc = entries * 64; |
3404 | reg_value = I915_READ(WM1_LP_ILK); | 3454 | plane_fbc = DIV_ROUND_UP(plane_fbc, line_size); |
3405 | reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK | | ||
3406 | WM1_LP_CURSOR_MASK); | ||
3407 | reg_value |= (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | | ||
3408 | (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm; | ||
3409 | 3455 | ||
3410 | I915_WRITE(WM1_LP_ILK, reg_value); | 3456 | plane_wm = entries + ironlake_display_srwm_info.guard_size; |
3411 | DRM_DEBUG_KMS("self-refresh watermark: display plane %d " | 3457 | if (plane_wm > (int)ironlake_display_srwm_info.max_wm) |
3412 | "cursor %d\n", sr_wm, cursor_wm); | 3458 | plane_wm = ironlake_display_srwm_info.max_wm; |
3413 | 3459 | ||
3414 | } else { | 3460 | /* calculate the self-refresh watermark for display cursor */ |
3415 | /* Turn off self refresh if both pipes are enabled */ | 3461 | entries = line_count * pixel_size * 64; |
3416 | I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); | 3462 | entries = DIV_ROUND_UP(entries, |
3417 | } | 3463 | ironlake_cursor_srwm_info.cacheline_size); |
3464 | |||
3465 | cursor_wm = entries + ironlake_cursor_srwm_info.guard_size; | ||
3466 | if (cursor_wm > (int)ironlake_cursor_srwm_info.max_wm) | ||
3467 | cursor_wm = ironlake_cursor_srwm_info.max_wm; | ||
3468 | |||
3469 | /* configure watermark and enable self-refresh */ | ||
3470 | tmp = (WM1_LP_SR_EN | | ||
3471 | (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | | ||
3472 | (plane_fbc << WM1_LP_FBC_SHIFT) | | ||
3473 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
3474 | cursor_wm); | ||
3475 | DRM_DEBUG_KMS("self-refresh watermark: display plane %d, fbc lines %d," | ||
3476 | " cursor %d\n", plane_wm, plane_fbc, cursor_wm); | ||
3477 | } | ||
3478 | I915_WRITE(WM1_LP_ILK, tmp); | ||
3479 | /* XXX setup WM2 and WM3 */ | ||
3418 | } | 3480 | } |
3481 | |||
3419 | /** | 3482 | /** |
3420 | * intel_update_watermarks - update FIFO watermark values based on current modes | 3483 | * intel_update_watermarks - update FIFO watermark values based on current modes |
3421 | * | 3484 | * |
@@ -3447,7 +3510,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | |||
3447 | * | 3510 | * |
3448 | * We don't use the sprite, so we can ignore that. And on Crestline we have | 3511 | * We don't use the sprite, so we can ignore that. And on Crestline we have |
3449 | * to set the non-SR watermarks to 8. | 3512 | * to set the non-SR watermarks to 8. |
3450 | */ | 3513 | */ |
3451 | static void intel_update_watermarks(struct drm_device *dev) | 3514 | static void intel_update_watermarks(struct drm_device *dev) |
3452 | { | 3515 | { |
3453 | struct drm_i915_private *dev_priv = dev->dev_private; | 3516 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -3463,15 +3526,15 @@ static void intel_update_watermarks(struct drm_device *dev) | |||
3463 | /* Get the clock config from both planes */ | 3526 | /* Get the clock config from both planes */ |
3464 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 3527 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
3465 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 3528 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
3466 | if (intel_crtc->dpms_mode == DRM_MODE_DPMS_ON) { | 3529 | if (intel_crtc->active) { |
3467 | enabled++; | 3530 | enabled++; |
3468 | if (intel_crtc->plane == 0) { | 3531 | if (intel_crtc->plane == 0) { |
3469 | DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n", | 3532 | DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n", |
3470 | intel_crtc->pipe, crtc->mode.clock); | 3533 | intel_crtc->pipe, crtc->mode.clock); |
3471 | planea_clock = crtc->mode.clock; | 3534 | planea_clock = crtc->mode.clock; |
3472 | } else { | 3535 | } else { |
3473 | DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n", | 3536 | DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n", |
3474 | intel_crtc->pipe, crtc->mode.clock); | 3537 | intel_crtc->pipe, crtc->mode.clock); |
3475 | planeb_clock = crtc->mode.clock; | 3538 | planeb_clock = crtc->mode.clock; |
3476 | } | 3539 | } |
3477 | sr_hdisplay = crtc->mode.hdisplay; | 3540 | sr_hdisplay = crtc->mode.hdisplay; |
@@ -3502,62 +3565,35 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3502 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 3565 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
3503 | int pipe = intel_crtc->pipe; | 3566 | int pipe = intel_crtc->pipe; |
3504 | int plane = intel_crtc->plane; | 3567 | int plane = intel_crtc->plane; |
3505 | int fp_reg = (pipe == 0) ? FPA0 : FPB0; | 3568 | u32 fp_reg, dpll_reg; |
3506 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
3507 | int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; | ||
3508 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | ||
3509 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
3510 | int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
3511 | int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
3512 | int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
3513 | int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
3514 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
3515 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
3516 | int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE; | ||
3517 | int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS; | ||
3518 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
3519 | int refclk, num_connectors = 0; | 3569 | int refclk, num_connectors = 0; |
3520 | intel_clock_t clock, reduced_clock; | 3570 | intel_clock_t clock, reduced_clock; |
3521 | u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf; | 3571 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; |
3522 | bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; | 3572 | bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; |
3523 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; | 3573 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
3524 | struct intel_encoder *has_edp_encoder = NULL; | 3574 | struct intel_encoder *has_edp_encoder = NULL; |
3525 | struct drm_mode_config *mode_config = &dev->mode_config; | 3575 | struct drm_mode_config *mode_config = &dev->mode_config; |
3526 | struct drm_encoder *encoder; | 3576 | struct intel_encoder *encoder; |
3527 | const intel_limit_t *limit; | 3577 | const intel_limit_t *limit; |
3528 | int ret; | 3578 | int ret; |
3529 | struct fdi_m_n m_n = {0}; | 3579 | struct fdi_m_n m_n = {0}; |
3530 | int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1; | 3580 | u32 reg, temp; |
3531 | int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1; | ||
3532 | int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1; | ||
3533 | int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1; | ||
3534 | int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0; | ||
3535 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | ||
3536 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | ||
3537 | int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; | ||
3538 | int trans_dpll_sel = (pipe == 0) ? 0 : 1; | ||
3539 | int lvds_reg = LVDS; | ||
3540 | u32 temp; | ||
3541 | int sdvo_pixel_multiply; | ||
3542 | int target_clock; | 3581 | int target_clock; |
3543 | 3582 | ||
3544 | drm_vblank_pre_modeset(dev, pipe); | 3583 | drm_vblank_pre_modeset(dev, pipe); |
3545 | 3584 | ||
3546 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | 3585 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { |
3547 | struct intel_encoder *intel_encoder; | 3586 | if (encoder->base.crtc != crtc) |
3548 | |||
3549 | if (encoder->crtc != crtc) | ||
3550 | continue; | 3587 | continue; |
3551 | 3588 | ||
3552 | intel_encoder = enc_to_intel_encoder(encoder); | 3589 | switch (encoder->type) { |
3553 | switch (intel_encoder->type) { | ||
3554 | case INTEL_OUTPUT_LVDS: | 3590 | case INTEL_OUTPUT_LVDS: |
3555 | is_lvds = true; | 3591 | is_lvds = true; |
3556 | break; | 3592 | break; |
3557 | case INTEL_OUTPUT_SDVO: | 3593 | case INTEL_OUTPUT_SDVO: |
3558 | case INTEL_OUTPUT_HDMI: | 3594 | case INTEL_OUTPUT_HDMI: |
3559 | is_sdvo = true; | 3595 | is_sdvo = true; |
3560 | if (intel_encoder->needs_tv_clock) | 3596 | if (encoder->needs_tv_clock) |
3561 | is_tv = true; | 3597 | is_tv = true; |
3562 | break; | 3598 | break; |
3563 | case INTEL_OUTPUT_DVO: | 3599 | case INTEL_OUTPUT_DVO: |
@@ -3573,7 +3609,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3573 | is_dp = true; | 3609 | is_dp = true; |
3574 | break; | 3610 | break; |
3575 | case INTEL_OUTPUT_EDP: | 3611 | case INTEL_OUTPUT_EDP: |
3576 | has_edp_encoder = intel_encoder; | 3612 | has_edp_encoder = encoder; |
3577 | break; | 3613 | break; |
3578 | } | 3614 | } |
3579 | 3615 | ||
@@ -3583,15 +3619,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3583 | if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) { | 3619 | if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) { |
3584 | refclk = dev_priv->lvds_ssc_freq * 1000; | 3620 | refclk = dev_priv->lvds_ssc_freq * 1000; |
3585 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | 3621 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", |
3586 | refclk / 1000); | 3622 | refclk / 1000); |
3587 | } else if (IS_I9XX(dev)) { | 3623 | } else if (!IS_GEN2(dev)) { |
3588 | refclk = 96000; | 3624 | refclk = 96000; |
3589 | if (HAS_PCH_SPLIT(dev)) | 3625 | if (HAS_PCH_SPLIT(dev)) |
3590 | refclk = 120000; /* 120Mhz refclk */ | 3626 | refclk = 120000; /* 120Mhz refclk */ |
3591 | } else { | 3627 | } else { |
3592 | refclk = 48000; | 3628 | refclk = 48000; |
3593 | } | 3629 | } |
3594 | |||
3595 | 3630 | ||
3596 | /* | 3631 | /* |
3597 | * Returns a set of divisors for the desired target clock with the given | 3632 | * Returns a set of divisors for the desired target clock with the given |
@@ -3607,13 +3642,13 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3607 | } | 3642 | } |
3608 | 3643 | ||
3609 | /* Ensure that the cursor is valid for the new mode before changing... */ | 3644 | /* Ensure that the cursor is valid for the new mode before changing... */ |
3610 | intel_crtc_update_cursor(crtc); | 3645 | intel_crtc_update_cursor(crtc, true); |
3611 | 3646 | ||
3612 | if (is_lvds && dev_priv->lvds_downclock_avail) { | 3647 | if (is_lvds && dev_priv->lvds_downclock_avail) { |
3613 | has_reduced_clock = limit->find_pll(limit, crtc, | 3648 | has_reduced_clock = limit->find_pll(limit, crtc, |
3614 | dev_priv->lvds_downclock, | 3649 | dev_priv->lvds_downclock, |
3615 | refclk, | 3650 | refclk, |
3616 | &reduced_clock); | 3651 | &reduced_clock); |
3617 | if (has_reduced_clock && (clock.p != reduced_clock.p)) { | 3652 | if (has_reduced_clock && (clock.p != reduced_clock.p)) { |
3618 | /* | 3653 | /* |
3619 | * If the different P is found, it means that we can't | 3654 | * If the different P is found, it means that we can't |
@@ -3622,7 +3657,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3622 | * feature. | 3657 | * feature. |
3623 | */ | 3658 | */ |
3624 | DRM_DEBUG_KMS("Different P is found for " | 3659 | DRM_DEBUG_KMS("Different P is found for " |
3625 | "LVDS clock/downclock\n"); | 3660 | "LVDS clock/downclock\n"); |
3626 | has_reduced_clock = 0; | 3661 | has_reduced_clock = 0; |
3627 | } | 3662 | } |
3628 | } | 3663 | } |
@@ -3630,14 +3665,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3630 | this mirrors vbios setting. */ | 3665 | this mirrors vbios setting. */ |
3631 | if (is_sdvo && is_tv) { | 3666 | if (is_sdvo && is_tv) { |
3632 | if (adjusted_mode->clock >= 100000 | 3667 | if (adjusted_mode->clock >= 100000 |
3633 | && adjusted_mode->clock < 140500) { | 3668 | && adjusted_mode->clock < 140500) { |
3634 | clock.p1 = 2; | 3669 | clock.p1 = 2; |
3635 | clock.p2 = 10; | 3670 | clock.p2 = 10; |
3636 | clock.n = 3; | 3671 | clock.n = 3; |
3637 | clock.m1 = 16; | 3672 | clock.m1 = 16; |
3638 | clock.m2 = 8; | 3673 | clock.m2 = 8; |
3639 | } else if (adjusted_mode->clock >= 140500 | 3674 | } else if (adjusted_mode->clock >= 140500 |
3640 | && adjusted_mode->clock <= 200000) { | 3675 | && adjusted_mode->clock <= 200000) { |
3641 | clock.p1 = 1; | 3676 | clock.p1 = 1; |
3642 | clock.p2 = 10; | 3677 | clock.p2 = 10; |
3643 | clock.n = 6; | 3678 | clock.n = 6; |
@@ -3662,21 +3697,28 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3662 | target_clock = mode->clock; | 3697 | target_clock = mode->clock; |
3663 | else | 3698 | else |
3664 | target_clock = adjusted_mode->clock; | 3699 | target_clock = adjusted_mode->clock; |
3665 | link_bw = 270000; | 3700 | |
3701 | /* FDI is a binary signal running at ~2.7GHz, encoding | ||
3702 | * each output octet as 10 bits. The actual frequency | ||
3703 | * is stored as a divider into a 100MHz clock, and the | ||
3704 | * mode pixel clock is stored in units of 1KHz. | ||
3705 | * Hence the bw of each lane in terms of the mode signal | ||
3706 | * is: | ||
3707 | */ | ||
3708 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; | ||
3666 | } | 3709 | } |
3667 | 3710 | ||
3668 | /* determine panel color depth */ | 3711 | /* determine panel color depth */ |
3669 | temp = I915_READ(pipeconf_reg); | 3712 | temp = I915_READ(PIPECONF(pipe)); |
3670 | temp &= ~PIPE_BPC_MASK; | 3713 | temp &= ~PIPE_BPC_MASK; |
3671 | if (is_lvds) { | 3714 | if (is_lvds) { |
3672 | int lvds_reg = I915_READ(PCH_LVDS); | ||
3673 | /* the BPC will be 6 if it is 18-bit LVDS panel */ | 3715 | /* the BPC will be 6 if it is 18-bit LVDS panel */ |
3674 | if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) | 3716 | if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) |
3675 | temp |= PIPE_8BPC; | 3717 | temp |= PIPE_8BPC; |
3676 | else | 3718 | else |
3677 | temp |= PIPE_6BPC; | 3719 | temp |= PIPE_6BPC; |
3678 | } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) { | 3720 | } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) { |
3679 | switch (dev_priv->edp_bpp/3) { | 3721 | switch (dev_priv->edp.bpp/3) { |
3680 | case 8: | 3722 | case 8: |
3681 | temp |= PIPE_8BPC; | 3723 | temp |= PIPE_8BPC; |
3682 | break; | 3724 | break; |
@@ -3692,8 +3734,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3692 | } | 3734 | } |
3693 | } else | 3735 | } else |
3694 | temp |= PIPE_8BPC; | 3736 | temp |= PIPE_8BPC; |
3695 | I915_WRITE(pipeconf_reg, temp); | 3737 | I915_WRITE(PIPECONF(pipe), temp); |
3696 | I915_READ(pipeconf_reg); | ||
3697 | 3738 | ||
3698 | switch (temp & PIPE_BPC_MASK) { | 3739 | switch (temp & PIPE_BPC_MASK) { |
3699 | case PIPE_8BPC: | 3740 | case PIPE_8BPC: |
@@ -3738,33 +3779,27 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3738 | /* Always enable nonspread source */ | 3779 | /* Always enable nonspread source */ |
3739 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; | 3780 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; |
3740 | temp |= DREF_NONSPREAD_SOURCE_ENABLE; | 3781 | temp |= DREF_NONSPREAD_SOURCE_ENABLE; |
3741 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
3742 | POSTING_READ(PCH_DREF_CONTROL); | ||
3743 | |||
3744 | temp &= ~DREF_SSC_SOURCE_MASK; | 3782 | temp &= ~DREF_SSC_SOURCE_MASK; |
3745 | temp |= DREF_SSC_SOURCE_ENABLE; | 3783 | temp |= DREF_SSC_SOURCE_ENABLE; |
3746 | I915_WRITE(PCH_DREF_CONTROL, temp); | 3784 | I915_WRITE(PCH_DREF_CONTROL, temp); |
3747 | POSTING_READ(PCH_DREF_CONTROL); | ||
3748 | 3785 | ||
3786 | POSTING_READ(PCH_DREF_CONTROL); | ||
3749 | udelay(200); | 3787 | udelay(200); |
3750 | 3788 | ||
3751 | if (has_edp_encoder) { | 3789 | if (has_edp_encoder) { |
3752 | if (dev_priv->lvds_use_ssc) { | 3790 | if (dev_priv->lvds_use_ssc) { |
3753 | temp |= DREF_SSC1_ENABLE; | 3791 | temp |= DREF_SSC1_ENABLE; |
3754 | I915_WRITE(PCH_DREF_CONTROL, temp); | 3792 | I915_WRITE(PCH_DREF_CONTROL, temp); |
3755 | POSTING_READ(PCH_DREF_CONTROL); | ||
3756 | 3793 | ||
3794 | POSTING_READ(PCH_DREF_CONTROL); | ||
3757 | udelay(200); | 3795 | udelay(200); |
3758 | 3796 | ||
3759 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | 3797 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; |
3760 | temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; | 3798 | temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; |
3761 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
3762 | POSTING_READ(PCH_DREF_CONTROL); | ||
3763 | } else { | 3799 | } else { |
3764 | temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; | 3800 | temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; |
3765 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
3766 | POSTING_READ(PCH_DREF_CONTROL); | ||
3767 | } | 3801 | } |
3802 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
3768 | } | 3803 | } |
3769 | } | 3804 | } |
3770 | 3805 | ||
@@ -3780,21 +3815,24 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3780 | reduced_clock.m2; | 3815 | reduced_clock.m2; |
3781 | } | 3816 | } |
3782 | 3817 | ||
3818 | dpll = 0; | ||
3783 | if (!HAS_PCH_SPLIT(dev)) | 3819 | if (!HAS_PCH_SPLIT(dev)) |
3784 | dpll = DPLL_VGA_MODE_DIS; | 3820 | dpll = DPLL_VGA_MODE_DIS; |
3785 | 3821 | ||
3786 | if (IS_I9XX(dev)) { | 3822 | if (!IS_GEN2(dev)) { |
3787 | if (is_lvds) | 3823 | if (is_lvds) |
3788 | dpll |= DPLLB_MODE_LVDS; | 3824 | dpll |= DPLLB_MODE_LVDS; |
3789 | else | 3825 | else |
3790 | dpll |= DPLLB_MODE_DAC_SERIAL; | 3826 | dpll |= DPLLB_MODE_DAC_SERIAL; |
3791 | if (is_sdvo) { | 3827 | if (is_sdvo) { |
3828 | int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
3829 | if (pixel_multiplier > 1) { | ||
3830 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | ||
3831 | dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
3832 | else if (HAS_PCH_SPLIT(dev)) | ||
3833 | dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | ||
3834 | } | ||
3792 | dpll |= DPLL_DVO_HIGH_SPEED; | 3835 | dpll |= DPLL_DVO_HIGH_SPEED; |
3793 | sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | ||
3794 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | ||
3795 | dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
3796 | else if (HAS_PCH_SPLIT(dev)) | ||
3797 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | ||
3798 | } | 3836 | } |
3799 | if (is_dp) | 3837 | if (is_dp) |
3800 | dpll |= DPLL_DVO_HIGH_SPEED; | 3838 | dpll |= DPLL_DVO_HIGH_SPEED; |
@@ -3824,7 +3862,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3824 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; | 3862 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; |
3825 | break; | 3863 | break; |
3826 | } | 3864 | } |
3827 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) | 3865 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) |
3828 | dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); | 3866 | dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); |
3829 | } else { | 3867 | } else { |
3830 | if (is_lvds) { | 3868 | if (is_lvds) { |
@@ -3851,7 +3889,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3851 | dpll |= PLL_REF_INPUT_DREFCLK; | 3889 | dpll |= PLL_REF_INPUT_DREFCLK; |
3852 | 3890 | ||
3853 | /* setup pipeconf */ | 3891 | /* setup pipeconf */ |
3854 | pipeconf = I915_READ(pipeconf_reg); | 3892 | pipeconf = I915_READ(PIPECONF(pipe)); |
3855 | 3893 | ||
3856 | /* Set up the display plane register */ | 3894 | /* Set up the display plane register */ |
3857 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 3895 | dspcntr = DISPPLANE_GAMMA_ENABLE; |
@@ -3865,7 +3903,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3865 | dspcntr |= DISPPLANE_SEL_PIPE_B; | 3903 | dspcntr |= DISPPLANE_SEL_PIPE_B; |
3866 | } | 3904 | } |
3867 | 3905 | ||
3868 | if (pipe == 0 && !IS_I965G(dev)) { | 3906 | if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { |
3869 | /* Enable pixel doubling when the dot clock is > 90% of the (display) | 3907 | /* Enable pixel doubling when the dot clock is > 90% of the (display) |
3870 | * core speed. | 3908 | * core speed. |
3871 | * | 3909 | * |
@@ -3874,51 +3912,46 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3874 | */ | 3912 | */ |
3875 | if (mode->clock > | 3913 | if (mode->clock > |
3876 | dev_priv->display.get_display_clock_speed(dev) * 9 / 10) | 3914 | dev_priv->display.get_display_clock_speed(dev) * 9 / 10) |
3877 | pipeconf |= PIPEACONF_DOUBLE_WIDE; | 3915 | pipeconf |= PIPECONF_DOUBLE_WIDE; |
3878 | else | 3916 | else |
3879 | pipeconf &= ~PIPEACONF_DOUBLE_WIDE; | 3917 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; |
3880 | } | 3918 | } |
3881 | 3919 | ||
3882 | dspcntr |= DISPLAY_PLANE_ENABLE; | 3920 | dspcntr |= DISPLAY_PLANE_ENABLE; |
3883 | pipeconf |= PIPEACONF_ENABLE; | 3921 | pipeconf |= PIPECONF_ENABLE; |
3884 | dpll |= DPLL_VCO_ENABLE; | 3922 | dpll |= DPLL_VCO_ENABLE; |
3885 | 3923 | ||
3886 | |||
3887 | /* Disable the panel fitter if it was on our pipe */ | ||
3888 | if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe) | ||
3889 | I915_WRITE(PFIT_CONTROL, 0); | ||
3890 | |||
3891 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | 3924 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); |
3892 | drm_mode_debug_printmodeline(mode); | 3925 | drm_mode_debug_printmodeline(mode); |
3893 | 3926 | ||
3894 | /* assign to Ironlake registers */ | 3927 | /* assign to Ironlake registers */ |
3895 | if (HAS_PCH_SPLIT(dev)) { | 3928 | if (HAS_PCH_SPLIT(dev)) { |
3896 | fp_reg = pch_fp_reg; | 3929 | fp_reg = PCH_FP0(pipe); |
3897 | dpll_reg = pch_dpll_reg; | 3930 | dpll_reg = PCH_DPLL(pipe); |
3931 | } else { | ||
3932 | fp_reg = FP0(pipe); | ||
3933 | dpll_reg = DPLL(pipe); | ||
3898 | } | 3934 | } |
3899 | 3935 | ||
3900 | if (!has_edp_encoder) { | 3936 | if (!has_edp_encoder) { |
3901 | I915_WRITE(fp_reg, fp); | 3937 | I915_WRITE(fp_reg, fp); |
3902 | I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); | 3938 | I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); |
3903 | I915_READ(dpll_reg); | 3939 | |
3940 | POSTING_READ(dpll_reg); | ||
3904 | udelay(150); | 3941 | udelay(150); |
3905 | } | 3942 | } |
3906 | 3943 | ||
3907 | /* enable transcoder DPLL */ | 3944 | /* enable transcoder DPLL */ |
3908 | if (HAS_PCH_CPT(dev)) { | 3945 | if (HAS_PCH_CPT(dev)) { |
3909 | temp = I915_READ(PCH_DPLL_SEL); | 3946 | temp = I915_READ(PCH_DPLL_SEL); |
3910 | if (trans_dpll_sel == 0) | 3947 | if (pipe == 0) |
3911 | temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); | 3948 | temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; |
3912 | else | 3949 | else |
3913 | temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); | 3950 | temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; |
3914 | I915_WRITE(PCH_DPLL_SEL, temp); | 3951 | I915_WRITE(PCH_DPLL_SEL, temp); |
3915 | I915_READ(PCH_DPLL_SEL); | ||
3916 | udelay(150); | ||
3917 | } | ||
3918 | 3952 | ||
3919 | if (HAS_PCH_SPLIT(dev)) { | 3953 | POSTING_READ(PCH_DPLL_SEL); |
3920 | pipeconf &= ~PIPE_ENABLE_DITHER; | 3954 | udelay(150); |
3921 | pipeconf &= ~PIPE_DITHER_TYPE_MASK; | ||
3922 | } | 3955 | } |
3923 | 3956 | ||
3924 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. | 3957 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. |
@@ -3926,55 +3959,57 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3926 | * things on. | 3959 | * things on. |
3927 | */ | 3960 | */ |
3928 | if (is_lvds) { | 3961 | if (is_lvds) { |
3929 | u32 lvds; | 3962 | reg = LVDS; |
3930 | |||
3931 | if (HAS_PCH_SPLIT(dev)) | 3963 | if (HAS_PCH_SPLIT(dev)) |
3932 | lvds_reg = PCH_LVDS; | 3964 | reg = PCH_LVDS; |
3933 | 3965 | ||
3934 | lvds = I915_READ(lvds_reg); | 3966 | temp = I915_READ(reg); |
3935 | lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; | 3967 | temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; |
3936 | if (pipe == 1) { | 3968 | if (pipe == 1) { |
3937 | if (HAS_PCH_CPT(dev)) | 3969 | if (HAS_PCH_CPT(dev)) |
3938 | lvds |= PORT_TRANS_B_SEL_CPT; | 3970 | temp |= PORT_TRANS_B_SEL_CPT; |
3939 | else | 3971 | else |
3940 | lvds |= LVDS_PIPEB_SELECT; | 3972 | temp |= LVDS_PIPEB_SELECT; |
3941 | } else { | 3973 | } else { |
3942 | if (HAS_PCH_CPT(dev)) | 3974 | if (HAS_PCH_CPT(dev)) |
3943 | lvds &= ~PORT_TRANS_SEL_MASK; | 3975 | temp &= ~PORT_TRANS_SEL_MASK; |
3944 | else | 3976 | else |
3945 | lvds &= ~LVDS_PIPEB_SELECT; | 3977 | temp &= ~LVDS_PIPEB_SELECT; |
3946 | } | 3978 | } |
3947 | /* set the corresponsding LVDS_BORDER bit */ | 3979 | /* set the corresponsding LVDS_BORDER bit */ |
3948 | lvds |= dev_priv->lvds_border_bits; | 3980 | temp |= dev_priv->lvds_border_bits; |
3949 | /* Set the B0-B3 data pairs corresponding to whether we're going to | 3981 | /* Set the B0-B3 data pairs corresponding to whether we're going to |
3950 | * set the DPLLs for dual-channel mode or not. | 3982 | * set the DPLLs for dual-channel mode or not. |
3951 | */ | 3983 | */ |
3952 | if (clock.p2 == 7) | 3984 | if (clock.p2 == 7) |
3953 | lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; | 3985 | temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; |
3954 | else | 3986 | else |
3955 | lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); | 3987 | temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); |
3956 | 3988 | ||
3957 | /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) | 3989 | /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) |
3958 | * appropriately here, but we need to look more thoroughly into how | 3990 | * appropriately here, but we need to look more thoroughly into how |
3959 | * panels behave in the two modes. | 3991 | * panels behave in the two modes. |
3960 | */ | 3992 | */ |
3961 | /* set the dithering flag */ | 3993 | /* set the dithering flag on non-PCH LVDS as needed */ |
3962 | if (IS_I965G(dev)) { | 3994 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
3963 | if (dev_priv->lvds_dither) { | 3995 | if (dev_priv->lvds_dither) |
3964 | if (HAS_PCH_SPLIT(dev)) { | 3996 | temp |= LVDS_ENABLE_DITHER; |
3965 | pipeconf |= PIPE_ENABLE_DITHER; | 3997 | else |
3966 | pipeconf |= PIPE_DITHER_TYPE_ST01; | 3998 | temp &= ~LVDS_ENABLE_DITHER; |
3967 | } else | ||
3968 | lvds |= LVDS_ENABLE_DITHER; | ||
3969 | } else { | ||
3970 | if (!HAS_PCH_SPLIT(dev)) { | ||
3971 | lvds &= ~LVDS_ENABLE_DITHER; | ||
3972 | } | ||
3973 | } | ||
3974 | } | 3999 | } |
3975 | I915_WRITE(lvds_reg, lvds); | 4000 | I915_WRITE(reg, temp); |
3976 | I915_READ(lvds_reg); | ||
3977 | } | 4001 | } |
4002 | |||
4003 | /* set the dithering flag and clear for anything other than a panel. */ | ||
4004 | if (HAS_PCH_SPLIT(dev)) { | ||
4005 | pipeconf &= ~PIPECONF_DITHER_EN; | ||
4006 | pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; | ||
4007 | if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { | ||
4008 | pipeconf |= PIPECONF_DITHER_EN; | ||
4009 | pipeconf |= PIPECONF_DITHER_TYPE_ST1; | ||
4010 | } | ||
4011 | } | ||
4012 | |||
3978 | if (is_dp) | 4013 | if (is_dp) |
3979 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | 4014 | intel_dp_set_m_n(crtc, mode, adjusted_mode); |
3980 | else if (HAS_PCH_SPLIT(dev)) { | 4015 | else if (HAS_PCH_SPLIT(dev)) { |
@@ -3995,26 +4030,32 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3995 | if (!has_edp_encoder) { | 4030 | if (!has_edp_encoder) { |
3996 | I915_WRITE(fp_reg, fp); | 4031 | I915_WRITE(fp_reg, fp); |
3997 | I915_WRITE(dpll_reg, dpll); | 4032 | I915_WRITE(dpll_reg, dpll); |
3998 | I915_READ(dpll_reg); | 4033 | |
3999 | /* Wait for the clocks to stabilize. */ | 4034 | /* Wait for the clocks to stabilize. */ |
4035 | POSTING_READ(dpll_reg); | ||
4000 | udelay(150); | 4036 | udelay(150); |
4001 | 4037 | ||
4002 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { | 4038 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
4039 | temp = 0; | ||
4003 | if (is_sdvo) { | 4040 | if (is_sdvo) { |
4004 | sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; | 4041 | temp = intel_mode_get_pixel_multiplier(adjusted_mode); |
4005 | I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | | 4042 | if (temp > 1) |
4006 | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); | 4043 | temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; |
4007 | } else | 4044 | else |
4008 | I915_WRITE(dpll_md_reg, 0); | 4045 | temp = 0; |
4046 | } | ||
4047 | I915_WRITE(DPLL_MD(pipe), temp); | ||
4009 | } else { | 4048 | } else { |
4010 | /* write it again -- the BIOS does, after all */ | 4049 | /* write it again -- the BIOS does, after all */ |
4011 | I915_WRITE(dpll_reg, dpll); | 4050 | I915_WRITE(dpll_reg, dpll); |
4012 | } | 4051 | } |
4013 | I915_READ(dpll_reg); | 4052 | |
4014 | /* Wait for the clocks to stabilize. */ | 4053 | /* Wait for the clocks to stabilize. */ |
4054 | POSTING_READ(dpll_reg); | ||
4015 | udelay(150); | 4055 | udelay(150); |
4016 | } | 4056 | } |
4017 | 4057 | ||
4058 | intel_crtc->lowfreq_avail = false; | ||
4018 | if (is_lvds && has_reduced_clock && i915_powersave) { | 4059 | if (is_lvds && has_reduced_clock && i915_powersave) { |
4019 | I915_WRITE(fp_reg + 4, fp2); | 4060 | I915_WRITE(fp_reg + 4, fp2); |
4020 | intel_crtc->lowfreq_avail = true; | 4061 | intel_crtc->lowfreq_avail = true; |
@@ -4024,7 +4065,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4024 | } | 4065 | } |
4025 | } else { | 4066 | } else { |
4026 | I915_WRITE(fp_reg + 4, fp); | 4067 | I915_WRITE(fp_reg + 4, fp); |
4027 | intel_crtc->lowfreq_avail = false; | ||
4028 | if (HAS_PIPE_CXSR(dev)) { | 4068 | if (HAS_PIPE_CXSR(dev)) { |
4029 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); | 4069 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); |
4030 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; | 4070 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; |
@@ -4043,58 +4083,72 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4043 | } else | 4083 | } else |
4044 | pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ | 4084 | pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ |
4045 | 4085 | ||
4046 | I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | | 4086 | I915_WRITE(HTOTAL(pipe), |
4087 | (adjusted_mode->crtc_hdisplay - 1) | | ||
4047 | ((adjusted_mode->crtc_htotal - 1) << 16)); | 4088 | ((adjusted_mode->crtc_htotal - 1) << 16)); |
4048 | I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | | 4089 | I915_WRITE(HBLANK(pipe), |
4090 | (adjusted_mode->crtc_hblank_start - 1) | | ||
4049 | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | 4091 | ((adjusted_mode->crtc_hblank_end - 1) << 16)); |
4050 | I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | | 4092 | I915_WRITE(HSYNC(pipe), |
4093 | (adjusted_mode->crtc_hsync_start - 1) | | ||
4051 | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | 4094 | ((adjusted_mode->crtc_hsync_end - 1) << 16)); |
4052 | I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | | 4095 | |
4096 | I915_WRITE(VTOTAL(pipe), | ||
4097 | (adjusted_mode->crtc_vdisplay - 1) | | ||
4053 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | 4098 | ((adjusted_mode->crtc_vtotal - 1) << 16)); |
4054 | I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | | 4099 | I915_WRITE(VBLANK(pipe), |
4100 | (adjusted_mode->crtc_vblank_start - 1) | | ||
4055 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | 4101 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); |
4056 | I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | | 4102 | I915_WRITE(VSYNC(pipe), |
4103 | (adjusted_mode->crtc_vsync_start - 1) | | ||
4057 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | 4104 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); |
4058 | /* pipesrc and dspsize control the size that is scaled from, which should | 4105 | |
4059 | * always be the user's requested size. | 4106 | /* pipesrc and dspsize control the size that is scaled from, |
4107 | * which should always be the user's requested size. | ||
4060 | */ | 4108 | */ |
4061 | if (!HAS_PCH_SPLIT(dev)) { | 4109 | if (!HAS_PCH_SPLIT(dev)) { |
4062 | I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | | 4110 | I915_WRITE(DSPSIZE(plane), |
4063 | (mode->hdisplay - 1)); | 4111 | ((mode->vdisplay - 1) << 16) | |
4064 | I915_WRITE(dsppos_reg, 0); | 4112 | (mode->hdisplay - 1)); |
4113 | I915_WRITE(DSPPOS(plane), 0); | ||
4065 | } | 4114 | } |
4066 | I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | 4115 | I915_WRITE(PIPESRC(pipe), |
4116 | ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | ||
4067 | 4117 | ||
4068 | if (HAS_PCH_SPLIT(dev)) { | 4118 | if (HAS_PCH_SPLIT(dev)) { |
4069 | I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m); | 4119 | I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); |
4070 | I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n); | 4120 | I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); |
4071 | I915_WRITE(link_m1_reg, m_n.link_m); | 4121 | I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); |
4072 | I915_WRITE(link_n1_reg, m_n.link_n); | 4122 | I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); |
4073 | 4123 | ||
4074 | if (has_edp_encoder) { | 4124 | if (has_edp_encoder) { |
4075 | ironlake_set_pll_edp(crtc, adjusted_mode->clock); | 4125 | ironlake_set_pll_edp(crtc, adjusted_mode->clock); |
4076 | } else { | 4126 | } else { |
4077 | /* enable FDI RX PLL too */ | 4127 | /* enable FDI RX PLL too */ |
4078 | temp = I915_READ(fdi_rx_reg); | 4128 | reg = FDI_RX_CTL(pipe); |
4079 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); | 4129 | temp = I915_READ(reg); |
4080 | I915_READ(fdi_rx_reg); | 4130 | I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE); |
4131 | |||
4132 | POSTING_READ(reg); | ||
4081 | udelay(200); | 4133 | udelay(200); |
4082 | 4134 | ||
4083 | /* enable FDI TX PLL too */ | 4135 | /* enable FDI TX PLL too */ |
4084 | temp = I915_READ(fdi_tx_reg); | 4136 | reg = FDI_TX_CTL(pipe); |
4085 | I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE); | 4137 | temp = I915_READ(reg); |
4086 | I915_READ(fdi_tx_reg); | 4138 | I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE); |
4087 | 4139 | ||
4088 | /* enable FDI RX PCDCLK */ | 4140 | /* enable FDI RX PCDCLK */ |
4089 | temp = I915_READ(fdi_rx_reg); | 4141 | reg = FDI_RX_CTL(pipe); |
4090 | I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK); | 4142 | temp = I915_READ(reg); |
4091 | I915_READ(fdi_rx_reg); | 4143 | I915_WRITE(reg, temp | FDI_PCDCLK); |
4144 | |||
4145 | POSTING_READ(reg); | ||
4092 | udelay(200); | 4146 | udelay(200); |
4093 | } | 4147 | } |
4094 | } | 4148 | } |
4095 | 4149 | ||
4096 | I915_WRITE(pipeconf_reg, pipeconf); | 4150 | I915_WRITE(PIPECONF(pipe), pipeconf); |
4097 | I915_READ(pipeconf_reg); | 4151 | POSTING_READ(PIPECONF(pipe)); |
4098 | 4152 | ||
4099 | intel_wait_for_vblank(dev, pipe); | 4153 | intel_wait_for_vblank(dev, pipe); |
4100 | 4154 | ||
@@ -4104,9 +4158,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4104 | I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); | 4158 | I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); |
4105 | } | 4159 | } |
4106 | 4160 | ||
4107 | I915_WRITE(dspcntr_reg, dspcntr); | 4161 | I915_WRITE(DSPCNTR(plane), dspcntr); |
4108 | 4162 | ||
4109 | /* Flush the plane changes */ | ||
4110 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 4163 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
4111 | 4164 | ||
4112 | intel_update_watermarks(dev); | 4165 | intel_update_watermarks(dev); |
@@ -4199,7 +4252,8 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) | |||
4199 | } | 4252 | } |
4200 | 4253 | ||
4201 | /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ | 4254 | /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ |
4202 | static void intel_crtc_update_cursor(struct drm_crtc *crtc) | 4255 | static void intel_crtc_update_cursor(struct drm_crtc *crtc, |
4256 | bool on) | ||
4203 | { | 4257 | { |
4204 | struct drm_device *dev = crtc->dev; | 4258 | struct drm_device *dev = crtc->dev; |
4205 | struct drm_i915_private *dev_priv = dev->dev_private; | 4259 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -4212,7 +4266,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc) | |||
4212 | 4266 | ||
4213 | pos = 0; | 4267 | pos = 0; |
4214 | 4268 | ||
4215 | if (intel_crtc->cursor_on && crtc->fb) { | 4269 | if (on && crtc->enabled && crtc->fb) { |
4216 | base = intel_crtc->cursor_addr; | 4270 | base = intel_crtc->cursor_addr; |
4217 | if (x > (int) crtc->fb->width) | 4271 | if (x > (int) crtc->fb->width) |
4218 | base = 0; | 4272 | base = 0; |
@@ -4324,7 +4378,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
4324 | addr = obj_priv->phys_obj->handle->busaddr; | 4378 | addr = obj_priv->phys_obj->handle->busaddr; |
4325 | } | 4379 | } |
4326 | 4380 | ||
4327 | if (!IS_I9XX(dev)) | 4381 | if (IS_GEN2(dev)) |
4328 | I915_WRITE(CURSIZE, (height << 12) | width); | 4382 | I915_WRITE(CURSIZE, (height << 12) | width); |
4329 | 4383 | ||
4330 | finish: | 4384 | finish: |
@@ -4344,7 +4398,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
4344 | intel_crtc->cursor_width = width; | 4398 | intel_crtc->cursor_width = width; |
4345 | intel_crtc->cursor_height = height; | 4399 | intel_crtc->cursor_height = height; |
4346 | 4400 | ||
4347 | intel_crtc_update_cursor(crtc); | 4401 | intel_crtc_update_cursor(crtc, true); |
4348 | 4402 | ||
4349 | return 0; | 4403 | return 0; |
4350 | fail_unpin: | 4404 | fail_unpin: |
@@ -4363,7 +4417,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | |||
4363 | intel_crtc->cursor_x = x; | 4417 | intel_crtc->cursor_x = x; |
4364 | intel_crtc->cursor_y = y; | 4418 | intel_crtc->cursor_y = y; |
4365 | 4419 | ||
4366 | intel_crtc_update_cursor(crtc); | 4420 | intel_crtc_update_cursor(crtc, true); |
4367 | 4421 | ||
4368 | return 0; | 4422 | return 0; |
4369 | } | 4423 | } |
@@ -4432,7 +4486,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, | |||
4432 | struct intel_crtc *intel_crtc; | 4486 | struct intel_crtc *intel_crtc; |
4433 | struct drm_crtc *possible_crtc; | 4487 | struct drm_crtc *possible_crtc; |
4434 | struct drm_crtc *supported_crtc =NULL; | 4488 | struct drm_crtc *supported_crtc =NULL; |
4435 | struct drm_encoder *encoder = &intel_encoder->enc; | 4489 | struct drm_encoder *encoder = &intel_encoder->base; |
4436 | struct drm_crtc *crtc = NULL; | 4490 | struct drm_crtc *crtc = NULL; |
4437 | struct drm_device *dev = encoder->dev; | 4491 | struct drm_device *dev = encoder->dev; |
4438 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | 4492 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; |
@@ -4513,7 +4567,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, | |||
4513 | void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, | 4567 | void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, |
4514 | struct drm_connector *connector, int dpms_mode) | 4568 | struct drm_connector *connector, int dpms_mode) |
4515 | { | 4569 | { |
4516 | struct drm_encoder *encoder = &intel_encoder->enc; | 4570 | struct drm_encoder *encoder = &intel_encoder->base; |
4517 | struct drm_device *dev = encoder->dev; | 4571 | struct drm_device *dev = encoder->dev; |
4518 | struct drm_crtc *crtc = encoder->crtc; | 4572 | struct drm_crtc *crtc = encoder->crtc; |
4519 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | 4573 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; |
@@ -4559,7 +4613,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | |||
4559 | clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; | 4613 | clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; |
4560 | } | 4614 | } |
4561 | 4615 | ||
4562 | if (IS_I9XX(dev)) { | 4616 | if (!IS_GEN2(dev)) { |
4563 | if (IS_PINEVIEW(dev)) | 4617 | if (IS_PINEVIEW(dev)) |
4564 | clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> | 4618 | clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> |
4565 | DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); | 4619 | DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); |
@@ -4663,8 +4717,6 @@ static void intel_gpu_idle_timer(unsigned long arg) | |||
4663 | struct drm_device *dev = (struct drm_device *)arg; | 4717 | struct drm_device *dev = (struct drm_device *)arg; |
4664 | drm_i915_private_t *dev_priv = dev->dev_private; | 4718 | drm_i915_private_t *dev_priv = dev->dev_private; |
4665 | 4719 | ||
4666 | DRM_DEBUG_DRIVER("idle timer fired, downclocking\n"); | ||
4667 | |||
4668 | dev_priv->busy = false; | 4720 | dev_priv->busy = false; |
4669 | 4721 | ||
4670 | queue_work(dev_priv->wq, &dev_priv->idle_work); | 4722 | queue_work(dev_priv->wq, &dev_priv->idle_work); |
@@ -4678,14 +4730,12 @@ static void intel_crtc_idle_timer(unsigned long arg) | |||
4678 | struct drm_crtc *crtc = &intel_crtc->base; | 4730 | struct drm_crtc *crtc = &intel_crtc->base; |
4679 | drm_i915_private_t *dev_priv = crtc->dev->dev_private; | 4731 | drm_i915_private_t *dev_priv = crtc->dev->dev_private; |
4680 | 4732 | ||
4681 | DRM_DEBUG_DRIVER("idle timer fired, downclocking\n"); | ||
4682 | |||
4683 | intel_crtc->busy = false; | 4733 | intel_crtc->busy = false; |
4684 | 4734 | ||
4685 | queue_work(dev_priv->wq, &dev_priv->idle_work); | 4735 | queue_work(dev_priv->wq, &dev_priv->idle_work); |
4686 | } | 4736 | } |
4687 | 4737 | ||
4688 | static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) | 4738 | static void intel_increase_pllclock(struct drm_crtc *crtc) |
4689 | { | 4739 | { |
4690 | struct drm_device *dev = crtc->dev; | 4740 | struct drm_device *dev = crtc->dev; |
4691 | drm_i915_private_t *dev_priv = dev->dev_private; | 4741 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -4720,9 +4770,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) | |||
4720 | } | 4770 | } |
4721 | 4771 | ||
4722 | /* Schedule downclock */ | 4772 | /* Schedule downclock */ |
4723 | if (schedule) | 4773 | mod_timer(&intel_crtc->idle_timer, jiffies + |
4724 | mod_timer(&intel_crtc->idle_timer, jiffies + | 4774 | msecs_to_jiffies(CRTC_IDLE_TIMEOUT)); |
4725 | msecs_to_jiffies(CRTC_IDLE_TIMEOUT)); | ||
4726 | } | 4775 | } |
4727 | 4776 | ||
4728 | static void intel_decrease_pllclock(struct drm_crtc *crtc) | 4777 | static void intel_decrease_pllclock(struct drm_crtc *crtc) |
@@ -4858,7 +4907,7 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) | |||
4858 | I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK); | 4907 | I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK); |
4859 | } | 4908 | } |
4860 | /* Non-busy -> busy, upclock */ | 4909 | /* Non-busy -> busy, upclock */ |
4861 | intel_increase_pllclock(crtc, true); | 4910 | intel_increase_pllclock(crtc); |
4862 | intel_crtc->busy = true; | 4911 | intel_crtc->busy = true; |
4863 | } else { | 4912 | } else { |
4864 | /* Busy -> busy, put off timer */ | 4913 | /* Busy -> busy, put off timer */ |
@@ -4872,8 +4921,22 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) | |||
4872 | static void intel_crtc_destroy(struct drm_crtc *crtc) | 4921 | static void intel_crtc_destroy(struct drm_crtc *crtc) |
4873 | { | 4922 | { |
4874 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4923 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4924 | struct drm_device *dev = crtc->dev; | ||
4925 | struct intel_unpin_work *work; | ||
4926 | unsigned long flags; | ||
4927 | |||
4928 | spin_lock_irqsave(&dev->event_lock, flags); | ||
4929 | work = intel_crtc->unpin_work; | ||
4930 | intel_crtc->unpin_work = NULL; | ||
4931 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
4932 | |||
4933 | if (work) { | ||
4934 | cancel_work_sync(&work->work); | ||
4935 | kfree(work); | ||
4936 | } | ||
4875 | 4937 | ||
4876 | drm_crtc_cleanup(crtc); | 4938 | drm_crtc_cleanup(crtc); |
4939 | |||
4877 | kfree(intel_crtc); | 4940 | kfree(intel_crtc); |
4878 | } | 4941 | } |
4879 | 4942 | ||
@@ -4933,7 +4996,7 @@ static void do_intel_finish_page_flip(struct drm_device *dev, | |||
4933 | /* Initial scanout buffer will have a 0 pending flip count */ | 4996 | /* Initial scanout buffer will have a 0 pending flip count */ |
4934 | if ((atomic_read(&obj_priv->pending_flip) == 0) || | 4997 | if ((atomic_read(&obj_priv->pending_flip) == 0) || |
4935 | atomic_dec_and_test(&obj_priv->pending_flip)) | 4998 | atomic_dec_and_test(&obj_priv->pending_flip)) |
4936 | DRM_WAKEUP(&dev_priv->pending_flip_queue); | 4999 | wake_up(&dev_priv->pending_flip_queue); |
4937 | schedule_work(&work->work); | 5000 | schedule_work(&work->work); |
4938 | 5001 | ||
4939 | trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); | 5002 | trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); |
@@ -5014,7 +5077,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
5014 | obj = intel_fb->obj; | 5077 | obj = intel_fb->obj; |
5015 | 5078 | ||
5016 | mutex_lock(&dev->struct_mutex); | 5079 | mutex_lock(&dev->struct_mutex); |
5017 | ret = intel_pin_and_fence_fb_obj(dev, obj); | 5080 | ret = intel_pin_and_fence_fb_obj(dev, obj, true); |
5018 | if (ret) | 5081 | if (ret) |
5019 | goto cleanup_work; | 5082 | goto cleanup_work; |
5020 | 5083 | ||
@@ -5023,9 +5086,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
5023 | drm_gem_object_reference(obj); | 5086 | drm_gem_object_reference(obj); |
5024 | 5087 | ||
5025 | crtc->fb = fb; | 5088 | crtc->fb = fb; |
5026 | ret = i915_gem_object_flush_write_domain(obj); | ||
5027 | if (ret) | ||
5028 | goto cleanup_objs; | ||
5029 | 5089 | ||
5030 | ret = drm_vblank_get(dev, intel_crtc->pipe); | 5090 | ret = drm_vblank_get(dev, intel_crtc->pipe); |
5031 | if (ret) | 5091 | if (ret) |
@@ -5038,14 +5098,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
5038 | if (IS_GEN3(dev) || IS_GEN2(dev)) { | 5098 | if (IS_GEN3(dev) || IS_GEN2(dev)) { |
5039 | u32 flip_mask; | 5099 | u32 flip_mask; |
5040 | 5100 | ||
5101 | /* Can't queue multiple flips, so wait for the previous | ||
5102 | * one to finish before executing the next. | ||
5103 | */ | ||
5104 | BEGIN_LP_RING(2); | ||
5041 | if (intel_crtc->plane) | 5105 | if (intel_crtc->plane) |
5042 | flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; | 5106 | flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; |
5043 | else | 5107 | else |
5044 | flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; | 5108 | flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; |
5045 | |||
5046 | BEGIN_LP_RING(2); | ||
5047 | OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); | 5109 | OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); |
5048 | OUT_RING(0); | 5110 | OUT_RING(MI_NOOP); |
5049 | ADVANCE_LP_RING(); | 5111 | ADVANCE_LP_RING(); |
5050 | } | 5112 | } |
5051 | 5113 | ||
@@ -5126,15 +5188,14 @@ cleanup_work: | |||
5126 | return ret; | 5188 | return ret; |
5127 | } | 5189 | } |
5128 | 5190 | ||
5129 | static const struct drm_crtc_helper_funcs intel_helper_funcs = { | 5191 | static struct drm_crtc_helper_funcs intel_helper_funcs = { |
5130 | .dpms = intel_crtc_dpms, | 5192 | .dpms = intel_crtc_dpms, |
5131 | .mode_fixup = intel_crtc_mode_fixup, | 5193 | .mode_fixup = intel_crtc_mode_fixup, |
5132 | .mode_set = intel_crtc_mode_set, | 5194 | .mode_set = intel_crtc_mode_set, |
5133 | .mode_set_base = intel_pipe_set_base, | 5195 | .mode_set_base = intel_pipe_set_base, |
5134 | .mode_set_base_atomic = intel_pipe_set_base_atomic, | 5196 | .mode_set_base_atomic = intel_pipe_set_base_atomic, |
5135 | .prepare = intel_crtc_prepare, | ||
5136 | .commit = intel_crtc_commit, | ||
5137 | .load_lut = intel_crtc_load_lut, | 5197 | .load_lut = intel_crtc_load_lut, |
5198 | .disable = intel_crtc_disable, | ||
5138 | }; | 5199 | }; |
5139 | 5200 | ||
5140 | static const struct drm_crtc_funcs intel_crtc_funcs = { | 5201 | static const struct drm_crtc_funcs intel_crtc_funcs = { |
@@ -5160,8 +5221,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
5160 | drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); | 5221 | drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs); |
5161 | 5222 | ||
5162 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); | 5223 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); |
5163 | intel_crtc->pipe = pipe; | ||
5164 | intel_crtc->plane = pipe; | ||
5165 | for (i = 0; i < 256; i++) { | 5224 | for (i = 0; i < 256; i++) { |
5166 | intel_crtc->lut_r[i] = i; | 5225 | intel_crtc->lut_r[i] = i; |
5167 | intel_crtc->lut_g[i] = i; | 5226 | intel_crtc->lut_g[i] = i; |
@@ -5171,9 +5230,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
5171 | /* Swap pipes & planes for FBC on pre-965 */ | 5230 | /* Swap pipes & planes for FBC on pre-965 */ |
5172 | intel_crtc->pipe = pipe; | 5231 | intel_crtc->pipe = pipe; |
5173 | intel_crtc->plane = pipe; | 5232 | intel_crtc->plane = pipe; |
5174 | if (IS_MOBILE(dev) && (IS_I9XX(dev) && !IS_I965G(dev))) { | 5233 | if (IS_MOBILE(dev) && IS_GEN3(dev)) { |
5175 | DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); | 5234 | DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); |
5176 | intel_crtc->plane = ((pipe == 0) ? 1 : 0); | 5235 | intel_crtc->plane = !pipe; |
5177 | } | 5236 | } |
5178 | 5237 | ||
5179 | BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || | 5238 | BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || |
@@ -5183,6 +5242,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
5183 | 5242 | ||
5184 | intel_crtc->cursor_addr = 0; | 5243 | intel_crtc->cursor_addr = 0; |
5185 | intel_crtc->dpms_mode = -1; | 5244 | intel_crtc->dpms_mode = -1; |
5245 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ | ||
5246 | |||
5247 | if (HAS_PCH_SPLIT(dev)) { | ||
5248 | intel_helper_funcs.prepare = ironlake_crtc_prepare; | ||
5249 | intel_helper_funcs.commit = ironlake_crtc_commit; | ||
5250 | } else { | ||
5251 | intel_helper_funcs.prepare = i9xx_crtc_prepare; | ||
5252 | intel_helper_funcs.commit = i9xx_crtc_commit; | ||
5253 | } | ||
5254 | |||
5186 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); | 5255 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); |
5187 | 5256 | ||
5188 | intel_crtc->busy = false; | 5257 | intel_crtc->busy = false; |
@@ -5218,38 +5287,25 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | |||
5218 | return 0; | 5287 | return 0; |
5219 | } | 5288 | } |
5220 | 5289 | ||
5221 | struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) | ||
5222 | { | ||
5223 | struct drm_crtc *crtc = NULL; | ||
5224 | |||
5225 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
5226 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
5227 | if (intel_crtc->pipe == pipe) | ||
5228 | break; | ||
5229 | } | ||
5230 | return crtc; | ||
5231 | } | ||
5232 | |||
5233 | static int intel_encoder_clones(struct drm_device *dev, int type_mask) | 5290 | static int intel_encoder_clones(struct drm_device *dev, int type_mask) |
5234 | { | 5291 | { |
5292 | struct intel_encoder *encoder; | ||
5235 | int index_mask = 0; | 5293 | int index_mask = 0; |
5236 | struct drm_encoder *encoder; | ||
5237 | int entry = 0; | 5294 | int entry = 0; |
5238 | 5295 | ||
5239 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 5296 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { |
5240 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 5297 | if (type_mask & encoder->clone_mask) |
5241 | if (type_mask & intel_encoder->clone_mask) | ||
5242 | index_mask |= (1 << entry); | 5298 | index_mask |= (1 << entry); |
5243 | entry++; | 5299 | entry++; |
5244 | } | 5300 | } |
5301 | |||
5245 | return index_mask; | 5302 | return index_mask; |
5246 | } | 5303 | } |
5247 | 5304 | ||
5248 | |||
5249 | static void intel_setup_outputs(struct drm_device *dev) | 5305 | static void intel_setup_outputs(struct drm_device *dev) |
5250 | { | 5306 | { |
5251 | struct drm_i915_private *dev_priv = dev->dev_private; | 5307 | struct drm_i915_private *dev_priv = dev->dev_private; |
5252 | struct drm_encoder *encoder; | 5308 | struct intel_encoder *encoder; |
5253 | bool dpd_is_edp = false; | 5309 | bool dpd_is_edp = false; |
5254 | 5310 | ||
5255 | if (IS_MOBILE(dev) && !IS_I830(dev)) | 5311 | if (IS_MOBILE(dev) && !IS_I830(dev)) |
@@ -5338,12 +5394,10 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
5338 | if (SUPPORTS_TV(dev)) | 5394 | if (SUPPORTS_TV(dev)) |
5339 | intel_tv_init(dev); | 5395 | intel_tv_init(dev); |
5340 | 5396 | ||
5341 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 5397 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { |
5342 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 5398 | encoder->base.possible_crtcs = encoder->crtc_mask; |
5343 | 5399 | encoder->base.possible_clones = | |
5344 | encoder->possible_crtcs = intel_encoder->crtc_mask; | 5400 | intel_encoder_clones(dev, encoder->clone_mask); |
5345 | encoder->possible_clones = intel_encoder_clones(dev, | ||
5346 | intel_encoder->clone_mask); | ||
5347 | } | 5401 | } |
5348 | } | 5402 | } |
5349 | 5403 | ||
@@ -5377,8 +5431,25 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
5377 | struct drm_mode_fb_cmd *mode_cmd, | 5431 | struct drm_mode_fb_cmd *mode_cmd, |
5378 | struct drm_gem_object *obj) | 5432 | struct drm_gem_object *obj) |
5379 | { | 5433 | { |
5434 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | ||
5380 | int ret; | 5435 | int ret; |
5381 | 5436 | ||
5437 | if (obj_priv->tiling_mode == I915_TILING_Y) | ||
5438 | return -EINVAL; | ||
5439 | |||
5440 | if (mode_cmd->pitch & 63) | ||
5441 | return -EINVAL; | ||
5442 | |||
5443 | switch (mode_cmd->bpp) { | ||
5444 | case 8: | ||
5445 | case 16: | ||
5446 | case 24: | ||
5447 | case 32: | ||
5448 | break; | ||
5449 | default: | ||
5450 | return -EINVAL; | ||
5451 | } | ||
5452 | |||
5382 | ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); | 5453 | ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); |
5383 | if (ret) { | 5454 | if (ret) { |
5384 | DRM_ERROR("framebuffer init failed %d\n", ret); | 5455 | DRM_ERROR("framebuffer init failed %d\n", ret); |
@@ -5487,6 +5558,10 @@ void ironlake_enable_drps(struct drm_device *dev) | |||
5487 | u32 rgvmodectl = I915_READ(MEMMODECTL); | 5558 | u32 rgvmodectl = I915_READ(MEMMODECTL); |
5488 | u8 fmax, fmin, fstart, vstart; | 5559 | u8 fmax, fmin, fstart, vstart; |
5489 | 5560 | ||
5561 | /* Enable temp reporting */ | ||
5562 | I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN); | ||
5563 | I915_WRITE16(TSC1, I915_READ(TSC1) | TSE); | ||
5564 | |||
5490 | /* 100ms RC evaluation intervals */ | 5565 | /* 100ms RC evaluation intervals */ |
5491 | I915_WRITE(RCUPEI, 100000); | 5566 | I915_WRITE(RCUPEI, 100000); |
5492 | I915_WRITE(RCDNEI, 100000); | 5567 | I915_WRITE(RCDNEI, 100000); |
@@ -5529,7 +5604,7 @@ void ironlake_enable_drps(struct drm_device *dev) | |||
5529 | rgvmodectl |= MEMMODE_SWMODE_EN; | 5604 | rgvmodectl |= MEMMODE_SWMODE_EN; |
5530 | I915_WRITE(MEMMODECTL, rgvmodectl); | 5605 | I915_WRITE(MEMMODECTL, rgvmodectl); |
5531 | 5606 | ||
5532 | if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 1, 0)) | 5607 | if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) |
5533 | DRM_ERROR("stuck trying to change perf mode\n"); | 5608 | DRM_ERROR("stuck trying to change perf mode\n"); |
5534 | msleep(1); | 5609 | msleep(1); |
5535 | 5610 | ||
@@ -5728,20 +5803,20 @@ void intel_init_clock_gating(struct drm_device *dev) | |||
5728 | if (IS_GM45(dev)) | 5803 | if (IS_GM45(dev)) |
5729 | dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; | 5804 | dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; |
5730 | I915_WRITE(DSPCLK_GATE_D, dspclk_gate); | 5805 | I915_WRITE(DSPCLK_GATE_D, dspclk_gate); |
5731 | } else if (IS_I965GM(dev)) { | 5806 | } else if (IS_CRESTLINE(dev)) { |
5732 | I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); | 5807 | I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); |
5733 | I915_WRITE(RENCLK_GATE_D2, 0); | 5808 | I915_WRITE(RENCLK_GATE_D2, 0); |
5734 | I915_WRITE(DSPCLK_GATE_D, 0); | 5809 | I915_WRITE(DSPCLK_GATE_D, 0); |
5735 | I915_WRITE(RAMCLK_GATE_D, 0); | 5810 | I915_WRITE(RAMCLK_GATE_D, 0); |
5736 | I915_WRITE16(DEUC, 0); | 5811 | I915_WRITE16(DEUC, 0); |
5737 | } else if (IS_I965G(dev)) { | 5812 | } else if (IS_BROADWATER(dev)) { |
5738 | I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | | 5813 | I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | |
5739 | I965_RCC_CLOCK_GATE_DISABLE | | 5814 | I965_RCC_CLOCK_GATE_DISABLE | |
5740 | I965_RCPB_CLOCK_GATE_DISABLE | | 5815 | I965_RCPB_CLOCK_GATE_DISABLE | |
5741 | I965_ISC_CLOCK_GATE_DISABLE | | 5816 | I965_ISC_CLOCK_GATE_DISABLE | |
5742 | I965_FBC_CLOCK_GATE_DISABLE); | 5817 | I965_FBC_CLOCK_GATE_DISABLE); |
5743 | I915_WRITE(RENCLK_GATE_D2, 0); | 5818 | I915_WRITE(RENCLK_GATE_D2, 0); |
5744 | } else if (IS_I9XX(dev)) { | 5819 | } else if (IS_GEN3(dev)) { |
5745 | u32 dstate = I915_READ(D_STATE); | 5820 | u32 dstate = I915_READ(D_STATE); |
5746 | 5821 | ||
5747 | dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | | 5822 | dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | |
@@ -5823,7 +5898,7 @@ static void intel_init_display(struct drm_device *dev) | |||
5823 | dev_priv->display.fbc_enabled = g4x_fbc_enabled; | 5898 | dev_priv->display.fbc_enabled = g4x_fbc_enabled; |
5824 | dev_priv->display.enable_fbc = g4x_enable_fbc; | 5899 | dev_priv->display.enable_fbc = g4x_enable_fbc; |
5825 | dev_priv->display.disable_fbc = g4x_disable_fbc; | 5900 | dev_priv->display.disable_fbc = g4x_disable_fbc; |
5826 | } else if (IS_I965GM(dev)) { | 5901 | } else if (IS_CRESTLINE(dev)) { |
5827 | dev_priv->display.fbc_enabled = i8xx_fbc_enabled; | 5902 | dev_priv->display.fbc_enabled = i8xx_fbc_enabled; |
5828 | dev_priv->display.enable_fbc = i8xx_enable_fbc; | 5903 | dev_priv->display.enable_fbc = i8xx_enable_fbc; |
5829 | dev_priv->display.disable_fbc = i8xx_disable_fbc; | 5904 | dev_priv->display.disable_fbc = i8xx_disable_fbc; |
@@ -5883,9 +5958,9 @@ static void intel_init_display(struct drm_device *dev) | |||
5883 | dev_priv->display.update_wm = pineview_update_wm; | 5958 | dev_priv->display.update_wm = pineview_update_wm; |
5884 | } else if (IS_G4X(dev)) | 5959 | } else if (IS_G4X(dev)) |
5885 | dev_priv->display.update_wm = g4x_update_wm; | 5960 | dev_priv->display.update_wm = g4x_update_wm; |
5886 | else if (IS_I965G(dev)) | 5961 | else if (IS_GEN4(dev)) |
5887 | dev_priv->display.update_wm = i965_update_wm; | 5962 | dev_priv->display.update_wm = i965_update_wm; |
5888 | else if (IS_I9XX(dev)) { | 5963 | else if (IS_GEN3(dev)) { |
5889 | dev_priv->display.update_wm = i9xx_update_wm; | 5964 | dev_priv->display.update_wm = i9xx_update_wm; |
5890 | dev_priv->display.get_fifo_size = i9xx_get_fifo_size; | 5965 | dev_priv->display.get_fifo_size = i9xx_get_fifo_size; |
5891 | } else if (IS_I85X(dev)) { | 5966 | } else if (IS_I85X(dev)) { |
@@ -5999,24 +6074,24 @@ void intel_modeset_init(struct drm_device *dev) | |||
5999 | 6074 | ||
6000 | intel_init_display(dev); | 6075 | intel_init_display(dev); |
6001 | 6076 | ||
6002 | if (IS_I965G(dev)) { | 6077 | if (IS_GEN2(dev)) { |
6003 | dev->mode_config.max_width = 8192; | 6078 | dev->mode_config.max_width = 2048; |
6004 | dev->mode_config.max_height = 8192; | 6079 | dev->mode_config.max_height = 2048; |
6005 | } else if (IS_I9XX(dev)) { | 6080 | } else if (IS_GEN3(dev)) { |
6006 | dev->mode_config.max_width = 4096; | 6081 | dev->mode_config.max_width = 4096; |
6007 | dev->mode_config.max_height = 4096; | 6082 | dev->mode_config.max_height = 4096; |
6008 | } else { | 6083 | } else { |
6009 | dev->mode_config.max_width = 2048; | 6084 | dev->mode_config.max_width = 8192; |
6010 | dev->mode_config.max_height = 2048; | 6085 | dev->mode_config.max_height = 8192; |
6011 | } | 6086 | } |
6012 | 6087 | ||
6013 | /* set memory base */ | 6088 | /* set memory base */ |
6014 | if (IS_I9XX(dev)) | 6089 | if (IS_GEN2(dev)) |
6015 | dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); | ||
6016 | else | ||
6017 | dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); | 6090 | dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); |
6091 | else | ||
6092 | dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); | ||
6018 | 6093 | ||
6019 | if (IS_MOBILE(dev) || IS_I9XX(dev)) | 6094 | if (IS_MOBILE(dev) || !IS_GEN2(dev)) |
6020 | dev_priv->num_pipe = 2; | 6095 | dev_priv->num_pipe = 2; |
6021 | else | 6096 | else |
6022 | dev_priv->num_pipe = 1; | 6097 | dev_priv->num_pipe = 1; |
@@ -6052,10 +6127,8 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
6052 | struct drm_crtc *crtc; | 6127 | struct drm_crtc *crtc; |
6053 | struct intel_crtc *intel_crtc; | 6128 | struct intel_crtc *intel_crtc; |
6054 | 6129 | ||
6055 | mutex_lock(&dev->struct_mutex); | ||
6056 | |||
6057 | drm_kms_helper_poll_fini(dev); | 6130 | drm_kms_helper_poll_fini(dev); |
6058 | intel_fbdev_fini(dev); | 6131 | mutex_lock(&dev->struct_mutex); |
6059 | 6132 | ||
6060 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 6133 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
6061 | /* Skip inactive CRTCs */ | 6134 | /* Skip inactive CRTCs */ |
@@ -6063,12 +6136,9 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
6063 | continue; | 6136 | continue; |
6064 | 6137 | ||
6065 | intel_crtc = to_intel_crtc(crtc); | 6138 | intel_crtc = to_intel_crtc(crtc); |
6066 | intel_increase_pllclock(crtc, false); | 6139 | intel_increase_pllclock(crtc); |
6067 | del_timer_sync(&intel_crtc->idle_timer); | ||
6068 | } | 6140 | } |
6069 | 6141 | ||
6070 | del_timer_sync(&dev_priv->idle_timer); | ||
6071 | |||
6072 | if (dev_priv->display.disable_fbc) | 6142 | if (dev_priv->display.disable_fbc) |
6073 | dev_priv->display.disable_fbc(dev); | 6143 | dev_priv->display.disable_fbc(dev); |
6074 | 6144 | ||
@@ -6097,33 +6167,36 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
6097 | 6167 | ||
6098 | mutex_unlock(&dev->struct_mutex); | 6168 | mutex_unlock(&dev->struct_mutex); |
6099 | 6169 | ||
6170 | /* Disable the irq before mode object teardown, for the irq might | ||
6171 | * enqueue unpin/hotplug work. */ | ||
6172 | drm_irq_uninstall(dev); | ||
6173 | cancel_work_sync(&dev_priv->hotplug_work); | ||
6174 | |||
6175 | /* Shut off idle work before the crtcs get freed. */ | ||
6176 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
6177 | intel_crtc = to_intel_crtc(crtc); | ||
6178 | del_timer_sync(&intel_crtc->idle_timer); | ||
6179 | } | ||
6180 | del_timer_sync(&dev_priv->idle_timer); | ||
6181 | cancel_work_sync(&dev_priv->idle_work); | ||
6182 | |||
6100 | drm_mode_config_cleanup(dev); | 6183 | drm_mode_config_cleanup(dev); |
6101 | } | 6184 | } |
6102 | 6185 | ||
6103 | |||
6104 | /* | 6186 | /* |
6105 | * Return which encoder is currently attached for connector. | 6187 | * Return which encoder is currently attached for connector. |
6106 | */ | 6188 | */ |
6107 | struct drm_encoder *intel_attached_encoder (struct drm_connector *connector) | 6189 | struct drm_encoder *intel_best_encoder(struct drm_connector *connector) |
6108 | { | 6190 | { |
6109 | struct drm_mode_object *obj; | 6191 | return &intel_attached_encoder(connector)->base; |
6110 | struct drm_encoder *encoder; | 6192 | } |
6111 | int i; | ||
6112 | |||
6113 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
6114 | if (connector->encoder_ids[i] == 0) | ||
6115 | break; | ||
6116 | |||
6117 | obj = drm_mode_object_find(connector->dev, | ||
6118 | connector->encoder_ids[i], | ||
6119 | DRM_MODE_OBJECT_ENCODER); | ||
6120 | if (!obj) | ||
6121 | continue; | ||
6122 | 6193 | ||
6123 | encoder = obj_to_encoder(obj); | 6194 | void intel_connector_attach_encoder(struct intel_connector *connector, |
6124 | return encoder; | 6195 | struct intel_encoder *encoder) |
6125 | } | 6196 | { |
6126 | return NULL; | 6197 | connector->encoder = encoder; |
6198 | drm_mode_connector_attach_encoder(&connector->base, | ||
6199 | &encoder->base); | ||
6127 | } | 6200 | } |
6128 | 6201 | ||
6129 | /* | 6202 | /* |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9ab8708ac6ba..152d94507b79 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -58,14 +58,23 @@ struct intel_dp { | |||
58 | struct i2c_adapter adapter; | 58 | struct i2c_adapter adapter; |
59 | struct i2c_algo_dp_aux_data algo; | 59 | struct i2c_algo_dp_aux_data algo; |
60 | bool is_pch_edp; | 60 | bool is_pch_edp; |
61 | uint8_t train_set[4]; | ||
62 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
61 | }; | 63 | }; |
62 | 64 | ||
63 | static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder) | 65 | static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder) |
64 | { | 66 | { |
65 | return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base); | 67 | return container_of(encoder, struct intel_dp, base.base); |
68 | } | ||
69 | |||
70 | static struct intel_dp *intel_attached_dp(struct drm_connector *connector) | ||
71 | { | ||
72 | return container_of(intel_attached_encoder(connector), | ||
73 | struct intel_dp, base); | ||
66 | } | 74 | } |
67 | 75 | ||
68 | static void intel_dp_link_train(struct intel_dp *intel_dp); | 76 | static void intel_dp_start_link_train(struct intel_dp *intel_dp); |
77 | static void intel_dp_complete_link_train(struct intel_dp *intel_dp); | ||
69 | static void intel_dp_link_down(struct intel_dp *intel_dp); | 78 | static void intel_dp_link_down(struct intel_dp *intel_dp); |
70 | 79 | ||
71 | void | 80 | void |
@@ -130,7 +139,7 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi | |||
130 | struct drm_i915_private *dev_priv = dev->dev_private; | 139 | struct drm_i915_private *dev_priv = dev->dev_private; |
131 | 140 | ||
132 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) | 141 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) |
133 | return (pixel_clock * dev_priv->edp_bpp) / 8; | 142 | return (pixel_clock * dev_priv->edp.bpp + 7) / 8; |
134 | else | 143 | else |
135 | return pixel_clock * 3; | 144 | return pixel_clock * 3; |
136 | } | 145 | } |
@@ -145,8 +154,7 @@ static int | |||
145 | intel_dp_mode_valid(struct drm_connector *connector, | 154 | intel_dp_mode_valid(struct drm_connector *connector, |
146 | struct drm_display_mode *mode) | 155 | struct drm_display_mode *mode) |
147 | { | 156 | { |
148 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 157 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
149 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | ||
150 | struct drm_device *dev = connector->dev; | 158 | struct drm_device *dev = connector->dev; |
151 | struct drm_i915_private *dev_priv = dev->dev_private; | 159 | struct drm_i915_private *dev_priv = dev->dev_private; |
152 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); | 160 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); |
@@ -233,7 +241,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
233 | uint8_t *recv, int recv_size) | 241 | uint8_t *recv, int recv_size) |
234 | { | 242 | { |
235 | uint32_t output_reg = intel_dp->output_reg; | 243 | uint32_t output_reg = intel_dp->output_reg; |
236 | struct drm_device *dev = intel_dp->base.enc.dev; | 244 | struct drm_device *dev = intel_dp->base.base.dev; |
237 | struct drm_i915_private *dev_priv = dev->dev_private; | 245 | struct drm_i915_private *dev_priv = dev->dev_private; |
238 | uint32_t ch_ctl = output_reg + 0x10; | 246 | uint32_t ch_ctl = output_reg + 0x10; |
239 | uint32_t ch_data = ch_ctl + 4; | 247 | uint32_t ch_data = ch_ctl + 4; |
@@ -246,8 +254,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
246 | /* The clock divider is based off the hrawclk, | 254 | /* The clock divider is based off the hrawclk, |
247 | * and would like to run at 2MHz. So, take the | 255 | * and would like to run at 2MHz. So, take the |
248 | * hrawclk value and divide by 2 and use that | 256 | * hrawclk value and divide by 2 and use that |
257 | * | ||
258 | * Note that PCH attached eDP panels should use a 125MHz input | ||
259 | * clock divider. | ||
249 | */ | 260 | */ |
250 | if (IS_eDP(intel_dp)) { | 261 | if (IS_eDP(intel_dp) && !IS_PCH_eDP(intel_dp)) { |
251 | if (IS_GEN6(dev)) | 262 | if (IS_GEN6(dev)) |
252 | aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ | 263 | aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ |
253 | else | 264 | else |
@@ -642,7 +653,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
642 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) { | 653 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) { |
643 | lane_count = intel_dp->lane_count; | 654 | lane_count = intel_dp->lane_count; |
644 | if (IS_PCH_eDP(intel_dp)) | 655 | if (IS_PCH_eDP(intel_dp)) |
645 | bpp = dev_priv->edp_bpp; | 656 | bpp = dev_priv->edp.bpp; |
646 | break; | 657 | break; |
647 | } | 658 | } |
648 | } | 659 | } |
@@ -698,7 +709,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
698 | { | 709 | { |
699 | struct drm_device *dev = encoder->dev; | 710 | struct drm_device *dev = encoder->dev; |
700 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 711 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
701 | struct drm_crtc *crtc = intel_dp->base.enc.crtc; | 712 | struct drm_crtc *crtc = intel_dp->base.base.crtc; |
702 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 713 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
703 | 714 | ||
704 | intel_dp->DP = (DP_VOLTAGE_0_4 | | 715 | intel_dp->DP = (DP_VOLTAGE_0_4 | |
@@ -754,13 +765,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
754 | } | 765 | } |
755 | } | 766 | } |
756 | 767 | ||
757 | static void ironlake_edp_panel_on (struct drm_device *dev) | 768 | /* Returns true if the panel was already on when called */ |
769 | static bool ironlake_edp_panel_on (struct drm_device *dev) | ||
758 | { | 770 | { |
759 | struct drm_i915_private *dev_priv = dev->dev_private; | 771 | struct drm_i915_private *dev_priv = dev->dev_private; |
760 | u32 pp; | 772 | u32 pp; |
761 | 773 | ||
762 | if (I915_READ(PCH_PP_STATUS) & PP_ON) | 774 | if (I915_READ(PCH_PP_STATUS) & PP_ON) |
763 | return; | 775 | return true; |
764 | 776 | ||
765 | pp = I915_READ(PCH_PP_CONTROL); | 777 | pp = I915_READ(PCH_PP_CONTROL); |
766 | 778 | ||
@@ -769,17 +781,24 @@ static void ironlake_edp_panel_on (struct drm_device *dev) | |||
769 | I915_WRITE(PCH_PP_CONTROL, pp); | 781 | I915_WRITE(PCH_PP_CONTROL, pp); |
770 | POSTING_READ(PCH_PP_CONTROL); | 782 | POSTING_READ(PCH_PP_CONTROL); |
771 | 783 | ||
772 | pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; | 784 | pp |= POWER_TARGET_ON; |
773 | I915_WRITE(PCH_PP_CONTROL, pp); | 785 | I915_WRITE(PCH_PP_CONTROL, pp); |
774 | 786 | ||
775 | if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000, 10)) | 787 | /* Ouch. We need to wait here for some panels, like Dell e6510 |
788 | * https://bugs.freedesktop.org/show_bug.cgi?id=29278i | ||
789 | */ | ||
790 | msleep(300); | ||
791 | |||
792 | if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000)) | ||
776 | DRM_ERROR("panel on wait timed out: 0x%08x\n", | 793 | DRM_ERROR("panel on wait timed out: 0x%08x\n", |
777 | I915_READ(PCH_PP_STATUS)); | 794 | I915_READ(PCH_PP_STATUS)); |
778 | 795 | ||
779 | pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD); | 796 | pp &= ~(PANEL_UNLOCK_REGS); |
780 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ | 797 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ |
781 | I915_WRITE(PCH_PP_CONTROL, pp); | 798 | I915_WRITE(PCH_PP_CONTROL, pp); |
782 | POSTING_READ(PCH_PP_CONTROL); | 799 | POSTING_READ(PCH_PP_CONTROL); |
800 | |||
801 | return false; | ||
783 | } | 802 | } |
784 | 803 | ||
785 | static void ironlake_edp_panel_off (struct drm_device *dev) | 804 | static void ironlake_edp_panel_off (struct drm_device *dev) |
@@ -797,14 +816,43 @@ static void ironlake_edp_panel_off (struct drm_device *dev) | |||
797 | pp &= ~POWER_TARGET_ON; | 816 | pp &= ~POWER_TARGET_ON; |
798 | I915_WRITE(PCH_PP_CONTROL, pp); | 817 | I915_WRITE(PCH_PP_CONTROL, pp); |
799 | 818 | ||
800 | if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000, 10)) | 819 | if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000)) |
801 | DRM_ERROR("panel off wait timed out: 0x%08x\n", | 820 | DRM_ERROR("panel off wait timed out: 0x%08x\n", |
802 | I915_READ(PCH_PP_STATUS)); | 821 | I915_READ(PCH_PP_STATUS)); |
803 | 822 | ||
804 | /* Make sure VDD is enabled so DP AUX will work */ | 823 | /* Make sure VDD is enabled so DP AUX will work */ |
805 | pp |= EDP_FORCE_VDD | PANEL_POWER_RESET; /* restore panel reset bit */ | 824 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ |
825 | I915_WRITE(PCH_PP_CONTROL, pp); | ||
826 | POSTING_READ(PCH_PP_CONTROL); | ||
827 | |||
828 | /* Ouch. We need to wait here for some panels, like Dell e6510 | ||
829 | * https://bugs.freedesktop.org/show_bug.cgi?id=29278i | ||
830 | */ | ||
831 | msleep(300); | ||
832 | } | ||
833 | |||
834 | static void ironlake_edp_panel_vdd_on(struct drm_device *dev) | ||
835 | { | ||
836 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
837 | u32 pp; | ||
838 | |||
839 | pp = I915_READ(PCH_PP_CONTROL); | ||
840 | pp |= EDP_FORCE_VDD; | ||
841 | I915_WRITE(PCH_PP_CONTROL, pp); | ||
842 | POSTING_READ(PCH_PP_CONTROL); | ||
843 | msleep(300); | ||
844 | } | ||
845 | |||
846 | static void ironlake_edp_panel_vdd_off(struct drm_device *dev) | ||
847 | { | ||
848 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
849 | u32 pp; | ||
850 | |||
851 | pp = I915_READ(PCH_PP_CONTROL); | ||
852 | pp &= ~EDP_FORCE_VDD; | ||
806 | I915_WRITE(PCH_PP_CONTROL, pp); | 853 | I915_WRITE(PCH_PP_CONTROL, pp); |
807 | POSTING_READ(PCH_PP_CONTROL); | 854 | POSTING_READ(PCH_PP_CONTROL); |
855 | msleep(300); | ||
808 | } | 856 | } |
809 | 857 | ||
810 | static void ironlake_edp_backlight_on (struct drm_device *dev) | 858 | static void ironlake_edp_backlight_on (struct drm_device *dev) |
@@ -850,6 +898,7 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder) | |||
850 | dpa_ctl = I915_READ(DP_A); | 898 | dpa_ctl = I915_READ(DP_A); |
851 | dpa_ctl |= DP_PLL_ENABLE; | 899 | dpa_ctl |= DP_PLL_ENABLE; |
852 | I915_WRITE(DP_A, dpa_ctl); | 900 | I915_WRITE(DP_A, dpa_ctl); |
901 | POSTING_READ(DP_A); | ||
853 | udelay(200); | 902 | udelay(200); |
854 | } | 903 | } |
855 | 904 | ||
@@ -860,9 +909,10 @@ static void intel_dp_prepare(struct drm_encoder *encoder) | |||
860 | struct drm_i915_private *dev_priv = dev->dev_private; | 909 | struct drm_i915_private *dev_priv = dev->dev_private; |
861 | uint32_t dp_reg = I915_READ(intel_dp->output_reg); | 910 | uint32_t dp_reg = I915_READ(intel_dp->output_reg); |
862 | 911 | ||
863 | if (IS_eDP(intel_dp)) { | 912 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) { |
913 | ironlake_edp_panel_off(dev); | ||
864 | ironlake_edp_backlight_off(dev); | 914 | ironlake_edp_backlight_off(dev); |
865 | ironlake_edp_panel_on(dev); | 915 | ironlake_edp_panel_vdd_on(dev); |
866 | ironlake_edp_pll_on(encoder); | 916 | ironlake_edp_pll_on(encoder); |
867 | } | 917 | } |
868 | if (dp_reg & DP_PORT_EN) | 918 | if (dp_reg & DP_PORT_EN) |
@@ -873,14 +923,17 @@ static void intel_dp_commit(struct drm_encoder *encoder) | |||
873 | { | 923 | { |
874 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 924 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
875 | struct drm_device *dev = encoder->dev; | 925 | struct drm_device *dev = encoder->dev; |
876 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
877 | uint32_t dp_reg = I915_READ(intel_dp->output_reg); | ||
878 | 926 | ||
879 | if (!(dp_reg & DP_PORT_EN)) { | 927 | intel_dp_start_link_train(intel_dp); |
880 | intel_dp_link_train(intel_dp); | 928 | |
881 | } | 929 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) |
930 | ironlake_edp_panel_on(dev); | ||
931 | |||
932 | intel_dp_complete_link_train(intel_dp); | ||
933 | |||
882 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) | 934 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) |
883 | ironlake_edp_backlight_on(dev); | 935 | ironlake_edp_backlight_on(dev); |
936 | intel_dp->dpms_mode = DRM_MODE_DPMS_ON; | ||
884 | } | 937 | } |
885 | 938 | ||
886 | static void | 939 | static void |
@@ -902,9 +955,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
902 | ironlake_edp_pll_off(encoder); | 955 | ironlake_edp_pll_off(encoder); |
903 | } else { | 956 | } else { |
904 | if (!(dp_reg & DP_PORT_EN)) { | 957 | if (!(dp_reg & DP_PORT_EN)) { |
958 | intel_dp_start_link_train(intel_dp); | ||
905 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) | 959 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) |
906 | ironlake_edp_panel_on(dev); | 960 | ironlake_edp_panel_on(dev); |
907 | intel_dp_link_train(intel_dp); | 961 | intel_dp_complete_link_train(intel_dp); |
908 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) | 962 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) |
909 | ironlake_edp_backlight_on(dev); | 963 | ironlake_edp_backlight_on(dev); |
910 | } | 964 | } |
@@ -917,14 +971,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
917 | * link status information | 971 | * link status information |
918 | */ | 972 | */ |
919 | static bool | 973 | static bool |
920 | intel_dp_get_link_status(struct intel_dp *intel_dp, | 974 | intel_dp_get_link_status(struct intel_dp *intel_dp) |
921 | uint8_t link_status[DP_LINK_STATUS_SIZE]) | ||
922 | { | 975 | { |
923 | int ret; | 976 | int ret; |
924 | 977 | ||
925 | ret = intel_dp_aux_native_read(intel_dp, | 978 | ret = intel_dp_aux_native_read(intel_dp, |
926 | DP_LANE0_1_STATUS, | 979 | DP_LANE0_1_STATUS, |
927 | link_status, DP_LINK_STATUS_SIZE); | 980 | intel_dp->link_status, DP_LINK_STATUS_SIZE); |
928 | if (ret != DP_LINK_STATUS_SIZE) | 981 | if (ret != DP_LINK_STATUS_SIZE) |
929 | return false; | 982 | return false; |
930 | return true; | 983 | return true; |
@@ -999,18 +1052,15 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing) | |||
999 | } | 1052 | } |
1000 | 1053 | ||
1001 | static void | 1054 | static void |
1002 | intel_get_adjust_train(struct intel_dp *intel_dp, | 1055 | intel_get_adjust_train(struct intel_dp *intel_dp) |
1003 | uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
1004 | int lane_count, | ||
1005 | uint8_t train_set[4]) | ||
1006 | { | 1056 | { |
1007 | uint8_t v = 0; | 1057 | uint8_t v = 0; |
1008 | uint8_t p = 0; | 1058 | uint8_t p = 0; |
1009 | int lane; | 1059 | int lane; |
1010 | 1060 | ||
1011 | for (lane = 0; lane < lane_count; lane++) { | 1061 | for (lane = 0; lane < intel_dp->lane_count; lane++) { |
1012 | uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane); | 1062 | uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane); |
1013 | uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane); | 1063 | uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); |
1014 | 1064 | ||
1015 | if (this_v > v) | 1065 | if (this_v > v) |
1016 | v = this_v; | 1066 | v = this_v; |
@@ -1025,7 +1075,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp, | |||
1025 | p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; | 1075 | p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
1026 | 1076 | ||
1027 | for (lane = 0; lane < 4; lane++) | 1077 | for (lane = 0; lane < 4; lane++) |
1028 | train_set[lane] = v | p; | 1078 | intel_dp->train_set[lane] = v | p; |
1029 | } | 1079 | } |
1030 | 1080 | ||
1031 | static uint32_t | 1081 | static uint32_t |
@@ -1116,18 +1166,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count | |||
1116 | DP_LANE_CHANNEL_EQ_DONE|\ | 1166 | DP_LANE_CHANNEL_EQ_DONE|\ |
1117 | DP_LANE_SYMBOL_LOCKED) | 1167 | DP_LANE_SYMBOL_LOCKED) |
1118 | static bool | 1168 | static bool |
1119 | intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | 1169 | intel_channel_eq_ok(struct intel_dp *intel_dp) |
1120 | { | 1170 | { |
1121 | uint8_t lane_align; | 1171 | uint8_t lane_align; |
1122 | uint8_t lane_status; | 1172 | uint8_t lane_status; |
1123 | int lane; | 1173 | int lane; |
1124 | 1174 | ||
1125 | lane_align = intel_dp_link_status(link_status, | 1175 | lane_align = intel_dp_link_status(intel_dp->link_status, |
1126 | DP_LANE_ALIGN_STATUS_UPDATED); | 1176 | DP_LANE_ALIGN_STATUS_UPDATED); |
1127 | if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) | 1177 | if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) |
1128 | return false; | 1178 | return false; |
1129 | for (lane = 0; lane < lane_count; lane++) { | 1179 | for (lane = 0; lane < intel_dp->lane_count; lane++) { |
1130 | lane_status = intel_get_lane_status(link_status, lane); | 1180 | lane_status = intel_get_lane_status(intel_dp->link_status, lane); |
1131 | if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) | 1181 | if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) |
1132 | return false; | 1182 | return false; |
1133 | } | 1183 | } |
@@ -1137,10 +1187,9 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | |||
1137 | static bool | 1187 | static bool |
1138 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 1188 | intel_dp_set_link_train(struct intel_dp *intel_dp, |
1139 | uint32_t dp_reg_value, | 1189 | uint32_t dp_reg_value, |
1140 | uint8_t dp_train_pat, | 1190 | uint8_t dp_train_pat) |
1141 | uint8_t train_set[4]) | ||
1142 | { | 1191 | { |
1143 | struct drm_device *dev = intel_dp->base.enc.dev; | 1192 | struct drm_device *dev = intel_dp->base.base.dev; |
1144 | struct drm_i915_private *dev_priv = dev->dev_private; | 1193 | struct drm_i915_private *dev_priv = dev->dev_private; |
1145 | int ret; | 1194 | int ret; |
1146 | 1195 | ||
@@ -1152,28 +1201,27 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
1152 | dp_train_pat); | 1201 | dp_train_pat); |
1153 | 1202 | ||
1154 | ret = intel_dp_aux_native_write(intel_dp, | 1203 | ret = intel_dp_aux_native_write(intel_dp, |
1155 | DP_TRAINING_LANE0_SET, train_set, 4); | 1204 | DP_TRAINING_LANE0_SET, |
1205 | intel_dp->train_set, 4); | ||
1156 | if (ret != 4) | 1206 | if (ret != 4) |
1157 | return false; | 1207 | return false; |
1158 | 1208 | ||
1159 | return true; | 1209 | return true; |
1160 | } | 1210 | } |
1161 | 1211 | ||
1212 | /* Enable corresponding port and start training pattern 1 */ | ||
1162 | static void | 1213 | static void |
1163 | intel_dp_link_train(struct intel_dp *intel_dp) | 1214 | intel_dp_start_link_train(struct intel_dp *intel_dp) |
1164 | { | 1215 | { |
1165 | struct drm_device *dev = intel_dp->base.enc.dev; | 1216 | struct drm_device *dev = intel_dp->base.base.dev; |
1166 | struct drm_i915_private *dev_priv = dev->dev_private; | 1217 | struct drm_i915_private *dev_priv = dev->dev_private; |
1167 | uint8_t train_set[4]; | 1218 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc); |
1168 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
1169 | int i; | 1219 | int i; |
1170 | uint8_t voltage; | 1220 | uint8_t voltage; |
1171 | bool clock_recovery = false; | 1221 | bool clock_recovery = false; |
1172 | bool channel_eq = false; | ||
1173 | int tries; | 1222 | int tries; |
1174 | u32 reg; | 1223 | u32 reg; |
1175 | uint32_t DP = intel_dp->DP; | 1224 | uint32_t DP = intel_dp->DP; |
1176 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); | ||
1177 | 1225 | ||
1178 | /* Enable output, wait for it to become active */ | 1226 | /* Enable output, wait for it to become active */ |
1179 | I915_WRITE(intel_dp->output_reg, intel_dp->DP); | 1227 | I915_WRITE(intel_dp->output_reg, intel_dp->DP); |
@@ -1190,18 +1238,18 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1190 | DP &= ~DP_LINK_TRAIN_MASK_CPT; | 1238 | DP &= ~DP_LINK_TRAIN_MASK_CPT; |
1191 | else | 1239 | else |
1192 | DP &= ~DP_LINK_TRAIN_MASK; | 1240 | DP &= ~DP_LINK_TRAIN_MASK; |
1193 | memset(train_set, 0, 4); | 1241 | memset(intel_dp->train_set, 0, 4); |
1194 | voltage = 0xff; | 1242 | voltage = 0xff; |
1195 | tries = 0; | 1243 | tries = 0; |
1196 | clock_recovery = false; | 1244 | clock_recovery = false; |
1197 | for (;;) { | 1245 | for (;;) { |
1198 | /* Use train_set[0] to set the voltage and pre emphasis values */ | 1246 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ |
1199 | uint32_t signal_levels; | 1247 | uint32_t signal_levels; |
1200 | if (IS_GEN6(dev) && IS_eDP(intel_dp)) { | 1248 | if (IS_GEN6(dev) && IS_eDP(intel_dp)) { |
1201 | signal_levels = intel_gen6_edp_signal_levels(train_set[0]); | 1249 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
1202 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1250 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
1203 | } else { | 1251 | } else { |
1204 | signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count); | 1252 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); |
1205 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1253 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
1206 | } | 1254 | } |
1207 | 1255 | ||
@@ -1211,51 +1259,64 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1211 | reg = DP | DP_LINK_TRAIN_PAT_1; | 1259 | reg = DP | DP_LINK_TRAIN_PAT_1; |
1212 | 1260 | ||
1213 | if (!intel_dp_set_link_train(intel_dp, reg, | 1261 | if (!intel_dp_set_link_train(intel_dp, reg, |
1214 | DP_TRAINING_PATTERN_1, train_set)) | 1262 | DP_TRAINING_PATTERN_1)) |
1215 | break; | 1263 | break; |
1216 | /* Set training pattern 1 */ | 1264 | /* Set training pattern 1 */ |
1217 | 1265 | ||
1218 | udelay(100); | 1266 | udelay(100); |
1219 | if (!intel_dp_get_link_status(intel_dp, link_status)) | 1267 | if (!intel_dp_get_link_status(intel_dp)) |
1220 | break; | 1268 | break; |
1221 | 1269 | ||
1222 | if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) { | 1270 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
1223 | clock_recovery = true; | 1271 | clock_recovery = true; |
1224 | break; | 1272 | break; |
1225 | } | 1273 | } |
1226 | 1274 | ||
1227 | /* Check to see if we've tried the max voltage */ | 1275 | /* Check to see if we've tried the max voltage */ |
1228 | for (i = 0; i < intel_dp->lane_count; i++) | 1276 | for (i = 0; i < intel_dp->lane_count; i++) |
1229 | if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | 1277 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
1230 | break; | 1278 | break; |
1231 | if (i == intel_dp->lane_count) | 1279 | if (i == intel_dp->lane_count) |
1232 | break; | 1280 | break; |
1233 | 1281 | ||
1234 | /* Check to see if we've tried the same voltage 5 times */ | 1282 | /* Check to see if we've tried the same voltage 5 times */ |
1235 | if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | 1283 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
1236 | ++tries; | 1284 | ++tries; |
1237 | if (tries == 5) | 1285 | if (tries == 5) |
1238 | break; | 1286 | break; |
1239 | } else | 1287 | } else |
1240 | tries = 0; | 1288 | tries = 0; |
1241 | voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | 1289 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
1242 | 1290 | ||
1243 | /* Compute new train_set as requested by target */ | 1291 | /* Compute new intel_dp->train_set as requested by target */ |
1244 | intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set); | 1292 | intel_get_adjust_train(intel_dp); |
1245 | } | 1293 | } |
1246 | 1294 | ||
1295 | intel_dp->DP = DP; | ||
1296 | } | ||
1297 | |||
1298 | static void | ||
1299 | intel_dp_complete_link_train(struct intel_dp *intel_dp) | ||
1300 | { | ||
1301 | struct drm_device *dev = intel_dp->base.base.dev; | ||
1302 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1303 | bool channel_eq = false; | ||
1304 | int tries; | ||
1305 | u32 reg; | ||
1306 | uint32_t DP = intel_dp->DP; | ||
1307 | |||
1247 | /* channel equalization */ | 1308 | /* channel equalization */ |
1248 | tries = 0; | 1309 | tries = 0; |
1249 | channel_eq = false; | 1310 | channel_eq = false; |
1250 | for (;;) { | 1311 | for (;;) { |
1251 | /* Use train_set[0] to set the voltage and pre emphasis values */ | 1312 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ |
1252 | uint32_t signal_levels; | 1313 | uint32_t signal_levels; |
1253 | 1314 | ||
1254 | if (IS_GEN6(dev) && IS_eDP(intel_dp)) { | 1315 | if (IS_GEN6(dev) && IS_eDP(intel_dp)) { |
1255 | signal_levels = intel_gen6_edp_signal_levels(train_set[0]); | 1316 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
1256 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1317 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
1257 | } else { | 1318 | } else { |
1258 | signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count); | 1319 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); |
1259 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1320 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
1260 | } | 1321 | } |
1261 | 1322 | ||
@@ -1266,14 +1327,14 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1266 | 1327 | ||
1267 | /* channel eq pattern */ | 1328 | /* channel eq pattern */ |
1268 | if (!intel_dp_set_link_train(intel_dp, reg, | 1329 | if (!intel_dp_set_link_train(intel_dp, reg, |
1269 | DP_TRAINING_PATTERN_2, train_set)) | 1330 | DP_TRAINING_PATTERN_2)) |
1270 | break; | 1331 | break; |
1271 | 1332 | ||
1272 | udelay(400); | 1333 | udelay(400); |
1273 | if (!intel_dp_get_link_status(intel_dp, link_status)) | 1334 | if (!intel_dp_get_link_status(intel_dp)) |
1274 | break; | 1335 | break; |
1275 | 1336 | ||
1276 | if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) { | 1337 | if (intel_channel_eq_ok(intel_dp)) { |
1277 | channel_eq = true; | 1338 | channel_eq = true; |
1278 | break; | 1339 | break; |
1279 | } | 1340 | } |
@@ -1282,8 +1343,8 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1282 | if (tries > 5) | 1343 | if (tries > 5) |
1283 | break; | 1344 | break; |
1284 | 1345 | ||
1285 | /* Compute new train_set as requested by target */ | 1346 | /* Compute new intel_dp->train_set as requested by target */ |
1286 | intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set); | 1347 | intel_get_adjust_train(intel_dp); |
1287 | ++tries; | 1348 | ++tries; |
1288 | } | 1349 | } |
1289 | 1350 | ||
@@ -1301,7 +1362,7 @@ intel_dp_link_train(struct intel_dp *intel_dp) | |||
1301 | static void | 1362 | static void |
1302 | intel_dp_link_down(struct intel_dp *intel_dp) | 1363 | intel_dp_link_down(struct intel_dp *intel_dp) |
1303 | { | 1364 | { |
1304 | struct drm_device *dev = intel_dp->base.enc.dev; | 1365 | struct drm_device *dev = intel_dp->base.base.dev; |
1305 | struct drm_i915_private *dev_priv = dev->dev_private; | 1366 | struct drm_i915_private *dev_priv = dev->dev_private; |
1306 | uint32_t DP = intel_dp->DP; | 1367 | uint32_t DP = intel_dp->DP; |
1307 | 1368 | ||
@@ -1317,14 +1378,13 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
1317 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) { | 1378 | if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) { |
1318 | DP &= ~DP_LINK_TRAIN_MASK_CPT; | 1379 | DP &= ~DP_LINK_TRAIN_MASK_CPT; |
1319 | I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); | 1380 | I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); |
1320 | POSTING_READ(intel_dp->output_reg); | ||
1321 | } else { | 1381 | } else { |
1322 | DP &= ~DP_LINK_TRAIN_MASK; | 1382 | DP &= ~DP_LINK_TRAIN_MASK; |
1323 | I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); | 1383 | I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); |
1324 | POSTING_READ(intel_dp->output_reg); | ||
1325 | } | 1384 | } |
1385 | POSTING_READ(intel_dp->output_reg); | ||
1326 | 1386 | ||
1327 | udelay(17000); | 1387 | msleep(17); |
1328 | 1388 | ||
1329 | if (IS_eDP(intel_dp)) | 1389 | if (IS_eDP(intel_dp)) |
1330 | DP |= DP_LINK_TRAIN_OFF; | 1390 | DP |= DP_LINK_TRAIN_OFF; |
@@ -1344,27 +1404,29 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
1344 | static void | 1404 | static void |
1345 | intel_dp_check_link_status(struct intel_dp *intel_dp) | 1405 | intel_dp_check_link_status(struct intel_dp *intel_dp) |
1346 | { | 1406 | { |
1347 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | 1407 | if (!intel_dp->base.base.crtc) |
1348 | |||
1349 | if (!intel_dp->base.enc.crtc) | ||
1350 | return; | 1408 | return; |
1351 | 1409 | ||
1352 | if (!intel_dp_get_link_status(intel_dp, link_status)) { | 1410 | if (!intel_dp_get_link_status(intel_dp)) { |
1353 | intel_dp_link_down(intel_dp); | 1411 | intel_dp_link_down(intel_dp); |
1354 | return; | 1412 | return; |
1355 | } | 1413 | } |
1356 | 1414 | ||
1357 | if (!intel_channel_eq_ok(link_status, intel_dp->lane_count)) | 1415 | if (!intel_channel_eq_ok(intel_dp)) { |
1358 | intel_dp_link_train(intel_dp); | 1416 | intel_dp_start_link_train(intel_dp); |
1417 | intel_dp_complete_link_train(intel_dp); | ||
1418 | } | ||
1359 | } | 1419 | } |
1360 | 1420 | ||
1361 | static enum drm_connector_status | 1421 | static enum drm_connector_status |
1362 | ironlake_dp_detect(struct drm_connector *connector) | 1422 | ironlake_dp_detect(struct drm_connector *connector) |
1363 | { | 1423 | { |
1364 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1424 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
1365 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | ||
1366 | enum drm_connector_status status; | 1425 | enum drm_connector_status status; |
1367 | 1426 | ||
1427 | /* Panel needs power for AUX to work */ | ||
1428 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) | ||
1429 | ironlake_edp_panel_vdd_on(connector->dev); | ||
1368 | status = connector_status_disconnected; | 1430 | status = connector_status_disconnected; |
1369 | if (intel_dp_aux_native_read(intel_dp, | 1431 | if (intel_dp_aux_native_read(intel_dp, |
1370 | 0x000, intel_dp->dpcd, | 1432 | 0x000, intel_dp->dpcd, |
@@ -1375,6 +1437,8 @@ ironlake_dp_detect(struct drm_connector *connector) | |||
1375 | } | 1437 | } |
1376 | DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], | 1438 | DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], |
1377 | intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]); | 1439 | intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]); |
1440 | if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) | ||
1441 | ironlake_edp_panel_vdd_off(connector->dev); | ||
1378 | return status; | 1442 | return status; |
1379 | } | 1443 | } |
1380 | 1444 | ||
@@ -1387,9 +1451,8 @@ ironlake_dp_detect(struct drm_connector *connector) | |||
1387 | static enum drm_connector_status | 1451 | static enum drm_connector_status |
1388 | intel_dp_detect(struct drm_connector *connector, bool force) | 1452 | intel_dp_detect(struct drm_connector *connector, bool force) |
1389 | { | 1453 | { |
1390 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1454 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
1391 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1455 | struct drm_device *dev = intel_dp->base.base.dev; |
1392 | struct drm_device *dev = intel_dp->base.enc.dev; | ||
1393 | struct drm_i915_private *dev_priv = dev->dev_private; | 1456 | struct drm_i915_private *dev_priv = dev->dev_private; |
1394 | uint32_t temp, bit; | 1457 | uint32_t temp, bit; |
1395 | enum drm_connector_status status; | 1458 | enum drm_connector_status status; |
@@ -1431,16 +1494,15 @@ intel_dp_detect(struct drm_connector *connector, bool force) | |||
1431 | 1494 | ||
1432 | static int intel_dp_get_modes(struct drm_connector *connector) | 1495 | static int intel_dp_get_modes(struct drm_connector *connector) |
1433 | { | 1496 | { |
1434 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1497 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
1435 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1498 | struct drm_device *dev = intel_dp->base.base.dev; |
1436 | struct drm_device *dev = intel_dp->base.enc.dev; | ||
1437 | struct drm_i915_private *dev_priv = dev->dev_private; | 1499 | struct drm_i915_private *dev_priv = dev->dev_private; |
1438 | int ret; | 1500 | int ret; |
1439 | 1501 | ||
1440 | /* We should parse the EDID data and find out if it has an audio sink | 1502 | /* We should parse the EDID data and find out if it has an audio sink |
1441 | */ | 1503 | */ |
1442 | 1504 | ||
1443 | ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus); | 1505 | ret = intel_ddc_get_modes(connector, &intel_dp->adapter); |
1444 | if (ret) { | 1506 | if (ret) { |
1445 | if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && | 1507 | if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && |
1446 | !dev_priv->panel_fixed_mode) { | 1508 | !dev_priv->panel_fixed_mode) { |
@@ -1478,6 +1540,15 @@ intel_dp_destroy (struct drm_connector *connector) | |||
1478 | kfree(connector); | 1540 | kfree(connector); |
1479 | } | 1541 | } |
1480 | 1542 | ||
1543 | static void intel_dp_encoder_destroy(struct drm_encoder *encoder) | ||
1544 | { | ||
1545 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | ||
1546 | |||
1547 | i2c_del_adapter(&intel_dp->adapter); | ||
1548 | drm_encoder_cleanup(encoder); | ||
1549 | kfree(intel_dp); | ||
1550 | } | ||
1551 | |||
1481 | static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { | 1552 | static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { |
1482 | .dpms = intel_dp_dpms, | 1553 | .dpms = intel_dp_dpms, |
1483 | .mode_fixup = intel_dp_mode_fixup, | 1554 | .mode_fixup = intel_dp_mode_fixup, |
@@ -1496,14 +1567,14 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { | |||
1496 | static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { | 1567 | static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { |
1497 | .get_modes = intel_dp_get_modes, | 1568 | .get_modes = intel_dp_get_modes, |
1498 | .mode_valid = intel_dp_mode_valid, | 1569 | .mode_valid = intel_dp_mode_valid, |
1499 | .best_encoder = intel_attached_encoder, | 1570 | .best_encoder = intel_best_encoder, |
1500 | }; | 1571 | }; |
1501 | 1572 | ||
1502 | static const struct drm_encoder_funcs intel_dp_enc_funcs = { | 1573 | static const struct drm_encoder_funcs intel_dp_enc_funcs = { |
1503 | .destroy = intel_encoder_destroy, | 1574 | .destroy = intel_dp_encoder_destroy, |
1504 | }; | 1575 | }; |
1505 | 1576 | ||
1506 | void | 1577 | static void |
1507 | intel_dp_hot_plug(struct intel_encoder *intel_encoder) | 1578 | intel_dp_hot_plug(struct intel_encoder *intel_encoder) |
1508 | { | 1579 | { |
1509 | struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); | 1580 | struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); |
@@ -1612,12 +1683,11 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1612 | intel_dp->has_audio = false; | 1683 | intel_dp->has_audio = false; |
1613 | intel_dp->dpms_mode = DRM_MODE_DPMS_ON; | 1684 | intel_dp->dpms_mode = DRM_MODE_DPMS_ON; |
1614 | 1685 | ||
1615 | drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs, | 1686 | drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs, |
1616 | DRM_MODE_ENCODER_TMDS); | 1687 | DRM_MODE_ENCODER_TMDS); |
1617 | drm_encoder_helper_add(&intel_encoder->enc, &intel_dp_helper_funcs); | 1688 | drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs); |
1618 | 1689 | ||
1619 | drm_mode_connector_attach_encoder(&intel_connector->base, | 1690 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
1620 | &intel_encoder->enc); | ||
1621 | drm_sysfs_connector_add(connector); | 1691 | drm_sysfs_connector_add(connector); |
1622 | 1692 | ||
1623 | /* Set up the DDC bus. */ | 1693 | /* Set up the DDC bus. */ |
@@ -1647,7 +1717,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1647 | 1717 | ||
1648 | intel_dp_i2c_init(intel_dp, intel_connector, name); | 1718 | intel_dp_i2c_init(intel_dp, intel_connector, name); |
1649 | 1719 | ||
1650 | intel_encoder->ddc_bus = &intel_dp->adapter; | ||
1651 | intel_encoder->hot_plug = intel_dp_hot_plug; | 1720 | intel_encoder->hot_plug = intel_dp_hot_plug; |
1652 | 1721 | ||
1653 | if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) { | 1722 | if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) { |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8828b3ac6414..40e99bf27ff7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -26,14 +26,12 @@ | |||
26 | #define __INTEL_DRV_H__ | 26 | #define __INTEL_DRV_H__ |
27 | 27 | ||
28 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
29 | #include <linux/i2c-id.h> | ||
30 | #include <linux/i2c-algo-bit.h> | ||
31 | #include "i915_drv.h" | 29 | #include "i915_drv.h" |
32 | #include "drm_crtc.h" | 30 | #include "drm_crtc.h" |
33 | |||
34 | #include "drm_crtc_helper.h" | 31 | #include "drm_crtc_helper.h" |
32 | #include "drm_fb_helper.h" | ||
35 | 33 | ||
36 | #define wait_for(COND, MS, W) ({ \ | 34 | #define _wait_for(COND, MS, W) ({ \ |
37 | unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ | 35 | unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ |
38 | int ret__ = 0; \ | 36 | int ret__ = 0; \ |
39 | while (! (COND)) { \ | 37 | while (! (COND)) { \ |
@@ -41,11 +39,24 @@ | |||
41 | ret__ = -ETIMEDOUT; \ | 39 | ret__ = -ETIMEDOUT; \ |
42 | break; \ | 40 | break; \ |
43 | } \ | 41 | } \ |
44 | if (W) msleep(W); \ | 42 | if (W && !in_dbg_master()) msleep(W); \ |
45 | } \ | 43 | } \ |
46 | ret__; \ | 44 | ret__; \ |
47 | }) | 45 | }) |
48 | 46 | ||
47 | #define wait_for(COND, MS) _wait_for(COND, MS, 1) | ||
48 | #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) | ||
49 | |||
50 | #define MSLEEP(x) do { \ | ||
51 | if (in_dbg_master()) \ | ||
52 | mdelay(x); \ | ||
53 | else \ | ||
54 | msleep(x); \ | ||
55 | } while(0) | ||
56 | |||
57 | #define KHz(x) (1000*x) | ||
58 | #define MHz(x) KHz(1000*x) | ||
59 | |||
49 | /* | 60 | /* |
50 | * Display related stuff | 61 | * Display related stuff |
51 | */ | 62 | */ |
@@ -96,24 +107,39 @@ | |||
96 | #define INTEL_DVO_CHIP_TMDS 2 | 107 | #define INTEL_DVO_CHIP_TMDS 2 |
97 | #define INTEL_DVO_CHIP_TVOUT 4 | 108 | #define INTEL_DVO_CHIP_TVOUT 4 |
98 | 109 | ||
99 | struct intel_i2c_chan { | 110 | /* drm_display_mode->private_flags */ |
100 | struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */ | 111 | #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) |
101 | u32 reg; /* GPIO reg */ | 112 | #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) |
102 | struct i2c_adapter adapter; | 113 | |
103 | struct i2c_algo_bit_data algo; | 114 | static inline void |
104 | }; | 115 | intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, |
116 | int multiplier) | ||
117 | { | ||
118 | mode->clock *= multiplier; | ||
119 | mode->private_flags |= multiplier; | ||
120 | } | ||
121 | |||
122 | static inline int | ||
123 | intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode) | ||
124 | { | ||
125 | return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT; | ||
126 | } | ||
105 | 127 | ||
106 | struct intel_framebuffer { | 128 | struct intel_framebuffer { |
107 | struct drm_framebuffer base; | 129 | struct drm_framebuffer base; |
108 | struct drm_gem_object *obj; | 130 | struct drm_gem_object *obj; |
109 | }; | 131 | }; |
110 | 132 | ||
133 | struct intel_fbdev { | ||
134 | struct drm_fb_helper helper; | ||
135 | struct intel_framebuffer ifb; | ||
136 | struct list_head fbdev_list; | ||
137 | struct drm_display_mode *our_mode; | ||
138 | }; | ||
111 | 139 | ||
112 | struct intel_encoder { | 140 | struct intel_encoder { |
113 | struct drm_encoder enc; | 141 | struct drm_encoder base; |
114 | int type; | 142 | int type; |
115 | struct i2c_adapter *i2c_bus; | ||
116 | struct i2c_adapter *ddc_bus; | ||
117 | bool load_detect_temp; | 143 | bool load_detect_temp; |
118 | bool needs_tv_clock; | 144 | bool needs_tv_clock; |
119 | void (*hot_plug)(struct intel_encoder *); | 145 | void (*hot_plug)(struct intel_encoder *); |
@@ -123,32 +149,7 @@ struct intel_encoder { | |||
123 | 149 | ||
124 | struct intel_connector { | 150 | struct intel_connector { |
125 | struct drm_connector base; | 151 | struct drm_connector base; |
126 | }; | 152 | struct intel_encoder *encoder; |
127 | |||
128 | struct intel_crtc; | ||
129 | struct intel_overlay { | ||
130 | struct drm_device *dev; | ||
131 | struct intel_crtc *crtc; | ||
132 | struct drm_i915_gem_object *vid_bo; | ||
133 | struct drm_i915_gem_object *old_vid_bo; | ||
134 | int active; | ||
135 | int pfit_active; | ||
136 | u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ | ||
137 | u32 color_key; | ||
138 | u32 brightness, contrast, saturation; | ||
139 | u32 old_xscale, old_yscale; | ||
140 | /* register access */ | ||
141 | u32 flip_addr; | ||
142 | struct drm_i915_gem_object *reg_bo; | ||
143 | void *virt_addr; | ||
144 | /* flip handling */ | ||
145 | uint32_t last_flip_req; | ||
146 | int hw_wedged; | ||
147 | #define HW_WEDGED 1 | ||
148 | #define NEEDS_WAIT_FOR_FLIP 2 | ||
149 | #define RELEASE_OLD_VID 3 | ||
150 | #define SWITCH_OFF_STAGE_1 4 | ||
151 | #define SWITCH_OFF_STAGE_2 5 | ||
152 | }; | 153 | }; |
153 | 154 | ||
154 | struct intel_crtc { | 155 | struct intel_crtc { |
@@ -157,6 +158,7 @@ struct intel_crtc { | |||
157 | enum plane plane; | 158 | enum plane plane; |
158 | u8 lut_r[256], lut_g[256], lut_b[256]; | 159 | u8 lut_r[256], lut_g[256], lut_b[256]; |
159 | int dpms_mode; | 160 | int dpms_mode; |
161 | bool active; /* is the crtc on? independent of the dpms mode */ | ||
160 | bool busy; /* is scanout buffer being updated frequently? */ | 162 | bool busy; /* is scanout buffer being updated frequently? */ |
161 | struct timer_list idle_timer; | 163 | struct timer_list idle_timer; |
162 | bool lowfreq_avail; | 164 | bool lowfreq_avail; |
@@ -168,14 +170,21 @@ struct intel_crtc { | |||
168 | uint32_t cursor_addr; | 170 | uint32_t cursor_addr; |
169 | int16_t cursor_x, cursor_y; | 171 | int16_t cursor_x, cursor_y; |
170 | int16_t cursor_width, cursor_height; | 172 | int16_t cursor_width, cursor_height; |
171 | bool cursor_visible, cursor_on; | 173 | bool cursor_visible; |
172 | }; | 174 | }; |
173 | 175 | ||
174 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) | 176 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) |
175 | #define to_intel_connector(x) container_of(x, struct intel_connector, base) | 177 | #define to_intel_connector(x) container_of(x, struct intel_connector, base) |
176 | #define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc) | 178 | #define to_intel_encoder(x) container_of(x, struct intel_encoder, base) |
177 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) | 179 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) |
178 | 180 | ||
181 | static inline struct drm_crtc * | ||
182 | intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) | ||
183 | { | ||
184 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
185 | return dev_priv->pipe_to_crtc_mapping[pipe]; | ||
186 | } | ||
187 | |||
179 | struct intel_unpin_work { | 188 | struct intel_unpin_work { |
180 | struct work_struct work; | 189 | struct work_struct work; |
181 | struct drm_device *dev; | 190 | struct drm_device *dev; |
@@ -186,13 +195,8 @@ struct intel_unpin_work { | |||
186 | bool enable_stall_check; | 195 | bool enable_stall_check; |
187 | }; | 196 | }; |
188 | 197 | ||
189 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, | ||
190 | const char *name); | ||
191 | void intel_i2c_destroy(struct i2c_adapter *adapter); | ||
192 | int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); | 198 | int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); |
193 | extern bool intel_ddc_probe(struct intel_encoder *intel_encoder); | 199 | extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); |
194 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); | ||
195 | void intel_i2c_reset_gmbus(struct drm_device *dev); | ||
196 | 200 | ||
197 | extern void intel_crt_init(struct drm_device *dev); | 201 | extern void intel_crt_init(struct drm_device *dev); |
198 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); | 202 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); |
@@ -209,28 +213,37 @@ extern bool intel_pch_has_edp(struct drm_crtc *crtc); | |||
209 | extern bool intel_dpd_is_edp(struct drm_device *dev); | 213 | extern bool intel_dpd_is_edp(struct drm_device *dev); |
210 | extern void intel_edp_link_config (struct intel_encoder *, int *, int *); | 214 | extern void intel_edp_link_config (struct intel_encoder *, int *, int *); |
211 | 215 | ||
212 | 216 | /* intel_panel.c */ | |
213 | extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | 217 | extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, |
214 | struct drm_display_mode *adjusted_mode); | 218 | struct drm_display_mode *adjusted_mode); |
215 | extern void intel_pch_panel_fitting(struct drm_device *dev, | 219 | extern void intel_pch_panel_fitting(struct drm_device *dev, |
216 | int fitting_mode, | 220 | int fitting_mode, |
217 | struct drm_display_mode *mode, | 221 | struct drm_display_mode *mode, |
218 | struct drm_display_mode *adjusted_mode); | 222 | struct drm_display_mode *adjusted_mode); |
223 | extern u32 intel_panel_get_max_backlight(struct drm_device *dev); | ||
224 | extern u32 intel_panel_get_backlight(struct drm_device *dev); | ||
225 | extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); | ||
219 | 226 | ||
220 | extern int intel_panel_fitter_pipe (struct drm_device *dev); | ||
221 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); | 227 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); |
222 | extern void intel_encoder_prepare (struct drm_encoder *encoder); | 228 | extern void intel_encoder_prepare (struct drm_encoder *encoder); |
223 | extern void intel_encoder_commit (struct drm_encoder *encoder); | 229 | extern void intel_encoder_commit (struct drm_encoder *encoder); |
224 | extern void intel_encoder_destroy(struct drm_encoder *encoder); | 230 | extern void intel_encoder_destroy(struct drm_encoder *encoder); |
225 | 231 | ||
226 | extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector); | 232 | static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) |
233 | { | ||
234 | return to_intel_connector(connector)->encoder; | ||
235 | } | ||
236 | |||
237 | extern void intel_connector_attach_encoder(struct intel_connector *connector, | ||
238 | struct intel_encoder *encoder); | ||
239 | extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); | ||
227 | 240 | ||
228 | extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, | 241 | extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, |
229 | struct drm_crtc *crtc); | 242 | struct drm_crtc *crtc); |
230 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | 243 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
231 | struct drm_file *file_priv); | 244 | struct drm_file *file_priv); |
232 | extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); | 245 | extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); |
233 | extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); | 246 | extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); |
234 | extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, | 247 | extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, |
235 | struct drm_connector *connector, | 248 | struct drm_connector *connector, |
236 | struct drm_display_mode *mode, | 249 | struct drm_display_mode *mode, |
@@ -252,7 +265,8 @@ extern void ironlake_enable_drps(struct drm_device *dev); | |||
252 | extern void ironlake_disable_drps(struct drm_device *dev); | 265 | extern void ironlake_disable_drps(struct drm_device *dev); |
253 | 266 | ||
254 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, | 267 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, |
255 | struct drm_gem_object *obj); | 268 | struct drm_gem_object *obj, |
269 | bool pipelined); | ||
256 | 270 | ||
257 | extern int intel_framebuffer_init(struct drm_device *dev, | 271 | extern int intel_framebuffer_init(struct drm_device *dev, |
258 | struct intel_framebuffer *ifb, | 272 | struct intel_framebuffer *ifb, |
@@ -267,9 +281,8 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); | |||
267 | 281 | ||
268 | extern void intel_setup_overlay(struct drm_device *dev); | 282 | extern void intel_setup_overlay(struct drm_device *dev); |
269 | extern void intel_cleanup_overlay(struct drm_device *dev); | 283 | extern void intel_cleanup_overlay(struct drm_device *dev); |
270 | extern int intel_overlay_switch_off(struct intel_overlay *overlay); | 284 | extern int intel_overlay_switch_off(struct intel_overlay *overlay, |
271 | extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, | 285 | bool interruptible); |
272 | int interruptible); | ||
273 | extern int intel_overlay_put_image(struct drm_device *dev, void *data, | 286 | extern int intel_overlay_put_image(struct drm_device *dev, void *data, |
274 | struct drm_file *file_priv); | 287 | struct drm_file *file_priv); |
275 | extern int intel_overlay_attrs(struct drm_device *dev, void *data, | 288 | extern int intel_overlay_attrs(struct drm_device *dev, void *data, |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 7c9ec1472d46..ea373283c93b 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
@@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { | |||
72 | .name = "ch7017", | 72 | .name = "ch7017", |
73 | .dvo_reg = DVOC, | 73 | .dvo_reg = DVOC, |
74 | .slave_addr = 0x75, | 74 | .slave_addr = 0x75, |
75 | .gpio = GPIOE, | 75 | .gpio = GMBUS_PORT_DPB, |
76 | .dev_ops = &ch7017_ops, | 76 | .dev_ops = &ch7017_ops, |
77 | } | 77 | } |
78 | }; | 78 | }; |
@@ -88,7 +88,13 @@ struct intel_dvo { | |||
88 | 88 | ||
89 | static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder) | 89 | static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder) |
90 | { | 90 | { |
91 | return container_of(enc_to_intel_encoder(encoder), struct intel_dvo, base); | 91 | return container_of(encoder, struct intel_dvo, base.base); |
92 | } | ||
93 | |||
94 | static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector) | ||
95 | { | ||
96 | return container_of(intel_attached_encoder(connector), | ||
97 | struct intel_dvo, base); | ||
92 | } | 98 | } |
93 | 99 | ||
94 | static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) | 100 | static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) |
@@ -112,8 +118,7 @@ static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) | |||
112 | static int intel_dvo_mode_valid(struct drm_connector *connector, | 118 | static int intel_dvo_mode_valid(struct drm_connector *connector, |
113 | struct drm_display_mode *mode) | 119 | struct drm_display_mode *mode) |
114 | { | 120 | { |
115 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 121 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
116 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | ||
117 | 122 | ||
118 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 123 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
119 | return MODE_NO_DBLESCAN; | 124 | return MODE_NO_DBLESCAN; |
@@ -224,23 +229,22 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, | |||
224 | static enum drm_connector_status | 229 | static enum drm_connector_status |
225 | intel_dvo_detect(struct drm_connector *connector, bool force) | 230 | intel_dvo_detect(struct drm_connector *connector, bool force) |
226 | { | 231 | { |
227 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 232 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
228 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | ||
229 | |||
230 | return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); | 233 | return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); |
231 | } | 234 | } |
232 | 235 | ||
233 | static int intel_dvo_get_modes(struct drm_connector *connector) | 236 | static int intel_dvo_get_modes(struct drm_connector *connector) |
234 | { | 237 | { |
235 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 238 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
236 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | 239 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
237 | 240 | ||
238 | /* We should probably have an i2c driver get_modes function for those | 241 | /* We should probably have an i2c driver get_modes function for those |
239 | * devices which will have a fixed set of modes determined by the chip | 242 | * devices which will have a fixed set of modes determined by the chip |
240 | * (TV-out, for example), but for now with just TMDS and LVDS, | 243 | * (TV-out, for example), but for now with just TMDS and LVDS, |
241 | * that's not the case. | 244 | * that's not the case. |
242 | */ | 245 | */ |
243 | intel_ddc_get_modes(connector, intel_dvo->base.ddc_bus); | 246 | intel_ddc_get_modes(connector, |
247 | &dev_priv->gmbus[GMBUS_PORT_DPC].adapter); | ||
244 | if (!list_empty(&connector->probed_modes)) | 248 | if (!list_empty(&connector->probed_modes)) |
245 | return 1; | 249 | return 1; |
246 | 250 | ||
@@ -281,7 +285,7 @@ static const struct drm_connector_funcs intel_dvo_connector_funcs = { | |||
281 | static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = { | 285 | static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = { |
282 | .mode_valid = intel_dvo_mode_valid, | 286 | .mode_valid = intel_dvo_mode_valid, |
283 | .get_modes = intel_dvo_get_modes, | 287 | .get_modes = intel_dvo_get_modes, |
284 | .best_encoder = intel_attached_encoder, | 288 | .best_encoder = intel_best_encoder, |
285 | }; | 289 | }; |
286 | 290 | ||
287 | static void intel_dvo_enc_destroy(struct drm_encoder *encoder) | 291 | static void intel_dvo_enc_destroy(struct drm_encoder *encoder) |
@@ -311,8 +315,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector) | |||
311 | { | 315 | { |
312 | struct drm_device *dev = connector->dev; | 316 | struct drm_device *dev = connector->dev; |
313 | struct drm_i915_private *dev_priv = dev->dev_private; | 317 | struct drm_i915_private *dev_priv = dev->dev_private; |
314 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 318 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
315 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | ||
316 | uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); | 319 | uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); |
317 | struct drm_display_mode *mode = NULL; | 320 | struct drm_display_mode *mode = NULL; |
318 | 321 | ||
@@ -323,7 +326,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector) | |||
323 | struct drm_crtc *crtc; | 326 | struct drm_crtc *crtc; |
324 | int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; | 327 | int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; |
325 | 328 | ||
326 | crtc = intel_get_crtc_from_pipe(dev, pipe); | 329 | crtc = intel_get_crtc_for_pipe(dev, pipe); |
327 | if (crtc) { | 330 | if (crtc) { |
328 | mode = intel_crtc_mode_get(dev, crtc); | 331 | mode = intel_crtc_mode_get(dev, crtc); |
329 | if (mode) { | 332 | if (mode) { |
@@ -341,11 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector) | |||
341 | 344 | ||
342 | void intel_dvo_init(struct drm_device *dev) | 345 | void intel_dvo_init(struct drm_device *dev) |
343 | { | 346 | { |
347 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
344 | struct intel_encoder *intel_encoder; | 348 | struct intel_encoder *intel_encoder; |
345 | struct intel_dvo *intel_dvo; | 349 | struct intel_dvo *intel_dvo; |
346 | struct intel_connector *intel_connector; | 350 | struct intel_connector *intel_connector; |
347 | struct i2c_adapter *i2cbus = NULL; | ||
348 | int ret = 0; | ||
349 | int i; | 351 | int i; |
350 | int encoder_type = DRM_MODE_ENCODER_NONE; | 352 | int encoder_type = DRM_MODE_ENCODER_NONE; |
351 | 353 | ||
@@ -360,16 +362,14 @@ void intel_dvo_init(struct drm_device *dev) | |||
360 | } | 362 | } |
361 | 363 | ||
362 | intel_encoder = &intel_dvo->base; | 364 | intel_encoder = &intel_dvo->base; |
363 | 365 | drm_encoder_init(dev, &intel_encoder->base, | |
364 | /* Set up the DDC bus */ | 366 | &intel_dvo_enc_funcs, encoder_type); |
365 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D"); | ||
366 | if (!intel_encoder->ddc_bus) | ||
367 | goto free_intel; | ||
368 | 367 | ||
369 | /* Now, try to find a controller */ | 368 | /* Now, try to find a controller */ |
370 | for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { | 369 | for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { |
371 | struct drm_connector *connector = &intel_connector->base; | 370 | struct drm_connector *connector = &intel_connector->base; |
372 | const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; | 371 | const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; |
372 | struct i2c_adapter *i2c; | ||
373 | int gpio; | 373 | int gpio; |
374 | 374 | ||
375 | /* Allow the I2C driver info to specify the GPIO to be used in | 375 | /* Allow the I2C driver info to specify the GPIO to be used in |
@@ -379,24 +379,18 @@ void intel_dvo_init(struct drm_device *dev) | |||
379 | if (dvo->gpio != 0) | 379 | if (dvo->gpio != 0) |
380 | gpio = dvo->gpio; | 380 | gpio = dvo->gpio; |
381 | else if (dvo->type == INTEL_DVO_CHIP_LVDS) | 381 | else if (dvo->type == INTEL_DVO_CHIP_LVDS) |
382 | gpio = GPIOB; | 382 | gpio = GMBUS_PORT_SSC; |
383 | else | 383 | else |
384 | gpio = GPIOE; | 384 | gpio = GMBUS_PORT_DPB; |
385 | 385 | ||
386 | /* Set up the I2C bus necessary for the chip we're probing. | 386 | /* Set up the I2C bus necessary for the chip we're probing. |
387 | * It appears that everything is on GPIOE except for panels | 387 | * It appears that everything is on GPIOE except for panels |
388 | * on i830 laptops, which are on GPIOB (DVOA). | 388 | * on i830 laptops, which are on GPIOB (DVOA). |
389 | */ | 389 | */ |
390 | if (i2cbus != NULL) | 390 | i2c = &dev_priv->gmbus[gpio].adapter; |
391 | intel_i2c_destroy(i2cbus); | ||
392 | if (!(i2cbus = intel_i2c_create(dev, gpio, | ||
393 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { | ||
394 | continue; | ||
395 | } | ||
396 | 391 | ||
397 | intel_dvo->dev = *dvo; | 392 | intel_dvo->dev = *dvo; |
398 | ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus); | 393 | if (!dvo->dev_ops->init(&intel_dvo->dev, i2c)) |
399 | if (!ret) | ||
400 | continue; | 394 | continue; |
401 | 395 | ||
402 | intel_encoder->type = INTEL_OUTPUT_DVO; | 396 | intel_encoder->type = INTEL_OUTPUT_DVO; |
@@ -427,13 +421,10 @@ void intel_dvo_init(struct drm_device *dev) | |||
427 | connector->interlace_allowed = false; | 421 | connector->interlace_allowed = false; |
428 | connector->doublescan_allowed = false; | 422 | connector->doublescan_allowed = false; |
429 | 423 | ||
430 | drm_encoder_init(dev, &intel_encoder->enc, | 424 | drm_encoder_helper_add(&intel_encoder->base, |
431 | &intel_dvo_enc_funcs, encoder_type); | ||
432 | drm_encoder_helper_add(&intel_encoder->enc, | ||
433 | &intel_dvo_helper_funcs); | 425 | &intel_dvo_helper_funcs); |
434 | 426 | ||
435 | drm_mode_connector_attach_encoder(&intel_connector->base, | 427 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
436 | &intel_encoder->enc); | ||
437 | if (dvo->type == INTEL_DVO_CHIP_LVDS) { | 428 | if (dvo->type == INTEL_DVO_CHIP_LVDS) { |
438 | /* For our LVDS chipsets, we should hopefully be able | 429 | /* For our LVDS chipsets, we should hopefully be able |
439 | * to dig the fixed panel mode out of the BIOS data. | 430 | * to dig the fixed panel mode out of the BIOS data. |
@@ -451,11 +442,7 @@ void intel_dvo_init(struct drm_device *dev) | |||
451 | return; | 442 | return; |
452 | } | 443 | } |
453 | 444 | ||
454 | intel_i2c_destroy(intel_encoder->ddc_bus); | 445 | drm_encoder_cleanup(&intel_encoder->base); |
455 | /* Didn't find a chip, so tear down. */ | ||
456 | if (i2cbus != NULL) | ||
457 | intel_i2c_destroy(i2cbus); | ||
458 | free_intel: | ||
459 | kfree(intel_dvo); | 446 | kfree(intel_dvo); |
460 | kfree(intel_connector); | 447 | kfree(intel_connector); |
461 | } | 448 | } |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index b61966c126d3..521622b9be7a 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -44,13 +44,6 @@ | |||
44 | #include "i915_drm.h" | 44 | #include "i915_drm.h" |
45 | #include "i915_drv.h" | 45 | #include "i915_drv.h" |
46 | 46 | ||
47 | struct intel_fbdev { | ||
48 | struct drm_fb_helper helper; | ||
49 | struct intel_framebuffer ifb; | ||
50 | struct list_head fbdev_list; | ||
51 | struct drm_display_mode *our_mode; | ||
52 | }; | ||
53 | |||
54 | static struct fb_ops intelfb_ops = { | 47 | static struct fb_ops intelfb_ops = { |
55 | .owner = THIS_MODULE, | 48 | .owner = THIS_MODULE, |
56 | .fb_check_var = drm_fb_helper_check_var, | 49 | .fb_check_var = drm_fb_helper_check_var, |
@@ -75,7 +68,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
75 | struct drm_gem_object *fbo = NULL; | 68 | struct drm_gem_object *fbo = NULL; |
76 | struct drm_i915_gem_object *obj_priv; | 69 | struct drm_i915_gem_object *obj_priv; |
77 | struct device *device = &dev->pdev->dev; | 70 | struct device *device = &dev->pdev->dev; |
78 | int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; | 71 | int size, ret, mmio_bar = IS_GEN2(dev) ? 1 : 0; |
79 | 72 | ||
80 | /* we don't do packed 24bpp */ | 73 | /* we don't do packed 24bpp */ |
81 | if (sizes->surface_bpp == 24) | 74 | if (sizes->surface_bpp == 24) |
@@ -100,19 +93,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
100 | 93 | ||
101 | mutex_lock(&dev->struct_mutex); | 94 | mutex_lock(&dev->struct_mutex); |
102 | 95 | ||
103 | ret = intel_pin_and_fence_fb_obj(dev, fbo); | 96 | /* Flush everything out, we'll be doing GTT only from now on */ |
97 | ret = intel_pin_and_fence_fb_obj(dev, fbo, false); | ||
104 | if (ret) { | 98 | if (ret) { |
105 | DRM_ERROR("failed to pin fb: %d\n", ret); | 99 | DRM_ERROR("failed to pin fb: %d\n", ret); |
106 | goto out_unref; | 100 | goto out_unref; |
107 | } | 101 | } |
108 | 102 | ||
109 | /* Flush everything out, we'll be doing GTT only from now on */ | ||
110 | ret = i915_gem_object_set_to_gtt_domain(fbo, 1); | ||
111 | if (ret) { | ||
112 | DRM_ERROR("failed to bind fb: %d.\n", ret); | ||
113 | goto out_unpin; | ||
114 | } | ||
115 | |||
116 | info = framebuffer_alloc(0, device); | 103 | info = framebuffer_alloc(0, device); |
117 | if (!info) { | 104 | if (!info) { |
118 | ret = -ENOMEM; | 105 | ret = -ENOMEM; |
@@ -142,7 +129,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
142 | goto out_unpin; | 129 | goto out_unpin; |
143 | } | 130 | } |
144 | info->apertures->ranges[0].base = dev->mode_config.fb_base; | 131 | info->apertures->ranges[0].base = dev->mode_config.fb_base; |
145 | if (IS_I9XX(dev)) | 132 | if (!IS_GEN2(dev)) |
146 | info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2); | 133 | info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2); |
147 | else | 134 | else |
148 | info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); | 135 | info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); |
@@ -219,8 +206,8 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = { | |||
219 | .fb_probe = intel_fb_find_or_create_single, | 206 | .fb_probe = intel_fb_find_or_create_single, |
220 | }; | 207 | }; |
221 | 208 | ||
222 | int intel_fbdev_destroy(struct drm_device *dev, | 209 | static void intel_fbdev_destroy(struct drm_device *dev, |
223 | struct intel_fbdev *ifbdev) | 210 | struct intel_fbdev *ifbdev) |
224 | { | 211 | { |
225 | struct fb_info *info; | 212 | struct fb_info *info; |
226 | struct intel_framebuffer *ifb = &ifbdev->ifb; | 213 | struct intel_framebuffer *ifb = &ifbdev->ifb; |
@@ -241,8 +228,6 @@ int intel_fbdev_destroy(struct drm_device *dev, | |||
241 | drm_gem_object_unreference(ifb->obj); | 228 | drm_gem_object_unreference(ifb->obj); |
242 | ifb->obj = NULL; | 229 | ifb->obj = NULL; |
243 | } | 230 | } |
244 | |||
245 | return 0; | ||
246 | } | 231 | } |
247 | 232 | ||
248 | int intel_fbdev_init(struct drm_device *dev) | 233 | int intel_fbdev_init(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 926934a482ec..9fb9501f2d07 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -40,12 +40,19 @@ | |||
40 | struct intel_hdmi { | 40 | struct intel_hdmi { |
41 | struct intel_encoder base; | 41 | struct intel_encoder base; |
42 | u32 sdvox_reg; | 42 | u32 sdvox_reg; |
43 | int ddc_bus; | ||
43 | bool has_hdmi_sink; | 44 | bool has_hdmi_sink; |
44 | }; | 45 | }; |
45 | 46 | ||
46 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) | 47 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
47 | { | 48 | { |
48 | return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base); | 49 | return container_of(encoder, struct intel_hdmi, base.base); |
50 | } | ||
51 | |||
52 | static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) | ||
53 | { | ||
54 | return container_of(intel_attached_encoder(connector), | ||
55 | struct intel_hdmi, base); | ||
49 | } | 56 | } |
50 | 57 | ||
51 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | 58 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
@@ -141,13 +148,14 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
141 | static enum drm_connector_status | 148 | static enum drm_connector_status |
142 | intel_hdmi_detect(struct drm_connector *connector, bool force) | 149 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
143 | { | 150 | { |
144 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 151 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 152 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
146 | struct edid *edid = NULL; | 153 | struct edid *edid; |
147 | enum drm_connector_status status = connector_status_disconnected; | 154 | enum drm_connector_status status = connector_status_disconnected; |
148 | 155 | ||
149 | intel_hdmi->has_hdmi_sink = false; | 156 | intel_hdmi->has_hdmi_sink = false; |
150 | edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus); | 157 | edid = drm_get_edid(connector, |
158 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | ||
151 | 159 | ||
152 | if (edid) { | 160 | if (edid) { |
153 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 161 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
@@ -163,14 +171,15 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) | |||
163 | 171 | ||
164 | static int intel_hdmi_get_modes(struct drm_connector *connector) | 172 | static int intel_hdmi_get_modes(struct drm_connector *connector) |
165 | { | 173 | { |
166 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 174 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
167 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 175 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
168 | 176 | ||
169 | /* We should parse the EDID data and find out if it's an HDMI sink so | 177 | /* We should parse the EDID data and find out if it's an HDMI sink so |
170 | * we can send audio to it. | 178 | * we can send audio to it. |
171 | */ | 179 | */ |
172 | 180 | ||
173 | return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus); | 181 | return intel_ddc_get_modes(connector, |
182 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | ||
174 | } | 183 | } |
175 | 184 | ||
176 | static void intel_hdmi_destroy(struct drm_connector *connector) | 185 | static void intel_hdmi_destroy(struct drm_connector *connector) |
@@ -198,7 +207,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | |||
198 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { | 207 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { |
199 | .get_modes = intel_hdmi_get_modes, | 208 | .get_modes = intel_hdmi_get_modes, |
200 | .mode_valid = intel_hdmi_mode_valid, | 209 | .mode_valid = intel_hdmi_mode_valid, |
201 | .best_encoder = intel_attached_encoder, | 210 | .best_encoder = intel_best_encoder, |
202 | }; | 211 | }; |
203 | 212 | ||
204 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | 213 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { |
@@ -224,6 +233,9 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
224 | } | 233 | } |
225 | 234 | ||
226 | intel_encoder = &intel_hdmi->base; | 235 | intel_encoder = &intel_hdmi->base; |
236 | drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, | ||
237 | DRM_MODE_ENCODER_TMDS); | ||
238 | |||
227 | connector = &intel_connector->base; | 239 | connector = &intel_connector->base; |
228 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | 240 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
229 | DRM_MODE_CONNECTOR_HDMIA); | 241 | DRM_MODE_CONNECTOR_HDMIA); |
@@ -239,39 +251,31 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
239 | /* Set up the DDC bus. */ | 251 | /* Set up the DDC bus. */ |
240 | if (sdvox_reg == SDVOB) { | 252 | if (sdvox_reg == SDVOB) { |
241 | intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); | 253 | intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); |
242 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); | 254 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
243 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; | 255 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
244 | } else if (sdvox_reg == SDVOC) { | 256 | } else if (sdvox_reg == SDVOC) { |
245 | intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); | 257 | intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); |
246 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); | 258 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
247 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; | 259 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
248 | } else if (sdvox_reg == HDMIB) { | 260 | } else if (sdvox_reg == HDMIB) { |
249 | intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); | 261 | intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); |
250 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, | 262 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
251 | "HDMIB"); | ||
252 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; | 263 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
253 | } else if (sdvox_reg == HDMIC) { | 264 | } else if (sdvox_reg == HDMIC) { |
254 | intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); | 265 | intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); |
255 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, | 266 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
256 | "HDMIC"); | ||
257 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; | 267 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
258 | } else if (sdvox_reg == HDMID) { | 268 | } else if (sdvox_reg == HDMID) { |
259 | intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); | 269 | intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); |
260 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, | 270 | intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
261 | "HDMID"); | ||
262 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; | 271 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; |
263 | } | 272 | } |
264 | if (!intel_encoder->ddc_bus) | ||
265 | goto err_connector; | ||
266 | 273 | ||
267 | intel_hdmi->sdvox_reg = sdvox_reg; | 274 | intel_hdmi->sdvox_reg = sdvox_reg; |
268 | 275 | ||
269 | drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs, | 276 | drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); |
270 | DRM_MODE_ENCODER_TMDS); | ||
271 | drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs); | ||
272 | 277 | ||
273 | drm_mode_connector_attach_encoder(&intel_connector->base, | 278 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
274 | &intel_encoder->enc); | ||
275 | drm_sysfs_connector_add(connector); | 279 | drm_sysfs_connector_add(connector); |
276 | 280 | ||
277 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | 281 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
@@ -282,13 +286,4 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
282 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | 286 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); |
283 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | 287 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); |
284 | } | 288 | } |
285 | |||
286 | return; | ||
287 | |||
288 | err_connector: | ||
289 | drm_connector_cleanup(connector); | ||
290 | kfree(intel_hdmi); | ||
291 | kfree(intel_connector); | ||
292 | |||
293 | return; | ||
294 | } | 289 | } |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index c2649c7df14c..2449a74d4d80 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> | 2 | * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> |
3 | * Copyright © 2006-2008 Intel Corporation | 3 | * Copyright © 2006-2008,2010 Intel Corporation |
4 | * Jesse Barnes <jesse.barnes@intel.com> | 4 | * Jesse Barnes <jesse.barnes@intel.com> |
5 | * | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
@@ -24,10 +24,9 @@ | |||
24 | * | 24 | * |
25 | * Authors: | 25 | * Authors: |
26 | * Eric Anholt <eric@anholt.net> | 26 | * Eric Anholt <eric@anholt.net> |
27 | * Chris Wilson <chris@chris-wilson.co.uk> | ||
27 | */ | 28 | */ |
28 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
29 | #include <linux/slab.h> | ||
30 | #include <linux/i2c-id.h> | ||
31 | #include <linux/i2c-algo-bit.h> | 30 | #include <linux/i2c-algo-bit.h> |
32 | #include "drmP.h" | 31 | #include "drmP.h" |
33 | #include "drm.h" | 32 | #include "drm.h" |
@@ -35,79 +34,106 @@ | |||
35 | #include "i915_drm.h" | 34 | #include "i915_drm.h" |
36 | #include "i915_drv.h" | 35 | #include "i915_drv.h" |
37 | 36 | ||
38 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable) | 37 | /* Intel GPIO access functions */ |
38 | |||
39 | #define I2C_RISEFALL_TIME 20 | ||
40 | |||
41 | static inline struct intel_gmbus * | ||
42 | to_intel_gmbus(struct i2c_adapter *i2c) | ||
43 | { | ||
44 | return container_of(i2c, struct intel_gmbus, adapter); | ||
45 | } | ||
46 | |||
47 | struct intel_gpio { | ||
48 | struct i2c_adapter adapter; | ||
49 | struct i2c_algo_bit_data algo; | ||
50 | struct drm_i915_private *dev_priv; | ||
51 | u32 reg; | ||
52 | }; | ||
53 | |||
54 | void | ||
55 | intel_i2c_reset(struct drm_device *dev) | ||
39 | { | 56 | { |
40 | struct drm_i915_private *dev_priv = dev->dev_private; | 57 | struct drm_i915_private *dev_priv = dev->dev_private; |
58 | if (HAS_PCH_SPLIT(dev)) | ||
59 | I915_WRITE(PCH_GMBUS0, 0); | ||
60 | else | ||
61 | I915_WRITE(GMBUS0, 0); | ||
62 | } | ||
63 | |||
64 | static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) | ||
65 | { | ||
66 | u32 val; | ||
41 | 67 | ||
42 | /* When using bit bashing for I2C, this bit needs to be set to 1 */ | 68 | /* When using bit bashing for I2C, this bit needs to be set to 1 */ |
43 | if (!IS_PINEVIEW(dev)) | 69 | if (!IS_PINEVIEW(dev_priv->dev)) |
44 | return; | 70 | return; |
71 | |||
72 | val = I915_READ(DSPCLK_GATE_D); | ||
45 | if (enable) | 73 | if (enable) |
46 | I915_WRITE(DSPCLK_GATE_D, | 74 | val |= DPCUNIT_CLOCK_GATE_DISABLE; |
47 | I915_READ(DSPCLK_GATE_D) | DPCUNIT_CLOCK_GATE_DISABLE); | ||
48 | else | 75 | else |
49 | I915_WRITE(DSPCLK_GATE_D, | 76 | val &= ~DPCUNIT_CLOCK_GATE_DISABLE; |
50 | I915_READ(DSPCLK_GATE_D) & (~DPCUNIT_CLOCK_GATE_DISABLE)); | 77 | I915_WRITE(DSPCLK_GATE_D, val); |
51 | } | 78 | } |
52 | 79 | ||
53 | /* | 80 | static u32 get_reserved(struct intel_gpio *gpio) |
54 | * Intel GPIO access functions | 81 | { |
55 | */ | 82 | struct drm_i915_private *dev_priv = gpio->dev_priv; |
83 | struct drm_device *dev = dev_priv->dev; | ||
84 | u32 reserved = 0; | ||
56 | 85 | ||
57 | #define I2C_RISEFALL_TIME 20 | 86 | /* On most chips, these bits must be preserved in software. */ |
87 | if (!IS_I830(dev) && !IS_845G(dev)) | ||
88 | reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE | | ||
89 | GPIO_CLOCK_PULLUP_DISABLE); | ||
90 | |||
91 | return reserved; | ||
92 | } | ||
58 | 93 | ||
59 | static int get_clock(void *data) | 94 | static int get_clock(void *data) |
60 | { | 95 | { |
61 | struct intel_i2c_chan *chan = data; | 96 | struct intel_gpio *gpio = data; |
62 | struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; | 97 | struct drm_i915_private *dev_priv = gpio->dev_priv; |
63 | u32 val; | 98 | u32 reserved = get_reserved(gpio); |
64 | 99 | I915_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); | |
65 | val = I915_READ(chan->reg); | 100 | I915_WRITE(gpio->reg, reserved); |
66 | return ((val & GPIO_CLOCK_VAL_IN) != 0); | 101 | return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; |
67 | } | 102 | } |
68 | 103 | ||
69 | static int get_data(void *data) | 104 | static int get_data(void *data) |
70 | { | 105 | { |
71 | struct intel_i2c_chan *chan = data; | 106 | struct intel_gpio *gpio = data; |
72 | struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; | 107 | struct drm_i915_private *dev_priv = gpio->dev_priv; |
73 | u32 val; | 108 | u32 reserved = get_reserved(gpio); |
74 | 109 | I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); | |
75 | val = I915_READ(chan->reg); | 110 | I915_WRITE(gpio->reg, reserved); |
76 | return ((val & GPIO_DATA_VAL_IN) != 0); | 111 | return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; |
77 | } | 112 | } |
78 | 113 | ||
79 | static void set_clock(void *data, int state_high) | 114 | static void set_clock(void *data, int state_high) |
80 | { | 115 | { |
81 | struct intel_i2c_chan *chan = data; | 116 | struct intel_gpio *gpio = data; |
82 | struct drm_device *dev = chan->drm_dev; | 117 | struct drm_i915_private *dev_priv = gpio->dev_priv; |
83 | struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; | 118 | u32 reserved = get_reserved(gpio); |
84 | u32 reserved = 0, clock_bits; | 119 | u32 clock_bits; |
85 | |||
86 | /* On most chips, these bits must be preserved in software. */ | ||
87 | if (!IS_I830(dev) && !IS_845G(dev)) | ||
88 | reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | | ||
89 | GPIO_CLOCK_PULLUP_DISABLE); | ||
90 | 120 | ||
91 | if (state_high) | 121 | if (state_high) |
92 | clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; | 122 | clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; |
93 | else | 123 | else |
94 | clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | | 124 | clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | |
95 | GPIO_CLOCK_VAL_MASK; | 125 | GPIO_CLOCK_VAL_MASK; |
96 | I915_WRITE(chan->reg, reserved | clock_bits); | 126 | |
97 | udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ | 127 | I915_WRITE(gpio->reg, reserved | clock_bits); |
128 | POSTING_READ(gpio->reg); | ||
98 | } | 129 | } |
99 | 130 | ||
100 | static void set_data(void *data, int state_high) | 131 | static void set_data(void *data, int state_high) |
101 | { | 132 | { |
102 | struct intel_i2c_chan *chan = data; | 133 | struct intel_gpio *gpio = data; |
103 | struct drm_device *dev = chan->drm_dev; | 134 | struct drm_i915_private *dev_priv = gpio->dev_priv; |
104 | struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; | 135 | u32 reserved = get_reserved(gpio); |
105 | u32 reserved = 0, data_bits; | 136 | u32 data_bits; |
106 | |||
107 | /* On most chips, these bits must be preserved in software. */ | ||
108 | if (!IS_I830(dev) && !IS_845G(dev)) | ||
109 | reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | | ||
110 | GPIO_CLOCK_PULLUP_DISABLE); | ||
111 | 137 | ||
112 | if (state_high) | 138 | if (state_high) |
113 | data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; | 139 | data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; |
@@ -115,109 +141,312 @@ static void set_data(void *data, int state_high) | |||
115 | data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | | 141 | data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | |
116 | GPIO_DATA_VAL_MASK; | 142 | GPIO_DATA_VAL_MASK; |
117 | 143 | ||
118 | I915_WRITE(chan->reg, reserved | data_bits); | 144 | I915_WRITE(gpio->reg, reserved | data_bits); |
119 | udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ | 145 | POSTING_READ(gpio->reg); |
120 | } | 146 | } |
121 | 147 | ||
122 | /* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C | 148 | static struct i2c_adapter * |
123 | * engine, but if the BIOS leaves it enabled, then that can break our use | 149 | intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) |
124 | * of the bit-banging I2C interfaces. This is notably the case with the | ||
125 | * Mac Mini in EFI mode. | ||
126 | */ | ||
127 | void | ||
128 | intel_i2c_reset_gmbus(struct drm_device *dev) | ||
129 | { | 150 | { |
130 | struct drm_i915_private *dev_priv = dev->dev_private; | 151 | static const int map_pin_to_reg[] = { |
152 | 0, | ||
153 | GPIOB, | ||
154 | GPIOA, | ||
155 | GPIOC, | ||
156 | GPIOD, | ||
157 | GPIOE, | ||
158 | GPIOF, | ||
159 | }; | ||
160 | struct intel_gpio *gpio; | ||
131 | 161 | ||
132 | if (HAS_PCH_SPLIT(dev)) { | 162 | if (pin < 1 || pin > 7) |
133 | I915_WRITE(PCH_GMBUS0, 0); | 163 | return NULL; |
134 | } else { | 164 | |
135 | I915_WRITE(GMBUS0, 0); | 165 | gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); |
166 | if (gpio == NULL) | ||
167 | return NULL; | ||
168 | |||
169 | gpio->reg = map_pin_to_reg[pin]; | ||
170 | if (HAS_PCH_SPLIT(dev_priv->dev)) | ||
171 | gpio->reg += PCH_GPIOA - GPIOA; | ||
172 | gpio->dev_priv = dev_priv; | ||
173 | |||
174 | snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO%c", "?BACDEF?"[pin]); | ||
175 | gpio->adapter.owner = THIS_MODULE; | ||
176 | gpio->adapter.algo_data = &gpio->algo; | ||
177 | gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; | ||
178 | gpio->algo.setsda = set_data; | ||
179 | gpio->algo.setscl = set_clock; | ||
180 | gpio->algo.getsda = get_data; | ||
181 | gpio->algo.getscl = get_clock; | ||
182 | gpio->algo.udelay = I2C_RISEFALL_TIME; | ||
183 | gpio->algo.timeout = usecs_to_jiffies(2200); | ||
184 | gpio->algo.data = gpio; | ||
185 | |||
186 | if (i2c_bit_add_bus(&gpio->adapter)) | ||
187 | goto out_free; | ||
188 | |||
189 | return &gpio->adapter; | ||
190 | |||
191 | out_free: | ||
192 | kfree(gpio); | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | static int | ||
197 | intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv, | ||
198 | struct i2c_adapter *adapter, | ||
199 | struct i2c_msg *msgs, | ||
200 | int num) | ||
201 | { | ||
202 | struct intel_gpio *gpio = container_of(adapter, | ||
203 | struct intel_gpio, | ||
204 | adapter); | ||
205 | int ret; | ||
206 | |||
207 | intel_i2c_reset(dev_priv->dev); | ||
208 | |||
209 | intel_i2c_quirk_set(dev_priv, true); | ||
210 | set_data(gpio, 1); | ||
211 | set_clock(gpio, 1); | ||
212 | udelay(I2C_RISEFALL_TIME); | ||
213 | |||
214 | ret = adapter->algo->master_xfer(adapter, msgs, num); | ||
215 | |||
216 | set_data(gpio, 1); | ||
217 | set_clock(gpio, 1); | ||
218 | intel_i2c_quirk_set(dev_priv, false); | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int | ||
224 | gmbus_xfer(struct i2c_adapter *adapter, | ||
225 | struct i2c_msg *msgs, | ||
226 | int num) | ||
227 | { | ||
228 | struct intel_gmbus *bus = container_of(adapter, | ||
229 | struct intel_gmbus, | ||
230 | adapter); | ||
231 | struct drm_i915_private *dev_priv = adapter->algo_data; | ||
232 | int i, reg_offset; | ||
233 | |||
234 | if (bus->force_bit) | ||
235 | return intel_i2c_quirk_xfer(dev_priv, | ||
236 | bus->force_bit, msgs, num); | ||
237 | |||
238 | reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0; | ||
239 | |||
240 | I915_WRITE(GMBUS0 + reg_offset, bus->reg0); | ||
241 | |||
242 | for (i = 0; i < num; i++) { | ||
243 | u16 len = msgs[i].len; | ||
244 | u8 *buf = msgs[i].buf; | ||
245 | |||
246 | if (msgs[i].flags & I2C_M_RD) { | ||
247 | I915_WRITE(GMBUS1 + reg_offset, | ||
248 | GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | | ||
249 | (len << GMBUS_BYTE_COUNT_SHIFT) | | ||
250 | (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | | ||
251 | GMBUS_SLAVE_READ | GMBUS_SW_RDY); | ||
252 | POSTING_READ(GMBUS2+reg_offset); | ||
253 | do { | ||
254 | u32 val, loop = 0; | ||
255 | |||
256 | if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) | ||
257 | goto timeout; | ||
258 | if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) | ||
259 | return 0; | ||
260 | |||
261 | val = I915_READ(GMBUS3 + reg_offset); | ||
262 | do { | ||
263 | *buf++ = val & 0xff; | ||
264 | val >>= 8; | ||
265 | } while (--len && ++loop < 4); | ||
266 | } while (len); | ||
267 | } else { | ||
268 | u32 val, loop; | ||
269 | |||
270 | val = loop = 0; | ||
271 | do { | ||
272 | val |= *buf++ << (8 * loop); | ||
273 | } while (--len && ++loop < 4); | ||
274 | |||
275 | I915_WRITE(GMBUS3 + reg_offset, val); | ||
276 | I915_WRITE(GMBUS1 + reg_offset, | ||
277 | (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | | ||
278 | (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | | ||
279 | (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | | ||
280 | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); | ||
281 | POSTING_READ(GMBUS2+reg_offset); | ||
282 | |||
283 | while (len) { | ||
284 | if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) | ||
285 | goto timeout; | ||
286 | if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) | ||
287 | return 0; | ||
288 | |||
289 | val = loop = 0; | ||
290 | do { | ||
291 | val |= *buf++ << (8 * loop); | ||
292 | } while (--len && ++loop < 4); | ||
293 | |||
294 | I915_WRITE(GMBUS3 + reg_offset, val); | ||
295 | POSTING_READ(GMBUS2+reg_offset); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) | ||
300 | goto timeout; | ||
301 | if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) | ||
302 | return 0; | ||
136 | } | 303 | } |
304 | |||
305 | return num; | ||
306 | |||
307 | timeout: | ||
308 | DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", | ||
309 | bus->reg0 & 0xff, bus->adapter.name); | ||
310 | /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ | ||
311 | bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); | ||
312 | if (!bus->force_bit) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); | ||
137 | } | 316 | } |
138 | 317 | ||
318 | static u32 gmbus_func(struct i2c_adapter *adapter) | ||
319 | { | ||
320 | struct intel_gmbus *bus = container_of(adapter, | ||
321 | struct intel_gmbus, | ||
322 | adapter); | ||
323 | |||
324 | if (bus->force_bit) | ||
325 | bus->force_bit->algo->functionality(bus->force_bit); | ||
326 | |||
327 | return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
328 | /* I2C_FUNC_10BIT_ADDR | */ | ||
329 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
330 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL); | ||
331 | } | ||
332 | |||
333 | static const struct i2c_algorithm gmbus_algorithm = { | ||
334 | .master_xfer = gmbus_xfer, | ||
335 | .functionality = gmbus_func | ||
336 | }; | ||
337 | |||
139 | /** | 338 | /** |
140 | * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg | 339 | * intel_gmbus_setup - instantiate all Intel i2c GMBuses |
141 | * @dev: DRM device | 340 | * @dev: DRM device |
142 | * @output: driver specific output device | ||
143 | * @reg: GPIO reg to use | ||
144 | * @name: name for this bus | ||
145 | * @slave_addr: slave address (if fixed) | ||
146 | * | ||
147 | * Creates and registers a new i2c bus with the Linux i2c layer, for use | ||
148 | * in output probing and control (e.g. DDC or SDVO control functions). | ||
149 | * | ||
150 | * Possible values for @reg include: | ||
151 | * %GPIOA | ||
152 | * %GPIOB | ||
153 | * %GPIOC | ||
154 | * %GPIOD | ||
155 | * %GPIOE | ||
156 | * %GPIOF | ||
157 | * %GPIOG | ||
158 | * %GPIOH | ||
159 | * see PRM for details on how these different busses are used. | ||
160 | */ | 341 | */ |
161 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, | 342 | int intel_setup_gmbus(struct drm_device *dev) |
162 | const char *name) | ||
163 | { | 343 | { |
164 | struct intel_i2c_chan *chan; | 344 | static const char *names[GMBUS_NUM_PORTS] = { |
345 | "disabled", | ||
346 | "ssc", | ||
347 | "vga", | ||
348 | "panel", | ||
349 | "dpc", | ||
350 | "dpb", | ||
351 | "reserved" | ||
352 | "dpd", | ||
353 | }; | ||
354 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
355 | int ret, i; | ||
165 | 356 | ||
166 | chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL); | 357 | dev_priv->gmbus = kcalloc(sizeof(struct intel_gmbus), GMBUS_NUM_PORTS, |
167 | if (!chan) | 358 | GFP_KERNEL); |
168 | goto out_free; | 359 | if (dev_priv->gmbus == NULL) |
360 | return -ENOMEM; | ||
169 | 361 | ||
170 | chan->drm_dev = dev; | 362 | for (i = 0; i < GMBUS_NUM_PORTS; i++) { |
171 | chan->reg = reg; | 363 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; |
172 | snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); | ||
173 | chan->adapter.owner = THIS_MODULE; | ||
174 | chan->adapter.algo_data = &chan->algo; | ||
175 | chan->adapter.dev.parent = &dev->pdev->dev; | ||
176 | chan->algo.setsda = set_data; | ||
177 | chan->algo.setscl = set_clock; | ||
178 | chan->algo.getsda = get_data; | ||
179 | chan->algo.getscl = get_clock; | ||
180 | chan->algo.udelay = 20; | ||
181 | chan->algo.timeout = usecs_to_jiffies(2200); | ||
182 | chan->algo.data = chan; | ||
183 | |||
184 | i2c_set_adapdata(&chan->adapter, chan); | ||
185 | |||
186 | if(i2c_bit_add_bus(&chan->adapter)) | ||
187 | goto out_free; | ||
188 | 364 | ||
189 | intel_i2c_reset_gmbus(dev); | 365 | bus->adapter.owner = THIS_MODULE; |
366 | bus->adapter.class = I2C_CLASS_DDC; | ||
367 | snprintf(bus->adapter.name, | ||
368 | I2C_NAME_SIZE, | ||
369 | "gmbus %s", | ||
370 | names[i]); | ||
190 | 371 | ||
191 | /* JJJ: raise SCL and SDA? */ | 372 | bus->adapter.dev.parent = &dev->pdev->dev; |
192 | intel_i2c_quirk_set(dev, true); | 373 | bus->adapter.algo_data = dev_priv; |
193 | set_data(chan, 1); | ||
194 | set_clock(chan, 1); | ||
195 | intel_i2c_quirk_set(dev, false); | ||
196 | udelay(20); | ||
197 | 374 | ||
198 | return &chan->adapter; | 375 | bus->adapter.algo = &gmbus_algorithm; |
376 | ret = i2c_add_adapter(&bus->adapter); | ||
377 | if (ret) | ||
378 | goto err; | ||
199 | 379 | ||
200 | out_free: | 380 | /* By default use a conservative clock rate */ |
201 | kfree(chan); | 381 | bus->reg0 = i | GMBUS_RATE_100KHZ; |
202 | return NULL; | 382 | |
383 | /* XXX force bit banging until GMBUS is fully debugged */ | ||
384 | bus->force_bit = intel_gpio_create(dev_priv, i); | ||
385 | } | ||
386 | |||
387 | intel_i2c_reset(dev_priv->dev); | ||
388 | |||
389 | return 0; | ||
390 | |||
391 | err: | ||
392 | while (--i) { | ||
393 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; | ||
394 | i2c_del_adapter(&bus->adapter); | ||
395 | } | ||
396 | kfree(dev_priv->gmbus); | ||
397 | dev_priv->gmbus = NULL; | ||
398 | return ret; | ||
203 | } | 399 | } |
204 | 400 | ||
205 | /** | 401 | void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) |
206 | * intel_i2c_destroy - unregister and free i2c bus resources | 402 | { |
207 | * @output: channel to free | 403 | struct intel_gmbus *bus = to_intel_gmbus(adapter); |
208 | * | 404 | |
209 | * Unregister the adapter from the i2c layer, then free the structure. | 405 | /* speed: |
210 | */ | 406 | * 0x0 = 100 KHz |
211 | void intel_i2c_destroy(struct i2c_adapter *adapter) | 407 | * 0x1 = 50 KHz |
408 | * 0x2 = 400 KHz | ||
409 | * 0x3 = 1000 Khz | ||
410 | */ | ||
411 | bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8); | ||
412 | } | ||
413 | |||
414 | void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) | ||
415 | { | ||
416 | struct intel_gmbus *bus = to_intel_gmbus(adapter); | ||
417 | |||
418 | if (force_bit) { | ||
419 | if (bus->force_bit == NULL) { | ||
420 | struct drm_i915_private *dev_priv = adapter->algo_data; | ||
421 | bus->force_bit = intel_gpio_create(dev_priv, | ||
422 | bus->reg0 & 0xff); | ||
423 | } | ||
424 | } else { | ||
425 | if (bus->force_bit) { | ||
426 | i2c_del_adapter(bus->force_bit); | ||
427 | kfree(bus->force_bit); | ||
428 | bus->force_bit = NULL; | ||
429 | } | ||
430 | } | ||
431 | } | ||
432 | |||
433 | void intel_teardown_gmbus(struct drm_device *dev) | ||
212 | { | 434 | { |
213 | struct intel_i2c_chan *chan; | 435 | struct drm_i915_private *dev_priv = dev->dev_private; |
436 | int i; | ||
214 | 437 | ||
215 | if (!adapter) | 438 | if (dev_priv->gmbus == NULL) |
216 | return; | 439 | return; |
217 | 440 | ||
218 | chan = container_of(adapter, | 441 | for (i = 0; i < GMBUS_NUM_PORTS; i++) { |
219 | struct intel_i2c_chan, | 442 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; |
220 | adapter); | 443 | if (bus->force_bit) { |
221 | i2c_del_adapter(&chan->adapter); | 444 | i2c_del_adapter(bus->force_bit); |
222 | kfree(chan); | 445 | kfree(bus->force_bit); |
446 | } | ||
447 | i2c_del_adapter(&bus->adapter); | ||
448 | } | ||
449 | |||
450 | kfree(dev_priv->gmbus); | ||
451 | dev_priv->gmbus = NULL; | ||
223 | } | 452 | } |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 6ec39a86ed06..f1a649990ea9 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -43,102 +43,76 @@ | |||
43 | /* Private structure for the integrated LVDS support */ | 43 | /* Private structure for the integrated LVDS support */ |
44 | struct intel_lvds { | 44 | struct intel_lvds { |
45 | struct intel_encoder base; | 45 | struct intel_encoder base; |
46 | |||
47 | struct edid *edid; | ||
48 | |||
46 | int fitting_mode; | 49 | int fitting_mode; |
47 | u32 pfit_control; | 50 | u32 pfit_control; |
48 | u32 pfit_pgm_ratios; | 51 | u32 pfit_pgm_ratios; |
52 | bool pfit_dirty; | ||
53 | |||
54 | struct drm_display_mode *fixed_mode; | ||
49 | }; | 55 | }; |
50 | 56 | ||
51 | static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder) | 57 | static struct intel_lvds *to_intel_lvds(struct drm_encoder *encoder) |
52 | { | 58 | { |
53 | return container_of(enc_to_intel_encoder(encoder), struct intel_lvds, base); | 59 | return container_of(encoder, struct intel_lvds, base.base); |
54 | } | ||
55 | |||
56 | /** | ||
57 | * Sets the backlight level. | ||
58 | * | ||
59 | * \param level backlight level, from 0 to intel_lvds_get_max_backlight(). | ||
60 | */ | ||
61 | static void intel_lvds_set_backlight(struct drm_device *dev, int level) | ||
62 | { | ||
63 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
64 | u32 blc_pwm_ctl, reg; | ||
65 | |||
66 | if (HAS_PCH_SPLIT(dev)) | ||
67 | reg = BLC_PWM_CPU_CTL; | ||
68 | else | ||
69 | reg = BLC_PWM_CTL; | ||
70 | |||
71 | blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
72 | I915_WRITE(reg, (blc_pwm_ctl | | ||
73 | (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); | ||
74 | } | 60 | } |
75 | 61 | ||
76 | /** | 62 | static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) |
77 | * Returns the maximum level of the backlight duty cycle field. | ||
78 | */ | ||
79 | static u32 intel_lvds_get_max_backlight(struct drm_device *dev) | ||
80 | { | 63 | { |
81 | struct drm_i915_private *dev_priv = dev->dev_private; | 64 | return container_of(intel_attached_encoder(connector), |
82 | u32 reg; | 65 | struct intel_lvds, base); |
83 | |||
84 | if (HAS_PCH_SPLIT(dev)) | ||
85 | reg = BLC_PWM_PCH_CTL2; | ||
86 | else | ||
87 | reg = BLC_PWM_CTL; | ||
88 | |||
89 | return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
90 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; | ||
91 | } | 66 | } |
92 | 67 | ||
93 | /** | 68 | /** |
94 | * Sets the power state for the panel. | 69 | * Sets the power state for the panel. |
95 | */ | 70 | */ |
96 | static void intel_lvds_set_power(struct drm_device *dev, bool on) | 71 | static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) |
97 | { | 72 | { |
73 | struct drm_device *dev = intel_lvds->base.base.dev; | ||
98 | struct drm_i915_private *dev_priv = dev->dev_private; | 74 | struct drm_i915_private *dev_priv = dev->dev_private; |
99 | u32 ctl_reg, status_reg, lvds_reg; | 75 | u32 ctl_reg, lvds_reg; |
100 | 76 | ||
101 | if (HAS_PCH_SPLIT(dev)) { | 77 | if (HAS_PCH_SPLIT(dev)) { |
102 | ctl_reg = PCH_PP_CONTROL; | 78 | ctl_reg = PCH_PP_CONTROL; |
103 | status_reg = PCH_PP_STATUS; | ||
104 | lvds_reg = PCH_LVDS; | 79 | lvds_reg = PCH_LVDS; |
105 | } else { | 80 | } else { |
106 | ctl_reg = PP_CONTROL; | 81 | ctl_reg = PP_CONTROL; |
107 | status_reg = PP_STATUS; | ||
108 | lvds_reg = LVDS; | 82 | lvds_reg = LVDS; |
109 | } | 83 | } |
110 | 84 | ||
111 | if (on) { | 85 | if (on) { |
112 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); | 86 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); |
113 | POSTING_READ(lvds_reg); | 87 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); |
114 | 88 | intel_panel_set_backlight(dev, dev_priv->backlight_level); | |
115 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | | ||
116 | POWER_TARGET_ON); | ||
117 | if (wait_for(I915_READ(status_reg) & PP_ON, 1000, 0)) | ||
118 | DRM_ERROR("timed out waiting to enable LVDS pipe"); | ||
119 | |||
120 | intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); | ||
121 | } else { | 89 | } else { |
122 | intel_lvds_set_backlight(dev, 0); | 90 | dev_priv->backlight_level = intel_panel_get_backlight(dev); |
91 | |||
92 | intel_panel_set_backlight(dev, 0); | ||
93 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); | ||
123 | 94 | ||
124 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & | 95 | if (intel_lvds->pfit_control) { |
125 | ~POWER_TARGET_ON); | 96 | if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) |
126 | if (wait_for((I915_READ(status_reg) & PP_ON) == 0, 1000, 0)) | 97 | DRM_ERROR("timed out waiting for panel to power off\n"); |
127 | DRM_ERROR("timed out waiting for LVDS pipe to turn off"); | 98 | I915_WRITE(PFIT_CONTROL, 0); |
99 | intel_lvds->pfit_control = 0; | ||
100 | intel_lvds->pfit_dirty = false; | ||
101 | } | ||
128 | 102 | ||
129 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); | 103 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); |
130 | POSTING_READ(lvds_reg); | ||
131 | } | 104 | } |
105 | POSTING_READ(lvds_reg); | ||
132 | } | 106 | } |
133 | 107 | ||
134 | static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) | 108 | static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) |
135 | { | 109 | { |
136 | struct drm_device *dev = encoder->dev; | 110 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
137 | 111 | ||
138 | if (mode == DRM_MODE_DPMS_ON) | 112 | if (mode == DRM_MODE_DPMS_ON) |
139 | intel_lvds_set_power(dev, true); | 113 | intel_lvds_set_power(intel_lvds, true); |
140 | else | 114 | else |
141 | intel_lvds_set_power(dev, false); | 115 | intel_lvds_set_power(intel_lvds, false); |
142 | 116 | ||
143 | /* XXX: We never power down the LVDS pairs. */ | 117 | /* XXX: We never power down the LVDS pairs. */ |
144 | } | 118 | } |
@@ -146,16 +120,13 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) | |||
146 | static int intel_lvds_mode_valid(struct drm_connector *connector, | 120 | static int intel_lvds_mode_valid(struct drm_connector *connector, |
147 | struct drm_display_mode *mode) | 121 | struct drm_display_mode *mode) |
148 | { | 122 | { |
149 | struct drm_device *dev = connector->dev; | 123 | struct intel_lvds *intel_lvds = intel_attached_lvds(connector); |
150 | struct drm_i915_private *dev_priv = dev->dev_private; | 124 | struct drm_display_mode *fixed_mode = intel_lvds->fixed_mode; |
151 | struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode; | ||
152 | 125 | ||
153 | if (fixed_mode) { | 126 | if (mode->hdisplay > fixed_mode->hdisplay) |
154 | if (mode->hdisplay > fixed_mode->hdisplay) | 127 | return MODE_PANEL; |
155 | return MODE_PANEL; | 128 | if (mode->vdisplay > fixed_mode->vdisplay) |
156 | if (mode->vdisplay > fixed_mode->vdisplay) | 129 | return MODE_PANEL; |
157 | return MODE_PANEL; | ||
158 | } | ||
159 | 130 | ||
160 | return MODE_OK; | 131 | return MODE_OK; |
161 | } | 132 | } |
@@ -223,12 +194,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
223 | struct drm_device *dev = encoder->dev; | 194 | struct drm_device *dev = encoder->dev; |
224 | struct drm_i915_private *dev_priv = dev->dev_private; | 195 | struct drm_i915_private *dev_priv = dev->dev_private; |
225 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 196 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
226 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); | 197 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
227 | struct drm_encoder *tmp_encoder; | 198 | struct drm_encoder *tmp_encoder; |
228 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; | 199 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
229 | 200 | ||
230 | /* Should never happen!! */ | 201 | /* Should never happen!! */ |
231 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { | 202 | if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { |
232 | DRM_ERROR("Can't support LVDS on pipe A\n"); | 203 | DRM_ERROR("Can't support LVDS on pipe A\n"); |
233 | return false; | 204 | return false; |
234 | } | 205 | } |
@@ -241,9 +212,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
241 | return false; | 212 | return false; |
242 | } | 213 | } |
243 | } | 214 | } |
244 | /* If we don't have a panel mode, there is nothing we can do */ | ||
245 | if (dev_priv->panel_fixed_mode == NULL) | ||
246 | return true; | ||
247 | 215 | ||
248 | /* | 216 | /* |
249 | * We have timings from the BIOS for the panel, put them in | 217 | * We have timings from the BIOS for the panel, put them in |
@@ -251,7 +219,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
251 | * with the panel scaling set up to source from the H/VDisplay | 219 | * with the panel scaling set up to source from the H/VDisplay |
252 | * of the original mode. | 220 | * of the original mode. |
253 | */ | 221 | */ |
254 | intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode); | 222 | intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode); |
255 | 223 | ||
256 | if (HAS_PCH_SPLIT(dev)) { | 224 | if (HAS_PCH_SPLIT(dev)) { |
257 | intel_pch_panel_fitting(dev, intel_lvds->fitting_mode, | 225 | intel_pch_panel_fitting(dev, intel_lvds->fitting_mode, |
@@ -260,8 +228,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
260 | } | 228 | } |
261 | 229 | ||
262 | /* Make sure pre-965s set dither correctly */ | 230 | /* Make sure pre-965s set dither correctly */ |
263 | if (!IS_I965G(dev)) { | 231 | if (INTEL_INFO(dev)->gen < 4) { |
264 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | 232 | if (dev_priv->lvds_dither) |
265 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | 233 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
266 | } | 234 | } |
267 | 235 | ||
@@ -271,7 +239,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
271 | goto out; | 239 | goto out; |
272 | 240 | ||
273 | /* 965+ wants fuzzy fitting */ | 241 | /* 965+ wants fuzzy fitting */ |
274 | if (IS_I965G(dev)) | 242 | if (INTEL_INFO(dev)->gen >= 4) |
275 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | | 243 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
276 | PFIT_FILTER_FUZZY); | 244 | PFIT_FILTER_FUZZY); |
277 | 245 | ||
@@ -297,7 +265,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
297 | 265 | ||
298 | case DRM_MODE_SCALE_ASPECT: | 266 | case DRM_MODE_SCALE_ASPECT: |
299 | /* Scale but preserve the aspect ratio */ | 267 | /* Scale but preserve the aspect ratio */ |
300 | if (IS_I965G(dev)) { | 268 | if (INTEL_INFO(dev)->gen >= 4) { |
301 | u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; | 269 | u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; |
302 | u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; | 270 | u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; |
303 | 271 | ||
@@ -356,7 +324,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
356 | * Fortunately this is all done for us in hw. | 324 | * Fortunately this is all done for us in hw. |
357 | */ | 325 | */ |
358 | pfit_control |= PFIT_ENABLE; | 326 | pfit_control |= PFIT_ENABLE; |
359 | if (IS_I965G(dev)) | 327 | if (INTEL_INFO(dev)->gen >= 4) |
360 | pfit_control |= PFIT_SCALING_AUTO; | 328 | pfit_control |= PFIT_SCALING_AUTO; |
361 | else | 329 | else |
362 | pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | | 330 | pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
@@ -369,8 +337,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
369 | } | 337 | } |
370 | 338 | ||
371 | out: | 339 | out: |
372 | intel_lvds->pfit_control = pfit_control; | 340 | if (pfit_control != intel_lvds->pfit_control || |
373 | intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios; | 341 | pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) { |
342 | intel_lvds->pfit_control = pfit_control; | ||
343 | intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios; | ||
344 | intel_lvds->pfit_dirty = true; | ||
345 | } | ||
374 | dev_priv->lvds_border_bits = border; | 346 | dev_priv->lvds_border_bits = border; |
375 | 347 | ||
376 | /* | 348 | /* |
@@ -386,30 +358,60 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) | |||
386 | { | 358 | { |
387 | struct drm_device *dev = encoder->dev; | 359 | struct drm_device *dev = encoder->dev; |
388 | struct drm_i915_private *dev_priv = dev->dev_private; | 360 | struct drm_i915_private *dev_priv = dev->dev_private; |
389 | u32 reg; | 361 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
390 | 362 | ||
391 | if (HAS_PCH_SPLIT(dev)) | 363 | dev_priv->backlight_level = intel_panel_get_backlight(dev); |
392 | reg = BLC_PWM_CPU_CTL; | 364 | |
393 | else | 365 | /* We try to do the minimum that is necessary in order to unlock |
394 | reg = BLC_PWM_CTL; | 366 | * the registers for mode setting. |
395 | 367 | * | |
396 | dev_priv->saveBLC_PWM_CTL = I915_READ(reg); | 368 | * On Ironlake, this is quite simple as we just set the unlock key |
397 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & | 369 | * and ignore all subtleties. (This may cause some issues...) |
398 | BACKLIGHT_DUTY_CYCLE_MASK); | 370 | * |
371 | * Prior to Ironlake, we must disable the pipe if we want to adjust | ||
372 | * the panel fitter. However at all other times we can just reset | ||
373 | * the registers regardless. | ||
374 | */ | ||
399 | 375 | ||
400 | intel_lvds_set_power(dev, false); | 376 | if (HAS_PCH_SPLIT(dev)) { |
377 | I915_WRITE(PCH_PP_CONTROL, | ||
378 | I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); | ||
379 | } else if (intel_lvds->pfit_dirty) { | ||
380 | I915_WRITE(PP_CONTROL, | ||
381 | (I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS) | ||
382 | & ~POWER_TARGET_ON); | ||
383 | } else { | ||
384 | I915_WRITE(PP_CONTROL, | ||
385 | I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); | ||
386 | } | ||
401 | } | 387 | } |
402 | 388 | ||
403 | static void intel_lvds_commit( struct drm_encoder *encoder) | 389 | static void intel_lvds_commit(struct drm_encoder *encoder) |
404 | { | 390 | { |
405 | struct drm_device *dev = encoder->dev; | 391 | struct drm_device *dev = encoder->dev; |
406 | struct drm_i915_private *dev_priv = dev->dev_private; | 392 | struct drm_i915_private *dev_priv = dev->dev_private; |
393 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | ||
407 | 394 | ||
408 | if (dev_priv->backlight_duty_cycle == 0) | 395 | if (dev_priv->backlight_level == 0) |
409 | dev_priv->backlight_duty_cycle = | 396 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); |
410 | intel_lvds_get_max_backlight(dev); | 397 | |
398 | /* Undo any unlocking done in prepare to prevent accidental | ||
399 | * adjustment of the registers. | ||
400 | */ | ||
401 | if (HAS_PCH_SPLIT(dev)) { | ||
402 | u32 val = I915_READ(PCH_PP_CONTROL); | ||
403 | if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS) | ||
404 | I915_WRITE(PCH_PP_CONTROL, val & 0x3); | ||
405 | } else { | ||
406 | u32 val = I915_READ(PP_CONTROL); | ||
407 | if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS) | ||
408 | I915_WRITE(PP_CONTROL, val & 0x3); | ||
409 | } | ||
411 | 410 | ||
412 | intel_lvds_set_power(dev, true); | 411 | /* Always do a full power on as we do not know what state |
412 | * we were left in. | ||
413 | */ | ||
414 | intel_lvds_set_power(intel_lvds, true); | ||
413 | } | 415 | } |
414 | 416 | ||
415 | static void intel_lvds_mode_set(struct drm_encoder *encoder, | 417 | static void intel_lvds_mode_set(struct drm_encoder *encoder, |
@@ -418,7 +420,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
418 | { | 420 | { |
419 | struct drm_device *dev = encoder->dev; | 421 | struct drm_device *dev = encoder->dev; |
420 | struct drm_i915_private *dev_priv = dev->dev_private; | 422 | struct drm_i915_private *dev_priv = dev->dev_private; |
421 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); | 423 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
422 | 424 | ||
423 | /* | 425 | /* |
424 | * The LVDS pin pair will already have been turned on in the | 426 | * The LVDS pin pair will already have been turned on in the |
@@ -429,13 +431,23 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
429 | if (HAS_PCH_SPLIT(dev)) | 431 | if (HAS_PCH_SPLIT(dev)) |
430 | return; | 432 | return; |
431 | 433 | ||
434 | if (!intel_lvds->pfit_dirty) | ||
435 | return; | ||
436 | |||
432 | /* | 437 | /* |
433 | * Enable automatic panel scaling so that non-native modes fill the | 438 | * Enable automatic panel scaling so that non-native modes fill the |
434 | * screen. Should be enabled before the pipe is enabled, according to | 439 | * screen. Should be enabled before the pipe is enabled, according to |
435 | * register description and PRM. | 440 | * register description and PRM. |
436 | */ | 441 | */ |
442 | DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n", | ||
443 | intel_lvds->pfit_control, | ||
444 | intel_lvds->pfit_pgm_ratios); | ||
445 | if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) | ||
446 | DRM_ERROR("timed out waiting for panel to power off\n"); | ||
447 | |||
437 | I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios); | 448 | I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios); |
438 | I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); | 449 | I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); |
450 | intel_lvds->pfit_dirty = false; | ||
439 | } | 451 | } |
440 | 452 | ||
441 | /** | 453 | /** |
@@ -465,38 +477,22 @@ intel_lvds_detect(struct drm_connector *connector, bool force) | |||
465 | */ | 477 | */ |
466 | static int intel_lvds_get_modes(struct drm_connector *connector) | 478 | static int intel_lvds_get_modes(struct drm_connector *connector) |
467 | { | 479 | { |
480 | struct intel_lvds *intel_lvds = intel_attached_lvds(connector); | ||
468 | struct drm_device *dev = connector->dev; | 481 | struct drm_device *dev = connector->dev; |
469 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 482 | struct drm_display_mode *mode; |
470 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
471 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
472 | int ret = 0; | ||
473 | |||
474 | if (dev_priv->lvds_edid_good) { | ||
475 | ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); | ||
476 | 483 | ||
477 | if (ret) | 484 | if (intel_lvds->edid) { |
478 | return ret; | 485 | drm_mode_connector_update_edid_property(connector, |
486 | intel_lvds->edid); | ||
487 | return drm_add_edid_modes(connector, intel_lvds->edid); | ||
479 | } | 488 | } |
480 | 489 | ||
481 | /* Didn't get an EDID, so | 490 | mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); |
482 | * Set wide sync ranges so we get all modes | 491 | if (mode == 0) |
483 | * handed to valid_mode for checking | 492 | return 0; |
484 | */ | ||
485 | connector->display_info.min_vfreq = 0; | ||
486 | connector->display_info.max_vfreq = 200; | ||
487 | connector->display_info.min_hfreq = 0; | ||
488 | connector->display_info.max_hfreq = 200; | ||
489 | |||
490 | if (dev_priv->panel_fixed_mode != NULL) { | ||
491 | struct drm_display_mode *mode; | ||
492 | |||
493 | mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); | ||
494 | drm_mode_probed_add(connector, mode); | ||
495 | |||
496 | return 1; | ||
497 | } | ||
498 | 493 | ||
499 | return 0; | 494 | drm_mode_probed_add(connector, mode); |
495 | return 1; | ||
500 | } | 496 | } |
501 | 497 | ||
502 | static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id) | 498 | static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id) |
@@ -587,18 +583,17 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
587 | struct drm_property *property, | 583 | struct drm_property *property, |
588 | uint64_t value) | 584 | uint64_t value) |
589 | { | 585 | { |
586 | struct intel_lvds *intel_lvds = intel_attached_lvds(connector); | ||
590 | struct drm_device *dev = connector->dev; | 587 | struct drm_device *dev = connector->dev; |
591 | 588 | ||
592 | if (property == dev->mode_config.scaling_mode_property && | 589 | if (property == dev->mode_config.scaling_mode_property) { |
593 | connector->encoder) { | 590 | struct drm_crtc *crtc = intel_lvds->base.base.crtc; |
594 | struct drm_crtc *crtc = connector->encoder->crtc; | ||
595 | struct drm_encoder *encoder = connector->encoder; | ||
596 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); | ||
597 | 591 | ||
598 | if (value == DRM_MODE_SCALE_NONE) { | 592 | if (value == DRM_MODE_SCALE_NONE) { |
599 | DRM_DEBUG_KMS("no scaling not supported\n"); | 593 | DRM_DEBUG_KMS("no scaling not supported\n"); |
600 | return 0; | 594 | return -EINVAL; |
601 | } | 595 | } |
596 | |||
602 | if (intel_lvds->fitting_mode == value) { | 597 | if (intel_lvds->fitting_mode == value) { |
603 | /* the LVDS scaling property is not changed */ | 598 | /* the LVDS scaling property is not changed */ |
604 | return 0; | 599 | return 0; |
@@ -628,7 +623,7 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = { | |||
628 | static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { | 623 | static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { |
629 | .get_modes = intel_lvds_get_modes, | 624 | .get_modes = intel_lvds_get_modes, |
630 | .mode_valid = intel_lvds_mode_valid, | 625 | .mode_valid = intel_lvds_mode_valid, |
631 | .best_encoder = intel_attached_encoder, | 626 | .best_encoder = intel_best_encoder, |
632 | }; | 627 | }; |
633 | 628 | ||
634 | static const struct drm_connector_funcs intel_lvds_connector_funcs = { | 629 | static const struct drm_connector_funcs intel_lvds_connector_funcs = { |
@@ -726,16 +721,14 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
726 | * Find the reduced downclock for LVDS in EDID. | 721 | * Find the reduced downclock for LVDS in EDID. |
727 | */ | 722 | */ |
728 | static void intel_find_lvds_downclock(struct drm_device *dev, | 723 | static void intel_find_lvds_downclock(struct drm_device *dev, |
729 | struct drm_connector *connector) | 724 | struct drm_display_mode *fixed_mode, |
725 | struct drm_connector *connector) | ||
730 | { | 726 | { |
731 | struct drm_i915_private *dev_priv = dev->dev_private; | 727 | struct drm_i915_private *dev_priv = dev->dev_private; |
732 | struct drm_display_mode *scan, *panel_fixed_mode; | 728 | struct drm_display_mode *scan; |
733 | int temp_downclock; | 729 | int temp_downclock; |
734 | 730 | ||
735 | panel_fixed_mode = dev_priv->panel_fixed_mode; | 731 | temp_downclock = fixed_mode->clock; |
736 | temp_downclock = panel_fixed_mode->clock; | ||
737 | |||
738 | mutex_lock(&dev->mode_config.mutex); | ||
739 | list_for_each_entry(scan, &connector->probed_modes, head) { | 732 | list_for_each_entry(scan, &connector->probed_modes, head) { |
740 | /* | 733 | /* |
741 | * If one mode has the same resolution with the fixed_panel | 734 | * If one mode has the same resolution with the fixed_panel |
@@ -744,14 +737,14 @@ static void intel_find_lvds_downclock(struct drm_device *dev, | |||
744 | * case we can set the different FPx0/1 to dynamically select | 737 | * case we can set the different FPx0/1 to dynamically select |
745 | * between low and high frequency. | 738 | * between low and high frequency. |
746 | */ | 739 | */ |
747 | if (scan->hdisplay == panel_fixed_mode->hdisplay && | 740 | if (scan->hdisplay == fixed_mode->hdisplay && |
748 | scan->hsync_start == panel_fixed_mode->hsync_start && | 741 | scan->hsync_start == fixed_mode->hsync_start && |
749 | scan->hsync_end == panel_fixed_mode->hsync_end && | 742 | scan->hsync_end == fixed_mode->hsync_end && |
750 | scan->htotal == panel_fixed_mode->htotal && | 743 | scan->htotal == fixed_mode->htotal && |
751 | scan->vdisplay == panel_fixed_mode->vdisplay && | 744 | scan->vdisplay == fixed_mode->vdisplay && |
752 | scan->vsync_start == panel_fixed_mode->vsync_start && | 745 | scan->vsync_start == fixed_mode->vsync_start && |
753 | scan->vsync_end == panel_fixed_mode->vsync_end && | 746 | scan->vsync_end == fixed_mode->vsync_end && |
754 | scan->vtotal == panel_fixed_mode->vtotal) { | 747 | scan->vtotal == fixed_mode->vtotal) { |
755 | if (scan->clock < temp_downclock) { | 748 | if (scan->clock < temp_downclock) { |
756 | /* | 749 | /* |
757 | * The downclock is already found. But we | 750 | * The downclock is already found. But we |
@@ -761,17 +754,14 @@ static void intel_find_lvds_downclock(struct drm_device *dev, | |||
761 | } | 754 | } |
762 | } | 755 | } |
763 | } | 756 | } |
764 | mutex_unlock(&dev->mode_config.mutex); | 757 | if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) { |
765 | if (temp_downclock < panel_fixed_mode->clock && | ||
766 | i915_lvds_downclock) { | ||
767 | /* We found the downclock for LVDS. */ | 758 | /* We found the downclock for LVDS. */ |
768 | dev_priv->lvds_downclock_avail = 1; | 759 | dev_priv->lvds_downclock_avail = 1; |
769 | dev_priv->lvds_downclock = temp_downclock; | 760 | dev_priv->lvds_downclock = temp_downclock; |
770 | DRM_DEBUG_KMS("LVDS downclock is found in EDID. " | 761 | DRM_DEBUG_KMS("LVDS downclock is found in EDID. " |
771 | "Normal clock %dKhz, downclock %dKhz\n", | 762 | "Normal clock %dKhz, downclock %dKhz\n", |
772 | panel_fixed_mode->clock, temp_downclock); | 763 | fixed_mode->clock, temp_downclock); |
773 | } | 764 | } |
774 | return; | ||
775 | } | 765 | } |
776 | 766 | ||
777 | /* | 767 | /* |
@@ -780,38 +770,67 @@ static void intel_find_lvds_downclock(struct drm_device *dev, | |||
780 | * If it is present, return 1. | 770 | * If it is present, return 1. |
781 | * If it is not present, return false. | 771 | * If it is not present, return false. |
782 | * If no child dev is parsed from VBT, it assumes that the LVDS is present. | 772 | * If no child dev is parsed from VBT, it assumes that the LVDS is present. |
783 | * Note: The addin_offset should also be checked for LVDS panel. | ||
784 | * Only when it is non-zero, it is assumed that it is present. | ||
785 | */ | 773 | */ |
786 | static int lvds_is_present_in_vbt(struct drm_device *dev) | 774 | static bool lvds_is_present_in_vbt(struct drm_device *dev, |
775 | u8 *i2c_pin) | ||
787 | { | 776 | { |
788 | struct drm_i915_private *dev_priv = dev->dev_private; | 777 | struct drm_i915_private *dev_priv = dev->dev_private; |
789 | struct child_device_config *p_child; | 778 | int i; |
790 | int i, ret; | ||
791 | 779 | ||
792 | if (!dev_priv->child_dev_num) | 780 | if (!dev_priv->child_dev_num) |
793 | return 1; | 781 | return true; |
794 | 782 | ||
795 | ret = 0; | ||
796 | for (i = 0; i < dev_priv->child_dev_num; i++) { | 783 | for (i = 0; i < dev_priv->child_dev_num; i++) { |
797 | p_child = dev_priv->child_dev + i; | 784 | struct child_device_config *child = dev_priv->child_dev + i; |
798 | /* | 785 | |
799 | * If the device type is not LFP, continue. | 786 | /* If the device type is not LFP, continue. |
800 | * If the device type is 0x22, it is also regarded as LFP. | 787 | * We have to check both the new identifiers as well as the |
788 | * old for compatibility with some BIOSes. | ||
801 | */ | 789 | */ |
802 | if (p_child->device_type != DEVICE_TYPE_INT_LFP && | 790 | if (child->device_type != DEVICE_TYPE_INT_LFP && |
803 | p_child->device_type != DEVICE_TYPE_LFP) | 791 | child->device_type != DEVICE_TYPE_LFP) |
804 | continue; | 792 | continue; |
805 | 793 | ||
806 | /* The addin_offset should be checked. Only when it is | 794 | if (child->i2c_pin) |
807 | * non-zero, it is regarded as present. | 795 | *i2c_pin = child->i2c_pin; |
796 | |||
797 | /* However, we cannot trust the BIOS writers to populate | ||
798 | * the VBT correctly. Since LVDS requires additional | ||
799 | * information from AIM blocks, a non-zero addin offset is | ||
800 | * a good indicator that the LVDS is actually present. | ||
808 | */ | 801 | */ |
809 | if (p_child->addin_offset) { | 802 | if (child->addin_offset) |
810 | ret = 1; | 803 | return true; |
811 | break; | 804 | |
812 | } | 805 | /* But even then some BIOS writers perform some black magic |
806 | * and instantiate the device without reference to any | ||
807 | * additional data. Trust that if the VBT was written into | ||
808 | * the OpRegion then they have validated the LVDS's existence. | ||
809 | */ | ||
810 | if (dev_priv->opregion.vbt) | ||
811 | return true; | ||
813 | } | 812 | } |
814 | return ret; | 813 | |
814 | return false; | ||
815 | } | ||
816 | |||
817 | static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin) | ||
818 | { | ||
819 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
820 | u8 buf = 0; | ||
821 | struct i2c_msg msgs[] = { | ||
822 | { | ||
823 | .addr = 0xA0, | ||
824 | .flags = 0, | ||
825 | .len = 1, | ||
826 | .buf = &buf, | ||
827 | }, | ||
828 | }; | ||
829 | struct i2c_adapter *i2c = &dev_priv->gmbus[pin].adapter; | ||
830 | /* XXX this only appears to work when using GMBUS */ | ||
831 | if (intel_gmbus_is_forced_bit(i2c)) | ||
832 | return true; | ||
833 | return i2c_transfer(i2c, msgs, 1) == 1; | ||
815 | } | 834 | } |
816 | 835 | ||
817 | /** | 836 | /** |
@@ -832,13 +851,15 @@ void intel_lvds_init(struct drm_device *dev) | |||
832 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 851 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
833 | struct drm_crtc *crtc; | 852 | struct drm_crtc *crtc; |
834 | u32 lvds; | 853 | u32 lvds; |
835 | int pipe, gpio = GPIOC; | 854 | int pipe; |
855 | u8 pin; | ||
836 | 856 | ||
837 | /* Skip init on machines we know falsely report LVDS */ | 857 | /* Skip init on machines we know falsely report LVDS */ |
838 | if (dmi_check_system(intel_no_lvds)) | 858 | if (dmi_check_system(intel_no_lvds)) |
839 | return; | 859 | return; |
840 | 860 | ||
841 | if (!lvds_is_present_in_vbt(dev)) { | 861 | pin = GMBUS_PORT_PANEL; |
862 | if (!lvds_is_present_in_vbt(dev, &pin)) { | ||
842 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); | 863 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); |
843 | return; | 864 | return; |
844 | } | 865 | } |
@@ -846,11 +867,15 @@ void intel_lvds_init(struct drm_device *dev) | |||
846 | if (HAS_PCH_SPLIT(dev)) { | 867 | if (HAS_PCH_SPLIT(dev)) { |
847 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | 868 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
848 | return; | 869 | return; |
849 | if (dev_priv->edp_support) { | 870 | if (dev_priv->edp.support) { |
850 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); | 871 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); |
851 | return; | 872 | return; |
852 | } | 873 | } |
853 | gpio = PCH_GPIOC; | 874 | } |
875 | |||
876 | if (!intel_lvds_ddc_probe(dev, pin)) { | ||
877 | DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); | ||
878 | return; | ||
854 | } | 879 | } |
855 | 880 | ||
856 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); | 881 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); |
@@ -864,16 +889,20 @@ void intel_lvds_init(struct drm_device *dev) | |||
864 | return; | 889 | return; |
865 | } | 890 | } |
866 | 891 | ||
892 | if (!HAS_PCH_SPLIT(dev)) { | ||
893 | intel_lvds->pfit_control = I915_READ(PFIT_CONTROL); | ||
894 | } | ||
895 | |||
867 | intel_encoder = &intel_lvds->base; | 896 | intel_encoder = &intel_lvds->base; |
868 | encoder = &intel_encoder->enc; | 897 | encoder = &intel_encoder->base; |
869 | connector = &intel_connector->base; | 898 | connector = &intel_connector->base; |
870 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, | 899 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, |
871 | DRM_MODE_CONNECTOR_LVDS); | 900 | DRM_MODE_CONNECTOR_LVDS); |
872 | 901 | ||
873 | drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs, | 902 | drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs, |
874 | DRM_MODE_ENCODER_LVDS); | 903 | DRM_MODE_ENCODER_LVDS); |
875 | 904 | ||
876 | drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc); | 905 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
877 | intel_encoder->type = INTEL_OUTPUT_LVDS; | 906 | intel_encoder->type = INTEL_OUTPUT_LVDS; |
878 | 907 | ||
879 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 908 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
@@ -904,43 +933,41 @@ void intel_lvds_init(struct drm_device *dev) | |||
904 | * if closed, act like it's not there for now | 933 | * if closed, act like it's not there for now |
905 | */ | 934 | */ |
906 | 935 | ||
907 | /* Set up the DDC bus. */ | ||
908 | intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C"); | ||
909 | if (!intel_encoder->ddc_bus) { | ||
910 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | ||
911 | "failed.\n"); | ||
912 | goto failed; | ||
913 | } | ||
914 | |||
915 | /* | 936 | /* |
916 | * Attempt to get the fixed panel mode from DDC. Assume that the | 937 | * Attempt to get the fixed panel mode from DDC. Assume that the |
917 | * preferred mode is the right one. | 938 | * preferred mode is the right one. |
918 | */ | 939 | */ |
919 | dev_priv->lvds_edid_good = true; | 940 | intel_lvds->edid = drm_get_edid(connector, |
941 | &dev_priv->gmbus[pin].adapter); | ||
920 | 942 | ||
921 | if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus)) | 943 | if (!intel_lvds->edid) { |
922 | dev_priv->lvds_edid_good = false; | 944 | /* Didn't get an EDID, so |
945 | * Set wide sync ranges so we get all modes | ||
946 | * handed to valid_mode for checking | ||
947 | */ | ||
948 | connector->display_info.min_vfreq = 0; | ||
949 | connector->display_info.max_vfreq = 200; | ||
950 | connector->display_info.min_hfreq = 0; | ||
951 | connector->display_info.max_hfreq = 200; | ||
952 | } | ||
923 | 953 | ||
924 | list_for_each_entry(scan, &connector->probed_modes, head) { | 954 | list_for_each_entry(scan, &connector->probed_modes, head) { |
925 | mutex_lock(&dev->mode_config.mutex); | ||
926 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { | 955 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { |
927 | dev_priv->panel_fixed_mode = | 956 | intel_lvds->fixed_mode = |
928 | drm_mode_duplicate(dev, scan); | 957 | drm_mode_duplicate(dev, scan); |
929 | mutex_unlock(&dev->mode_config.mutex); | 958 | intel_find_lvds_downclock(dev, |
930 | intel_find_lvds_downclock(dev, connector); | 959 | intel_lvds->fixed_mode, |
960 | connector); | ||
931 | goto out; | 961 | goto out; |
932 | } | 962 | } |
933 | mutex_unlock(&dev->mode_config.mutex); | ||
934 | } | 963 | } |
935 | 964 | ||
936 | /* Failed to get EDID, what about VBT? */ | 965 | /* Failed to get EDID, what about VBT? */ |
937 | if (dev_priv->lfp_lvds_vbt_mode) { | 966 | if (dev_priv->lfp_lvds_vbt_mode) { |
938 | mutex_lock(&dev->mode_config.mutex); | 967 | intel_lvds->fixed_mode = |
939 | dev_priv->panel_fixed_mode = | ||
940 | drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); | 968 | drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); |
941 | mutex_unlock(&dev->mode_config.mutex); | 969 | if (intel_lvds->fixed_mode) { |
942 | if (dev_priv->panel_fixed_mode) { | 970 | intel_lvds->fixed_mode->type |= |
943 | dev_priv->panel_fixed_mode->type |= | ||
944 | DRM_MODE_TYPE_PREFERRED; | 971 | DRM_MODE_TYPE_PREFERRED; |
945 | goto out; | 972 | goto out; |
946 | } | 973 | } |
@@ -958,19 +985,19 @@ void intel_lvds_init(struct drm_device *dev) | |||
958 | 985 | ||
959 | lvds = I915_READ(LVDS); | 986 | lvds = I915_READ(LVDS); |
960 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; | 987 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; |
961 | crtc = intel_get_crtc_from_pipe(dev, pipe); | 988 | crtc = intel_get_crtc_for_pipe(dev, pipe); |
962 | 989 | ||
963 | if (crtc && (lvds & LVDS_PORT_EN)) { | 990 | if (crtc && (lvds & LVDS_PORT_EN)) { |
964 | dev_priv->panel_fixed_mode = intel_crtc_mode_get(dev, crtc); | 991 | intel_lvds->fixed_mode = intel_crtc_mode_get(dev, crtc); |
965 | if (dev_priv->panel_fixed_mode) { | 992 | if (intel_lvds->fixed_mode) { |
966 | dev_priv->panel_fixed_mode->type |= | 993 | intel_lvds->fixed_mode->type |= |
967 | DRM_MODE_TYPE_PREFERRED; | 994 | DRM_MODE_TYPE_PREFERRED; |
968 | goto out; | 995 | goto out; |
969 | } | 996 | } |
970 | } | 997 | } |
971 | 998 | ||
972 | /* If we still don't have a mode after all that, give up. */ | 999 | /* If we still don't have a mode after all that, give up. */ |
973 | if (!dev_priv->panel_fixed_mode) | 1000 | if (!intel_lvds->fixed_mode) |
974 | goto failed; | 1001 | goto failed; |
975 | 1002 | ||
976 | out: | 1003 | out: |
@@ -997,8 +1024,6 @@ out: | |||
997 | 1024 | ||
998 | failed: | 1025 | failed: |
999 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); | 1026 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); |
1000 | if (intel_encoder->ddc_bus) | ||
1001 | intel_i2c_destroy(intel_encoder->ddc_bus); | ||
1002 | drm_connector_cleanup(connector); | 1027 | drm_connector_cleanup(connector); |
1003 | drm_encoder_cleanup(encoder); | 1028 | drm_encoder_cleanup(encoder); |
1004 | kfree(intel_lvds); | 1029 | kfree(intel_lvds); |
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 4b1fd3d9c73c..f70b7cf32bff 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> | 2 | * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> |
3 | * Copyright (c) 2007 Intel Corporation | 3 | * Copyright (c) 2007, 2010 Intel Corporation |
4 | * Jesse Barnes <jesse.barnes@intel.com> | 4 | * Jesse Barnes <jesse.barnes@intel.com> |
5 | * | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
@@ -34,11 +34,11 @@ | |||
34 | * intel_ddc_probe | 34 | * intel_ddc_probe |
35 | * | 35 | * |
36 | */ | 36 | */ |
37 | bool intel_ddc_probe(struct intel_encoder *intel_encoder) | 37 | bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) |
38 | { | 38 | { |
39 | struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; | ||
39 | u8 out_buf[] = { 0x0, 0x0}; | 40 | u8 out_buf[] = { 0x0, 0x0}; |
40 | u8 buf[2]; | 41 | u8 buf[2]; |
41 | int ret; | ||
42 | struct i2c_msg msgs[] = { | 42 | struct i2c_msg msgs[] = { |
43 | { | 43 | { |
44 | .addr = 0x50, | 44 | .addr = 0x50, |
@@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder) | |||
54 | } | 54 | } |
55 | }; | 55 | }; |
56 | 56 | ||
57 | intel_i2c_quirk_set(intel_encoder->enc.dev, true); | 57 | return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2; |
58 | ret = i2c_transfer(intel_encoder->ddc_bus, msgs, 2); | ||
59 | intel_i2c_quirk_set(intel_encoder->enc.dev, false); | ||
60 | if (ret == 2) | ||
61 | return true; | ||
62 | |||
63 | return false; | ||
64 | } | 58 | } |
65 | 59 | ||
66 | /** | 60 | /** |
@@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector, | |||
76 | struct edid *edid; | 70 | struct edid *edid; |
77 | int ret = 0; | 71 | int ret = 0; |
78 | 72 | ||
79 | intel_i2c_quirk_set(connector->dev, true); | ||
80 | edid = drm_get_edid(connector, adapter); | 73 | edid = drm_get_edid(connector, adapter); |
81 | intel_i2c_quirk_set(connector->dev, false); | ||
82 | if (edid) { | 74 | if (edid) { |
83 | drm_mode_connector_update_edid_property(connector, edid); | 75 | drm_mode_connector_update_edid_property(connector, edid); |
84 | ret = drm_add_edid_modes(connector, edid); | 76 | ret = drm_add_edid_modes(connector, edid); |
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index ea5d3fea4b61..917c7dc3cd6b 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
@@ -31,17 +31,16 @@ | |||
31 | #include "drmP.h" | 31 | #include "drmP.h" |
32 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
33 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
34 | #include "intel_drv.h" | ||
34 | 35 | ||
35 | #define PCI_ASLE 0xe4 | 36 | #define PCI_ASLE 0xe4 |
36 | #define PCI_LBPC 0xf4 | ||
37 | #define PCI_ASLS 0xfc | 37 | #define PCI_ASLS 0xfc |
38 | 38 | ||
39 | #define OPREGION_SZ (8*1024) | ||
40 | #define OPREGION_HEADER_OFFSET 0 | 39 | #define OPREGION_HEADER_OFFSET 0 |
41 | #define OPREGION_ACPI_OFFSET 0x100 | 40 | #define OPREGION_ACPI_OFFSET 0x100 |
42 | #define OPREGION_SWSCI_OFFSET 0x200 | 41 | #define OPREGION_SWSCI_OFFSET 0x200 |
43 | #define OPREGION_ASLE_OFFSET 0x300 | 42 | #define OPREGION_ASLE_OFFSET 0x300 |
44 | #define OPREGION_VBT_OFFSET 0x1000 | 43 | #define OPREGION_VBT_OFFSET 0x400 |
45 | 44 | ||
46 | #define OPREGION_SIGNATURE "IntelGraphicsMem" | 45 | #define OPREGION_SIGNATURE "IntelGraphicsMem" |
47 | #define MBOX_ACPI (1<<0) | 46 | #define MBOX_ACPI (1<<0) |
@@ -143,40 +142,22 @@ struct opregion_asle { | |||
143 | #define ACPI_DIGITAL_OUTPUT (3<<8) | 142 | #define ACPI_DIGITAL_OUTPUT (3<<8) |
144 | #define ACPI_LVDS_OUTPUT (4<<8) | 143 | #define ACPI_LVDS_OUTPUT (4<<8) |
145 | 144 | ||
145 | #ifdef CONFIG_ACPI | ||
146 | static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | 146 | static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) |
147 | { | 147 | { |
148 | struct drm_i915_private *dev_priv = dev->dev_private; | 148 | struct drm_i915_private *dev_priv = dev->dev_private; |
149 | struct opregion_asle *asle = dev_priv->opregion.asle; | 149 | struct opregion_asle *asle = dev_priv->opregion.asle; |
150 | u32 blc_pwm_ctl, blc_pwm_ctl2; | 150 | u32 max; |
151 | u32 max_backlight, level, shift; | ||
152 | 151 | ||
153 | if (!(bclp & ASLE_BCLP_VALID)) | 152 | if (!(bclp & ASLE_BCLP_VALID)) |
154 | return ASLE_BACKLIGHT_FAILED; | 153 | return ASLE_BACKLIGHT_FAILED; |
155 | 154 | ||
156 | bclp &= ASLE_BCLP_MSK; | 155 | bclp &= ASLE_BCLP_MSK; |
157 | if (bclp < 0 || bclp > 255) | 156 | if (bclp > 255) |
158 | return ASLE_BACKLIGHT_FAILED; | 157 | return ASLE_BACKLIGHT_FAILED; |
159 | 158 | ||
160 | blc_pwm_ctl = I915_READ(BLC_PWM_CTL); | 159 | max = intel_panel_get_max_backlight(dev); |
161 | blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2); | 160 | intel_panel_set_backlight(dev, bclp * max / 255); |
162 | |||
163 | if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE)) | ||
164 | pci_write_config_dword(dev->pdev, PCI_LBPC, bclp); | ||
165 | else { | ||
166 | if (IS_PINEVIEW(dev)) { | ||
167 | blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); | ||
168 | max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
169 | BACKLIGHT_MODULATION_FREQ_SHIFT; | ||
170 | shift = BACKLIGHT_DUTY_CYCLE_SHIFT + 1; | ||
171 | } else { | ||
172 | blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
173 | max_backlight = ((blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
174 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; | ||
175 | shift = BACKLIGHT_DUTY_CYCLE_SHIFT; | ||
176 | } | ||
177 | level = (bclp * max_backlight) / 255; | ||
178 | I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | (level << shift)); | ||
179 | } | ||
180 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; | 161 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; |
181 | 162 | ||
182 | return 0; | 163 | return 0; |
@@ -211,7 +192,7 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit) | |||
211 | return 0; | 192 | return 0; |
212 | } | 193 | } |
213 | 194 | ||
214 | void opregion_asle_intr(struct drm_device *dev) | 195 | void intel_opregion_asle_intr(struct drm_device *dev) |
215 | { | 196 | { |
216 | struct drm_i915_private *dev_priv = dev->dev_private; | 197 | struct drm_i915_private *dev_priv = dev->dev_private; |
217 | struct opregion_asle *asle = dev_priv->opregion.asle; | 198 | struct opregion_asle *asle = dev_priv->opregion.asle; |
@@ -243,37 +224,8 @@ void opregion_asle_intr(struct drm_device *dev) | |||
243 | asle->aslc = asle_stat; | 224 | asle->aslc = asle_stat; |
244 | } | 225 | } |
245 | 226 | ||
246 | static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp) | 227 | /* Only present on Ironlake+ */ |
247 | { | 228 | void intel_opregion_gse_intr(struct drm_device *dev) |
248 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
249 | struct opregion_asle *asle = dev_priv->opregion.asle; | ||
250 | u32 cpu_pwm_ctl, pch_pwm_ctl2; | ||
251 | u32 max_backlight, level; | ||
252 | |||
253 | if (!(bclp & ASLE_BCLP_VALID)) | ||
254 | return ASLE_BACKLIGHT_FAILED; | ||
255 | |||
256 | bclp &= ASLE_BCLP_MSK; | ||
257 | if (bclp < 0 || bclp > 255) | ||
258 | return ASLE_BACKLIGHT_FAILED; | ||
259 | |||
260 | cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL); | ||
261 | pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); | ||
262 | /* get the max PWM frequency */ | ||
263 | max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK; | ||
264 | /* calculate the expected PMW frequency */ | ||
265 | level = (bclp * max_backlight) / 255; | ||
266 | /* reserve the high 16 bits */ | ||
267 | cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK); | ||
268 | /* write the updated PWM frequency */ | ||
269 | I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level); | ||
270 | |||
271 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | void ironlake_opregion_gse_intr(struct drm_device *dev) | ||
277 | { | 229 | { |
278 | struct drm_i915_private *dev_priv = dev->dev_private; | 230 | struct drm_i915_private *dev_priv = dev->dev_private; |
279 | struct opregion_asle *asle = dev_priv->opregion.asle; | 231 | struct opregion_asle *asle = dev_priv->opregion.asle; |
@@ -296,7 +248,7 @@ void ironlake_opregion_gse_intr(struct drm_device *dev) | |||
296 | } | 248 | } |
297 | 249 | ||
298 | if (asle_req & ASLE_SET_BACKLIGHT) | 250 | if (asle_req & ASLE_SET_BACKLIGHT) |
299 | asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp); | 251 | asle_stat |= asle_set_backlight(dev, asle->bclp); |
300 | 252 | ||
301 | if (asle_req & ASLE_SET_PFIT) { | 253 | if (asle_req & ASLE_SET_PFIT) { |
302 | DRM_DEBUG_DRIVER("Pfit is not supported\n"); | 254 | DRM_DEBUG_DRIVER("Pfit is not supported\n"); |
@@ -315,7 +267,7 @@ void ironlake_opregion_gse_intr(struct drm_device *dev) | |||
315 | #define ASLE_PFIT_EN (1<<2) | 267 | #define ASLE_PFIT_EN (1<<2) |
316 | #define ASLE_PFMB_EN (1<<3) | 268 | #define ASLE_PFMB_EN (1<<3) |
317 | 269 | ||
318 | void opregion_enable_asle(struct drm_device *dev) | 270 | void intel_opregion_enable_asle(struct drm_device *dev) |
319 | { | 271 | { |
320 | struct drm_i915_private *dev_priv = dev->dev_private; | 272 | struct drm_i915_private *dev_priv = dev->dev_private; |
321 | struct opregion_asle *asle = dev_priv->opregion.asle; | 273 | struct opregion_asle *asle = dev_priv->opregion.asle; |
@@ -464,7 +416,58 @@ blind_set: | |||
464 | goto end; | 416 | goto end; |
465 | } | 417 | } |
466 | 418 | ||
467 | int intel_opregion_init(struct drm_device *dev, int resume) | 419 | void intel_opregion_init(struct drm_device *dev) |
420 | { | ||
421 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
422 | struct intel_opregion *opregion = &dev_priv->opregion; | ||
423 | |||
424 | if (!opregion->header) | ||
425 | return; | ||
426 | |||
427 | if (opregion->acpi) { | ||
428 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
429 | intel_didl_outputs(dev); | ||
430 | |||
431 | /* Notify BIOS we are ready to handle ACPI video ext notifs. | ||
432 | * Right now, all the events are handled by the ACPI video module. | ||
433 | * We don't actually need to do anything with them. */ | ||
434 | opregion->acpi->csts = 0; | ||
435 | opregion->acpi->drdy = 1; | ||
436 | |||
437 | system_opregion = opregion; | ||
438 | register_acpi_notifier(&intel_opregion_notifier); | ||
439 | } | ||
440 | |||
441 | if (opregion->asle) | ||
442 | intel_opregion_enable_asle(dev); | ||
443 | } | ||
444 | |||
445 | void intel_opregion_fini(struct drm_device *dev) | ||
446 | { | ||
447 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
448 | struct intel_opregion *opregion = &dev_priv->opregion; | ||
449 | |||
450 | if (!opregion->header) | ||
451 | return; | ||
452 | |||
453 | if (opregion->acpi) { | ||
454 | opregion->acpi->drdy = 0; | ||
455 | |||
456 | system_opregion = NULL; | ||
457 | unregister_acpi_notifier(&intel_opregion_notifier); | ||
458 | } | ||
459 | |||
460 | /* just clear all opregion memory pointers now */ | ||
461 | iounmap(opregion->header); | ||
462 | opregion->header = NULL; | ||
463 | opregion->acpi = NULL; | ||
464 | opregion->swsci = NULL; | ||
465 | opregion->asle = NULL; | ||
466 | opregion->vbt = NULL; | ||
467 | } | ||
468 | #endif | ||
469 | |||
470 | int intel_opregion_setup(struct drm_device *dev) | ||
468 | { | 471 | { |
469 | struct drm_i915_private *dev_priv = dev->dev_private; | 472 | struct drm_i915_private *dev_priv = dev->dev_private; |
470 | struct intel_opregion *opregion = &dev_priv->opregion; | 473 | struct intel_opregion *opregion = &dev_priv->opregion; |
@@ -479,29 +482,23 @@ int intel_opregion_init(struct drm_device *dev, int resume) | |||
479 | return -ENOTSUPP; | 482 | return -ENOTSUPP; |
480 | } | 483 | } |
481 | 484 | ||
482 | base = ioremap(asls, OPREGION_SZ); | 485 | base = ioremap(asls, OPREGION_SIZE); |
483 | if (!base) | 486 | if (!base) |
484 | return -ENOMEM; | 487 | return -ENOMEM; |
485 | 488 | ||
486 | opregion->header = base; | 489 | if (memcmp(base, OPREGION_SIGNATURE, 16)) { |
487 | if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) { | ||
488 | DRM_DEBUG_DRIVER("opregion signature mismatch\n"); | 490 | DRM_DEBUG_DRIVER("opregion signature mismatch\n"); |
489 | err = -EINVAL; | 491 | err = -EINVAL; |
490 | goto err_out; | 492 | goto err_out; |
491 | } | 493 | } |
494 | opregion->header = base; | ||
495 | opregion->vbt = base + OPREGION_VBT_OFFSET; | ||
492 | 496 | ||
493 | mboxes = opregion->header->mboxes; | 497 | mboxes = opregion->header->mboxes; |
494 | if (mboxes & MBOX_ACPI) { | 498 | if (mboxes & MBOX_ACPI) { |
495 | DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); | 499 | DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); |
496 | opregion->acpi = base + OPREGION_ACPI_OFFSET; | 500 | opregion->acpi = base + OPREGION_ACPI_OFFSET; |
497 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
498 | intel_didl_outputs(dev); | ||
499 | } else { | ||
500 | DRM_DEBUG_DRIVER("Public ACPI methods not supported\n"); | ||
501 | err = -ENOTSUPP; | ||
502 | goto err_out; | ||
503 | } | 501 | } |
504 | opregion->enabled = 1; | ||
505 | 502 | ||
506 | if (mboxes & MBOX_SWSCI) { | 503 | if (mboxes & MBOX_SWSCI) { |
507 | DRM_DEBUG_DRIVER("SWSCI supported\n"); | 504 | DRM_DEBUG_DRIVER("SWSCI supported\n"); |
@@ -510,53 +507,11 @@ int intel_opregion_init(struct drm_device *dev, int resume) | |||
510 | if (mboxes & MBOX_ASLE) { | 507 | if (mboxes & MBOX_ASLE) { |
511 | DRM_DEBUG_DRIVER("ASLE supported\n"); | 508 | DRM_DEBUG_DRIVER("ASLE supported\n"); |
512 | opregion->asle = base + OPREGION_ASLE_OFFSET; | 509 | opregion->asle = base + OPREGION_ASLE_OFFSET; |
513 | opregion_enable_asle(dev); | ||
514 | } | 510 | } |
515 | 511 | ||
516 | if (!resume) | ||
517 | acpi_video_register(); | ||
518 | |||
519 | |||
520 | /* Notify BIOS we are ready to handle ACPI video ext notifs. | ||
521 | * Right now, all the events are handled by the ACPI video module. | ||
522 | * We don't actually need to do anything with them. */ | ||
523 | opregion->acpi->csts = 0; | ||
524 | opregion->acpi->drdy = 1; | ||
525 | |||
526 | system_opregion = opregion; | ||
527 | register_acpi_notifier(&intel_opregion_notifier); | ||
528 | |||
529 | return 0; | 512 | return 0; |
530 | 513 | ||
531 | err_out: | 514 | err_out: |
532 | iounmap(opregion->header); | 515 | iounmap(opregion->header); |
533 | opregion->header = NULL; | ||
534 | acpi_video_register(); | ||
535 | return err; | 516 | return err; |
536 | } | 517 | } |
537 | |||
538 | void intel_opregion_free(struct drm_device *dev, int suspend) | ||
539 | { | ||
540 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
541 | struct intel_opregion *opregion = &dev_priv->opregion; | ||
542 | |||
543 | if (!opregion->enabled) | ||
544 | return; | ||
545 | |||
546 | if (!suspend) | ||
547 | acpi_video_unregister(); | ||
548 | |||
549 | opregion->acpi->drdy = 0; | ||
550 | |||
551 | system_opregion = NULL; | ||
552 | unregister_acpi_notifier(&intel_opregion_notifier); | ||
553 | |||
554 | /* just clear all opregion memory pointers now */ | ||
555 | iounmap(opregion->header); | ||
556 | opregion->header = NULL; | ||
557 | opregion->acpi = NULL; | ||
558 | opregion->swsci = NULL; | ||
559 | opregion->asle = NULL; | ||
560 | |||
561 | opregion->enabled = 0; | ||
562 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 1d306a458be6..375316a8420e 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -170,57 +170,143 @@ struct overlay_registers { | |||
170 | u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; | 170 | u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | /* overlay flip addr flag */ | 173 | struct intel_overlay { |
174 | #define OFC_UPDATE 0x1 | 174 | struct drm_device *dev; |
175 | 175 | struct intel_crtc *crtc; | |
176 | #define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev)) | 176 | struct drm_i915_gem_object *vid_bo; |
177 | #define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev)) | 177 | struct drm_i915_gem_object *old_vid_bo; |
178 | 178 | int active; | |
179 | int pfit_active; | ||
180 | u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */ | ||
181 | u32 color_key; | ||
182 | u32 brightness, contrast, saturation; | ||
183 | u32 old_xscale, old_yscale; | ||
184 | /* register access */ | ||
185 | u32 flip_addr; | ||
186 | struct drm_i915_gem_object *reg_bo; | ||
187 | /* flip handling */ | ||
188 | uint32_t last_flip_req; | ||
189 | void (*flip_tail)(struct intel_overlay *); | ||
190 | }; | ||
179 | 191 | ||
180 | static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay) | 192 | static struct overlay_registers * |
193 | intel_overlay_map_regs(struct intel_overlay *overlay) | ||
181 | { | 194 | { |
182 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; | 195 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; |
183 | struct overlay_registers *regs; | 196 | struct overlay_registers *regs; |
184 | 197 | ||
185 | /* no recursive mappings */ | 198 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
186 | BUG_ON(overlay->virt_addr); | 199 | regs = overlay->reg_bo->phys_obj->handle->vaddr; |
200 | else | ||
201 | regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping, | ||
202 | overlay->reg_bo->gtt_offset); | ||
187 | 203 | ||
188 | if (OVERLAY_NONPHYSICAL(overlay->dev)) { | 204 | return regs; |
189 | regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 205 | } |
190 | overlay->reg_bo->gtt_offset, | ||
191 | KM_USER0); | ||
192 | 206 | ||
193 | if (!regs) { | 207 | static void intel_overlay_unmap_regs(struct intel_overlay *overlay, |
194 | DRM_ERROR("failed to map overlay regs in GTT\n"); | 208 | struct overlay_registers *regs) |
195 | return NULL; | 209 | { |
196 | } | 210 | if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
197 | } else | 211 | io_mapping_unmap(regs); |
198 | regs = overlay->reg_bo->phys_obj->handle->vaddr; | 212 | } |
213 | |||
214 | static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | ||
215 | struct drm_i915_gem_request *request, | ||
216 | bool interruptible, | ||
217 | void (*tail)(struct intel_overlay *)) | ||
218 | { | ||
219 | struct drm_device *dev = overlay->dev; | ||
220 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
221 | int ret; | ||
222 | |||
223 | BUG_ON(overlay->last_flip_req); | ||
224 | overlay->last_flip_req = | ||
225 | i915_add_request(dev, NULL, request, &dev_priv->render_ring); | ||
226 | if (overlay->last_flip_req == 0) | ||
227 | return -ENOMEM; | ||
199 | 228 | ||
200 | return overlay->virt_addr = regs; | 229 | overlay->flip_tail = tail; |
230 | ret = i915_do_wait_request(dev, | ||
231 | overlay->last_flip_req, true, | ||
232 | &dev_priv->render_ring); | ||
233 | if (ret) | ||
234 | return ret; | ||
235 | |||
236 | overlay->last_flip_req = 0; | ||
237 | return 0; | ||
201 | } | 238 | } |
202 | 239 | ||
203 | static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) | 240 | /* Workaround for i830 bug where pipe a must be enable to change control regs */ |
241 | static int | ||
242 | i830_activate_pipe_a(struct drm_device *dev) | ||
204 | { | 243 | { |
205 | if (OVERLAY_NONPHYSICAL(overlay->dev)) | 244 | drm_i915_private_t *dev_priv = dev->dev_private; |
206 | io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0); | 245 | struct intel_crtc *crtc; |
246 | struct drm_crtc_helper_funcs *crtc_funcs; | ||
247 | struct drm_display_mode vesa_640x480 = { | ||
248 | DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
249 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
250 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) | ||
251 | }, *mode; | ||
252 | |||
253 | crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]); | ||
254 | if (crtc->dpms_mode == DRM_MODE_DPMS_ON) | ||
255 | return 0; | ||
207 | 256 | ||
208 | overlay->virt_addr = NULL; | 257 | /* most i8xx have pipe a forced on, so don't trust dpms mode */ |
258 | if (I915_READ(PIPEACONF) & PIPECONF_ENABLE) | ||
259 | return 0; | ||
209 | 260 | ||
210 | return; | 261 | crtc_funcs = crtc->base.helper_private; |
262 | if (crtc_funcs->dpms == NULL) | ||
263 | return 0; | ||
264 | |||
265 | DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n"); | ||
266 | |||
267 | mode = drm_mode_duplicate(dev, &vesa_640x480); | ||
268 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | ||
269 | if(!drm_crtc_helper_set_mode(&crtc->base, mode, | ||
270 | crtc->base.x, crtc->base.y, | ||
271 | crtc->base.fb)) | ||
272 | return 0; | ||
273 | |||
274 | crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON); | ||
275 | return 1; | ||
276 | } | ||
277 | |||
278 | static void | ||
279 | i830_deactivate_pipe_a(struct drm_device *dev) | ||
280 | { | ||
281 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
282 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; | ||
283 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
284 | |||
285 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
211 | } | 286 | } |
212 | 287 | ||
213 | /* overlay needs to be disable in OCMD reg */ | 288 | /* overlay needs to be disable in OCMD reg */ |
214 | static int intel_overlay_on(struct intel_overlay *overlay) | 289 | static int intel_overlay_on(struct intel_overlay *overlay) |
215 | { | 290 | { |
216 | struct drm_device *dev = overlay->dev; | 291 | struct drm_device *dev = overlay->dev; |
292 | struct drm_i915_gem_request *request; | ||
293 | int pipe_a_quirk = 0; | ||
217 | int ret; | 294 | int ret; |
218 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
219 | 295 | ||
220 | BUG_ON(overlay->active); | 296 | BUG_ON(overlay->active); |
221 | |||
222 | overlay->active = 1; | 297 | overlay->active = 1; |
223 | overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP; | 298 | |
299 | if (IS_I830(dev)) { | ||
300 | pipe_a_quirk = i830_activate_pipe_a(dev); | ||
301 | if (pipe_a_quirk < 0) | ||
302 | return pipe_a_quirk; | ||
303 | } | ||
304 | |||
305 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
306 | if (request == NULL) { | ||
307 | ret = -ENOMEM; | ||
308 | goto out; | ||
309 | } | ||
224 | 310 | ||
225 | BEGIN_LP_RING(4); | 311 | BEGIN_LP_RING(4); |
226 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); | 312 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); |
@@ -229,32 +315,30 @@ static int intel_overlay_on(struct intel_overlay *overlay) | |||
229 | OUT_RING(MI_NOOP); | 315 | OUT_RING(MI_NOOP); |
230 | ADVANCE_LP_RING(); | 316 | ADVANCE_LP_RING(); |
231 | 317 | ||
232 | overlay->last_flip_req = | 318 | ret = intel_overlay_do_wait_request(overlay, request, true, NULL); |
233 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 319 | out: |
234 | if (overlay->last_flip_req == 0) | 320 | if (pipe_a_quirk) |
235 | return -ENOMEM; | 321 | i830_deactivate_pipe_a(dev); |
236 | |||
237 | ret = i915_do_wait_request(dev, | ||
238 | overlay->last_flip_req, 1, &dev_priv->render_ring); | ||
239 | if (ret != 0) | ||
240 | return ret; | ||
241 | 322 | ||
242 | overlay->hw_wedged = 0; | 323 | return ret; |
243 | overlay->last_flip_req = 0; | ||
244 | return 0; | ||
245 | } | 324 | } |
246 | 325 | ||
247 | /* overlay needs to be enabled in OCMD reg */ | 326 | /* overlay needs to be enabled in OCMD reg */ |
248 | static void intel_overlay_continue(struct intel_overlay *overlay, | 327 | static int intel_overlay_continue(struct intel_overlay *overlay, |
249 | bool load_polyphase_filter) | 328 | bool load_polyphase_filter) |
250 | { | 329 | { |
251 | struct drm_device *dev = overlay->dev; | 330 | struct drm_device *dev = overlay->dev; |
252 | drm_i915_private_t *dev_priv = dev->dev_private; | 331 | drm_i915_private_t *dev_priv = dev->dev_private; |
332 | struct drm_i915_gem_request *request; | ||
253 | u32 flip_addr = overlay->flip_addr; | 333 | u32 flip_addr = overlay->flip_addr; |
254 | u32 tmp; | 334 | u32 tmp; |
255 | 335 | ||
256 | BUG_ON(!overlay->active); | 336 | BUG_ON(!overlay->active); |
257 | 337 | ||
338 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
339 | if (request == NULL) | ||
340 | return -ENOMEM; | ||
341 | |||
258 | if (load_polyphase_filter) | 342 | if (load_polyphase_filter) |
259 | flip_addr |= OFC_UPDATE; | 343 | flip_addr |= OFC_UPDATE; |
260 | 344 | ||
@@ -269,220 +353,132 @@ static void intel_overlay_continue(struct intel_overlay *overlay, | |||
269 | ADVANCE_LP_RING(); | 353 | ADVANCE_LP_RING(); |
270 | 354 | ||
271 | overlay->last_flip_req = | 355 | overlay->last_flip_req = |
272 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 356 | i915_add_request(dev, NULL, request, &dev_priv->render_ring); |
357 | return 0; | ||
273 | } | 358 | } |
274 | 359 | ||
275 | static int intel_overlay_wait_flip(struct intel_overlay *overlay) | 360 | static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) |
276 | { | 361 | { |
277 | struct drm_device *dev = overlay->dev; | 362 | struct drm_gem_object *obj = &overlay->old_vid_bo->base; |
278 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
279 | int ret; | ||
280 | u32 tmp; | ||
281 | |||
282 | if (overlay->last_flip_req != 0) { | ||
283 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
284 | 1, &dev_priv->render_ring); | ||
285 | if (ret == 0) { | ||
286 | overlay->last_flip_req = 0; | ||
287 | 363 | ||
288 | tmp = I915_READ(ISR); | 364 | i915_gem_object_unpin(obj); |
289 | 365 | drm_gem_object_unreference(obj); | |
290 | if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) | ||
291 | return 0; | ||
292 | } | ||
293 | } | ||
294 | 366 | ||
295 | /* synchronous slowpath */ | 367 | overlay->old_vid_bo = NULL; |
296 | overlay->hw_wedged = RELEASE_OLD_VID; | 368 | } |
297 | 369 | ||
298 | BEGIN_LP_RING(2); | 370 | static void intel_overlay_off_tail(struct intel_overlay *overlay) |
299 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 371 | { |
300 | OUT_RING(MI_NOOP); | 372 | struct drm_gem_object *obj; |
301 | ADVANCE_LP_RING(); | ||
302 | 373 | ||
303 | overlay->last_flip_req = | 374 | /* never have the overlay hw on without showing a frame */ |
304 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 375 | BUG_ON(!overlay->vid_bo); |
305 | if (overlay->last_flip_req == 0) | 376 | obj = &overlay->vid_bo->base; |
306 | return -ENOMEM; | ||
307 | 377 | ||
308 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | 378 | i915_gem_object_unpin(obj); |
309 | 1, &dev_priv->render_ring); | 379 | drm_gem_object_unreference(obj); |
310 | if (ret != 0) | 380 | overlay->vid_bo = NULL; |
311 | return ret; | ||
312 | 381 | ||
313 | overlay->hw_wedged = 0; | 382 | overlay->crtc->overlay = NULL; |
314 | overlay->last_flip_req = 0; | 383 | overlay->crtc = NULL; |
315 | return 0; | 384 | overlay->active = 0; |
316 | } | 385 | } |
317 | 386 | ||
318 | /* overlay needs to be disabled in OCMD reg */ | 387 | /* overlay needs to be disabled in OCMD reg */ |
319 | static int intel_overlay_off(struct intel_overlay *overlay) | 388 | static int intel_overlay_off(struct intel_overlay *overlay, |
389 | bool interruptible) | ||
320 | { | 390 | { |
321 | u32 flip_addr = overlay->flip_addr; | ||
322 | struct drm_device *dev = overlay->dev; | 391 | struct drm_device *dev = overlay->dev; |
323 | drm_i915_private_t *dev_priv = dev->dev_private; | 392 | u32 flip_addr = overlay->flip_addr; |
324 | int ret; | 393 | struct drm_i915_gem_request *request; |
325 | 394 | ||
326 | BUG_ON(!overlay->active); | 395 | BUG_ON(!overlay->active); |
327 | 396 | ||
397 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
398 | if (request == NULL) | ||
399 | return -ENOMEM; | ||
400 | |||
328 | /* According to intel docs the overlay hw may hang (when switching | 401 | /* According to intel docs the overlay hw may hang (when switching |
329 | * off) without loading the filter coeffs. It is however unclear whether | 402 | * off) without loading the filter coeffs. It is however unclear whether |
330 | * this applies to the disabling of the overlay or to the switching off | 403 | * this applies to the disabling of the overlay or to the switching off |
331 | * of the hw. Do it in both cases */ | 404 | * of the hw. Do it in both cases */ |
332 | flip_addr |= OFC_UPDATE; | 405 | flip_addr |= OFC_UPDATE; |
333 | 406 | ||
407 | BEGIN_LP_RING(6); | ||
334 | /* wait for overlay to go idle */ | 408 | /* wait for overlay to go idle */ |
335 | overlay->hw_wedged = SWITCH_OFF_STAGE_1; | ||
336 | |||
337 | BEGIN_LP_RING(4); | ||
338 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); | 409 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); |
339 | OUT_RING(flip_addr); | 410 | OUT_RING(flip_addr); |
340 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 411 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
341 | OUT_RING(MI_NOOP); | ||
342 | ADVANCE_LP_RING(); | ||
343 | |||
344 | overlay->last_flip_req = | ||
345 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | ||
346 | if (overlay->last_flip_req == 0) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
350 | 1, &dev_priv->render_ring); | ||
351 | if (ret != 0) | ||
352 | return ret; | ||
353 | |||
354 | /* turn overlay off */ | 412 | /* turn overlay off */ |
355 | overlay->hw_wedged = SWITCH_OFF_STAGE_2; | 413 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); |
356 | |||
357 | BEGIN_LP_RING(4); | ||
358 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); | ||
359 | OUT_RING(flip_addr); | 414 | OUT_RING(flip_addr); |
360 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 415 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
361 | OUT_RING(MI_NOOP); | ||
362 | ADVANCE_LP_RING(); | 416 | ADVANCE_LP_RING(); |
363 | 417 | ||
364 | overlay->last_flip_req = | 418 | return intel_overlay_do_wait_request(overlay, request, interruptible, |
365 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | 419 | intel_overlay_off_tail); |
366 | if (overlay->last_flip_req == 0) | ||
367 | return -ENOMEM; | ||
368 | |||
369 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
370 | 1, &dev_priv->render_ring); | ||
371 | if (ret != 0) | ||
372 | return ret; | ||
373 | |||
374 | overlay->hw_wedged = 0; | ||
375 | overlay->last_flip_req = 0; | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | static void intel_overlay_off_tail(struct intel_overlay *overlay) | ||
380 | { | ||
381 | struct drm_gem_object *obj; | ||
382 | |||
383 | /* never have the overlay hw on without showing a frame */ | ||
384 | BUG_ON(!overlay->vid_bo); | ||
385 | obj = &overlay->vid_bo->base; | ||
386 | |||
387 | i915_gem_object_unpin(obj); | ||
388 | drm_gem_object_unreference(obj); | ||
389 | overlay->vid_bo = NULL; | ||
390 | |||
391 | overlay->crtc->overlay = NULL; | ||
392 | overlay->crtc = NULL; | ||
393 | overlay->active = 0; | ||
394 | } | 420 | } |
395 | 421 | ||
396 | /* recover from an interruption due to a signal | 422 | /* recover from an interruption due to a signal |
397 | * We have to be careful not to repeat work forever an make forward progess. */ | 423 | * We have to be careful not to repeat work forever an make forward progess. */ |
398 | int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, | 424 | static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, |
399 | int interruptible) | 425 | bool interruptible) |
400 | { | 426 | { |
401 | struct drm_device *dev = overlay->dev; | 427 | struct drm_device *dev = overlay->dev; |
402 | struct drm_gem_object *obj; | ||
403 | drm_i915_private_t *dev_priv = dev->dev_private; | 428 | drm_i915_private_t *dev_priv = dev->dev_private; |
404 | u32 flip_addr; | ||
405 | int ret; | 429 | int ret; |
406 | 430 | ||
407 | if (overlay->hw_wedged == HW_WEDGED) | 431 | if (overlay->last_flip_req == 0) |
408 | return -EIO; | 432 | return 0; |
409 | |||
410 | if (overlay->last_flip_req == 0) { | ||
411 | overlay->last_flip_req = | ||
412 | i915_add_request(dev, NULL, 0, &dev_priv->render_ring); | ||
413 | if (overlay->last_flip_req == 0) | ||
414 | return -ENOMEM; | ||
415 | } | ||
416 | 433 | ||
417 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | 434 | ret = i915_do_wait_request(dev, overlay->last_flip_req, |
418 | interruptible, &dev_priv->render_ring); | 435 | interruptible, &dev_priv->render_ring); |
419 | if (ret != 0) | 436 | if (ret) |
420 | return ret; | 437 | return ret; |
421 | 438 | ||
422 | switch (overlay->hw_wedged) { | 439 | if (overlay->flip_tail) |
423 | case RELEASE_OLD_VID: | 440 | overlay->flip_tail(overlay); |
424 | obj = &overlay->old_vid_bo->base; | ||
425 | i915_gem_object_unpin(obj); | ||
426 | drm_gem_object_unreference(obj); | ||
427 | overlay->old_vid_bo = NULL; | ||
428 | break; | ||
429 | case SWITCH_OFF_STAGE_1: | ||
430 | flip_addr = overlay->flip_addr; | ||
431 | flip_addr |= OFC_UPDATE; | ||
432 | |||
433 | overlay->hw_wedged = SWITCH_OFF_STAGE_2; | ||
434 | |||
435 | BEGIN_LP_RING(4); | ||
436 | OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); | ||
437 | OUT_RING(flip_addr); | ||
438 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | ||
439 | OUT_RING(MI_NOOP); | ||
440 | ADVANCE_LP_RING(); | ||
441 | |||
442 | overlay->last_flip_req = i915_add_request(dev, NULL, | ||
443 | 0, &dev_priv->render_ring); | ||
444 | if (overlay->last_flip_req == 0) | ||
445 | return -ENOMEM; | ||
446 | |||
447 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | ||
448 | interruptible, &dev_priv->render_ring); | ||
449 | if (ret != 0) | ||
450 | return ret; | ||
451 | |||
452 | case SWITCH_OFF_STAGE_2: | ||
453 | intel_overlay_off_tail(overlay); | ||
454 | break; | ||
455 | default: | ||
456 | BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP); | ||
457 | } | ||
458 | 441 | ||
459 | overlay->hw_wedged = 0; | ||
460 | overlay->last_flip_req = 0; | 442 | overlay->last_flip_req = 0; |
461 | return 0; | 443 | return 0; |
462 | } | 444 | } |
463 | 445 | ||
464 | /* Wait for pending overlay flip and release old frame. | 446 | /* Wait for pending overlay flip and release old frame. |
465 | * Needs to be called before the overlay register are changed | 447 | * Needs to be called before the overlay register are changed |
466 | * via intel_overlay_(un)map_regs_atomic */ | 448 | * via intel_overlay_(un)map_regs |
449 | */ | ||
467 | static int intel_overlay_release_old_vid(struct intel_overlay *overlay) | 450 | static int intel_overlay_release_old_vid(struct intel_overlay *overlay) |
468 | { | 451 | { |
452 | struct drm_device *dev = overlay->dev; | ||
453 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
469 | int ret; | 454 | int ret; |
470 | struct drm_gem_object *obj; | ||
471 | 455 | ||
472 | /* only wait if there is actually an old frame to release to | 456 | /* Only wait if there is actually an old frame to release to |
473 | * guarantee forward progress */ | 457 | * guarantee forward progress. |
458 | */ | ||
474 | if (!overlay->old_vid_bo) | 459 | if (!overlay->old_vid_bo) |
475 | return 0; | 460 | return 0; |
476 | 461 | ||
477 | ret = intel_overlay_wait_flip(overlay); | 462 | if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { |
478 | if (ret != 0) | 463 | struct drm_i915_gem_request *request; |
479 | return ret; | ||
480 | 464 | ||
481 | obj = &overlay->old_vid_bo->base; | 465 | /* synchronous slowpath */ |
482 | i915_gem_object_unpin(obj); | 466 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
483 | drm_gem_object_unreference(obj); | 467 | if (request == NULL) |
484 | overlay->old_vid_bo = NULL; | 468 | return -ENOMEM; |
469 | |||
470 | BEGIN_LP_RING(2); | ||
471 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | ||
472 | OUT_RING(MI_NOOP); | ||
473 | ADVANCE_LP_RING(); | ||
485 | 474 | ||
475 | ret = intel_overlay_do_wait_request(overlay, request, true, | ||
476 | intel_overlay_release_old_vid_tail); | ||
477 | if (ret) | ||
478 | return ret; | ||
479 | } | ||
480 | |||
481 | intel_overlay_release_old_vid_tail(overlay); | ||
486 | return 0; | 482 | return 0; |
487 | } | 483 | } |
488 | 484 | ||
@@ -506,65 +502,65 @@ struct put_image_params { | |||
506 | static int packed_depth_bytes(u32 format) | 502 | static int packed_depth_bytes(u32 format) |
507 | { | 503 | { |
508 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 504 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
509 | case I915_OVERLAY_YUV422: | 505 | case I915_OVERLAY_YUV422: |
510 | return 4; | 506 | return 4; |
511 | case I915_OVERLAY_YUV411: | 507 | case I915_OVERLAY_YUV411: |
512 | /* return 6; not implemented */ | 508 | /* return 6; not implemented */ |
513 | default: | 509 | default: |
514 | return -EINVAL; | 510 | return -EINVAL; |
515 | } | 511 | } |
516 | } | 512 | } |
517 | 513 | ||
518 | static int packed_width_bytes(u32 format, short width) | 514 | static int packed_width_bytes(u32 format, short width) |
519 | { | 515 | { |
520 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 516 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
521 | case I915_OVERLAY_YUV422: | 517 | case I915_OVERLAY_YUV422: |
522 | return width << 1; | 518 | return width << 1; |
523 | default: | 519 | default: |
524 | return -EINVAL; | 520 | return -EINVAL; |
525 | } | 521 | } |
526 | } | 522 | } |
527 | 523 | ||
528 | static int uv_hsubsampling(u32 format) | 524 | static int uv_hsubsampling(u32 format) |
529 | { | 525 | { |
530 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 526 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
531 | case I915_OVERLAY_YUV422: | 527 | case I915_OVERLAY_YUV422: |
532 | case I915_OVERLAY_YUV420: | 528 | case I915_OVERLAY_YUV420: |
533 | return 2; | 529 | return 2; |
534 | case I915_OVERLAY_YUV411: | 530 | case I915_OVERLAY_YUV411: |
535 | case I915_OVERLAY_YUV410: | 531 | case I915_OVERLAY_YUV410: |
536 | return 4; | 532 | return 4; |
537 | default: | 533 | default: |
538 | return -EINVAL; | 534 | return -EINVAL; |
539 | } | 535 | } |
540 | } | 536 | } |
541 | 537 | ||
542 | static int uv_vsubsampling(u32 format) | 538 | static int uv_vsubsampling(u32 format) |
543 | { | 539 | { |
544 | switch (format & I915_OVERLAY_DEPTH_MASK) { | 540 | switch (format & I915_OVERLAY_DEPTH_MASK) { |
545 | case I915_OVERLAY_YUV420: | 541 | case I915_OVERLAY_YUV420: |
546 | case I915_OVERLAY_YUV410: | 542 | case I915_OVERLAY_YUV410: |
547 | return 2; | 543 | return 2; |
548 | case I915_OVERLAY_YUV422: | 544 | case I915_OVERLAY_YUV422: |
549 | case I915_OVERLAY_YUV411: | 545 | case I915_OVERLAY_YUV411: |
550 | return 1; | 546 | return 1; |
551 | default: | 547 | default: |
552 | return -EINVAL; | 548 | return -EINVAL; |
553 | } | 549 | } |
554 | } | 550 | } |
555 | 551 | ||
556 | static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) | 552 | static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) |
557 | { | 553 | { |
558 | u32 mask, shift, ret; | 554 | u32 mask, shift, ret; |
559 | if (IS_I9XX(dev)) { | 555 | if (IS_GEN2(dev)) { |
560 | mask = 0x3f; | ||
561 | shift = 6; | ||
562 | } else { | ||
563 | mask = 0x1f; | 556 | mask = 0x1f; |
564 | shift = 5; | 557 | shift = 5; |
558 | } else { | ||
559 | mask = 0x3f; | ||
560 | shift = 6; | ||
565 | } | 561 | } |
566 | ret = ((offset + width + mask) >> shift) - (offset >> shift); | 562 | ret = ((offset + width + mask) >> shift) - (offset >> shift); |
567 | if (IS_I9XX(dev)) | 563 | if (!IS_GEN2(dev)) |
568 | ret <<= 1; | 564 | ret <<= 1; |
569 | ret -=1; | 565 | ret -=1; |
570 | return ret << 2; | 566 | return ret << 2; |
@@ -587,7 +583,9 @@ static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = { | |||
587 | 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, | 583 | 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, |
588 | 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, | 584 | 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, |
589 | 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, | 585 | 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, |
590 | 0xb000, 0x3000, 0x0800, 0x3000, 0xb000}; | 586 | 0xb000, 0x3000, 0x0800, 0x3000, 0xb000 |
587 | }; | ||
588 | |||
591 | static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { | 589 | static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { |
592 | 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, | 590 | 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, |
593 | 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, | 591 | 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, |
@@ -597,7 +595,8 @@ static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { | |||
597 | 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, | 595 | 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, |
598 | 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, | 596 | 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, |
599 | 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, | 597 | 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, |
600 | 0x3000, 0x0800, 0x3000}; | 598 | 0x3000, 0x0800, 0x3000 |
599 | }; | ||
601 | 600 | ||
602 | static void update_polyphase_filter(struct overlay_registers *regs) | 601 | static void update_polyphase_filter(struct overlay_registers *regs) |
603 | { | 602 | { |
@@ -630,29 +629,31 @@ static bool update_scaling_factors(struct intel_overlay *overlay, | |||
630 | yscale = 1 << FP_SHIFT; | 629 | yscale = 1 << FP_SHIFT; |
631 | 630 | ||
632 | /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ | 631 | /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ |
633 | xscale_UV = xscale/uv_hscale; | 632 | xscale_UV = xscale/uv_hscale; |
634 | yscale_UV = yscale/uv_vscale; | 633 | yscale_UV = yscale/uv_vscale; |
635 | /* make the Y scale to UV scale ratio an exact multiply */ | 634 | /* make the Y scale to UV scale ratio an exact multiply */ |
636 | xscale = xscale_UV * uv_hscale; | 635 | xscale = xscale_UV * uv_hscale; |
637 | yscale = yscale_UV * uv_vscale; | 636 | yscale = yscale_UV * uv_vscale; |
638 | /*} else { | 637 | /*} else { |
639 | xscale_UV = 0; | 638 | xscale_UV = 0; |
640 | yscale_UV = 0; | 639 | yscale_UV = 0; |
641 | }*/ | 640 | }*/ |
642 | 641 | ||
643 | if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) | 642 | if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) |
644 | scale_changed = true; | 643 | scale_changed = true; |
645 | overlay->old_xscale = xscale; | 644 | overlay->old_xscale = xscale; |
646 | overlay->old_yscale = yscale; | 645 | overlay->old_yscale = yscale; |
647 | 646 | ||
648 | regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20) | 647 | regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) | |
649 | | ((xscale >> FP_SHIFT) << 16) | 648 | ((xscale >> FP_SHIFT) << 16) | |
650 | | ((xscale & FRACT_MASK) << 3); | 649 | ((xscale & FRACT_MASK) << 3)); |
651 | regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20) | 650 | |
652 | | ((xscale_UV >> FP_SHIFT) << 16) | 651 | regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) | |
653 | | ((xscale_UV & FRACT_MASK) << 3); | 652 | ((xscale_UV >> FP_SHIFT) << 16) | |
654 | regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16) | 653 | ((xscale_UV & FRACT_MASK) << 3)); |
655 | | ((yscale_UV >> FP_SHIFT) << 0); | 654 | |
655 | regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) | | ||
656 | ((yscale_UV >> FP_SHIFT) << 0))); | ||
656 | 657 | ||
657 | if (scale_changed) | 658 | if (scale_changed) |
658 | update_polyphase_filter(regs); | 659 | update_polyphase_filter(regs); |
@@ -664,22 +665,28 @@ static void update_colorkey(struct intel_overlay *overlay, | |||
664 | struct overlay_registers *regs) | 665 | struct overlay_registers *regs) |
665 | { | 666 | { |
666 | u32 key = overlay->color_key; | 667 | u32 key = overlay->color_key; |
668 | |||
667 | switch (overlay->crtc->base.fb->bits_per_pixel) { | 669 | switch (overlay->crtc->base.fb->bits_per_pixel) { |
668 | case 8: | 670 | case 8: |
669 | regs->DCLRKV = 0; | 671 | regs->DCLRKV = 0; |
670 | regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; | 672 | regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; |
671 | case 16: | 673 | break; |
672 | if (overlay->crtc->base.fb->depth == 15) { | 674 | |
673 | regs->DCLRKV = RGB15_TO_COLORKEY(key); | 675 | case 16: |
674 | regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; | 676 | if (overlay->crtc->base.fb->depth == 15) { |
675 | } else { | 677 | regs->DCLRKV = RGB15_TO_COLORKEY(key); |
676 | regs->DCLRKV = RGB16_TO_COLORKEY(key); | 678 | regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; |
677 | regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; | 679 | } else { |
678 | } | 680 | regs->DCLRKV = RGB16_TO_COLORKEY(key); |
679 | case 24: | 681 | regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; |
680 | case 32: | 682 | } |
681 | regs->DCLRKV = key; | 683 | break; |
682 | regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; | 684 | |
685 | case 24: | ||
686 | case 32: | ||
687 | regs->DCLRKV = key; | ||
688 | regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; | ||
689 | break; | ||
683 | } | 690 | } |
684 | } | 691 | } |
685 | 692 | ||
@@ -689,48 +696,48 @@ static u32 overlay_cmd_reg(struct put_image_params *params) | |||
689 | 696 | ||
690 | if (params->format & I915_OVERLAY_YUV_PLANAR) { | 697 | if (params->format & I915_OVERLAY_YUV_PLANAR) { |
691 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { | 698 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { |
692 | case I915_OVERLAY_YUV422: | 699 | case I915_OVERLAY_YUV422: |
693 | cmd |= OCMD_YUV_422_PLANAR; | 700 | cmd |= OCMD_YUV_422_PLANAR; |
694 | break; | 701 | break; |
695 | case I915_OVERLAY_YUV420: | 702 | case I915_OVERLAY_YUV420: |
696 | cmd |= OCMD_YUV_420_PLANAR; | 703 | cmd |= OCMD_YUV_420_PLANAR; |
697 | break; | 704 | break; |
698 | case I915_OVERLAY_YUV411: | 705 | case I915_OVERLAY_YUV411: |
699 | case I915_OVERLAY_YUV410: | 706 | case I915_OVERLAY_YUV410: |
700 | cmd |= OCMD_YUV_410_PLANAR; | 707 | cmd |= OCMD_YUV_410_PLANAR; |
701 | break; | 708 | break; |
702 | } | 709 | } |
703 | } else { /* YUV packed */ | 710 | } else { /* YUV packed */ |
704 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { | 711 | switch (params->format & I915_OVERLAY_DEPTH_MASK) { |
705 | case I915_OVERLAY_YUV422: | 712 | case I915_OVERLAY_YUV422: |
706 | cmd |= OCMD_YUV_422_PACKED; | 713 | cmd |= OCMD_YUV_422_PACKED; |
707 | break; | 714 | break; |
708 | case I915_OVERLAY_YUV411: | 715 | case I915_OVERLAY_YUV411: |
709 | cmd |= OCMD_YUV_411_PACKED; | 716 | cmd |= OCMD_YUV_411_PACKED; |
710 | break; | 717 | break; |
711 | } | 718 | } |
712 | 719 | ||
713 | switch (params->format & I915_OVERLAY_SWAP_MASK) { | 720 | switch (params->format & I915_OVERLAY_SWAP_MASK) { |
714 | case I915_OVERLAY_NO_SWAP: | 721 | case I915_OVERLAY_NO_SWAP: |
715 | break; | 722 | break; |
716 | case I915_OVERLAY_UV_SWAP: | 723 | case I915_OVERLAY_UV_SWAP: |
717 | cmd |= OCMD_UV_SWAP; | 724 | cmd |= OCMD_UV_SWAP; |
718 | break; | 725 | break; |
719 | case I915_OVERLAY_Y_SWAP: | 726 | case I915_OVERLAY_Y_SWAP: |
720 | cmd |= OCMD_Y_SWAP; | 727 | cmd |= OCMD_Y_SWAP; |
721 | break; | 728 | break; |
722 | case I915_OVERLAY_Y_AND_UV_SWAP: | 729 | case I915_OVERLAY_Y_AND_UV_SWAP: |
723 | cmd |= OCMD_Y_AND_UV_SWAP; | 730 | cmd |= OCMD_Y_AND_UV_SWAP; |
724 | break; | 731 | break; |
725 | } | 732 | } |
726 | } | 733 | } |
727 | 734 | ||
728 | return cmd; | 735 | return cmd; |
729 | } | 736 | } |
730 | 737 | ||
731 | int intel_overlay_do_put_image(struct intel_overlay *overlay, | 738 | static int intel_overlay_do_put_image(struct intel_overlay *overlay, |
732 | struct drm_gem_object *new_bo, | 739 | struct drm_gem_object *new_bo, |
733 | struct put_image_params *params) | 740 | struct put_image_params *params) |
734 | { | 741 | { |
735 | int ret, tmp_width; | 742 | int ret, tmp_width; |
736 | struct overlay_registers *regs; | 743 | struct overlay_registers *regs; |
@@ -755,24 +762,24 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
755 | goto out_unpin; | 762 | goto out_unpin; |
756 | 763 | ||
757 | if (!overlay->active) { | 764 | if (!overlay->active) { |
758 | regs = intel_overlay_map_regs_atomic(overlay); | 765 | regs = intel_overlay_map_regs(overlay); |
759 | if (!regs) { | 766 | if (!regs) { |
760 | ret = -ENOMEM; | 767 | ret = -ENOMEM; |
761 | goto out_unpin; | 768 | goto out_unpin; |
762 | } | 769 | } |
763 | regs->OCONFIG = OCONF_CC_OUT_8BIT; | 770 | regs->OCONFIG = OCONF_CC_OUT_8BIT; |
764 | if (IS_I965GM(overlay->dev)) | 771 | if (IS_GEN4(overlay->dev)) |
765 | regs->OCONFIG |= OCONF_CSC_MODE_BT709; | 772 | regs->OCONFIG |= OCONF_CSC_MODE_BT709; |
766 | regs->OCONFIG |= overlay->crtc->pipe == 0 ? | 773 | regs->OCONFIG |= overlay->crtc->pipe == 0 ? |
767 | OCONF_PIPE_A : OCONF_PIPE_B; | 774 | OCONF_PIPE_A : OCONF_PIPE_B; |
768 | intel_overlay_unmap_regs_atomic(overlay); | 775 | intel_overlay_unmap_regs(overlay, regs); |
769 | 776 | ||
770 | ret = intel_overlay_on(overlay); | 777 | ret = intel_overlay_on(overlay); |
771 | if (ret != 0) | 778 | if (ret != 0) |
772 | goto out_unpin; | 779 | goto out_unpin; |
773 | } | 780 | } |
774 | 781 | ||
775 | regs = intel_overlay_map_regs_atomic(overlay); | 782 | regs = intel_overlay_map_regs(overlay); |
776 | if (!regs) { | 783 | if (!regs) { |
777 | ret = -ENOMEM; | 784 | ret = -ENOMEM; |
778 | goto out_unpin; | 785 | goto out_unpin; |
@@ -788,7 +795,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
788 | 795 | ||
789 | regs->SWIDTH = params->src_w; | 796 | regs->SWIDTH = params->src_w; |
790 | regs->SWIDTHSW = calc_swidthsw(overlay->dev, | 797 | regs->SWIDTHSW = calc_swidthsw(overlay->dev, |
791 | params->offset_Y, tmp_width); | 798 | params->offset_Y, tmp_width); |
792 | regs->SHEIGHT = params->src_h; | 799 | regs->SHEIGHT = params->src_h; |
793 | regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; | 800 | regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; |
794 | regs->OSTRIDE = params->stride_Y; | 801 | regs->OSTRIDE = params->stride_Y; |
@@ -799,9 +806,9 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
799 | u32 tmp_U, tmp_V; | 806 | u32 tmp_U, tmp_V; |
800 | regs->SWIDTH |= (params->src_w/uv_hscale) << 16; | 807 | regs->SWIDTH |= (params->src_w/uv_hscale) << 16; |
801 | tmp_U = calc_swidthsw(overlay->dev, params->offset_U, | 808 | tmp_U = calc_swidthsw(overlay->dev, params->offset_U, |
802 | params->src_w/uv_hscale); | 809 | params->src_w/uv_hscale); |
803 | tmp_V = calc_swidthsw(overlay->dev, params->offset_V, | 810 | tmp_V = calc_swidthsw(overlay->dev, params->offset_V, |
804 | params->src_w/uv_hscale); | 811 | params->src_w/uv_hscale); |
805 | regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; | 812 | regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; |
806 | regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; | 813 | regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; |
807 | regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; | 814 | regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; |
@@ -815,9 +822,11 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
815 | 822 | ||
816 | regs->OCMD = overlay_cmd_reg(params); | 823 | regs->OCMD = overlay_cmd_reg(params); |
817 | 824 | ||
818 | intel_overlay_unmap_regs_atomic(overlay); | 825 | intel_overlay_unmap_regs(overlay, regs); |
819 | 826 | ||
820 | intel_overlay_continue(overlay, scale_changed); | 827 | ret = intel_overlay_continue(overlay, scale_changed); |
828 | if (ret) | ||
829 | goto out_unpin; | ||
821 | 830 | ||
822 | overlay->old_vid_bo = overlay->vid_bo; | 831 | overlay->old_vid_bo = overlay->vid_bo; |
823 | overlay->vid_bo = to_intel_bo(new_bo); | 832 | overlay->vid_bo = to_intel_bo(new_bo); |
@@ -829,20 +838,19 @@ out_unpin: | |||
829 | return ret; | 838 | return ret; |
830 | } | 839 | } |
831 | 840 | ||
832 | int intel_overlay_switch_off(struct intel_overlay *overlay) | 841 | int intel_overlay_switch_off(struct intel_overlay *overlay, |
842 | bool interruptible) | ||
833 | { | 843 | { |
834 | int ret; | ||
835 | struct overlay_registers *regs; | 844 | struct overlay_registers *regs; |
836 | struct drm_device *dev = overlay->dev; | 845 | struct drm_device *dev = overlay->dev; |
846 | int ret; | ||
837 | 847 | ||
838 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | 848 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); |
839 | BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); | 849 | BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
840 | 850 | ||
841 | if (overlay->hw_wedged) { | 851 | ret = intel_overlay_recover_from_interrupt(overlay, interruptible); |
842 | ret = intel_overlay_recover_from_interrupt(overlay, 1); | 852 | if (ret != 0) |
843 | if (ret != 0) | 853 | return ret; |
844 | return ret; | ||
845 | } | ||
846 | 854 | ||
847 | if (!overlay->active) | 855 | if (!overlay->active) |
848 | return 0; | 856 | return 0; |
@@ -851,33 +859,29 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) | |||
851 | if (ret != 0) | 859 | if (ret != 0) |
852 | return ret; | 860 | return ret; |
853 | 861 | ||
854 | regs = intel_overlay_map_regs_atomic(overlay); | 862 | regs = intel_overlay_map_regs(overlay); |
855 | regs->OCMD = 0; | 863 | regs->OCMD = 0; |
856 | intel_overlay_unmap_regs_atomic(overlay); | 864 | intel_overlay_unmap_regs(overlay, regs); |
857 | 865 | ||
858 | ret = intel_overlay_off(overlay); | 866 | ret = intel_overlay_off(overlay, interruptible); |
859 | if (ret != 0) | 867 | if (ret != 0) |
860 | return ret; | 868 | return ret; |
861 | 869 | ||
862 | intel_overlay_off_tail(overlay); | 870 | intel_overlay_off_tail(overlay); |
863 | |||
864 | return 0; | 871 | return 0; |
865 | } | 872 | } |
866 | 873 | ||
867 | static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, | 874 | static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, |
868 | struct intel_crtc *crtc) | 875 | struct intel_crtc *crtc) |
869 | { | 876 | { |
870 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; | 877 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; |
871 | u32 pipeconf; | ||
872 | int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
873 | 878 | ||
874 | if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON) | 879 | if (!crtc->active) |
875 | return -EINVAL; | 880 | return -EINVAL; |
876 | 881 | ||
877 | pipeconf = I915_READ(pipeconf_reg); | ||
878 | |||
879 | /* can't use the overlay with double wide pipe */ | 882 | /* can't use the overlay with double wide pipe */ |
880 | if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE) | 883 | if (INTEL_INFO(overlay->dev)->gen < 4 && |
884 | (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE) | ||
881 | return -EINVAL; | 885 | return -EINVAL; |
882 | 886 | ||
883 | return 0; | 887 | return 0; |
@@ -886,20 +890,22 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, | |||
886 | static void update_pfit_vscale_ratio(struct intel_overlay *overlay) | 890 | static void update_pfit_vscale_ratio(struct intel_overlay *overlay) |
887 | { | 891 | { |
888 | struct drm_device *dev = overlay->dev; | 892 | struct drm_device *dev = overlay->dev; |
889 | drm_i915_private_t *dev_priv = dev->dev_private; | 893 | drm_i915_private_t *dev_priv = dev->dev_private; |
890 | u32 ratio; | ||
891 | u32 pfit_control = I915_READ(PFIT_CONTROL); | 894 | u32 pfit_control = I915_READ(PFIT_CONTROL); |
895 | u32 ratio; | ||
892 | 896 | ||
893 | /* XXX: This is not the same logic as in the xorg driver, but more in | 897 | /* XXX: This is not the same logic as in the xorg driver, but more in |
894 | * line with the intel documentation for the i965 */ | 898 | * line with the intel documentation for the i965 |
895 | if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) { | 899 | */ |
896 | ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT; | 900 | if (INTEL_INFO(dev)->gen >= 4) { |
897 | } else { /* on i965 use the PGM reg to read out the autoscaler values */ | 901 | /* on i965 use the PGM reg to read out the autoscaler values */ |
898 | ratio = I915_READ(PFIT_PGM_RATIOS); | 902 | ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; |
899 | if (IS_I965G(dev)) | 903 | } else { |
900 | ratio >>= PFIT_VERT_SCALE_SHIFT_965; | 904 | if (pfit_control & VERT_AUTO_SCALE) |
905 | ratio = I915_READ(PFIT_AUTO_RATIOS); | ||
901 | else | 906 | else |
902 | ratio >>= PFIT_VERT_SCALE_SHIFT; | 907 | ratio = I915_READ(PFIT_PGM_RATIOS); |
908 | ratio >>= PFIT_VERT_SCALE_SHIFT; | ||
903 | } | 909 | } |
904 | 910 | ||
905 | overlay->pfit_vscale_ratio = ratio; | 911 | overlay->pfit_vscale_ratio = ratio; |
@@ -910,12 +916,10 @@ static int check_overlay_dst(struct intel_overlay *overlay, | |||
910 | { | 916 | { |
911 | struct drm_display_mode *mode = &overlay->crtc->base.mode; | 917 | struct drm_display_mode *mode = &overlay->crtc->base.mode; |
912 | 918 | ||
913 | if ((rec->dst_x < mode->crtc_hdisplay) | 919 | if (rec->dst_x < mode->crtc_hdisplay && |
914 | && (rec->dst_x + rec->dst_width | 920 | rec->dst_x + rec->dst_width <= mode->crtc_hdisplay && |
915 | <= mode->crtc_hdisplay) | 921 | rec->dst_y < mode->crtc_vdisplay && |
916 | && (rec->dst_y < mode->crtc_vdisplay) | 922 | rec->dst_y + rec->dst_height <= mode->crtc_vdisplay) |
917 | && (rec->dst_y + rec->dst_height | ||
918 | <= mode->crtc_vdisplay)) | ||
919 | return 0; | 923 | return 0; |
920 | else | 924 | else |
921 | return -EINVAL; | 925 | return -EINVAL; |
@@ -940,53 +944,57 @@ static int check_overlay_src(struct drm_device *dev, | |||
940 | struct drm_intel_overlay_put_image *rec, | 944 | struct drm_intel_overlay_put_image *rec, |
941 | struct drm_gem_object *new_bo) | 945 | struct drm_gem_object *new_bo) |
942 | { | 946 | { |
943 | u32 stride_mask; | ||
944 | int depth; | ||
945 | int uv_hscale = uv_hsubsampling(rec->flags); | 947 | int uv_hscale = uv_hsubsampling(rec->flags); |
946 | int uv_vscale = uv_vsubsampling(rec->flags); | 948 | int uv_vscale = uv_vsubsampling(rec->flags); |
947 | size_t tmp; | 949 | u32 stride_mask, depth, tmp; |
948 | 950 | ||
949 | /* check src dimensions */ | 951 | /* check src dimensions */ |
950 | if (IS_845G(dev) || IS_I830(dev)) { | 952 | if (IS_845G(dev) || IS_I830(dev)) { |
951 | if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY | 953 | if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY || |
952 | || rec->src_width > IMAGE_MAX_WIDTH_LEGACY) | 954 | rec->src_width > IMAGE_MAX_WIDTH_LEGACY) |
953 | return -EINVAL; | 955 | return -EINVAL; |
954 | } else { | 956 | } else { |
955 | if (rec->src_height > IMAGE_MAX_HEIGHT | 957 | if (rec->src_height > IMAGE_MAX_HEIGHT || |
956 | || rec->src_width > IMAGE_MAX_WIDTH) | 958 | rec->src_width > IMAGE_MAX_WIDTH) |
957 | return -EINVAL; | 959 | return -EINVAL; |
958 | } | 960 | } |
961 | |||
959 | /* better safe than sorry, use 4 as the maximal subsampling ratio */ | 962 | /* better safe than sorry, use 4 as the maximal subsampling ratio */ |
960 | if (rec->src_height < N_VERT_Y_TAPS*4 | 963 | if (rec->src_height < N_VERT_Y_TAPS*4 || |
961 | || rec->src_width < N_HORIZ_Y_TAPS*4) | 964 | rec->src_width < N_HORIZ_Y_TAPS*4) |
962 | return -EINVAL; | 965 | return -EINVAL; |
963 | 966 | ||
964 | /* check alignment constraints */ | 967 | /* check alignment constraints */ |
965 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { | 968 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { |
966 | case I915_OVERLAY_RGB: | 969 | case I915_OVERLAY_RGB: |
967 | /* not implemented */ | 970 | /* not implemented */ |
971 | return -EINVAL; | ||
972 | |||
973 | case I915_OVERLAY_YUV_PACKED: | ||
974 | if (uv_vscale != 1) | ||
968 | return -EINVAL; | 975 | return -EINVAL; |
969 | case I915_OVERLAY_YUV_PACKED: | 976 | |
970 | depth = packed_depth_bytes(rec->flags); | 977 | depth = packed_depth_bytes(rec->flags); |
971 | if (uv_vscale != 1) | 978 | if (depth < 0) |
972 | return -EINVAL; | 979 | return depth; |
973 | if (depth < 0) | 980 | |
974 | return depth; | 981 | /* ignore UV planes */ |
975 | /* ignore UV planes */ | 982 | rec->stride_UV = 0; |
976 | rec->stride_UV = 0; | 983 | rec->offset_U = 0; |
977 | rec->offset_U = 0; | 984 | rec->offset_V = 0; |
978 | rec->offset_V = 0; | 985 | /* check pixel alignment */ |
979 | /* check pixel alignment */ | 986 | if (rec->offset_Y % depth) |
980 | if (rec->offset_Y % depth) | 987 | return -EINVAL; |
981 | return -EINVAL; | 988 | break; |
982 | break; | 989 | |
983 | case I915_OVERLAY_YUV_PLANAR: | 990 | case I915_OVERLAY_YUV_PLANAR: |
984 | if (uv_vscale < 0 || uv_hscale < 0) | 991 | if (uv_vscale < 0 || uv_hscale < 0) |
985 | return -EINVAL; | ||
986 | /* no offset restrictions for planar formats */ | ||
987 | break; | ||
988 | default: | ||
989 | return -EINVAL; | 992 | return -EINVAL; |
993 | /* no offset restrictions for planar formats */ | ||
994 | break; | ||
995 | |||
996 | default: | ||
997 | return -EINVAL; | ||
990 | } | 998 | } |
991 | 999 | ||
992 | if (rec->src_width % uv_hscale) | 1000 | if (rec->src_width % uv_hscale) |
@@ -1000,47 +1008,74 @@ static int check_overlay_src(struct drm_device *dev, | |||
1000 | 1008 | ||
1001 | if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) | 1009 | if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask) |
1002 | return -EINVAL; | 1010 | return -EINVAL; |
1003 | if (IS_I965G(dev) && rec->stride_Y < 512) | 1011 | if (IS_GEN4(dev) && rec->stride_Y < 512) |
1004 | return -EINVAL; | 1012 | return -EINVAL; |
1005 | 1013 | ||
1006 | tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? | 1014 | tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ? |
1007 | 4 : 8; | 1015 | 4096 : 8192; |
1008 | if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024) | 1016 | if (rec->stride_Y > tmp || rec->stride_UV > 2*1024) |
1009 | return -EINVAL; | 1017 | return -EINVAL; |
1010 | 1018 | ||
1011 | /* check buffer dimensions */ | 1019 | /* check buffer dimensions */ |
1012 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { | 1020 | switch (rec->flags & I915_OVERLAY_TYPE_MASK) { |
1013 | case I915_OVERLAY_RGB: | 1021 | case I915_OVERLAY_RGB: |
1014 | case I915_OVERLAY_YUV_PACKED: | 1022 | case I915_OVERLAY_YUV_PACKED: |
1015 | /* always 4 Y values per depth pixels */ | 1023 | /* always 4 Y values per depth pixels */ |
1016 | if (packed_width_bytes(rec->flags, rec->src_width) | 1024 | if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y) |
1017 | > rec->stride_Y) | 1025 | return -EINVAL; |
1018 | return -EINVAL; | 1026 | |
1019 | 1027 | tmp = rec->stride_Y*rec->src_height; | |
1020 | tmp = rec->stride_Y*rec->src_height; | 1028 | if (rec->offset_Y + tmp > new_bo->size) |
1021 | if (rec->offset_Y + tmp > new_bo->size) | 1029 | return -EINVAL; |
1022 | return -EINVAL; | 1030 | break; |
1023 | break; | 1031 | |
1024 | case I915_OVERLAY_YUV_PLANAR: | 1032 | case I915_OVERLAY_YUV_PLANAR: |
1025 | if (rec->src_width > rec->stride_Y) | 1033 | if (rec->src_width > rec->stride_Y) |
1026 | return -EINVAL; | 1034 | return -EINVAL; |
1027 | if (rec->src_width/uv_hscale > rec->stride_UV) | 1035 | if (rec->src_width/uv_hscale > rec->stride_UV) |
1028 | return -EINVAL; | 1036 | return -EINVAL; |
1029 | 1037 | ||
1030 | tmp = rec->stride_Y*rec->src_height; | 1038 | tmp = rec->stride_Y * rec->src_height; |
1031 | if (rec->offset_Y + tmp > new_bo->size) | 1039 | if (rec->offset_Y + tmp > new_bo->size) |
1032 | return -EINVAL; | 1040 | return -EINVAL; |
1033 | tmp = rec->stride_UV*rec->src_height; | 1041 | |
1034 | tmp /= uv_vscale; | 1042 | tmp = rec->stride_UV * (rec->src_height / uv_vscale); |
1035 | if (rec->offset_U + tmp > new_bo->size | 1043 | if (rec->offset_U + tmp > new_bo->size || |
1036 | || rec->offset_V + tmp > new_bo->size) | 1044 | rec->offset_V + tmp > new_bo->size) |
1037 | return -EINVAL; | 1045 | return -EINVAL; |
1038 | break; | 1046 | break; |
1039 | } | 1047 | } |
1040 | 1048 | ||
1041 | return 0; | 1049 | return 0; |
1042 | } | 1050 | } |
1043 | 1051 | ||
1052 | /** | ||
1053 | * Return the pipe currently connected to the panel fitter, | ||
1054 | * or -1 if the panel fitter is not present or not in use | ||
1055 | */ | ||
1056 | static int intel_panel_fitter_pipe(struct drm_device *dev) | ||
1057 | { | ||
1058 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1059 | u32 pfit_control; | ||
1060 | |||
1061 | /* i830 doesn't have a panel fitter */ | ||
1062 | if (IS_I830(dev)) | ||
1063 | return -1; | ||
1064 | |||
1065 | pfit_control = I915_READ(PFIT_CONTROL); | ||
1066 | |||
1067 | /* See if the panel fitter is in use */ | ||
1068 | if ((pfit_control & PFIT_ENABLE) == 0) | ||
1069 | return -1; | ||
1070 | |||
1071 | /* 965 can place panel fitter on either pipe */ | ||
1072 | if (IS_GEN4(dev)) | ||
1073 | return (pfit_control >> 29) & 0x3; | ||
1074 | |||
1075 | /* older chips can only use pipe 1 */ | ||
1076 | return 1; | ||
1077 | } | ||
1078 | |||
1044 | int intel_overlay_put_image(struct drm_device *dev, void *data, | 1079 | int intel_overlay_put_image(struct drm_device *dev, void *data, |
1045 | struct drm_file *file_priv) | 1080 | struct drm_file *file_priv) |
1046 | { | 1081 | { |
@@ -1068,7 +1103,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1068 | mutex_lock(&dev->mode_config.mutex); | 1103 | mutex_lock(&dev->mode_config.mutex); |
1069 | mutex_lock(&dev->struct_mutex); | 1104 | mutex_lock(&dev->struct_mutex); |
1070 | 1105 | ||
1071 | ret = intel_overlay_switch_off(overlay); | 1106 | ret = intel_overlay_switch_off(overlay, true); |
1072 | 1107 | ||
1073 | mutex_unlock(&dev->struct_mutex); | 1108 | mutex_unlock(&dev->struct_mutex); |
1074 | mutex_unlock(&dev->mode_config.mutex); | 1109 | mutex_unlock(&dev->mode_config.mutex); |
@@ -1081,7 +1116,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1081 | return -ENOMEM; | 1116 | return -ENOMEM; |
1082 | 1117 | ||
1083 | drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, | 1118 | drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, |
1084 | DRM_MODE_OBJECT_CRTC); | 1119 | DRM_MODE_OBJECT_CRTC); |
1085 | if (!drmmode_obj) { | 1120 | if (!drmmode_obj) { |
1086 | ret = -ENOENT; | 1121 | ret = -ENOENT; |
1087 | goto out_free; | 1122 | goto out_free; |
@@ -1089,7 +1124,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1089 | crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); | 1124 | crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); |
1090 | 1125 | ||
1091 | new_bo = drm_gem_object_lookup(dev, file_priv, | 1126 | new_bo = drm_gem_object_lookup(dev, file_priv, |
1092 | put_image_rec->bo_handle); | 1127 | put_image_rec->bo_handle); |
1093 | if (!new_bo) { | 1128 | if (!new_bo) { |
1094 | ret = -ENOENT; | 1129 | ret = -ENOENT; |
1095 | goto out_free; | 1130 | goto out_free; |
@@ -1098,15 +1133,13 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1098 | mutex_lock(&dev->mode_config.mutex); | 1133 | mutex_lock(&dev->mode_config.mutex); |
1099 | mutex_lock(&dev->struct_mutex); | 1134 | mutex_lock(&dev->struct_mutex); |
1100 | 1135 | ||
1101 | if (overlay->hw_wedged) { | 1136 | ret = intel_overlay_recover_from_interrupt(overlay, true); |
1102 | ret = intel_overlay_recover_from_interrupt(overlay, 1); | 1137 | if (ret != 0) |
1103 | if (ret != 0) | 1138 | goto out_unlock; |
1104 | goto out_unlock; | ||
1105 | } | ||
1106 | 1139 | ||
1107 | if (overlay->crtc != crtc) { | 1140 | if (overlay->crtc != crtc) { |
1108 | struct drm_display_mode *mode = &crtc->base.mode; | 1141 | struct drm_display_mode *mode = &crtc->base.mode; |
1109 | ret = intel_overlay_switch_off(overlay); | 1142 | ret = intel_overlay_switch_off(overlay, true); |
1110 | if (ret != 0) | 1143 | if (ret != 0) |
1111 | goto out_unlock; | 1144 | goto out_unlock; |
1112 | 1145 | ||
@@ -1117,9 +1150,9 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1117 | overlay->crtc = crtc; | 1150 | overlay->crtc = crtc; |
1118 | crtc->overlay = overlay; | 1151 | crtc->overlay = overlay; |
1119 | 1152 | ||
1120 | if (intel_panel_fitter_pipe(dev) == crtc->pipe | 1153 | /* line too wide, i.e. one-line-mode */ |
1121 | /* and line to wide, i.e. one-line-mode */ | 1154 | if (mode->hdisplay > 1024 && |
1122 | && mode->hdisplay > 1024) { | 1155 | intel_panel_fitter_pipe(dev) == crtc->pipe) { |
1123 | overlay->pfit_active = 1; | 1156 | overlay->pfit_active = 1; |
1124 | update_pfit_vscale_ratio(overlay); | 1157 | update_pfit_vscale_ratio(overlay); |
1125 | } else | 1158 | } else |
@@ -1132,10 +1165,10 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1132 | 1165 | ||
1133 | if (overlay->pfit_active) { | 1166 | if (overlay->pfit_active) { |
1134 | params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / | 1167 | params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / |
1135 | overlay->pfit_vscale_ratio); | 1168 | overlay->pfit_vscale_ratio); |
1136 | /* shifting right rounds downwards, so add 1 */ | 1169 | /* shifting right rounds downwards, so add 1 */ |
1137 | params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / | 1170 | params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / |
1138 | overlay->pfit_vscale_ratio) + 1; | 1171 | overlay->pfit_vscale_ratio) + 1; |
1139 | } else { | 1172 | } else { |
1140 | params->dst_y = put_image_rec->dst_y; | 1173 | params->dst_y = put_image_rec->dst_y; |
1141 | params->dst_h = put_image_rec->dst_height; | 1174 | params->dst_h = put_image_rec->dst_height; |
@@ -1147,8 +1180,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1147 | params->src_h = put_image_rec->src_height; | 1180 | params->src_h = put_image_rec->src_height; |
1148 | params->src_scan_w = put_image_rec->src_scan_width; | 1181 | params->src_scan_w = put_image_rec->src_scan_width; |
1149 | params->src_scan_h = put_image_rec->src_scan_height; | 1182 | params->src_scan_h = put_image_rec->src_scan_height; |
1150 | if (params->src_scan_h > params->src_h | 1183 | if (params->src_scan_h > params->src_h || |
1151 | || params->src_scan_w > params->src_w) { | 1184 | params->src_scan_w > params->src_w) { |
1152 | ret = -EINVAL; | 1185 | ret = -EINVAL; |
1153 | goto out_unlock; | 1186 | goto out_unlock; |
1154 | } | 1187 | } |
@@ -1204,7 +1237,7 @@ static bool check_gamma_bounds(u32 gamma1, u32 gamma2) | |||
1204 | return false; | 1237 | return false; |
1205 | 1238 | ||
1206 | for (i = 0; i < 3; i++) { | 1239 | for (i = 0; i < 3; i++) { |
1207 | if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) | 1240 | if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) |
1208 | return false; | 1241 | return false; |
1209 | } | 1242 | } |
1210 | 1243 | ||
@@ -1225,16 +1258,18 @@ static bool check_gamma5_errata(u32 gamma5) | |||
1225 | 1258 | ||
1226 | static int check_gamma(struct drm_intel_overlay_attrs *attrs) | 1259 | static int check_gamma(struct drm_intel_overlay_attrs *attrs) |
1227 | { | 1260 | { |
1228 | if (!check_gamma_bounds(0, attrs->gamma0) | 1261 | if (!check_gamma_bounds(0, attrs->gamma0) || |
1229 | || !check_gamma_bounds(attrs->gamma0, attrs->gamma1) | 1262 | !check_gamma_bounds(attrs->gamma0, attrs->gamma1) || |
1230 | || !check_gamma_bounds(attrs->gamma1, attrs->gamma2) | 1263 | !check_gamma_bounds(attrs->gamma1, attrs->gamma2) || |
1231 | || !check_gamma_bounds(attrs->gamma2, attrs->gamma3) | 1264 | !check_gamma_bounds(attrs->gamma2, attrs->gamma3) || |
1232 | || !check_gamma_bounds(attrs->gamma3, attrs->gamma4) | 1265 | !check_gamma_bounds(attrs->gamma3, attrs->gamma4) || |
1233 | || !check_gamma_bounds(attrs->gamma4, attrs->gamma5) | 1266 | !check_gamma_bounds(attrs->gamma4, attrs->gamma5) || |
1234 | || !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) | 1267 | !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) |
1235 | return -EINVAL; | 1268 | return -EINVAL; |
1269 | |||
1236 | if (!check_gamma5_errata(attrs->gamma5)) | 1270 | if (!check_gamma5_errata(attrs->gamma5)) |
1237 | return -EINVAL; | 1271 | return -EINVAL; |
1272 | |||
1238 | return 0; | 1273 | return 0; |
1239 | } | 1274 | } |
1240 | 1275 | ||
@@ -1261,13 +1296,14 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1261 | mutex_lock(&dev->mode_config.mutex); | 1296 | mutex_lock(&dev->mode_config.mutex); |
1262 | mutex_lock(&dev->struct_mutex); | 1297 | mutex_lock(&dev->struct_mutex); |
1263 | 1298 | ||
1299 | ret = -EINVAL; | ||
1264 | if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { | 1300 | if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) { |
1265 | attrs->color_key = overlay->color_key; | 1301 | attrs->color_key = overlay->color_key; |
1266 | attrs->brightness = overlay->brightness; | 1302 | attrs->brightness = overlay->brightness; |
1267 | attrs->contrast = overlay->contrast; | 1303 | attrs->contrast = overlay->contrast; |
1268 | attrs->saturation = overlay->saturation; | 1304 | attrs->saturation = overlay->saturation; |
1269 | 1305 | ||
1270 | if (IS_I9XX(dev)) { | 1306 | if (!IS_GEN2(dev)) { |
1271 | attrs->gamma0 = I915_READ(OGAMC0); | 1307 | attrs->gamma0 = I915_READ(OGAMC0); |
1272 | attrs->gamma1 = I915_READ(OGAMC1); | 1308 | attrs->gamma1 = I915_READ(OGAMC1); |
1273 | attrs->gamma2 = I915_READ(OGAMC2); | 1309 | attrs->gamma2 = I915_READ(OGAMC2); |
@@ -1275,29 +1311,20 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1275 | attrs->gamma4 = I915_READ(OGAMC4); | 1311 | attrs->gamma4 = I915_READ(OGAMC4); |
1276 | attrs->gamma5 = I915_READ(OGAMC5); | 1312 | attrs->gamma5 = I915_READ(OGAMC5); |
1277 | } | 1313 | } |
1278 | ret = 0; | ||
1279 | } else { | 1314 | } else { |
1280 | overlay->color_key = attrs->color_key; | 1315 | if (attrs->brightness < -128 || attrs->brightness > 127) |
1281 | if (attrs->brightness >= -128 && attrs->brightness <= 127) { | ||
1282 | overlay->brightness = attrs->brightness; | ||
1283 | } else { | ||
1284 | ret = -EINVAL; | ||
1285 | goto out_unlock; | 1316 | goto out_unlock; |
1286 | } | 1317 | if (attrs->contrast > 255) |
1287 | if (attrs->contrast <= 255) { | ||
1288 | overlay->contrast = attrs->contrast; | ||
1289 | } else { | ||
1290 | ret = -EINVAL; | ||
1291 | goto out_unlock; | 1318 | goto out_unlock; |
1292 | } | 1319 | if (attrs->saturation > 1023) |
1293 | if (attrs->saturation <= 1023) { | ||
1294 | overlay->saturation = attrs->saturation; | ||
1295 | } else { | ||
1296 | ret = -EINVAL; | ||
1297 | goto out_unlock; | 1320 | goto out_unlock; |
1298 | } | ||
1299 | 1321 | ||
1300 | regs = intel_overlay_map_regs_atomic(overlay); | 1322 | overlay->color_key = attrs->color_key; |
1323 | overlay->brightness = attrs->brightness; | ||
1324 | overlay->contrast = attrs->contrast; | ||
1325 | overlay->saturation = attrs->saturation; | ||
1326 | |||
1327 | regs = intel_overlay_map_regs(overlay); | ||
1301 | if (!regs) { | 1328 | if (!regs) { |
1302 | ret = -ENOMEM; | 1329 | ret = -ENOMEM; |
1303 | goto out_unlock; | 1330 | goto out_unlock; |
@@ -1305,13 +1332,11 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1305 | 1332 | ||
1306 | update_reg_attrs(overlay, regs); | 1333 | update_reg_attrs(overlay, regs); |
1307 | 1334 | ||
1308 | intel_overlay_unmap_regs_atomic(overlay); | 1335 | intel_overlay_unmap_regs(overlay, regs); |
1309 | 1336 | ||
1310 | if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { | 1337 | if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { |
1311 | if (!IS_I9XX(dev)) { | 1338 | if (IS_GEN2(dev)) |
1312 | ret = -EINVAL; | ||
1313 | goto out_unlock; | 1339 | goto out_unlock; |
1314 | } | ||
1315 | 1340 | ||
1316 | if (overlay->active) { | 1341 | if (overlay->active) { |
1317 | ret = -EBUSY; | 1342 | ret = -EBUSY; |
@@ -1319,7 +1344,7 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1319 | } | 1344 | } |
1320 | 1345 | ||
1321 | ret = check_gamma(attrs); | 1346 | ret = check_gamma(attrs); |
1322 | if (ret != 0) | 1347 | if (ret) |
1323 | goto out_unlock; | 1348 | goto out_unlock; |
1324 | 1349 | ||
1325 | I915_WRITE(OGAMC0, attrs->gamma0); | 1350 | I915_WRITE(OGAMC0, attrs->gamma0); |
@@ -1329,9 +1354,9 @@ int intel_overlay_attrs(struct drm_device *dev, void *data, | |||
1329 | I915_WRITE(OGAMC4, attrs->gamma4); | 1354 | I915_WRITE(OGAMC4, attrs->gamma4); |
1330 | I915_WRITE(OGAMC5, attrs->gamma5); | 1355 | I915_WRITE(OGAMC5, attrs->gamma5); |
1331 | } | 1356 | } |
1332 | ret = 0; | ||
1333 | } | 1357 | } |
1334 | 1358 | ||
1359 | ret = 0; | ||
1335 | out_unlock: | 1360 | out_unlock: |
1336 | mutex_unlock(&dev->struct_mutex); | 1361 | mutex_unlock(&dev->struct_mutex); |
1337 | mutex_unlock(&dev->mode_config.mutex); | 1362 | mutex_unlock(&dev->mode_config.mutex); |
@@ -1347,7 +1372,7 @@ void intel_setup_overlay(struct drm_device *dev) | |||
1347 | struct overlay_registers *regs; | 1372 | struct overlay_registers *regs; |
1348 | int ret; | 1373 | int ret; |
1349 | 1374 | ||
1350 | if (!OVERLAY_EXISTS(dev)) | 1375 | if (!HAS_OVERLAY(dev)) |
1351 | return; | 1376 | return; |
1352 | 1377 | ||
1353 | overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); | 1378 | overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); |
@@ -1360,22 +1385,28 @@ void intel_setup_overlay(struct drm_device *dev) | |||
1360 | goto out_free; | 1385 | goto out_free; |
1361 | overlay->reg_bo = to_intel_bo(reg_bo); | 1386 | overlay->reg_bo = to_intel_bo(reg_bo); |
1362 | 1387 | ||
1363 | if (OVERLAY_NONPHYSICAL(dev)) { | 1388 | if (OVERLAY_NEEDS_PHYSICAL(dev)) { |
1364 | ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); | ||
1365 | if (ret) { | ||
1366 | DRM_ERROR("failed to pin overlay register bo\n"); | ||
1367 | goto out_free_bo; | ||
1368 | } | ||
1369 | overlay->flip_addr = overlay->reg_bo->gtt_offset; | ||
1370 | } else { | ||
1371 | ret = i915_gem_attach_phys_object(dev, reg_bo, | 1389 | ret = i915_gem_attach_phys_object(dev, reg_bo, |
1372 | I915_GEM_PHYS_OVERLAY_REGS, | 1390 | I915_GEM_PHYS_OVERLAY_REGS, |
1373 | 0); | 1391 | PAGE_SIZE); |
1374 | if (ret) { | 1392 | if (ret) { |
1375 | DRM_ERROR("failed to attach phys overlay regs\n"); | 1393 | DRM_ERROR("failed to attach phys overlay regs\n"); |
1376 | goto out_free_bo; | 1394 | goto out_free_bo; |
1377 | } | 1395 | } |
1378 | overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr; | 1396 | overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr; |
1397 | } else { | ||
1398 | ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); | ||
1399 | if (ret) { | ||
1400 | DRM_ERROR("failed to pin overlay register bo\n"); | ||
1401 | goto out_free_bo; | ||
1402 | } | ||
1403 | overlay->flip_addr = overlay->reg_bo->gtt_offset; | ||
1404 | |||
1405 | ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); | ||
1406 | if (ret) { | ||
1407 | DRM_ERROR("failed to move overlay register bo into the GTT\n"); | ||
1408 | goto out_unpin_bo; | ||
1409 | } | ||
1379 | } | 1410 | } |
1380 | 1411 | ||
1381 | /* init all values */ | 1412 | /* init all values */ |
@@ -1384,21 +1415,22 @@ void intel_setup_overlay(struct drm_device *dev) | |||
1384 | overlay->contrast = 75; | 1415 | overlay->contrast = 75; |
1385 | overlay->saturation = 146; | 1416 | overlay->saturation = 146; |
1386 | 1417 | ||
1387 | regs = intel_overlay_map_regs_atomic(overlay); | 1418 | regs = intel_overlay_map_regs(overlay); |
1388 | if (!regs) | 1419 | if (!regs) |
1389 | goto out_free_bo; | 1420 | goto out_free_bo; |
1390 | 1421 | ||
1391 | memset(regs, 0, sizeof(struct overlay_registers)); | 1422 | memset(regs, 0, sizeof(struct overlay_registers)); |
1392 | update_polyphase_filter(regs); | 1423 | update_polyphase_filter(regs); |
1393 | |||
1394 | update_reg_attrs(overlay, regs); | 1424 | update_reg_attrs(overlay, regs); |
1395 | 1425 | ||
1396 | intel_overlay_unmap_regs_atomic(overlay); | 1426 | intel_overlay_unmap_regs(overlay, regs); |
1397 | 1427 | ||
1398 | dev_priv->overlay = overlay; | 1428 | dev_priv->overlay = overlay; |
1399 | DRM_INFO("initialized overlay support\n"); | 1429 | DRM_INFO("initialized overlay support\n"); |
1400 | return; | 1430 | return; |
1401 | 1431 | ||
1432 | out_unpin_bo: | ||
1433 | i915_gem_object_unpin(reg_bo); | ||
1402 | out_free_bo: | 1434 | out_free_bo: |
1403 | drm_gem_object_unreference(reg_bo); | 1435 | drm_gem_object_unreference(reg_bo); |
1404 | out_free: | 1436 | out_free: |
@@ -1408,18 +1440,23 @@ out_free: | |||
1408 | 1440 | ||
1409 | void intel_cleanup_overlay(struct drm_device *dev) | 1441 | void intel_cleanup_overlay(struct drm_device *dev) |
1410 | { | 1442 | { |
1411 | drm_i915_private_t *dev_priv = dev->dev_private; | 1443 | drm_i915_private_t *dev_priv = dev->dev_private; |
1412 | 1444 | ||
1413 | if (dev_priv->overlay) { | 1445 | if (!dev_priv->overlay) |
1414 | /* The bo's should be free'd by the generic code already. | 1446 | return; |
1415 | * Furthermore modesetting teardown happens beforehand so the | ||
1416 | * hardware should be off already */ | ||
1417 | BUG_ON(dev_priv->overlay->active); | ||
1418 | 1447 | ||
1419 | kfree(dev_priv->overlay); | 1448 | /* The bo's should be free'd by the generic code already. |
1420 | } | 1449 | * Furthermore modesetting teardown happens beforehand so the |
1450 | * hardware should be off already */ | ||
1451 | BUG_ON(dev_priv->overlay->active); | ||
1452 | |||
1453 | drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base); | ||
1454 | kfree(dev_priv->overlay); | ||
1421 | } | 1455 | } |
1422 | 1456 | ||
1457 | #ifdef CONFIG_DEBUG_FS | ||
1458 | #include <linux/seq_file.h> | ||
1459 | |||
1423 | struct intel_overlay_error_state { | 1460 | struct intel_overlay_error_state { |
1424 | struct overlay_registers regs; | 1461 | struct overlay_registers regs; |
1425 | unsigned long base; | 1462 | unsigned long base; |
@@ -1427,6 +1464,32 @@ struct intel_overlay_error_state { | |||
1427 | u32 isr; | 1464 | u32 isr; |
1428 | }; | 1465 | }; |
1429 | 1466 | ||
1467 | static struct overlay_registers * | ||
1468 | intel_overlay_map_regs_atomic(struct intel_overlay *overlay, | ||
1469 | int slot) | ||
1470 | { | ||
1471 | drm_i915_private_t *dev_priv = overlay->dev->dev_private; | ||
1472 | struct overlay_registers *regs; | ||
1473 | |||
1474 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) | ||
1475 | regs = overlay->reg_bo->phys_obj->handle->vaddr; | ||
1476 | else | ||
1477 | regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | ||
1478 | overlay->reg_bo->gtt_offset, | ||
1479 | slot); | ||
1480 | |||
1481 | return regs; | ||
1482 | } | ||
1483 | |||
1484 | static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay, | ||
1485 | int slot, | ||
1486 | struct overlay_registers *regs) | ||
1487 | { | ||
1488 | if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev)) | ||
1489 | io_mapping_unmap_atomic(regs, slot); | ||
1490 | } | ||
1491 | |||
1492 | |||
1430 | struct intel_overlay_error_state * | 1493 | struct intel_overlay_error_state * |
1431 | intel_overlay_capture_error_state(struct drm_device *dev) | 1494 | intel_overlay_capture_error_state(struct drm_device *dev) |
1432 | { | 1495 | { |
@@ -1444,17 +1507,17 @@ intel_overlay_capture_error_state(struct drm_device *dev) | |||
1444 | 1507 | ||
1445 | error->dovsta = I915_READ(DOVSTA); | 1508 | error->dovsta = I915_READ(DOVSTA); |
1446 | error->isr = I915_READ(ISR); | 1509 | error->isr = I915_READ(ISR); |
1447 | if (OVERLAY_NONPHYSICAL(overlay->dev)) | 1510 | if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) |
1448 | error->base = (long) overlay->reg_bo->gtt_offset; | ||
1449 | else | ||
1450 | error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; | 1511 | error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; |
1512 | else | ||
1513 | error->base = (long) overlay->reg_bo->gtt_offset; | ||
1451 | 1514 | ||
1452 | regs = intel_overlay_map_regs_atomic(overlay); | 1515 | regs = intel_overlay_map_regs_atomic(overlay, KM_IRQ0); |
1453 | if (!regs) | 1516 | if (!regs) |
1454 | goto err; | 1517 | goto err; |
1455 | 1518 | ||
1456 | memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); | 1519 | memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); |
1457 | intel_overlay_unmap_regs_atomic(overlay); | 1520 | intel_overlay_unmap_regs_atomic(overlay, KM_IRQ0, regs); |
1458 | 1521 | ||
1459 | return error; | 1522 | return error; |
1460 | 1523 | ||
@@ -1515,3 +1578,4 @@ intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_s | |||
1515 | P(UVSCALEV); | 1578 | P(UVSCALEV); |
1516 | #undef P | 1579 | #undef P |
1517 | } | 1580 | } |
1581 | #endif | ||
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e7f5299d9d57..92ff8f385278 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #include "intel_drv.h" | 31 | #include "intel_drv.h" |
32 | 32 | ||
33 | #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ | ||
34 | |||
33 | void | 35 | void |
34 | intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | 36 | intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, |
35 | struct drm_display_mode *adjusted_mode) | 37 | struct drm_display_mode *adjusted_mode) |
@@ -109,3 +111,110 @@ done: | |||
109 | dev_priv->pch_pf_pos = (x << 16) | y; | 111 | dev_priv->pch_pf_pos = (x << 16) | y; |
110 | dev_priv->pch_pf_size = (width << 16) | height; | 112 | dev_priv->pch_pf_size = (width << 16) | height; |
111 | } | 113 | } |
114 | |||
115 | static int is_backlight_combination_mode(struct drm_device *dev) | ||
116 | { | ||
117 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
118 | |||
119 | if (INTEL_INFO(dev)->gen >= 4) | ||
120 | return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; | ||
121 | |||
122 | if (IS_GEN2(dev)) | ||
123 | return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | u32 intel_panel_get_max_backlight(struct drm_device *dev) | ||
129 | { | ||
130 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
131 | u32 max; | ||
132 | |||
133 | if (HAS_PCH_SPLIT(dev)) { | ||
134 | max = I915_READ(BLC_PWM_PCH_CTL2) >> 16; | ||
135 | } else { | ||
136 | max = I915_READ(BLC_PWM_CTL); | ||
137 | if (IS_PINEVIEW(dev)) { | ||
138 | max >>= 17; | ||
139 | } else { | ||
140 | max >>= 16; | ||
141 | if (INTEL_INFO(dev)->gen < 4) | ||
142 | max &= ~1; | ||
143 | } | ||
144 | |||
145 | if (is_backlight_combination_mode(dev)) | ||
146 | max *= 0xff; | ||
147 | } | ||
148 | |||
149 | if (max == 0) { | ||
150 | /* XXX add code here to query mode clock or hardware clock | ||
151 | * and program max PWM appropriately. | ||
152 | */ | ||
153 | DRM_ERROR("fixme: max PWM is zero.\n"); | ||
154 | max = 1; | ||
155 | } | ||
156 | |||
157 | DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); | ||
158 | return max; | ||
159 | } | ||
160 | |||
161 | u32 intel_panel_get_backlight(struct drm_device *dev) | ||
162 | { | ||
163 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
164 | u32 val; | ||
165 | |||
166 | if (HAS_PCH_SPLIT(dev)) { | ||
167 | val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; | ||
168 | } else { | ||
169 | val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; | ||
170 | if (IS_PINEVIEW(dev)) | ||
171 | val >>= 1; | ||
172 | |||
173 | if (is_backlight_combination_mode(dev)){ | ||
174 | u8 lbpc; | ||
175 | |||
176 | val &= ~1; | ||
177 | pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); | ||
178 | val *= lbpc; | ||
179 | val >>= 1; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); | ||
184 | return val; | ||
185 | } | ||
186 | |||
187 | static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) | ||
188 | { | ||
189 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
190 | u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
191 | I915_WRITE(BLC_PWM_CPU_CTL, val | level); | ||
192 | } | ||
193 | |||
194 | void intel_panel_set_backlight(struct drm_device *dev, u32 level) | ||
195 | { | ||
196 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
197 | u32 tmp; | ||
198 | |||
199 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); | ||
200 | |||
201 | if (HAS_PCH_SPLIT(dev)) | ||
202 | return intel_pch_panel_set_backlight(dev, level); | ||
203 | |||
204 | if (is_backlight_combination_mode(dev)){ | ||
205 | u32 max = intel_panel_get_max_backlight(dev); | ||
206 | u8 lpbc; | ||
207 | |||
208 | lpbc = level * 0xfe / max + 1; | ||
209 | level /= lpbc; | ||
210 | pci_write_config_byte(dev->pdev, PCI_LBPC, lpbc); | ||
211 | } | ||
212 | |||
213 | tmp = I915_READ(BLC_PWM_CTL); | ||
214 | if (IS_PINEVIEW(dev)) { | ||
215 | tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); | ||
216 | level <<= 1; | ||
217 | } else | ||
218 | tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
219 | I915_WRITE(BLC_PWM_CTL, tmp | level); | ||
220 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index cb3508f78bc3..d89b88791aac 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
34 | #include "i915_trace.h" | 34 | #include "i915_trace.h" |
35 | #include "intel_drv.h" | ||
35 | 36 | ||
36 | static u32 i915_gem_get_seqno(struct drm_device *dev) | 37 | static u32 i915_gem_get_seqno(struct drm_device *dev) |
37 | { | 38 | { |
@@ -49,9 +50,9 @@ static u32 i915_gem_get_seqno(struct drm_device *dev) | |||
49 | 50 | ||
50 | static void | 51 | static void |
51 | render_ring_flush(struct drm_device *dev, | 52 | render_ring_flush(struct drm_device *dev, |
52 | struct intel_ring_buffer *ring, | 53 | struct intel_ring_buffer *ring, |
53 | u32 invalidate_domains, | 54 | u32 invalidate_domains, |
54 | u32 flush_domains) | 55 | u32 flush_domains) |
55 | { | 56 | { |
56 | drm_i915_private_t *dev_priv = dev->dev_private; | 57 | drm_i915_private_t *dev_priv = dev->dev_private; |
57 | u32 cmd; | 58 | u32 cmd; |
@@ -97,7 +98,7 @@ render_ring_flush(struct drm_device *dev, | |||
97 | if ((invalidate_domains|flush_domains) & | 98 | if ((invalidate_domains|flush_domains) & |
98 | I915_GEM_DOMAIN_RENDER) | 99 | I915_GEM_DOMAIN_RENDER) |
99 | cmd &= ~MI_NO_WRITE_FLUSH; | 100 | cmd &= ~MI_NO_WRITE_FLUSH; |
100 | if (!IS_I965G(dev)) { | 101 | if (INTEL_INFO(dev)->gen < 4) { |
101 | /* | 102 | /* |
102 | * On the 965, the sampler cache always gets flushed | 103 | * On the 965, the sampler cache always gets flushed |
103 | * and this bit is reserved. | 104 | * and this bit is reserved. |
@@ -118,38 +119,26 @@ render_ring_flush(struct drm_device *dev, | |||
118 | } | 119 | } |
119 | } | 120 | } |
120 | 121 | ||
121 | static unsigned int render_ring_get_head(struct drm_device *dev, | 122 | static void ring_set_tail(struct drm_device *dev, |
122 | struct intel_ring_buffer *ring) | 123 | struct intel_ring_buffer *ring, |
123 | { | 124 | u32 value) |
124 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
125 | return I915_READ(PRB0_HEAD) & HEAD_ADDR; | ||
126 | } | ||
127 | |||
128 | static unsigned int render_ring_get_tail(struct drm_device *dev, | ||
129 | struct intel_ring_buffer *ring) | ||
130 | { | 125 | { |
131 | drm_i915_private_t *dev_priv = dev->dev_private; | 126 | drm_i915_private_t *dev_priv = dev->dev_private; |
132 | return I915_READ(PRB0_TAIL) & TAIL_ADDR; | 127 | I915_WRITE_TAIL(ring, ring->tail); |
133 | } | 128 | } |
134 | 129 | ||
135 | static unsigned int render_ring_get_active_head(struct drm_device *dev, | 130 | u32 intel_ring_get_active_head(struct drm_device *dev, |
136 | struct intel_ring_buffer *ring) | 131 | struct intel_ring_buffer *ring) |
137 | { | 132 | { |
138 | drm_i915_private_t *dev_priv = dev->dev_private; | 133 | drm_i915_private_t *dev_priv = dev->dev_private; |
139 | u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; | 134 | u32 acthd_reg = INTEL_INFO(dev)->gen >= 4 ? |
135 | RING_ACTHD(ring->mmio_base) : ACTHD; | ||
140 | 136 | ||
141 | return I915_READ(acthd_reg); | 137 | return I915_READ(acthd_reg); |
142 | } | 138 | } |
143 | 139 | ||
144 | static void render_ring_advance_ring(struct drm_device *dev, | ||
145 | struct intel_ring_buffer *ring) | ||
146 | { | ||
147 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
148 | I915_WRITE(PRB0_TAIL, ring->tail); | ||
149 | } | ||
150 | |||
151 | static int init_ring_common(struct drm_device *dev, | 140 | static int init_ring_common(struct drm_device *dev, |
152 | struct intel_ring_buffer *ring) | 141 | struct intel_ring_buffer *ring) |
153 | { | 142 | { |
154 | u32 head; | 143 | u32 head; |
155 | drm_i915_private_t *dev_priv = dev->dev_private; | 144 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -157,57 +146,57 @@ static int init_ring_common(struct drm_device *dev, | |||
157 | obj_priv = to_intel_bo(ring->gem_object); | 146 | obj_priv = to_intel_bo(ring->gem_object); |
158 | 147 | ||
159 | /* Stop the ring if it's running. */ | 148 | /* Stop the ring if it's running. */ |
160 | I915_WRITE(ring->regs.ctl, 0); | 149 | I915_WRITE_CTL(ring, 0); |
161 | I915_WRITE(ring->regs.head, 0); | 150 | I915_WRITE_HEAD(ring, 0); |
162 | I915_WRITE(ring->regs.tail, 0); | 151 | ring->set_tail(dev, ring, 0); |
163 | 152 | ||
164 | /* Initialize the ring. */ | 153 | /* Initialize the ring. */ |
165 | I915_WRITE(ring->regs.start, obj_priv->gtt_offset); | 154 | I915_WRITE_START(ring, obj_priv->gtt_offset); |
166 | head = ring->get_head(dev, ring); | 155 | head = I915_READ_HEAD(ring) & HEAD_ADDR; |
167 | 156 | ||
168 | /* G45 ring initialization fails to reset head to zero */ | 157 | /* G45 ring initialization fails to reset head to zero */ |
169 | if (head != 0) { | 158 | if (head != 0) { |
170 | DRM_ERROR("%s head not reset to zero " | 159 | DRM_ERROR("%s head not reset to zero " |
171 | "ctl %08x head %08x tail %08x start %08x\n", | 160 | "ctl %08x head %08x tail %08x start %08x\n", |
172 | ring->name, | 161 | ring->name, |
173 | I915_READ(ring->regs.ctl), | 162 | I915_READ_CTL(ring), |
174 | I915_READ(ring->regs.head), | 163 | I915_READ_HEAD(ring), |
175 | I915_READ(ring->regs.tail), | 164 | I915_READ_TAIL(ring), |
176 | I915_READ(ring->regs.start)); | 165 | I915_READ_START(ring)); |
177 | 166 | ||
178 | I915_WRITE(ring->regs.head, 0); | 167 | I915_WRITE_HEAD(ring, 0); |
179 | 168 | ||
180 | DRM_ERROR("%s head forced to zero " | 169 | DRM_ERROR("%s head forced to zero " |
181 | "ctl %08x head %08x tail %08x start %08x\n", | 170 | "ctl %08x head %08x tail %08x start %08x\n", |
182 | ring->name, | 171 | ring->name, |
183 | I915_READ(ring->regs.ctl), | 172 | I915_READ_CTL(ring), |
184 | I915_READ(ring->regs.head), | 173 | I915_READ_HEAD(ring), |
185 | I915_READ(ring->regs.tail), | 174 | I915_READ_TAIL(ring), |
186 | I915_READ(ring->regs.start)); | 175 | I915_READ_START(ring)); |
187 | } | 176 | } |
188 | 177 | ||
189 | I915_WRITE(ring->regs.ctl, | 178 | I915_WRITE_CTL(ring, |
190 | ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) | 179 | ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) |
191 | | RING_NO_REPORT | RING_VALID); | 180 | | RING_NO_REPORT | RING_VALID); |
192 | 181 | ||
193 | head = I915_READ(ring->regs.head) & HEAD_ADDR; | 182 | head = I915_READ_HEAD(ring) & HEAD_ADDR; |
194 | /* If the head is still not zero, the ring is dead */ | 183 | /* If the head is still not zero, the ring is dead */ |
195 | if (head != 0) { | 184 | if (head != 0) { |
196 | DRM_ERROR("%s initialization failed " | 185 | DRM_ERROR("%s initialization failed " |
197 | "ctl %08x head %08x tail %08x start %08x\n", | 186 | "ctl %08x head %08x tail %08x start %08x\n", |
198 | ring->name, | 187 | ring->name, |
199 | I915_READ(ring->regs.ctl), | 188 | I915_READ_CTL(ring), |
200 | I915_READ(ring->regs.head), | 189 | I915_READ_HEAD(ring), |
201 | I915_READ(ring->regs.tail), | 190 | I915_READ_TAIL(ring), |
202 | I915_READ(ring->regs.start)); | 191 | I915_READ_START(ring)); |
203 | return -EIO; | 192 | return -EIO; |
204 | } | 193 | } |
205 | 194 | ||
206 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 195 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
207 | i915_kernel_lost_context(dev); | 196 | i915_kernel_lost_context(dev); |
208 | else { | 197 | else { |
209 | ring->head = ring->get_head(dev, ring); | 198 | ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; |
210 | ring->tail = ring->get_tail(dev, ring); | 199 | ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; |
211 | ring->space = ring->head - (ring->tail + 8); | 200 | ring->space = ring->head - (ring->tail + 8); |
212 | if (ring->space < 0) | 201 | if (ring->space < 0) |
213 | ring->space += ring->size; | 202 | ring->space += ring->size; |
@@ -216,13 +205,13 @@ static int init_ring_common(struct drm_device *dev, | |||
216 | } | 205 | } |
217 | 206 | ||
218 | static int init_render_ring(struct drm_device *dev, | 207 | static int init_render_ring(struct drm_device *dev, |
219 | struct intel_ring_buffer *ring) | 208 | struct intel_ring_buffer *ring) |
220 | { | 209 | { |
221 | drm_i915_private_t *dev_priv = dev->dev_private; | 210 | drm_i915_private_t *dev_priv = dev->dev_private; |
222 | int ret = init_ring_common(dev, ring); | 211 | int ret = init_ring_common(dev, ring); |
223 | int mode; | 212 | int mode; |
224 | 213 | ||
225 | if (IS_I9XX(dev) && !IS_GEN3(dev)) { | 214 | if (INTEL_INFO(dev)->gen > 3) { |
226 | mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; | 215 | mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; |
227 | if (IS_GEN6(dev)) | 216 | if (IS_GEN6(dev)) |
228 | mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; | 217 | mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; |
@@ -250,9 +239,8 @@ do { \ | |||
250 | */ | 239 | */ |
251 | static u32 | 240 | static u32 |
252 | render_ring_add_request(struct drm_device *dev, | 241 | render_ring_add_request(struct drm_device *dev, |
253 | struct intel_ring_buffer *ring, | 242 | struct intel_ring_buffer *ring, |
254 | struct drm_file *file_priv, | 243 | u32 flush_domains) |
255 | u32 flush_domains) | ||
256 | { | 244 | { |
257 | drm_i915_private_t *dev_priv = dev->dev_private; | 245 | drm_i915_private_t *dev_priv = dev->dev_private; |
258 | u32 seqno; | 246 | u32 seqno; |
@@ -315,8 +303,8 @@ render_ring_add_request(struct drm_device *dev, | |||
315 | } | 303 | } |
316 | 304 | ||
317 | static u32 | 305 | static u32 |
318 | render_ring_get_gem_seqno(struct drm_device *dev, | 306 | render_ring_get_seqno(struct drm_device *dev, |
319 | struct intel_ring_buffer *ring) | 307 | struct intel_ring_buffer *ring) |
320 | { | 308 | { |
321 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 309 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
322 | if (HAS_PIPE_CONTROL(dev)) | 310 | if (HAS_PIPE_CONTROL(dev)) |
@@ -327,7 +315,7 @@ render_ring_get_gem_seqno(struct drm_device *dev, | |||
327 | 315 | ||
328 | static void | 316 | static void |
329 | render_ring_get_user_irq(struct drm_device *dev, | 317 | render_ring_get_user_irq(struct drm_device *dev, |
330 | struct intel_ring_buffer *ring) | 318 | struct intel_ring_buffer *ring) |
331 | { | 319 | { |
332 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 320 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
333 | unsigned long irqflags; | 321 | unsigned long irqflags; |
@@ -344,7 +332,7 @@ render_ring_get_user_irq(struct drm_device *dev, | |||
344 | 332 | ||
345 | static void | 333 | static void |
346 | render_ring_put_user_irq(struct drm_device *dev, | 334 | render_ring_put_user_irq(struct drm_device *dev, |
347 | struct intel_ring_buffer *ring) | 335 | struct intel_ring_buffer *ring) |
348 | { | 336 | { |
349 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 337 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
350 | unsigned long irqflags; | 338 | unsigned long irqflags; |
@@ -360,21 +348,23 @@ render_ring_put_user_irq(struct drm_device *dev, | |||
360 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); | 348 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); |
361 | } | 349 | } |
362 | 350 | ||
363 | static void render_setup_status_page(struct drm_device *dev, | 351 | void intel_ring_setup_status_page(struct drm_device *dev, |
364 | struct intel_ring_buffer *ring) | 352 | struct intel_ring_buffer *ring) |
365 | { | 353 | { |
366 | drm_i915_private_t *dev_priv = dev->dev_private; | 354 | drm_i915_private_t *dev_priv = dev->dev_private; |
367 | if (IS_GEN6(dev)) { | 355 | if (IS_GEN6(dev)) { |
368 | I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr); | 356 | I915_WRITE(RING_HWS_PGA_GEN6(ring->mmio_base), |
369 | I915_READ(HWS_PGA_GEN6); /* posting read */ | 357 | ring->status_page.gfx_addr); |
358 | I915_READ(RING_HWS_PGA_GEN6(ring->mmio_base)); /* posting read */ | ||
370 | } else { | 359 | } else { |
371 | I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); | 360 | I915_WRITE(RING_HWS_PGA(ring->mmio_base), |
372 | I915_READ(HWS_PGA); /* posting read */ | 361 | ring->status_page.gfx_addr); |
362 | I915_READ(RING_HWS_PGA(ring->mmio_base)); /* posting read */ | ||
373 | } | 363 | } |
374 | 364 | ||
375 | } | 365 | } |
376 | 366 | ||
377 | void | 367 | static void |
378 | bsd_ring_flush(struct drm_device *dev, | 368 | bsd_ring_flush(struct drm_device *dev, |
379 | struct intel_ring_buffer *ring, | 369 | struct intel_ring_buffer *ring, |
380 | u32 invalidate_domains, | 370 | u32 invalidate_domains, |
@@ -386,45 +376,16 @@ bsd_ring_flush(struct drm_device *dev, | |||
386 | intel_ring_advance(dev, ring); | 376 | intel_ring_advance(dev, ring); |
387 | } | 377 | } |
388 | 378 | ||
389 | static inline unsigned int bsd_ring_get_head(struct drm_device *dev, | ||
390 | struct intel_ring_buffer *ring) | ||
391 | { | ||
392 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
393 | return I915_READ(BSD_RING_HEAD) & HEAD_ADDR; | ||
394 | } | ||
395 | |||
396 | static inline unsigned int bsd_ring_get_tail(struct drm_device *dev, | ||
397 | struct intel_ring_buffer *ring) | ||
398 | { | ||
399 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
400 | return I915_READ(BSD_RING_TAIL) & TAIL_ADDR; | ||
401 | } | ||
402 | |||
403 | static inline unsigned int bsd_ring_get_active_head(struct drm_device *dev, | ||
404 | struct intel_ring_buffer *ring) | ||
405 | { | ||
406 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
407 | return I915_READ(BSD_RING_ACTHD); | ||
408 | } | ||
409 | |||
410 | static inline void bsd_ring_advance_ring(struct drm_device *dev, | ||
411 | struct intel_ring_buffer *ring) | ||
412 | { | ||
413 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
414 | I915_WRITE(BSD_RING_TAIL, ring->tail); | ||
415 | } | ||
416 | |||
417 | static int init_bsd_ring(struct drm_device *dev, | 379 | static int init_bsd_ring(struct drm_device *dev, |
418 | struct intel_ring_buffer *ring) | 380 | struct intel_ring_buffer *ring) |
419 | { | 381 | { |
420 | return init_ring_common(dev, ring); | 382 | return init_ring_common(dev, ring); |
421 | } | 383 | } |
422 | 384 | ||
423 | static u32 | 385 | static u32 |
424 | bsd_ring_add_request(struct drm_device *dev, | 386 | bsd_ring_add_request(struct drm_device *dev, |
425 | struct intel_ring_buffer *ring, | 387 | struct intel_ring_buffer *ring, |
426 | struct drm_file *file_priv, | 388 | u32 flush_domains) |
427 | u32 flush_domains) | ||
428 | { | 389 | { |
429 | u32 seqno; | 390 | u32 seqno; |
430 | 391 | ||
@@ -443,40 +404,32 @@ bsd_ring_add_request(struct drm_device *dev, | |||
443 | return seqno; | 404 | return seqno; |
444 | } | 405 | } |
445 | 406 | ||
446 | static void bsd_setup_status_page(struct drm_device *dev, | ||
447 | struct intel_ring_buffer *ring) | ||
448 | { | ||
449 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
450 | I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr); | ||
451 | I915_READ(BSD_HWS_PGA); | ||
452 | } | ||
453 | |||
454 | static void | 407 | static void |
455 | bsd_ring_get_user_irq(struct drm_device *dev, | 408 | bsd_ring_get_user_irq(struct drm_device *dev, |
456 | struct intel_ring_buffer *ring) | 409 | struct intel_ring_buffer *ring) |
457 | { | 410 | { |
458 | /* do nothing */ | 411 | /* do nothing */ |
459 | } | 412 | } |
460 | static void | 413 | static void |
461 | bsd_ring_put_user_irq(struct drm_device *dev, | 414 | bsd_ring_put_user_irq(struct drm_device *dev, |
462 | struct intel_ring_buffer *ring) | 415 | struct intel_ring_buffer *ring) |
463 | { | 416 | { |
464 | /* do nothing */ | 417 | /* do nothing */ |
465 | } | 418 | } |
466 | 419 | ||
467 | static u32 | 420 | static u32 |
468 | bsd_ring_get_gem_seqno(struct drm_device *dev, | 421 | bsd_ring_get_seqno(struct drm_device *dev, |
469 | struct intel_ring_buffer *ring) | 422 | struct intel_ring_buffer *ring) |
470 | { | 423 | { |
471 | return intel_read_status_page(ring, I915_GEM_HWS_INDEX); | 424 | return intel_read_status_page(ring, I915_GEM_HWS_INDEX); |
472 | } | 425 | } |
473 | 426 | ||
474 | static int | 427 | static int |
475 | bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, | 428 | bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, |
476 | struct intel_ring_buffer *ring, | 429 | struct intel_ring_buffer *ring, |
477 | struct drm_i915_gem_execbuffer2 *exec, | 430 | struct drm_i915_gem_execbuffer2 *exec, |
478 | struct drm_clip_rect *cliprects, | 431 | struct drm_clip_rect *cliprects, |
479 | uint64_t exec_offset) | 432 | uint64_t exec_offset) |
480 | { | 433 | { |
481 | uint32_t exec_start; | 434 | uint32_t exec_start; |
482 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; | 435 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; |
@@ -491,10 +444,10 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, | |||
491 | 444 | ||
492 | static int | 445 | static int |
493 | render_ring_dispatch_gem_execbuffer(struct drm_device *dev, | 446 | render_ring_dispatch_gem_execbuffer(struct drm_device *dev, |
494 | struct intel_ring_buffer *ring, | 447 | struct intel_ring_buffer *ring, |
495 | struct drm_i915_gem_execbuffer2 *exec, | 448 | struct drm_i915_gem_execbuffer2 *exec, |
496 | struct drm_clip_rect *cliprects, | 449 | struct drm_clip_rect *cliprects, |
497 | uint64_t exec_offset) | 450 | uint64_t exec_offset) |
498 | { | 451 | { |
499 | drm_i915_private_t *dev_priv = dev->dev_private; | 452 | drm_i915_private_t *dev_priv = dev->dev_private; |
500 | int nbox = exec->num_cliprects; | 453 | int nbox = exec->num_cliprects; |
@@ -524,7 +477,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, | |||
524 | intel_ring_emit(dev, ring, 0); | 477 | intel_ring_emit(dev, ring, 0); |
525 | } else { | 478 | } else { |
526 | intel_ring_begin(dev, ring, 4); | 479 | intel_ring_begin(dev, ring, 4); |
527 | if (IS_I965G(dev)) { | 480 | if (INTEL_INFO(dev)->gen >= 4) { |
528 | intel_ring_emit(dev, ring, | 481 | intel_ring_emit(dev, ring, |
529 | MI_BATCH_BUFFER_START | (2 << 6) | 482 | MI_BATCH_BUFFER_START | (2 << 6) |
530 | | MI_BATCH_NON_SECURE_I965); | 483 | | MI_BATCH_NON_SECURE_I965); |
@@ -553,7 +506,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev, | |||
553 | } | 506 | } |
554 | 507 | ||
555 | static void cleanup_status_page(struct drm_device *dev, | 508 | static void cleanup_status_page(struct drm_device *dev, |
556 | struct intel_ring_buffer *ring) | 509 | struct intel_ring_buffer *ring) |
557 | { | 510 | { |
558 | drm_i915_private_t *dev_priv = dev->dev_private; | 511 | drm_i915_private_t *dev_priv = dev->dev_private; |
559 | struct drm_gem_object *obj; | 512 | struct drm_gem_object *obj; |
@@ -573,7 +526,7 @@ static void cleanup_status_page(struct drm_device *dev, | |||
573 | } | 526 | } |
574 | 527 | ||
575 | static int init_status_page(struct drm_device *dev, | 528 | static int init_status_page(struct drm_device *dev, |
576 | struct intel_ring_buffer *ring) | 529 | struct intel_ring_buffer *ring) |
577 | { | 530 | { |
578 | drm_i915_private_t *dev_priv = dev->dev_private; | 531 | drm_i915_private_t *dev_priv = dev->dev_private; |
579 | struct drm_gem_object *obj; | 532 | struct drm_gem_object *obj; |
@@ -603,7 +556,7 @@ static int init_status_page(struct drm_device *dev, | |||
603 | ring->status_page.obj = obj; | 556 | ring->status_page.obj = obj; |
604 | memset(ring->status_page.page_addr, 0, PAGE_SIZE); | 557 | memset(ring->status_page.page_addr, 0, PAGE_SIZE); |
605 | 558 | ||
606 | ring->setup_status_page(dev, ring); | 559 | intel_ring_setup_status_page(dev, ring); |
607 | DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", | 560 | DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", |
608 | ring->name, ring->status_page.gfx_addr); | 561 | ring->name, ring->status_page.gfx_addr); |
609 | 562 | ||
@@ -617,15 +570,17 @@ err: | |||
617 | return ret; | 570 | return ret; |
618 | } | 571 | } |
619 | 572 | ||
620 | |||
621 | int intel_init_ring_buffer(struct drm_device *dev, | 573 | int intel_init_ring_buffer(struct drm_device *dev, |
622 | struct intel_ring_buffer *ring) | 574 | struct intel_ring_buffer *ring) |
623 | { | 575 | { |
576 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
624 | struct drm_i915_gem_object *obj_priv; | 577 | struct drm_i915_gem_object *obj_priv; |
625 | struct drm_gem_object *obj; | 578 | struct drm_gem_object *obj; |
626 | int ret; | 579 | int ret; |
627 | 580 | ||
628 | ring->dev = dev; | 581 | ring->dev = dev; |
582 | INIT_LIST_HEAD(&ring->active_list); | ||
583 | INIT_LIST_HEAD(&ring->request_list); | ||
629 | 584 | ||
630 | if (I915_NEED_GFX_HWS(dev)) { | 585 | if (I915_NEED_GFX_HWS(dev)) { |
631 | ret = init_status_page(dev, ring); | 586 | ret = init_status_page(dev, ring); |
@@ -642,7 +597,7 @@ int intel_init_ring_buffer(struct drm_device *dev, | |||
642 | 597 | ||
643 | ring->gem_object = obj; | 598 | ring->gem_object = obj; |
644 | 599 | ||
645 | ret = i915_gem_object_pin(obj, ring->alignment); | 600 | ret = i915_gem_object_pin(obj, PAGE_SIZE); |
646 | if (ret) | 601 | if (ret) |
647 | goto err_unref; | 602 | goto err_unref; |
648 | 603 | ||
@@ -668,14 +623,12 @@ int intel_init_ring_buffer(struct drm_device *dev, | |||
668 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 623 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
669 | i915_kernel_lost_context(dev); | 624 | i915_kernel_lost_context(dev); |
670 | else { | 625 | else { |
671 | ring->head = ring->get_head(dev, ring); | 626 | ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; |
672 | ring->tail = ring->get_tail(dev, ring); | 627 | ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; |
673 | ring->space = ring->head - (ring->tail + 8); | 628 | ring->space = ring->head - (ring->tail + 8); |
674 | if (ring->space < 0) | 629 | if (ring->space < 0) |
675 | ring->space += ring->size; | 630 | ring->space += ring->size; |
676 | } | 631 | } |
677 | INIT_LIST_HEAD(&ring->active_list); | ||
678 | INIT_LIST_HEAD(&ring->request_list); | ||
679 | return ret; | 632 | return ret; |
680 | 633 | ||
681 | err_unmap: | 634 | err_unmap: |
@@ -691,7 +644,7 @@ err_hws: | |||
691 | } | 644 | } |
692 | 645 | ||
693 | void intel_cleanup_ring_buffer(struct drm_device *dev, | 646 | void intel_cleanup_ring_buffer(struct drm_device *dev, |
694 | struct intel_ring_buffer *ring) | 647 | struct intel_ring_buffer *ring) |
695 | { | 648 | { |
696 | if (ring->gem_object == NULL) | 649 | if (ring->gem_object == NULL) |
697 | return; | 650 | return; |
@@ -704,8 +657,8 @@ void intel_cleanup_ring_buffer(struct drm_device *dev, | |||
704 | cleanup_status_page(dev, ring); | 657 | cleanup_status_page(dev, ring); |
705 | } | 658 | } |
706 | 659 | ||
707 | int intel_wrap_ring_buffer(struct drm_device *dev, | 660 | static int intel_wrap_ring_buffer(struct drm_device *dev, |
708 | struct intel_ring_buffer *ring) | 661 | struct intel_ring_buffer *ring) |
709 | { | 662 | { |
710 | unsigned int *virt; | 663 | unsigned int *virt; |
711 | int rem; | 664 | int rem; |
@@ -731,14 +684,15 @@ int intel_wrap_ring_buffer(struct drm_device *dev, | |||
731 | } | 684 | } |
732 | 685 | ||
733 | int intel_wait_ring_buffer(struct drm_device *dev, | 686 | int intel_wait_ring_buffer(struct drm_device *dev, |
734 | struct intel_ring_buffer *ring, int n) | 687 | struct intel_ring_buffer *ring, int n) |
735 | { | 688 | { |
736 | unsigned long end; | 689 | unsigned long end; |
690 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
737 | 691 | ||
738 | trace_i915_ring_wait_begin (dev); | 692 | trace_i915_ring_wait_begin (dev); |
739 | end = jiffies + 3 * HZ; | 693 | end = jiffies + 3 * HZ; |
740 | do { | 694 | do { |
741 | ring->head = ring->get_head(dev, ring); | 695 | ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; |
742 | ring->space = ring->head - (ring->tail + 8); | 696 | ring->space = ring->head - (ring->tail + 8); |
743 | if (ring->space < 0) | 697 | if (ring->space < 0) |
744 | ring->space += ring->size; | 698 | ring->space += ring->size; |
@@ -760,7 +714,8 @@ int intel_wait_ring_buffer(struct drm_device *dev, | |||
760 | } | 714 | } |
761 | 715 | ||
762 | void intel_ring_begin(struct drm_device *dev, | 716 | void intel_ring_begin(struct drm_device *dev, |
763 | struct intel_ring_buffer *ring, int num_dwords) | 717 | struct intel_ring_buffer *ring, |
718 | int num_dwords) | ||
764 | { | 719 | { |
765 | int n = 4*num_dwords; | 720 | int n = 4*num_dwords; |
766 | if (unlikely(ring->tail + n > ring->size)) | 721 | if (unlikely(ring->tail + n > ring->size)) |
@@ -772,16 +727,16 @@ void intel_ring_begin(struct drm_device *dev, | |||
772 | } | 727 | } |
773 | 728 | ||
774 | void intel_ring_advance(struct drm_device *dev, | 729 | void intel_ring_advance(struct drm_device *dev, |
775 | struct intel_ring_buffer *ring) | 730 | struct intel_ring_buffer *ring) |
776 | { | 731 | { |
777 | ring->tail &= ring->size - 1; | 732 | ring->tail &= ring->size - 1; |
778 | ring->advance_ring(dev, ring); | 733 | ring->set_tail(dev, ring, ring->tail); |
779 | } | 734 | } |
780 | 735 | ||
781 | void intel_fill_struct(struct drm_device *dev, | 736 | void intel_fill_struct(struct drm_device *dev, |
782 | struct intel_ring_buffer *ring, | 737 | struct intel_ring_buffer *ring, |
783 | void *data, | 738 | void *data, |
784 | unsigned int len) | 739 | unsigned int len) |
785 | { | 740 | { |
786 | unsigned int *virt = ring->virtual_start + ring->tail; | 741 | unsigned int *virt = ring->virtual_start + ring->tail; |
787 | BUG_ON((len&~(4-1)) != 0); | 742 | BUG_ON((len&~(4-1)) != 0); |
@@ -793,76 +748,136 @@ void intel_fill_struct(struct drm_device *dev, | |||
793 | intel_ring_advance(dev, ring); | 748 | intel_ring_advance(dev, ring); |
794 | } | 749 | } |
795 | 750 | ||
796 | struct intel_ring_buffer render_ring = { | 751 | static const struct intel_ring_buffer render_ring = { |
797 | .name = "render ring", | 752 | .name = "render ring", |
798 | .regs = { | 753 | .id = RING_RENDER, |
799 | .ctl = PRB0_CTL, | 754 | .mmio_base = RENDER_RING_BASE, |
800 | .head = PRB0_HEAD, | ||
801 | .tail = PRB0_TAIL, | ||
802 | .start = PRB0_START | ||
803 | }, | ||
804 | .ring_flag = I915_EXEC_RENDER, | ||
805 | .size = 32 * PAGE_SIZE, | 755 | .size = 32 * PAGE_SIZE, |
806 | .alignment = PAGE_SIZE, | ||
807 | .virtual_start = NULL, | ||
808 | .dev = NULL, | ||
809 | .gem_object = NULL, | ||
810 | .head = 0, | ||
811 | .tail = 0, | ||
812 | .space = 0, | ||
813 | .user_irq_refcount = 0, | ||
814 | .irq_gem_seqno = 0, | ||
815 | .waiting_gem_seqno = 0, | ||
816 | .setup_status_page = render_setup_status_page, | ||
817 | .init = init_render_ring, | 756 | .init = init_render_ring, |
818 | .get_head = render_ring_get_head, | 757 | .set_tail = ring_set_tail, |
819 | .get_tail = render_ring_get_tail, | ||
820 | .get_active_head = render_ring_get_active_head, | ||
821 | .advance_ring = render_ring_advance_ring, | ||
822 | .flush = render_ring_flush, | 758 | .flush = render_ring_flush, |
823 | .add_request = render_ring_add_request, | 759 | .add_request = render_ring_add_request, |
824 | .get_gem_seqno = render_ring_get_gem_seqno, | 760 | .get_seqno = render_ring_get_seqno, |
825 | .user_irq_get = render_ring_get_user_irq, | 761 | .user_irq_get = render_ring_get_user_irq, |
826 | .user_irq_put = render_ring_put_user_irq, | 762 | .user_irq_put = render_ring_put_user_irq, |
827 | .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer, | 763 | .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer, |
828 | .status_page = {NULL, 0, NULL}, | ||
829 | .map = {0,} | ||
830 | }; | 764 | }; |
831 | 765 | ||
832 | /* ring buffer for bit-stream decoder */ | 766 | /* ring buffer for bit-stream decoder */ |
833 | 767 | ||
834 | struct intel_ring_buffer bsd_ring = { | 768 | static const struct intel_ring_buffer bsd_ring = { |
835 | .name = "bsd ring", | 769 | .name = "bsd ring", |
836 | .regs = { | 770 | .id = RING_BSD, |
837 | .ctl = BSD_RING_CTL, | 771 | .mmio_base = BSD_RING_BASE, |
838 | .head = BSD_RING_HEAD, | ||
839 | .tail = BSD_RING_TAIL, | ||
840 | .start = BSD_RING_START | ||
841 | }, | ||
842 | .ring_flag = I915_EXEC_BSD, | ||
843 | .size = 32 * PAGE_SIZE, | 772 | .size = 32 * PAGE_SIZE, |
844 | .alignment = PAGE_SIZE, | ||
845 | .virtual_start = NULL, | ||
846 | .dev = NULL, | ||
847 | .gem_object = NULL, | ||
848 | .head = 0, | ||
849 | .tail = 0, | ||
850 | .space = 0, | ||
851 | .user_irq_refcount = 0, | ||
852 | .irq_gem_seqno = 0, | ||
853 | .waiting_gem_seqno = 0, | ||
854 | .setup_status_page = bsd_setup_status_page, | ||
855 | .init = init_bsd_ring, | 773 | .init = init_bsd_ring, |
856 | .get_head = bsd_ring_get_head, | 774 | .set_tail = ring_set_tail, |
857 | .get_tail = bsd_ring_get_tail, | ||
858 | .get_active_head = bsd_ring_get_active_head, | ||
859 | .advance_ring = bsd_ring_advance_ring, | ||
860 | .flush = bsd_ring_flush, | 775 | .flush = bsd_ring_flush, |
861 | .add_request = bsd_ring_add_request, | 776 | .add_request = bsd_ring_add_request, |
862 | .get_gem_seqno = bsd_ring_get_gem_seqno, | 777 | .get_seqno = bsd_ring_get_seqno, |
863 | .user_irq_get = bsd_ring_get_user_irq, | 778 | .user_irq_get = bsd_ring_get_user_irq, |
864 | .user_irq_put = bsd_ring_put_user_irq, | 779 | .user_irq_put = bsd_ring_put_user_irq, |
865 | .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer, | 780 | .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer, |
866 | .status_page = {NULL, 0, NULL}, | ||
867 | .map = {0,} | ||
868 | }; | 781 | }; |
782 | |||
783 | |||
784 | static void gen6_bsd_ring_set_tail(struct drm_device *dev, | ||
785 | struct intel_ring_buffer *ring, | ||
786 | u32 value) | ||
787 | { | ||
788 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
789 | |||
790 | /* Every tail move must follow the sequence below */ | ||
791 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, | ||
792 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | | ||
793 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); | ||
794 | I915_WRITE(GEN6_BSD_RNCID, 0x0); | ||
795 | |||
796 | if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & | ||
797 | GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, | ||
798 | 50)) | ||
799 | DRM_ERROR("timed out waiting for IDLE Indicator\n"); | ||
800 | |||
801 | I915_WRITE_TAIL(ring, value); | ||
802 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, | ||
803 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | | ||
804 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); | ||
805 | } | ||
806 | |||
807 | static void gen6_bsd_ring_flush(struct drm_device *dev, | ||
808 | struct intel_ring_buffer *ring, | ||
809 | u32 invalidate_domains, | ||
810 | u32 flush_domains) | ||
811 | { | ||
812 | intel_ring_begin(dev, ring, 4); | ||
813 | intel_ring_emit(dev, ring, MI_FLUSH_DW); | ||
814 | intel_ring_emit(dev, ring, 0); | ||
815 | intel_ring_emit(dev, ring, 0); | ||
816 | intel_ring_emit(dev, ring, 0); | ||
817 | intel_ring_advance(dev, ring); | ||
818 | } | ||
819 | |||
820 | static int | ||
821 | gen6_bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, | ||
822 | struct intel_ring_buffer *ring, | ||
823 | struct drm_i915_gem_execbuffer2 *exec, | ||
824 | struct drm_clip_rect *cliprects, | ||
825 | uint64_t exec_offset) | ||
826 | { | ||
827 | uint32_t exec_start; | ||
828 | |||
829 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; | ||
830 | |||
831 | intel_ring_begin(dev, ring, 2); | ||
832 | intel_ring_emit(dev, ring, | ||
833 | MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); | ||
834 | /* bit0-7 is the length on GEN6+ */ | ||
835 | intel_ring_emit(dev, ring, exec_start); | ||
836 | intel_ring_advance(dev, ring); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | /* ring buffer for Video Codec for Gen6+ */ | ||
842 | static const struct intel_ring_buffer gen6_bsd_ring = { | ||
843 | .name = "gen6 bsd ring", | ||
844 | .id = RING_BSD, | ||
845 | .mmio_base = GEN6_BSD_RING_BASE, | ||
846 | .size = 32 * PAGE_SIZE, | ||
847 | .init = init_bsd_ring, | ||
848 | .set_tail = gen6_bsd_ring_set_tail, | ||
849 | .flush = gen6_bsd_ring_flush, | ||
850 | .add_request = bsd_ring_add_request, | ||
851 | .get_seqno = bsd_ring_get_seqno, | ||
852 | .user_irq_get = bsd_ring_get_user_irq, | ||
853 | .user_irq_put = bsd_ring_put_user_irq, | ||
854 | .dispatch_gem_execbuffer = gen6_bsd_ring_dispatch_gem_execbuffer, | ||
855 | }; | ||
856 | |||
857 | int intel_init_render_ring_buffer(struct drm_device *dev) | ||
858 | { | ||
859 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
860 | |||
861 | dev_priv->render_ring = render_ring; | ||
862 | |||
863 | if (!I915_NEED_GFX_HWS(dev)) { | ||
864 | dev_priv->render_ring.status_page.page_addr | ||
865 | = dev_priv->status_page_dmah->vaddr; | ||
866 | memset(dev_priv->render_ring.status_page.page_addr, | ||
867 | 0, PAGE_SIZE); | ||
868 | } | ||
869 | |||
870 | return intel_init_ring_buffer(dev, &dev_priv->render_ring); | ||
871 | } | ||
872 | |||
873 | int intel_init_bsd_ring_buffer(struct drm_device *dev) | ||
874 | { | ||
875 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
876 | |||
877 | if (IS_GEN6(dev)) | ||
878 | dev_priv->bsd_ring = gen6_bsd_ring; | ||
879 | else | ||
880 | dev_priv->bsd_ring = bsd_ring; | ||
881 | |||
882 | return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); | ||
883 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 525e7d3edda8..9725f783db20 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -7,25 +7,31 @@ struct intel_hw_status_page { | |||
7 | struct drm_gem_object *obj; | 7 | struct drm_gem_object *obj; |
8 | }; | 8 | }; |
9 | 9 | ||
10 | #define I915_READ_TAIL(ring) I915_READ(RING_TAIL(ring->mmio_base)) | ||
11 | #define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL(ring->mmio_base), val) | ||
12 | #define I915_READ_START(ring) I915_READ(RING_START(ring->mmio_base)) | ||
13 | #define I915_WRITE_START(ring, val) I915_WRITE(RING_START(ring->mmio_base), val) | ||
14 | #define I915_READ_HEAD(ring) I915_READ(RING_HEAD(ring->mmio_base)) | ||
15 | #define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD(ring->mmio_base), val) | ||
16 | #define I915_READ_CTL(ring) I915_READ(RING_CTL(ring->mmio_base)) | ||
17 | #define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL(ring->mmio_base), val) | ||
18 | |||
10 | struct drm_i915_gem_execbuffer2; | 19 | struct drm_i915_gem_execbuffer2; |
11 | struct intel_ring_buffer { | 20 | struct intel_ring_buffer { |
12 | const char *name; | 21 | const char *name; |
13 | struct ring_regs { | 22 | enum intel_ring_id { |
14 | u32 ctl; | 23 | RING_RENDER = 0x1, |
15 | u32 head; | 24 | RING_BSD = 0x2, |
16 | u32 tail; | 25 | } id; |
17 | u32 start; | 26 | u32 mmio_base; |
18 | } regs; | ||
19 | unsigned int ring_flag; | ||
20 | unsigned long size; | 27 | unsigned long size; |
21 | unsigned int alignment; | ||
22 | void *virtual_start; | 28 | void *virtual_start; |
23 | struct drm_device *dev; | 29 | struct drm_device *dev; |
24 | struct drm_gem_object *gem_object; | 30 | struct drm_gem_object *gem_object; |
25 | 31 | ||
26 | unsigned int head; | 32 | unsigned int head; |
27 | unsigned int tail; | 33 | unsigned int tail; |
28 | unsigned int space; | 34 | int space; |
29 | struct intel_hw_status_page status_page; | 35 | struct intel_hw_status_page status_page; |
30 | 36 | ||
31 | u32 irq_gem_seqno; /* last seq seem at irq time */ | 37 | u32 irq_gem_seqno; /* last seq seem at irq time */ |
@@ -35,30 +41,22 @@ struct intel_ring_buffer { | |||
35 | struct intel_ring_buffer *ring); | 41 | struct intel_ring_buffer *ring); |
36 | void (*user_irq_put)(struct drm_device *dev, | 42 | void (*user_irq_put)(struct drm_device *dev, |
37 | struct intel_ring_buffer *ring); | 43 | struct intel_ring_buffer *ring); |
38 | void (*setup_status_page)(struct drm_device *dev, | ||
39 | struct intel_ring_buffer *ring); | ||
40 | 44 | ||
41 | int (*init)(struct drm_device *dev, | 45 | int (*init)(struct drm_device *dev, |
42 | struct intel_ring_buffer *ring); | 46 | struct intel_ring_buffer *ring); |
43 | 47 | ||
44 | unsigned int (*get_head)(struct drm_device *dev, | 48 | void (*set_tail)(struct drm_device *dev, |
45 | struct intel_ring_buffer *ring); | 49 | struct intel_ring_buffer *ring, |
46 | unsigned int (*get_tail)(struct drm_device *dev, | 50 | u32 value); |
47 | struct intel_ring_buffer *ring); | ||
48 | unsigned int (*get_active_head)(struct drm_device *dev, | ||
49 | struct intel_ring_buffer *ring); | ||
50 | void (*advance_ring)(struct drm_device *dev, | ||
51 | struct intel_ring_buffer *ring); | ||
52 | void (*flush)(struct drm_device *dev, | 51 | void (*flush)(struct drm_device *dev, |
53 | struct intel_ring_buffer *ring, | 52 | struct intel_ring_buffer *ring, |
54 | u32 invalidate_domains, | 53 | u32 invalidate_domains, |
55 | u32 flush_domains); | 54 | u32 flush_domains); |
56 | u32 (*add_request)(struct drm_device *dev, | 55 | u32 (*add_request)(struct drm_device *dev, |
57 | struct intel_ring_buffer *ring, | 56 | struct intel_ring_buffer *ring, |
58 | struct drm_file *file_priv, | ||
59 | u32 flush_domains); | 57 | u32 flush_domains); |
60 | u32 (*get_gem_seqno)(struct drm_device *dev, | 58 | u32 (*get_seqno)(struct drm_device *dev, |
61 | struct intel_ring_buffer *ring); | 59 | struct intel_ring_buffer *ring); |
62 | int (*dispatch_gem_execbuffer)(struct drm_device *dev, | 60 | int (*dispatch_gem_execbuffer)(struct drm_device *dev, |
63 | struct intel_ring_buffer *ring, | 61 | struct intel_ring_buffer *ring, |
64 | struct drm_i915_gem_execbuffer2 *exec, | 62 | struct drm_i915_gem_execbuffer2 *exec, |
@@ -83,6 +81,11 @@ struct intel_ring_buffer { | |||
83 | */ | 81 | */ |
84 | struct list_head request_list; | 82 | struct list_head request_list; |
85 | 83 | ||
84 | /** | ||
85 | * Do we have some not yet emitted requests outstanding? | ||
86 | */ | ||
87 | bool outstanding_lazy_request; | ||
88 | |||
86 | wait_queue_head_t irq_queue; | 89 | wait_queue_head_t irq_queue; |
87 | drm_local_map_t map; | 90 | drm_local_map_t map; |
88 | }; | 91 | }; |
@@ -96,15 +99,13 @@ intel_read_status_page(struct intel_ring_buffer *ring, | |||
96 | } | 99 | } |
97 | 100 | ||
98 | int intel_init_ring_buffer(struct drm_device *dev, | 101 | int intel_init_ring_buffer(struct drm_device *dev, |
99 | struct intel_ring_buffer *ring); | 102 | struct intel_ring_buffer *ring); |
100 | void intel_cleanup_ring_buffer(struct drm_device *dev, | 103 | void intel_cleanup_ring_buffer(struct drm_device *dev, |
101 | struct intel_ring_buffer *ring); | 104 | struct intel_ring_buffer *ring); |
102 | int intel_wait_ring_buffer(struct drm_device *dev, | 105 | int intel_wait_ring_buffer(struct drm_device *dev, |
103 | struct intel_ring_buffer *ring, int n); | 106 | struct intel_ring_buffer *ring, int n); |
104 | int intel_wrap_ring_buffer(struct drm_device *dev, | ||
105 | struct intel_ring_buffer *ring); | ||
106 | void intel_ring_begin(struct drm_device *dev, | 107 | void intel_ring_begin(struct drm_device *dev, |
107 | struct intel_ring_buffer *ring, int n); | 108 | struct intel_ring_buffer *ring, int n); |
108 | 109 | ||
109 | static inline void intel_ring_emit(struct drm_device *dev, | 110 | static inline void intel_ring_emit(struct drm_device *dev, |
110 | struct intel_ring_buffer *ring, | 111 | struct intel_ring_buffer *ring, |
@@ -125,7 +126,12 @@ void intel_ring_advance(struct drm_device *dev, | |||
125 | u32 intel_ring_get_seqno(struct drm_device *dev, | 126 | u32 intel_ring_get_seqno(struct drm_device *dev, |
126 | struct intel_ring_buffer *ring); | 127 | struct intel_ring_buffer *ring); |
127 | 128 | ||
128 | extern struct intel_ring_buffer render_ring; | 129 | int intel_init_render_ring_buffer(struct drm_device *dev); |
129 | extern struct intel_ring_buffer bsd_ring; | 130 | int intel_init_bsd_ring_buffer(struct drm_device *dev); |
131 | |||
132 | u32 intel_ring_get_active_head(struct drm_device *dev, | ||
133 | struct intel_ring_buffer *ring); | ||
134 | void intel_ring_setup_status_page(struct drm_device *dev, | ||
135 | struct intel_ring_buffer *ring); | ||
130 | 136 | ||
131 | #endif /* _INTEL_RINGBUFFER_H_ */ | 137 | #endif /* _INTEL_RINGBUFFER_H_ */ |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index ee73e428a84a..a84224f37605 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -65,8 +65,11 @@ static const char *tv_format_names[] = { | |||
65 | struct intel_sdvo { | 65 | struct intel_sdvo { |
66 | struct intel_encoder base; | 66 | struct intel_encoder base; |
67 | 67 | ||
68 | struct i2c_adapter *i2c; | ||
68 | u8 slave_addr; | 69 | u8 slave_addr; |
69 | 70 | ||
71 | struct i2c_adapter ddc; | ||
72 | |||
70 | /* Register for the SDVO device: SDVOB or SDVOC */ | 73 | /* Register for the SDVO device: SDVOB or SDVOC */ |
71 | int sdvo_reg; | 74 | int sdvo_reg; |
72 | 75 | ||
@@ -106,16 +109,12 @@ struct intel_sdvo { | |||
106 | bool is_hdmi; | 109 | bool is_hdmi; |
107 | 110 | ||
108 | /** | 111 | /** |
109 | * This is set if we detect output of sdvo device as LVDS. | 112 | * This is set if we detect output of sdvo device as LVDS and |
113 | * have a valid fixed mode to use with the panel. | ||
110 | */ | 114 | */ |
111 | bool is_lvds; | 115 | bool is_lvds; |
112 | 116 | ||
113 | /** | 117 | /** |
114 | * This is sdvo flags for input timing. | ||
115 | */ | ||
116 | uint8_t sdvo_flags; | ||
117 | |||
118 | /** | ||
119 | * This is sdvo fixed pannel mode pointer | 118 | * This is sdvo fixed pannel mode pointer |
120 | */ | 119 | */ |
121 | struct drm_display_mode *sdvo_lvds_fixed_mode; | 120 | struct drm_display_mode *sdvo_lvds_fixed_mode; |
@@ -129,9 +128,8 @@ struct intel_sdvo { | |||
129 | /* DDC bus used by this SDVO encoder */ | 128 | /* DDC bus used by this SDVO encoder */ |
130 | uint8_t ddc_bus; | 129 | uint8_t ddc_bus; |
131 | 130 | ||
132 | /* Mac mini hack -- use the same DDC as the analog connector */ | 131 | /* Input timings for adjusted_mode */ |
133 | struct i2c_adapter *analog_ddc_bus; | 132 | struct intel_sdvo_dtd input_dtd; |
134 | |||
135 | }; | 133 | }; |
136 | 134 | ||
137 | struct intel_sdvo_connector { | 135 | struct intel_sdvo_connector { |
@@ -186,9 +184,15 @@ struct intel_sdvo_connector { | |||
186 | u32 cur_dot_crawl, max_dot_crawl; | 184 | u32 cur_dot_crawl, max_dot_crawl; |
187 | }; | 185 | }; |
188 | 186 | ||
189 | static struct intel_sdvo *enc_to_intel_sdvo(struct drm_encoder *encoder) | 187 | static struct intel_sdvo *to_intel_sdvo(struct drm_encoder *encoder) |
188 | { | ||
189 | return container_of(encoder, struct intel_sdvo, base.base); | ||
190 | } | ||
191 | |||
192 | static struct intel_sdvo *intel_attached_sdvo(struct drm_connector *connector) | ||
190 | { | 193 | { |
191 | return container_of(enc_to_intel_encoder(encoder), struct intel_sdvo, base); | 194 | return container_of(intel_attached_encoder(connector), |
195 | struct intel_sdvo, base); | ||
192 | } | 196 | } |
193 | 197 | ||
194 | static struct intel_sdvo_connector *to_intel_sdvo_connector(struct drm_connector *connector) | 198 | static struct intel_sdvo_connector *to_intel_sdvo_connector(struct drm_connector *connector) |
@@ -213,7 +217,7 @@ intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, | |||
213 | */ | 217 | */ |
214 | static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) | 218 | static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) |
215 | { | 219 | { |
216 | struct drm_device *dev = intel_sdvo->base.enc.dev; | 220 | struct drm_device *dev = intel_sdvo->base.base.dev; |
217 | struct drm_i915_private *dev_priv = dev->dev_private; | 221 | struct drm_i915_private *dev_priv = dev->dev_private; |
218 | u32 bval = val, cval = val; | 222 | u32 bval = val, cval = val; |
219 | int i; | 223 | int i; |
@@ -245,49 +249,29 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) | |||
245 | 249 | ||
246 | static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) | 250 | static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) |
247 | { | 251 | { |
248 | u8 out_buf[2] = { addr, 0 }; | ||
249 | u8 buf[2]; | ||
250 | struct i2c_msg msgs[] = { | 252 | struct i2c_msg msgs[] = { |
251 | { | 253 | { |
252 | .addr = intel_sdvo->slave_addr >> 1, | 254 | .addr = intel_sdvo->slave_addr, |
253 | .flags = 0, | 255 | .flags = 0, |
254 | .len = 1, | 256 | .len = 1, |
255 | .buf = out_buf, | 257 | .buf = &addr, |
256 | }, | 258 | }, |
257 | { | 259 | { |
258 | .addr = intel_sdvo->slave_addr >> 1, | 260 | .addr = intel_sdvo->slave_addr, |
259 | .flags = I2C_M_RD, | 261 | .flags = I2C_M_RD, |
260 | .len = 1, | 262 | .len = 1, |
261 | .buf = buf, | 263 | .buf = ch, |
262 | } | 264 | } |
263 | }; | 265 | }; |
264 | int ret; | 266 | int ret; |
265 | 267 | ||
266 | if ((ret = i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 2)) == 2) | 268 | if ((ret = i2c_transfer(intel_sdvo->i2c, msgs, 2)) == 2) |
267 | { | ||
268 | *ch = buf[0]; | ||
269 | return true; | 269 | return true; |
270 | } | ||
271 | 270 | ||
272 | DRM_DEBUG_KMS("i2c transfer returned %d\n", ret); | 271 | DRM_DEBUG_KMS("i2c transfer returned %d\n", ret); |
273 | return false; | 272 | return false; |
274 | } | 273 | } |
275 | 274 | ||
276 | static bool intel_sdvo_write_byte(struct intel_sdvo *intel_sdvo, int addr, u8 ch) | ||
277 | { | ||
278 | u8 out_buf[2] = { addr, ch }; | ||
279 | struct i2c_msg msgs[] = { | ||
280 | { | ||
281 | .addr = intel_sdvo->slave_addr >> 1, | ||
282 | .flags = 0, | ||
283 | .len = 2, | ||
284 | .buf = out_buf, | ||
285 | } | ||
286 | }; | ||
287 | |||
288 | return i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 1) == 1; | ||
289 | } | ||
290 | |||
291 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} | 275 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} |
292 | /** Mapping of command numbers to names, for debug output */ | 276 | /** Mapping of command numbers to names, for debug output */ |
293 | static const struct _sdvo_cmd_name { | 277 | static const struct _sdvo_cmd_name { |
@@ -432,22 +416,6 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, | |||
432 | DRM_LOG_KMS("\n"); | 416 | DRM_LOG_KMS("\n"); |
433 | } | 417 | } |
434 | 418 | ||
435 | static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, | ||
436 | const void *args, int args_len) | ||
437 | { | ||
438 | int i; | ||
439 | |||
440 | intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); | ||
441 | |||
442 | for (i = 0; i < args_len; i++) { | ||
443 | if (!intel_sdvo_write_byte(intel_sdvo, SDVO_I2C_ARG_0 - i, | ||
444 | ((u8*)args)[i])) | ||
445 | return false; | ||
446 | } | ||
447 | |||
448 | return intel_sdvo_write_byte(intel_sdvo, SDVO_I2C_OPCODE, cmd); | ||
449 | } | ||
450 | |||
451 | static const char *cmd_status_names[] = { | 419 | static const char *cmd_status_names[] = { |
452 | "Power on", | 420 | "Power on", |
453 | "Success", | 421 | "Success", |
@@ -458,54 +426,115 @@ static const char *cmd_status_names[] = { | |||
458 | "Scaling not supported" | 426 | "Scaling not supported" |
459 | }; | 427 | }; |
460 | 428 | ||
461 | static void intel_sdvo_debug_response(struct intel_sdvo *intel_sdvo, | 429 | static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, |
462 | void *response, int response_len, | 430 | const void *args, int args_len) |
463 | u8 status) | ||
464 | { | 431 | { |
465 | int i; | 432 | u8 buf[args_len*2 + 2], status; |
433 | struct i2c_msg msgs[args_len + 3]; | ||
434 | int i, ret; | ||
466 | 435 | ||
467 | DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); | 436 | intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); |
468 | for (i = 0; i < response_len; i++) | 437 | |
469 | DRM_LOG_KMS("%02X ", ((u8 *)response)[i]); | 438 | for (i = 0; i < args_len; i++) { |
470 | for (; i < 8; i++) | 439 | msgs[i].addr = intel_sdvo->slave_addr; |
471 | DRM_LOG_KMS(" "); | 440 | msgs[i].flags = 0; |
472 | if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) | 441 | msgs[i].len = 2; |
473 | DRM_LOG_KMS("(%s)", cmd_status_names[status]); | 442 | msgs[i].buf = buf + 2 *i; |
474 | else | 443 | buf[2*i + 0] = SDVO_I2C_ARG_0 - i; |
475 | DRM_LOG_KMS("(??? %d)", status); | 444 | buf[2*i + 1] = ((u8*)args)[i]; |
476 | DRM_LOG_KMS("\n"); | 445 | } |
446 | msgs[i].addr = intel_sdvo->slave_addr; | ||
447 | msgs[i].flags = 0; | ||
448 | msgs[i].len = 2; | ||
449 | msgs[i].buf = buf + 2*i; | ||
450 | buf[2*i + 0] = SDVO_I2C_OPCODE; | ||
451 | buf[2*i + 1] = cmd; | ||
452 | |||
453 | /* the following two are to read the response */ | ||
454 | status = SDVO_I2C_CMD_STATUS; | ||
455 | msgs[i+1].addr = intel_sdvo->slave_addr; | ||
456 | msgs[i+1].flags = 0; | ||
457 | msgs[i+1].len = 1; | ||
458 | msgs[i+1].buf = &status; | ||
459 | |||
460 | msgs[i+2].addr = intel_sdvo->slave_addr; | ||
461 | msgs[i+2].flags = I2C_M_RD; | ||
462 | msgs[i+2].len = 1; | ||
463 | msgs[i+2].buf = &status; | ||
464 | |||
465 | ret = i2c_transfer(intel_sdvo->i2c, msgs, i+3); | ||
466 | if (ret < 0) { | ||
467 | DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); | ||
468 | return false; | ||
469 | } | ||
470 | if (ret != i+3) { | ||
471 | /* failure in I2C transfer */ | ||
472 | DRM_DEBUG_KMS("I2c transfer returned %d/%d\n", ret, i+3); | ||
473 | return false; | ||
474 | } | ||
475 | |||
476 | i = 3; | ||
477 | while (status == SDVO_CMD_STATUS_PENDING && i--) { | ||
478 | if (!intel_sdvo_read_byte(intel_sdvo, | ||
479 | SDVO_I2C_CMD_STATUS, | ||
480 | &status)) | ||
481 | return false; | ||
482 | } | ||
483 | if (status != SDVO_CMD_STATUS_SUCCESS) { | ||
484 | DRM_DEBUG_KMS("command returns response %s [%d]\n", | ||
485 | status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP ? cmd_status_names[status] : "???", | ||
486 | status); | ||
487 | return false; | ||
488 | } | ||
489 | |||
490 | return true; | ||
477 | } | 491 | } |
478 | 492 | ||
479 | static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, | 493 | static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, |
480 | void *response, int response_len) | 494 | void *response, int response_len) |
481 | { | 495 | { |
482 | int i; | 496 | u8 retry = 5; |
483 | u8 status; | 497 | u8 status; |
484 | u8 retry = 50; | 498 | int i; |
485 | |||
486 | while (retry--) { | ||
487 | /* Read the command response */ | ||
488 | for (i = 0; i < response_len; i++) { | ||
489 | if (!intel_sdvo_read_byte(intel_sdvo, | ||
490 | SDVO_I2C_RETURN_0 + i, | ||
491 | &((u8 *)response)[i])) | ||
492 | return false; | ||
493 | } | ||
494 | 499 | ||
495 | /* read the return status */ | 500 | /* |
496 | if (!intel_sdvo_read_byte(intel_sdvo, SDVO_I2C_CMD_STATUS, | 501 | * The documentation states that all commands will be |
502 | * processed within 15µs, and that we need only poll | ||
503 | * the status byte a maximum of 3 times in order for the | ||
504 | * command to be complete. | ||
505 | * | ||
506 | * Check 5 times in case the hardware failed to read the docs. | ||
507 | */ | ||
508 | do { | ||
509 | if (!intel_sdvo_read_byte(intel_sdvo, | ||
510 | SDVO_I2C_CMD_STATUS, | ||
497 | &status)) | 511 | &status)) |
498 | return false; | 512 | return false; |
513 | } while (status == SDVO_CMD_STATUS_PENDING && --retry); | ||
499 | 514 | ||
500 | intel_sdvo_debug_response(intel_sdvo, response, response_len, | 515 | DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); |
501 | status); | 516 | if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) |
502 | if (status != SDVO_CMD_STATUS_PENDING) | 517 | DRM_LOG_KMS("(%s)", cmd_status_names[status]); |
503 | break; | 518 | else |
519 | DRM_LOG_KMS("(??? %d)", status); | ||
504 | 520 | ||
505 | mdelay(50); | 521 | if (status != SDVO_CMD_STATUS_SUCCESS) |
522 | goto log_fail; | ||
523 | |||
524 | /* Read the command response */ | ||
525 | for (i = 0; i < response_len; i++) { | ||
526 | if (!intel_sdvo_read_byte(intel_sdvo, | ||
527 | SDVO_I2C_RETURN_0 + i, | ||
528 | &((u8 *)response)[i])) | ||
529 | goto log_fail; | ||
530 | DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); | ||
506 | } | 531 | } |
532 | DRM_LOG_KMS("\n"); | ||
533 | return true; | ||
507 | 534 | ||
508 | return status == SDVO_CMD_STATUS_SUCCESS; | 535 | log_fail: |
536 | DRM_LOG_KMS("\n"); | ||
537 | return false; | ||
509 | } | 538 | } |
510 | 539 | ||
511 | static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) | 540 | static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) |
@@ -518,71 +547,17 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) | |||
518 | return 4; | 547 | return 4; |
519 | } | 548 | } |
520 | 549 | ||
521 | /** | 550 | static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo, |
522 | * Try to read the response after issuie the DDC switch command. But it | 551 | u8 ddc_bus) |
523 | * is noted that we must do the action of reading response and issuing DDC | ||
524 | * switch command in one I2C transaction. Otherwise when we try to start | ||
525 | * another I2C transaction after issuing the DDC bus switch, it will be | ||
526 | * switched to the internal SDVO register. | ||
527 | */ | ||
528 | static void intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo, | ||
529 | u8 target) | ||
530 | { | 552 | { |
531 | u8 out_buf[2], cmd_buf[2], ret_value[2], ret; | 553 | return intel_sdvo_write_cmd(intel_sdvo, |
532 | struct i2c_msg msgs[] = { | 554 | SDVO_CMD_SET_CONTROL_BUS_SWITCH, |
533 | { | 555 | &ddc_bus, 1); |
534 | .addr = intel_sdvo->slave_addr >> 1, | ||
535 | .flags = 0, | ||
536 | .len = 2, | ||
537 | .buf = out_buf, | ||
538 | }, | ||
539 | /* the following two are to read the response */ | ||
540 | { | ||
541 | .addr = intel_sdvo->slave_addr >> 1, | ||
542 | .flags = 0, | ||
543 | .len = 1, | ||
544 | .buf = cmd_buf, | ||
545 | }, | ||
546 | { | ||
547 | .addr = intel_sdvo->slave_addr >> 1, | ||
548 | .flags = I2C_M_RD, | ||
549 | .len = 1, | ||
550 | .buf = ret_value, | ||
551 | }, | ||
552 | }; | ||
553 | |||
554 | intel_sdvo_debug_write(intel_sdvo, SDVO_CMD_SET_CONTROL_BUS_SWITCH, | ||
555 | &target, 1); | ||
556 | /* write the DDC switch command argument */ | ||
557 | intel_sdvo_write_byte(intel_sdvo, SDVO_I2C_ARG_0, target); | ||
558 | |||
559 | out_buf[0] = SDVO_I2C_OPCODE; | ||
560 | out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; | ||
561 | cmd_buf[0] = SDVO_I2C_CMD_STATUS; | ||
562 | cmd_buf[1] = 0; | ||
563 | ret_value[0] = 0; | ||
564 | ret_value[1] = 0; | ||
565 | |||
566 | ret = i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 3); | ||
567 | if (ret != 3) { | ||
568 | /* failure in I2C transfer */ | ||
569 | DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); | ||
570 | return; | ||
571 | } | ||
572 | if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { | ||
573 | DRM_DEBUG_KMS("DDC switch command returns response %d\n", | ||
574 | ret_value[0]); | ||
575 | return; | ||
576 | } | ||
577 | return; | ||
578 | } | 556 | } |
579 | 557 | ||
580 | static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len) | 558 | static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len) |
581 | { | 559 | { |
582 | if (!intel_sdvo_write_cmd(intel_sdvo, cmd, data, len)) | 560 | return intel_sdvo_write_cmd(intel_sdvo, cmd, data, len); |
583 | return false; | ||
584 | |||
585 | return intel_sdvo_read_response(intel_sdvo, NULL, 0); | ||
586 | } | 561 | } |
587 | 562 | ||
588 | static bool | 563 | static bool |
@@ -1022,8 +997,6 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, | |||
1022 | struct drm_display_mode *mode, | 997 | struct drm_display_mode *mode, |
1023 | struct drm_display_mode *adjusted_mode) | 998 | struct drm_display_mode *adjusted_mode) |
1024 | { | 999 | { |
1025 | struct intel_sdvo_dtd input_dtd; | ||
1026 | |||
1027 | /* Reset the input timing to the screen. Assume always input 0. */ | 1000 | /* Reset the input timing to the screen. Assume always input 0. */ |
1028 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 1001 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
1029 | return false; | 1002 | return false; |
@@ -1035,14 +1008,12 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, | |||
1035 | return false; | 1008 | return false; |
1036 | 1009 | ||
1037 | if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, | 1010 | if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, |
1038 | &input_dtd)) | 1011 | &intel_sdvo->input_dtd)) |
1039 | return false; | 1012 | return false; |
1040 | 1013 | ||
1041 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | 1014 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); |
1042 | intel_sdvo->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
1043 | 1015 | ||
1044 | drm_mode_set_crtcinfo(adjusted_mode, 0); | 1016 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
1045 | mode->clock = adjusted_mode->clock; | ||
1046 | return true; | 1017 | return true; |
1047 | } | 1018 | } |
1048 | 1019 | ||
@@ -1050,7 +1021,8 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
1050 | struct drm_display_mode *mode, | 1021 | struct drm_display_mode *mode, |
1051 | struct drm_display_mode *adjusted_mode) | 1022 | struct drm_display_mode *adjusted_mode) |
1052 | { | 1023 | { |
1053 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | 1024 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); |
1025 | int multiplier; | ||
1054 | 1026 | ||
1055 | /* We need to construct preferred input timings based on our | 1027 | /* We need to construct preferred input timings based on our |
1056 | * output timings. To do that, we have to set the output | 1028 | * output timings. To do that, we have to set the output |
@@ -1065,10 +1037,8 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
1065 | mode, | 1037 | mode, |
1066 | adjusted_mode); | 1038 | adjusted_mode); |
1067 | } else if (intel_sdvo->is_lvds) { | 1039 | } else if (intel_sdvo->is_lvds) { |
1068 | drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0); | ||
1069 | |||
1070 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, | 1040 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, |
1071 | intel_sdvo->sdvo_lvds_fixed_mode)) | 1041 | intel_sdvo->sdvo_lvds_fixed_mode)) |
1072 | return false; | 1042 | return false; |
1073 | 1043 | ||
1074 | (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, | 1044 | (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, |
@@ -1077,9 +1047,10 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
1077 | } | 1047 | } |
1078 | 1048 | ||
1079 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | 1049 | /* Make the CRTC code factor in the SDVO pixel multiplier. The |
1080 | * SDVO device will be told of the multiplier during mode_set. | 1050 | * SDVO device will factor out the multiplier during mode_set. |
1081 | */ | 1051 | */ |
1082 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | 1052 | multiplier = intel_sdvo_get_pixel_multiplier(adjusted_mode); |
1053 | intel_mode_set_pixel_multiplier(adjusted_mode, multiplier); | ||
1083 | 1054 | ||
1084 | return true; | 1055 | return true; |
1085 | } | 1056 | } |
@@ -1092,11 +1063,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
1092 | struct drm_i915_private *dev_priv = dev->dev_private; | 1063 | struct drm_i915_private *dev_priv = dev->dev_private; |
1093 | struct drm_crtc *crtc = encoder->crtc; | 1064 | struct drm_crtc *crtc = encoder->crtc; |
1094 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1065 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1095 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | 1066 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); |
1096 | u32 sdvox = 0; | 1067 | u32 sdvox; |
1097 | int sdvo_pixel_multiply, rate; | ||
1098 | struct intel_sdvo_in_out_map in_out; | 1068 | struct intel_sdvo_in_out_map in_out; |
1099 | struct intel_sdvo_dtd input_dtd; | 1069 | struct intel_sdvo_dtd input_dtd; |
1070 | int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
1071 | int rate; | ||
1100 | 1072 | ||
1101 | if (!mode) | 1073 | if (!mode) |
1102 | return; | 1074 | return; |
@@ -1114,28 +1086,23 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
1114 | SDVO_CMD_SET_IN_OUT_MAP, | 1086 | SDVO_CMD_SET_IN_OUT_MAP, |
1115 | &in_out, sizeof(in_out)); | 1087 | &in_out, sizeof(in_out)); |
1116 | 1088 | ||
1117 | if (intel_sdvo->is_hdmi) { | 1089 | /* Set the output timings to the screen */ |
1118 | if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) | 1090 | if (!intel_sdvo_set_target_output(intel_sdvo, |
1119 | return; | 1091 | intel_sdvo->attached_output)) |
1120 | 1092 | return; | |
1121 | sdvox |= SDVO_AUDIO_ENABLE; | ||
1122 | } | ||
1123 | 1093 | ||
1124 | /* We have tried to get input timing in mode_fixup, and filled into | 1094 | /* We have tried to get input timing in mode_fixup, and filled into |
1125 | adjusted_mode */ | 1095 | * adjusted_mode. |
1126 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | ||
1127 | if (intel_sdvo->is_tv || intel_sdvo->is_lvds) | ||
1128 | input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; | ||
1129 | |||
1130 | /* If it's a TV, we already set the output timing in mode_fixup. | ||
1131 | * Otherwise, the output timing is equal to the input timing. | ||
1132 | */ | 1096 | */ |
1133 | if (!intel_sdvo->is_tv && !intel_sdvo->is_lvds) { | 1097 | if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { |
1098 | input_dtd = intel_sdvo->input_dtd; | ||
1099 | } else { | ||
1134 | /* Set the output timing to the screen */ | 1100 | /* Set the output timing to the screen */ |
1135 | if (!intel_sdvo_set_target_output(intel_sdvo, | 1101 | if (!intel_sdvo_set_target_output(intel_sdvo, |
1136 | intel_sdvo->attached_output)) | 1102 | intel_sdvo->attached_output)) |
1137 | return; | 1103 | return; |
1138 | 1104 | ||
1105 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | ||
1139 | (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); | 1106 | (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); |
1140 | } | 1107 | } |
1141 | 1108 | ||
@@ -1143,31 +1110,18 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
1143 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 1110 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
1144 | return; | 1111 | return; |
1145 | 1112 | ||
1146 | if (intel_sdvo->is_tv) { | 1113 | if (intel_sdvo->is_hdmi && |
1147 | if (!intel_sdvo_set_tv_format(intel_sdvo)) | 1114 | !intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) |
1148 | return; | 1115 | return; |
1149 | } | ||
1150 | 1116 | ||
1151 | /* We would like to use intel_sdvo_create_preferred_input_timing() to | 1117 | if (intel_sdvo->is_tv && |
1152 | * provide the device with a timing it can support, if it supports that | 1118 | !intel_sdvo_set_tv_format(intel_sdvo)) |
1153 | * feature. However, presumably we would need to adjust the CRTC to | 1119 | return; |
1154 | * output the preferred timing, and we don't support that currently. | ||
1155 | */ | ||
1156 | #if 0 | ||
1157 | success = intel_sdvo_create_preferred_input_timing(encoder, clock, | ||
1158 | width, height); | ||
1159 | if (success) { | ||
1160 | struct intel_sdvo_dtd *input_dtd; | ||
1161 | 1120 | ||
1162 | intel_sdvo_get_preferred_input_timing(encoder, &input_dtd); | ||
1163 | intel_sdvo_set_input_timing(encoder, &input_dtd); | ||
1164 | } | ||
1165 | #else | ||
1166 | (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); | 1121 | (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); |
1167 | #endif | ||
1168 | 1122 | ||
1169 | sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); | 1123 | switch (pixel_multiplier) { |
1170 | switch (sdvo_pixel_multiply) { | 1124 | default: |
1171 | case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; | 1125 | case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; |
1172 | case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; | 1126 | case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; |
1173 | case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; | 1127 | case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; |
@@ -1176,14 +1130,14 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
1176 | return; | 1130 | return; |
1177 | 1131 | ||
1178 | /* Set the SDVO control regs. */ | 1132 | /* Set the SDVO control regs. */ |
1179 | if (IS_I965G(dev)) { | 1133 | if (INTEL_INFO(dev)->gen >= 4) { |
1180 | sdvox |= SDVO_BORDER_ENABLE; | 1134 | sdvox = SDVO_BORDER_ENABLE; |
1181 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 1135 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
1182 | sdvox |= SDVO_VSYNC_ACTIVE_HIGH; | 1136 | sdvox |= SDVO_VSYNC_ACTIVE_HIGH; |
1183 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 1137 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
1184 | sdvox |= SDVO_HSYNC_ACTIVE_HIGH; | 1138 | sdvox |= SDVO_HSYNC_ACTIVE_HIGH; |
1185 | } else { | 1139 | } else { |
1186 | sdvox |= I915_READ(intel_sdvo->sdvo_reg); | 1140 | sdvox = I915_READ(intel_sdvo->sdvo_reg); |
1187 | switch (intel_sdvo->sdvo_reg) { | 1141 | switch (intel_sdvo->sdvo_reg) { |
1188 | case SDVOB: | 1142 | case SDVOB: |
1189 | sdvox &= SDVOB_PRESERVE_MASK; | 1143 | sdvox &= SDVOB_PRESERVE_MASK; |
@@ -1196,16 +1150,18 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
1196 | } | 1150 | } |
1197 | if (intel_crtc->pipe == 1) | 1151 | if (intel_crtc->pipe == 1) |
1198 | sdvox |= SDVO_PIPE_B_SELECT; | 1152 | sdvox |= SDVO_PIPE_B_SELECT; |
1153 | if (intel_sdvo->is_hdmi) | ||
1154 | sdvox |= SDVO_AUDIO_ENABLE; | ||
1199 | 1155 | ||
1200 | if (IS_I965G(dev)) { | 1156 | if (INTEL_INFO(dev)->gen >= 4) { |
1201 | /* done in crtc_mode_set as the dpll_md reg must be written early */ | 1157 | /* done in crtc_mode_set as the dpll_md reg must be written early */ |
1202 | } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { | 1158 | } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { |
1203 | /* done in crtc_mode_set as it lives inside the dpll register */ | 1159 | /* done in crtc_mode_set as it lives inside the dpll register */ |
1204 | } else { | 1160 | } else { |
1205 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; | 1161 | sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT; |
1206 | } | 1162 | } |
1207 | 1163 | ||
1208 | if (intel_sdvo->sdvo_flags & SDVO_NEED_TO_STALL) | 1164 | if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL) |
1209 | sdvox |= SDVO_STALL_SELECT; | 1165 | sdvox |= SDVO_STALL_SELECT; |
1210 | intel_sdvo_write_sdvox(intel_sdvo, sdvox); | 1166 | intel_sdvo_write_sdvox(intel_sdvo, sdvox); |
1211 | } | 1167 | } |
@@ -1214,7 +1170,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) | |||
1214 | { | 1170 | { |
1215 | struct drm_device *dev = encoder->dev; | 1171 | struct drm_device *dev = encoder->dev; |
1216 | struct drm_i915_private *dev_priv = dev->dev_private; | 1172 | struct drm_i915_private *dev_priv = dev->dev_private; |
1217 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | 1173 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); |
1218 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 1174 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
1219 | u32 temp; | 1175 | u32 temp; |
1220 | 1176 | ||
@@ -1260,8 +1216,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) | |||
1260 | static int intel_sdvo_mode_valid(struct drm_connector *connector, | 1216 | static int intel_sdvo_mode_valid(struct drm_connector *connector, |
1261 | struct drm_display_mode *mode) | 1217 | struct drm_display_mode *mode) |
1262 | { | 1218 | { |
1263 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1219 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1264 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | ||
1265 | 1220 | ||
1266 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 1221 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
1267 | return MODE_NO_DBLESCAN; | 1222 | return MODE_NO_DBLESCAN; |
@@ -1285,7 +1240,38 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, | |||
1285 | 1240 | ||
1286 | static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps) | 1241 | static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps) |
1287 | { | 1242 | { |
1288 | return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_DEVICE_CAPS, caps, sizeof(*caps)); | 1243 | if (!intel_sdvo_get_value(intel_sdvo, |
1244 | SDVO_CMD_GET_DEVICE_CAPS, | ||
1245 | caps, sizeof(*caps))) | ||
1246 | return false; | ||
1247 | |||
1248 | DRM_DEBUG_KMS("SDVO capabilities:\n" | ||
1249 | " vendor_id: %d\n" | ||
1250 | " device_id: %d\n" | ||
1251 | " device_rev_id: %d\n" | ||
1252 | " sdvo_version_major: %d\n" | ||
1253 | " sdvo_version_minor: %d\n" | ||
1254 | " sdvo_inputs_mask: %d\n" | ||
1255 | " smooth_scaling: %d\n" | ||
1256 | " sharp_scaling: %d\n" | ||
1257 | " up_scaling: %d\n" | ||
1258 | " down_scaling: %d\n" | ||
1259 | " stall_support: %d\n" | ||
1260 | " output_flags: %d\n", | ||
1261 | caps->vendor_id, | ||
1262 | caps->device_id, | ||
1263 | caps->device_rev_id, | ||
1264 | caps->sdvo_version_major, | ||
1265 | caps->sdvo_version_minor, | ||
1266 | caps->sdvo_inputs_mask, | ||
1267 | caps->smooth_scaling, | ||
1268 | caps->sharp_scaling, | ||
1269 | caps->up_scaling, | ||
1270 | caps->down_scaling, | ||
1271 | caps->stall_support, | ||
1272 | caps->output_flags); | ||
1273 | |||
1274 | return true; | ||
1289 | } | 1275 | } |
1290 | 1276 | ||
1291 | /* No use! */ | 1277 | /* No use! */ |
@@ -1389,22 +1375,33 @@ intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) | |||
1389 | return (caps > 1); | 1375 | return (caps > 1); |
1390 | } | 1376 | } |
1391 | 1377 | ||
1378 | static struct edid * | ||
1379 | intel_sdvo_get_edid(struct drm_connector *connector) | ||
1380 | { | ||
1381 | struct intel_sdvo *sdvo = intel_attached_sdvo(connector); | ||
1382 | return drm_get_edid(connector, &sdvo->ddc); | ||
1383 | } | ||
1384 | |||
1392 | static struct drm_connector * | 1385 | static struct drm_connector * |
1393 | intel_find_analog_connector(struct drm_device *dev) | 1386 | intel_find_analog_connector(struct drm_device *dev) |
1394 | { | 1387 | { |
1395 | struct drm_connector *connector; | 1388 | struct drm_connector *connector; |
1396 | struct drm_encoder *encoder; | 1389 | struct intel_sdvo *encoder; |
1397 | struct intel_sdvo *intel_sdvo; | 1390 | |
1398 | 1391 | list_for_each_entry(encoder, | |
1399 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 1392 | &dev->mode_config.encoder_list, |
1400 | intel_sdvo = enc_to_intel_sdvo(encoder); | 1393 | base.base.head) { |
1401 | if (intel_sdvo->base.type == INTEL_OUTPUT_ANALOG) { | 1394 | if (encoder->base.type == INTEL_OUTPUT_ANALOG) { |
1402 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 1395 | list_for_each_entry(connector, |
1403 | if (encoder == intel_attached_encoder(connector)) | 1396 | &dev->mode_config.connector_list, |
1397 | head) { | ||
1398 | if (&encoder->base == | ||
1399 | intel_attached_encoder(connector)) | ||
1404 | return connector; | 1400 | return connector; |
1405 | } | 1401 | } |
1406 | } | 1402 | } |
1407 | } | 1403 | } |
1404 | |||
1408 | return NULL; | 1405 | return NULL; |
1409 | } | 1406 | } |
1410 | 1407 | ||
@@ -1424,65 +1421,66 @@ intel_analog_is_connected(struct drm_device *dev) | |||
1424 | return true; | 1421 | return true; |
1425 | } | 1422 | } |
1426 | 1423 | ||
1424 | /* Mac mini hack -- use the same DDC as the analog connector */ | ||
1425 | static struct edid * | ||
1426 | intel_sdvo_get_analog_edid(struct drm_connector *connector) | ||
1427 | { | ||
1428 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
1429 | |||
1430 | if (!intel_analog_is_connected(connector->dev)) | ||
1431 | return NULL; | ||
1432 | |||
1433 | return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); | ||
1434 | } | ||
1435 | |||
1427 | enum drm_connector_status | 1436 | enum drm_connector_status |
1428 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | 1437 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) |
1429 | { | 1438 | { |
1430 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1439 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1431 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | 1440 | enum drm_connector_status status; |
1432 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1441 | struct edid *edid; |
1433 | enum drm_connector_status status = connector_status_connected; | ||
1434 | struct edid *edid = NULL; | ||
1435 | 1442 | ||
1436 | edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus); | 1443 | edid = intel_sdvo_get_edid(connector); |
1437 | 1444 | ||
1438 | /* This is only applied to SDVO cards with multiple outputs */ | ||
1439 | if (edid == NULL && intel_sdvo_multifunc_encoder(intel_sdvo)) { | 1445 | if (edid == NULL && intel_sdvo_multifunc_encoder(intel_sdvo)) { |
1440 | uint8_t saved_ddc, temp_ddc; | 1446 | u8 ddc, saved_ddc = intel_sdvo->ddc_bus; |
1441 | saved_ddc = intel_sdvo->ddc_bus; | 1447 | |
1442 | temp_ddc = intel_sdvo->ddc_bus >> 1; | ||
1443 | /* | 1448 | /* |
1444 | * Don't use the 1 as the argument of DDC bus switch to get | 1449 | * Don't use the 1 as the argument of DDC bus switch to get |
1445 | * the EDID. It is used for SDVO SPD ROM. | 1450 | * the EDID. It is used for SDVO SPD ROM. |
1446 | */ | 1451 | */ |
1447 | while(temp_ddc > 1) { | 1452 | for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) { |
1448 | intel_sdvo->ddc_bus = temp_ddc; | 1453 | intel_sdvo->ddc_bus = ddc; |
1449 | edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus); | 1454 | edid = intel_sdvo_get_edid(connector); |
1450 | if (edid) { | 1455 | if (edid) |
1451 | /* | ||
1452 | * When we can get the EDID, maybe it is the | ||
1453 | * correct DDC bus. Update it. | ||
1454 | */ | ||
1455 | intel_sdvo->ddc_bus = temp_ddc; | ||
1456 | break; | 1456 | break; |
1457 | } | ||
1458 | temp_ddc >>= 1; | ||
1459 | } | 1457 | } |
1458 | /* | ||
1459 | * If we found the EDID on the other bus, | ||
1460 | * assume that is the correct DDC bus. | ||
1461 | */ | ||
1460 | if (edid == NULL) | 1462 | if (edid == NULL) |
1461 | intel_sdvo->ddc_bus = saved_ddc; | 1463 | intel_sdvo->ddc_bus = saved_ddc; |
1462 | } | 1464 | } |
1463 | /* when there is no edid and no monitor is connected with VGA | 1465 | |
1464 | * port, try to use the CRT ddc to read the EDID for DVI-connector | 1466 | /* |
1467 | * When there is no edid and no monitor is connected with VGA | ||
1468 | * port, try to use the CRT ddc to read the EDID for DVI-connector. | ||
1465 | */ | 1469 | */ |
1466 | if (edid == NULL && intel_sdvo->analog_ddc_bus && | 1470 | if (edid == NULL) |
1467 | !intel_analog_is_connected(connector->dev)) | 1471 | edid = intel_sdvo_get_analog_edid(connector); |
1468 | edid = drm_get_edid(connector, intel_sdvo->analog_ddc_bus); | ||
1469 | 1472 | ||
1473 | status = connector_status_unknown; | ||
1470 | if (edid != NULL) { | 1474 | if (edid != NULL) { |
1471 | bool is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); | ||
1472 | bool need_digital = !!(intel_sdvo_connector->output_flag & SDVO_TMDS_MASK); | ||
1473 | |||
1474 | /* DDC bus is shared, match EDID to connector type */ | 1475 | /* DDC bus is shared, match EDID to connector type */ |
1475 | if (is_digital && need_digital) | 1476 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
1477 | status = connector_status_connected; | ||
1476 | intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid); | 1478 | intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid); |
1477 | else if (is_digital != need_digital) | 1479 | } |
1478 | status = connector_status_disconnected; | ||
1479 | |||
1480 | connector->display_info.raw_edid = NULL; | 1480 | connector->display_info.raw_edid = NULL; |
1481 | } else | 1481 | kfree(edid); |
1482 | status = connector_status_disconnected; | 1482 | } |
1483 | 1483 | ||
1484 | kfree(edid); | ||
1485 | |||
1486 | return status; | 1484 | return status; |
1487 | } | 1485 | } |
1488 | 1486 | ||
@@ -1490,13 +1488,12 @@ static enum drm_connector_status | |||
1490 | intel_sdvo_detect(struct drm_connector *connector, bool force) | 1488 | intel_sdvo_detect(struct drm_connector *connector, bool force) |
1491 | { | 1489 | { |
1492 | uint16_t response; | 1490 | uint16_t response; |
1493 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1491 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1494 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | ||
1495 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1492 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
1496 | enum drm_connector_status ret; | 1493 | enum drm_connector_status ret; |
1497 | 1494 | ||
1498 | if (!intel_sdvo_write_cmd(intel_sdvo, | 1495 | if (!intel_sdvo_write_cmd(intel_sdvo, |
1499 | SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) | 1496 | SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) |
1500 | return connector_status_unknown; | 1497 | return connector_status_unknown; |
1501 | if (intel_sdvo->is_tv) { | 1498 | if (intel_sdvo->is_tv) { |
1502 | /* add 30ms delay when the output type is SDVO-TV */ | 1499 | /* add 30ms delay when the output type is SDVO-TV */ |
@@ -1505,7 +1502,9 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
1505 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) | 1502 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) |
1506 | return connector_status_unknown; | 1503 | return connector_status_unknown; |
1507 | 1504 | ||
1508 | DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8); | 1505 | DRM_DEBUG_KMS("SDVO response %d %d [%x]\n", |
1506 | response & 0xff, response >> 8, | ||
1507 | intel_sdvo_connector->output_flag); | ||
1509 | 1508 | ||
1510 | if (response == 0) | 1509 | if (response == 0) |
1511 | return connector_status_disconnected; | 1510 | return connector_status_disconnected; |
@@ -1538,12 +1537,10 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
1538 | 1537 | ||
1539 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | 1538 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) |
1540 | { | 1539 | { |
1541 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1540 | struct edid *edid; |
1542 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | ||
1543 | int num_modes; | ||
1544 | 1541 | ||
1545 | /* set the bus switch and get the modes */ | 1542 | /* set the bus switch and get the modes */ |
1546 | num_modes = intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus); | 1543 | edid = intel_sdvo_get_edid(connector); |
1547 | 1544 | ||
1548 | /* | 1545 | /* |
1549 | * Mac mini hack. On this device, the DVI-I connector shares one DDC | 1546 | * Mac mini hack. On this device, the DVI-I connector shares one DDC |
@@ -1551,12 +1548,14 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | |||
1551 | * DDC fails, check to see if the analog output is disconnected, in | 1548 | * DDC fails, check to see if the analog output is disconnected, in |
1552 | * which case we'll look there for the digital DDC data. | 1549 | * which case we'll look there for the digital DDC data. |
1553 | */ | 1550 | */ |
1554 | if (num_modes == 0 && | 1551 | if (edid == NULL) |
1555 | intel_sdvo->analog_ddc_bus && | 1552 | edid = intel_sdvo_get_analog_edid(connector); |
1556 | !intel_analog_is_connected(connector->dev)) { | 1553 | |
1557 | /* Switch to the analog ddc bus and try that | 1554 | if (edid != NULL) { |
1558 | */ | 1555 | drm_mode_connector_update_edid_property(connector, edid); |
1559 | (void) intel_ddc_get_modes(connector, intel_sdvo->analog_ddc_bus); | 1556 | drm_add_edid_modes(connector, edid); |
1557 | connector->display_info.raw_edid = NULL; | ||
1558 | kfree(edid); | ||
1560 | } | 1559 | } |
1561 | } | 1560 | } |
1562 | 1561 | ||
@@ -1627,8 +1626,7 @@ struct drm_display_mode sdvo_tv_modes[] = { | |||
1627 | 1626 | ||
1628 | static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | 1627 | static void intel_sdvo_get_tv_modes(struct drm_connector *connector) |
1629 | { | 1628 | { |
1630 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1629 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1631 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | ||
1632 | struct intel_sdvo_sdtv_resolution_request tv_res; | 1630 | struct intel_sdvo_sdtv_resolution_request tv_res; |
1633 | uint32_t reply = 0, format_map = 0; | 1631 | uint32_t reply = 0, format_map = 0; |
1634 | int i; | 1632 | int i; |
@@ -1644,7 +1642,8 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | |||
1644 | return; | 1642 | return; |
1645 | 1643 | ||
1646 | BUILD_BUG_ON(sizeof(tv_res) != 3); | 1644 | BUILD_BUG_ON(sizeof(tv_res) != 3); |
1647 | if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, | 1645 | if (!intel_sdvo_write_cmd(intel_sdvo, |
1646 | SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, | ||
1648 | &tv_res, sizeof(tv_res))) | 1647 | &tv_res, sizeof(tv_res))) |
1649 | return; | 1648 | return; |
1650 | if (!intel_sdvo_read_response(intel_sdvo, &reply, 3)) | 1649 | if (!intel_sdvo_read_response(intel_sdvo, &reply, 3)) |
@@ -1662,8 +1661,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | |||
1662 | 1661 | ||
1663 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | 1662 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) |
1664 | { | 1663 | { |
1665 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1664 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1666 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | ||
1667 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1665 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
1668 | struct drm_display_mode *newmode; | 1666 | struct drm_display_mode *newmode; |
1669 | 1667 | ||
@@ -1672,7 +1670,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
1672 | * Assume that the preferred modes are | 1670 | * Assume that the preferred modes are |
1673 | * arranged in priority order. | 1671 | * arranged in priority order. |
1674 | */ | 1672 | */ |
1675 | intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus); | 1673 | intel_ddc_get_modes(connector, intel_sdvo->i2c); |
1676 | if (list_empty(&connector->probed_modes) == false) | 1674 | if (list_empty(&connector->probed_modes) == false) |
1677 | goto end; | 1675 | goto end; |
1678 | 1676 | ||
@@ -1693,6 +1691,10 @@ end: | |||
1693 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | 1691 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { |
1694 | intel_sdvo->sdvo_lvds_fixed_mode = | 1692 | intel_sdvo->sdvo_lvds_fixed_mode = |
1695 | drm_mode_duplicate(connector->dev, newmode); | 1693 | drm_mode_duplicate(connector->dev, newmode); |
1694 | |||
1695 | drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, | ||
1696 | 0); | ||
1697 | |||
1696 | intel_sdvo->is_lvds = true; | 1698 | intel_sdvo->is_lvds = true; |
1697 | break; | 1699 | break; |
1698 | } | 1700 | } |
@@ -1775,8 +1777,7 @@ intel_sdvo_set_property(struct drm_connector *connector, | |||
1775 | struct drm_property *property, | 1777 | struct drm_property *property, |
1776 | uint64_t val) | 1778 | uint64_t val) |
1777 | { | 1779 | { |
1778 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1780 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1779 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | ||
1780 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1781 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
1781 | uint16_t temp_value; | 1782 | uint16_t temp_value; |
1782 | uint8_t cmd; | 1783 | uint8_t cmd; |
@@ -1879,9 +1880,8 @@ set_value: | |||
1879 | 1880 | ||
1880 | 1881 | ||
1881 | done: | 1882 | done: |
1882 | if (encoder->crtc) { | 1883 | if (intel_sdvo->base.base.crtc) { |
1883 | struct drm_crtc *crtc = encoder->crtc; | 1884 | struct drm_crtc *crtc = intel_sdvo->base.base.crtc; |
1884 | |||
1885 | drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, | 1885 | drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, |
1886 | crtc->y, crtc->fb); | 1886 | crtc->y, crtc->fb); |
1887 | } | 1887 | } |
@@ -1909,20 +1909,18 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = { | |||
1909 | static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = { | 1909 | static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = { |
1910 | .get_modes = intel_sdvo_get_modes, | 1910 | .get_modes = intel_sdvo_get_modes, |
1911 | .mode_valid = intel_sdvo_mode_valid, | 1911 | .mode_valid = intel_sdvo_mode_valid, |
1912 | .best_encoder = intel_attached_encoder, | 1912 | .best_encoder = intel_best_encoder, |
1913 | }; | 1913 | }; |
1914 | 1914 | ||
1915 | static void intel_sdvo_enc_destroy(struct drm_encoder *encoder) | 1915 | static void intel_sdvo_enc_destroy(struct drm_encoder *encoder) |
1916 | { | 1916 | { |
1917 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | 1917 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); |
1918 | |||
1919 | if (intel_sdvo->analog_ddc_bus) | ||
1920 | intel_i2c_destroy(intel_sdvo->analog_ddc_bus); | ||
1921 | 1918 | ||
1922 | if (intel_sdvo->sdvo_lvds_fixed_mode != NULL) | 1919 | if (intel_sdvo->sdvo_lvds_fixed_mode != NULL) |
1923 | drm_mode_destroy(encoder->dev, | 1920 | drm_mode_destroy(encoder->dev, |
1924 | intel_sdvo->sdvo_lvds_fixed_mode); | 1921 | intel_sdvo->sdvo_lvds_fixed_mode); |
1925 | 1922 | ||
1923 | i2c_del_adapter(&intel_sdvo->ddc); | ||
1926 | intel_encoder_destroy(encoder); | 1924 | intel_encoder_destroy(encoder); |
1927 | } | 1925 | } |
1928 | 1926 | ||
@@ -1990,54 +1988,39 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, | |||
1990 | intel_sdvo_guess_ddc_bus(sdvo); | 1988 | intel_sdvo_guess_ddc_bus(sdvo); |
1991 | } | 1989 | } |
1992 | 1990 | ||
1993 | static bool | 1991 | static void |
1994 | intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device) | 1992 | intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, |
1993 | struct intel_sdvo *sdvo, u32 reg) | ||
1995 | { | 1994 | { |
1996 | return intel_sdvo_set_target_output(intel_sdvo, | 1995 | struct sdvo_device_mapping *mapping; |
1997 | device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1) && | 1996 | u8 pin, speed; |
1998 | intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, | ||
1999 | &intel_sdvo->is_hdmi, 1); | ||
2000 | } | ||
2001 | 1997 | ||
2002 | static struct intel_sdvo * | 1998 | if (IS_SDVOB(reg)) |
2003 | intel_sdvo_chan_to_intel_sdvo(struct intel_i2c_chan *chan) | 1999 | mapping = &dev_priv->sdvo_mappings[0]; |
2004 | { | 2000 | else |
2005 | struct drm_device *dev = chan->drm_dev; | 2001 | mapping = &dev_priv->sdvo_mappings[1]; |
2006 | struct drm_encoder *encoder; | ||
2007 | 2002 | ||
2008 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 2003 | pin = GMBUS_PORT_DPB; |
2009 | struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder); | 2004 | speed = GMBUS_RATE_1MHZ >> 8; |
2010 | if (intel_sdvo->base.ddc_bus == &chan->adapter) | 2005 | if (mapping->initialized) { |
2011 | return intel_sdvo; | 2006 | pin = mapping->i2c_pin; |
2007 | speed = mapping->i2c_speed; | ||
2012 | } | 2008 | } |
2013 | 2009 | ||
2014 | return NULL; | 2010 | sdvo->i2c = &dev_priv->gmbus[pin].adapter; |
2011 | intel_gmbus_set_speed(sdvo->i2c, speed); | ||
2012 | intel_gmbus_force_bit(sdvo->i2c, true); | ||
2015 | } | 2013 | } |
2016 | 2014 | ||
2017 | static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | 2015 | static bool |
2018 | struct i2c_msg msgs[], int num) | 2016 | intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device) |
2019 | { | 2017 | { |
2020 | struct intel_sdvo *intel_sdvo; | 2018 | return intel_sdvo_set_target_output(intel_sdvo, |
2021 | struct i2c_algo_bit_data *algo_data; | 2019 | device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1) && |
2022 | const struct i2c_algorithm *algo; | 2020 | intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, |
2023 | 2021 | &intel_sdvo->is_hdmi, 1); | |
2024 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; | ||
2025 | intel_sdvo = | ||
2026 | intel_sdvo_chan_to_intel_sdvo((struct intel_i2c_chan *) | ||
2027 | (algo_data->data)); | ||
2028 | if (intel_sdvo == NULL) | ||
2029 | return -EINVAL; | ||
2030 | |||
2031 | algo = intel_sdvo->base.i2c_bus->algo; | ||
2032 | |||
2033 | intel_sdvo_set_control_bus_switch(intel_sdvo, intel_sdvo->ddc_bus); | ||
2034 | return algo->master_xfer(i2c_adap, msgs, num); | ||
2035 | } | 2022 | } |
2036 | 2023 | ||
2037 | static struct i2c_algorithm intel_sdvo_i2c_bit_algo = { | ||
2038 | .master_xfer = intel_sdvo_master_xfer, | ||
2039 | }; | ||
2040 | |||
2041 | static u8 | 2024 | static u8 |
2042 | intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) | 2025 | intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) |
2043 | { | 2026 | { |
@@ -2076,26 +2059,29 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) | |||
2076 | } | 2059 | } |
2077 | 2060 | ||
2078 | static void | 2061 | static void |
2079 | intel_sdvo_connector_init(struct drm_encoder *encoder, | 2062 | intel_sdvo_connector_init(struct intel_sdvo_connector *connector, |
2080 | struct drm_connector *connector) | 2063 | struct intel_sdvo *encoder) |
2081 | { | 2064 | { |
2082 | drm_connector_init(encoder->dev, connector, &intel_sdvo_connector_funcs, | 2065 | drm_connector_init(encoder->base.base.dev, |
2083 | connector->connector_type); | 2066 | &connector->base.base, |
2067 | &intel_sdvo_connector_funcs, | ||
2068 | connector->base.base.connector_type); | ||
2084 | 2069 | ||
2085 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); | 2070 | drm_connector_helper_add(&connector->base.base, |
2071 | &intel_sdvo_connector_helper_funcs); | ||
2086 | 2072 | ||
2087 | connector->interlace_allowed = 0; | 2073 | connector->base.base.interlace_allowed = 0; |
2088 | connector->doublescan_allowed = 0; | 2074 | connector->base.base.doublescan_allowed = 0; |
2089 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 2075 | connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; |
2090 | 2076 | ||
2091 | drm_mode_connector_attach_encoder(connector, encoder); | 2077 | intel_connector_attach_encoder(&connector->base, &encoder->base); |
2092 | drm_sysfs_connector_add(connector); | 2078 | drm_sysfs_connector_add(&connector->base.base); |
2093 | } | 2079 | } |
2094 | 2080 | ||
2095 | static bool | 2081 | static bool |
2096 | intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | 2082 | intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) |
2097 | { | 2083 | { |
2098 | struct drm_encoder *encoder = &intel_sdvo->base.enc; | 2084 | struct drm_encoder *encoder = &intel_sdvo->base.base; |
2099 | struct drm_connector *connector; | 2085 | struct drm_connector *connector; |
2100 | struct intel_connector *intel_connector; | 2086 | struct intel_connector *intel_connector; |
2101 | struct intel_sdvo_connector *intel_sdvo_connector; | 2087 | struct intel_sdvo_connector *intel_sdvo_connector; |
@@ -2130,7 +2116,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
2130 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 2116 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | |
2131 | (1 << INTEL_ANALOG_CLONE_BIT)); | 2117 | (1 << INTEL_ANALOG_CLONE_BIT)); |
2132 | 2118 | ||
2133 | intel_sdvo_connector_init(encoder, connector); | 2119 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
2134 | 2120 | ||
2135 | return true; | 2121 | return true; |
2136 | } | 2122 | } |
@@ -2138,36 +2124,36 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
2138 | static bool | 2124 | static bool |
2139 | intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) | 2125 | intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) |
2140 | { | 2126 | { |
2141 | struct drm_encoder *encoder = &intel_sdvo->base.enc; | 2127 | struct drm_encoder *encoder = &intel_sdvo->base.base; |
2142 | struct drm_connector *connector; | 2128 | struct drm_connector *connector; |
2143 | struct intel_connector *intel_connector; | 2129 | struct intel_connector *intel_connector; |
2144 | struct intel_sdvo_connector *intel_sdvo_connector; | 2130 | struct intel_sdvo_connector *intel_sdvo_connector; |
2145 | 2131 | ||
2146 | intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); | 2132 | intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); |
2147 | if (!intel_sdvo_connector) | 2133 | if (!intel_sdvo_connector) |
2148 | return false; | 2134 | return false; |
2149 | 2135 | ||
2150 | intel_connector = &intel_sdvo_connector->base; | 2136 | intel_connector = &intel_sdvo_connector->base; |
2151 | connector = &intel_connector->base; | 2137 | connector = &intel_connector->base; |
2152 | encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; | 2138 | encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; |
2153 | connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; | 2139 | connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; |
2154 | 2140 | ||
2155 | intel_sdvo->controlled_output |= type; | 2141 | intel_sdvo->controlled_output |= type; |
2156 | intel_sdvo_connector->output_flag = type; | 2142 | intel_sdvo_connector->output_flag = type; |
2157 | 2143 | ||
2158 | intel_sdvo->is_tv = true; | 2144 | intel_sdvo->is_tv = true; |
2159 | intel_sdvo->base.needs_tv_clock = true; | 2145 | intel_sdvo->base.needs_tv_clock = true; |
2160 | intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; | 2146 | intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; |
2161 | 2147 | ||
2162 | intel_sdvo_connector_init(encoder, connector); | 2148 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
2163 | 2149 | ||
2164 | if (!intel_sdvo_tv_create_property(intel_sdvo, intel_sdvo_connector, type)) | 2150 | if (!intel_sdvo_tv_create_property(intel_sdvo, intel_sdvo_connector, type)) |
2165 | goto err; | 2151 | goto err; |
2166 | 2152 | ||
2167 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) | 2153 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) |
2168 | goto err; | 2154 | goto err; |
2169 | 2155 | ||
2170 | return true; | 2156 | return true; |
2171 | 2157 | ||
2172 | err: | 2158 | err: |
2173 | intel_sdvo_destroy(connector); | 2159 | intel_sdvo_destroy(connector); |
@@ -2177,43 +2163,44 @@ err: | |||
2177 | static bool | 2163 | static bool |
2178 | intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) | 2164 | intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) |
2179 | { | 2165 | { |
2180 | struct drm_encoder *encoder = &intel_sdvo->base.enc; | 2166 | struct drm_encoder *encoder = &intel_sdvo->base.base; |
2181 | struct drm_connector *connector; | 2167 | struct drm_connector *connector; |
2182 | struct intel_connector *intel_connector; | 2168 | struct intel_connector *intel_connector; |
2183 | struct intel_sdvo_connector *intel_sdvo_connector; | 2169 | struct intel_sdvo_connector *intel_sdvo_connector; |
2184 | 2170 | ||
2185 | intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); | 2171 | intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); |
2186 | if (!intel_sdvo_connector) | 2172 | if (!intel_sdvo_connector) |
2187 | return false; | 2173 | return false; |
2188 | 2174 | ||
2189 | intel_connector = &intel_sdvo_connector->base; | 2175 | intel_connector = &intel_sdvo_connector->base; |
2190 | connector = &intel_connector->base; | 2176 | connector = &intel_connector->base; |
2191 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 2177 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
2192 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | 2178 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; |
2193 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | 2179 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; |
2194 | 2180 | ||
2195 | if (device == 0) { | 2181 | if (device == 0) { |
2196 | intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; | 2182 | intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; |
2197 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; | 2183 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; |
2198 | } else if (device == 1) { | 2184 | } else if (device == 1) { |
2199 | intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; | 2185 | intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; |
2200 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; | 2186 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; |
2201 | } | 2187 | } |
2202 | 2188 | ||
2203 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 2189 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | |
2204 | (1 << INTEL_ANALOG_CLONE_BIT)); | 2190 | (1 << INTEL_ANALOG_CLONE_BIT)); |
2205 | 2191 | ||
2206 | intel_sdvo_connector_init(encoder, connector); | 2192 | intel_sdvo_connector_init(intel_sdvo_connector, |
2207 | return true; | 2193 | intel_sdvo); |
2194 | return true; | ||
2208 | } | 2195 | } |
2209 | 2196 | ||
2210 | static bool | 2197 | static bool |
2211 | intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) | 2198 | intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) |
2212 | { | 2199 | { |
2213 | struct drm_encoder *encoder = &intel_sdvo->base.enc; | 2200 | struct drm_encoder *encoder = &intel_sdvo->base.base; |
2214 | struct drm_connector *connector; | 2201 | struct drm_connector *connector; |
2215 | struct intel_connector *intel_connector; | 2202 | struct intel_connector *intel_connector; |
2216 | struct intel_sdvo_connector *intel_sdvo_connector; | 2203 | struct intel_sdvo_connector *intel_sdvo_connector; |
2217 | 2204 | ||
2218 | intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); | 2205 | intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); |
2219 | if (!intel_sdvo_connector) | 2206 | if (!intel_sdvo_connector) |
@@ -2221,22 +2208,22 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) | |||
2221 | 2208 | ||
2222 | intel_connector = &intel_sdvo_connector->base; | 2209 | intel_connector = &intel_sdvo_connector->base; |
2223 | connector = &intel_connector->base; | 2210 | connector = &intel_connector->base; |
2224 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | 2211 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; |
2225 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | 2212 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; |
2226 | 2213 | ||
2227 | if (device == 0) { | 2214 | if (device == 0) { |
2228 | intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; | 2215 | intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; |
2229 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; | 2216 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; |
2230 | } else if (device == 1) { | 2217 | } else if (device == 1) { |
2231 | intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; | 2218 | intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; |
2232 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; | 2219 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; |
2233 | } | 2220 | } |
2234 | 2221 | ||
2235 | intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) | | 2222 | intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) | |
2236 | (1 << INTEL_SDVO_LVDS_CLONE_BIT)); | 2223 | (1 << INTEL_SDVO_LVDS_CLONE_BIT)); |
2237 | 2224 | ||
2238 | intel_sdvo_connector_init(encoder, connector); | 2225 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
2239 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) | 2226 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) |
2240 | goto err; | 2227 | goto err; |
2241 | 2228 | ||
2242 | return true; | 2229 | return true; |
@@ -2307,7 +2294,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, | |||
2307 | struct intel_sdvo_connector *intel_sdvo_connector, | 2294 | struct intel_sdvo_connector *intel_sdvo_connector, |
2308 | int type) | 2295 | int type) |
2309 | { | 2296 | { |
2310 | struct drm_device *dev = intel_sdvo->base.enc.dev; | 2297 | struct drm_device *dev = intel_sdvo->base.base.dev; |
2311 | struct intel_sdvo_tv_format format; | 2298 | struct intel_sdvo_tv_format format; |
2312 | uint32_t format_map, i; | 2299 | uint32_t format_map, i; |
2313 | 2300 | ||
@@ -2373,7 +2360,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, | |||
2373 | struct intel_sdvo_connector *intel_sdvo_connector, | 2360 | struct intel_sdvo_connector *intel_sdvo_connector, |
2374 | struct intel_sdvo_enhancements_reply enhancements) | 2361 | struct intel_sdvo_enhancements_reply enhancements) |
2375 | { | 2362 | { |
2376 | struct drm_device *dev = intel_sdvo->base.enc.dev; | 2363 | struct drm_device *dev = intel_sdvo->base.base.dev; |
2377 | struct drm_connector *connector = &intel_sdvo_connector->base.base; | 2364 | struct drm_connector *connector = &intel_sdvo_connector->base.base; |
2378 | uint16_t response, data_value[2]; | 2365 | uint16_t response, data_value[2]; |
2379 | 2366 | ||
@@ -2502,7 +2489,7 @@ intel_sdvo_create_enhance_property_lvds(struct intel_sdvo *intel_sdvo, | |||
2502 | struct intel_sdvo_connector *intel_sdvo_connector, | 2489 | struct intel_sdvo_connector *intel_sdvo_connector, |
2503 | struct intel_sdvo_enhancements_reply enhancements) | 2490 | struct intel_sdvo_enhancements_reply enhancements) |
2504 | { | 2491 | { |
2505 | struct drm_device *dev = intel_sdvo->base.enc.dev; | 2492 | struct drm_device *dev = intel_sdvo->base.base.dev; |
2506 | struct drm_connector *connector = &intel_sdvo_connector->base.base; | 2493 | struct drm_connector *connector = &intel_sdvo_connector->base.base; |
2507 | uint16_t response, data_value[2]; | 2494 | uint16_t response, data_value[2]; |
2508 | 2495 | ||
@@ -2535,7 +2522,43 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, | |||
2535 | return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply); | 2522 | return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply); |
2536 | else | 2523 | else |
2537 | return true; | 2524 | return true; |
2525 | } | ||
2526 | |||
2527 | static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter, | ||
2528 | struct i2c_msg *msgs, | ||
2529 | int num) | ||
2530 | { | ||
2531 | struct intel_sdvo *sdvo = adapter->algo_data; | ||
2532 | |||
2533 | if (!intel_sdvo_set_control_bus_switch(sdvo, sdvo->ddc_bus)) | ||
2534 | return -EIO; | ||
2535 | |||
2536 | return sdvo->i2c->algo->master_xfer(sdvo->i2c, msgs, num); | ||
2537 | } | ||
2538 | |||
2539 | static u32 intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter) | ||
2540 | { | ||
2541 | struct intel_sdvo *sdvo = adapter->algo_data; | ||
2542 | return sdvo->i2c->algo->functionality(sdvo->i2c); | ||
2543 | } | ||
2544 | |||
2545 | static const struct i2c_algorithm intel_sdvo_ddc_proxy = { | ||
2546 | .master_xfer = intel_sdvo_ddc_proxy_xfer, | ||
2547 | .functionality = intel_sdvo_ddc_proxy_func | ||
2548 | }; | ||
2538 | 2549 | ||
2550 | static bool | ||
2551 | intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, | ||
2552 | struct drm_device *dev) | ||
2553 | { | ||
2554 | sdvo->ddc.owner = THIS_MODULE; | ||
2555 | sdvo->ddc.class = I2C_CLASS_DDC; | ||
2556 | snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy"); | ||
2557 | sdvo->ddc.dev.parent = &dev->pdev->dev; | ||
2558 | sdvo->ddc.algo_data = sdvo; | ||
2559 | sdvo->ddc.algo = &intel_sdvo_ddc_proxy; | ||
2560 | |||
2561 | return i2c_add_adapter(&sdvo->ddc) == 0; | ||
2539 | } | 2562 | } |
2540 | 2563 | ||
2541 | bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) | 2564 | bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) |
@@ -2543,95 +2566,66 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) | |||
2543 | struct drm_i915_private *dev_priv = dev->dev_private; | 2566 | struct drm_i915_private *dev_priv = dev->dev_private; |
2544 | struct intel_encoder *intel_encoder; | 2567 | struct intel_encoder *intel_encoder; |
2545 | struct intel_sdvo *intel_sdvo; | 2568 | struct intel_sdvo *intel_sdvo; |
2546 | u8 ch[0x40]; | ||
2547 | int i; | 2569 | int i; |
2548 | u32 i2c_reg, ddc_reg, analog_ddc_reg; | ||
2549 | 2570 | ||
2550 | intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); | 2571 | intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); |
2551 | if (!intel_sdvo) | 2572 | if (!intel_sdvo) |
2552 | return false; | 2573 | return false; |
2553 | 2574 | ||
2575 | if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) { | ||
2576 | kfree(intel_sdvo); | ||
2577 | return false; | ||
2578 | } | ||
2579 | |||
2554 | intel_sdvo->sdvo_reg = sdvo_reg; | 2580 | intel_sdvo->sdvo_reg = sdvo_reg; |
2555 | 2581 | ||
2556 | intel_encoder = &intel_sdvo->base; | 2582 | intel_encoder = &intel_sdvo->base; |
2557 | intel_encoder->type = INTEL_OUTPUT_SDVO; | 2583 | intel_encoder->type = INTEL_OUTPUT_SDVO; |
2584 | /* encoder type will be decided later */ | ||
2585 | drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0); | ||
2558 | 2586 | ||
2559 | if (HAS_PCH_SPLIT(dev)) { | 2587 | intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1; |
2560 | i2c_reg = PCH_GPIOE; | 2588 | intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg); |
2561 | ddc_reg = PCH_GPIOE; | ||
2562 | analog_ddc_reg = PCH_GPIOA; | ||
2563 | } else { | ||
2564 | i2c_reg = GPIOE; | ||
2565 | ddc_reg = GPIOE; | ||
2566 | analog_ddc_reg = GPIOA; | ||
2567 | } | ||
2568 | |||
2569 | /* setup the DDC bus. */ | ||
2570 | if (IS_SDVOB(sdvo_reg)) | ||
2571 | intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOB"); | ||
2572 | else | ||
2573 | intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOC"); | ||
2574 | |||
2575 | if (!intel_encoder->i2c_bus) | ||
2576 | goto err_inteloutput; | ||
2577 | |||
2578 | intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg); | ||
2579 | |||
2580 | /* Save the bit-banging i2c functionality for use by the DDC wrapper */ | ||
2581 | intel_sdvo_i2c_bit_algo.functionality = intel_encoder->i2c_bus->algo->functionality; | ||
2582 | 2589 | ||
2583 | /* Read the regs to test if we can talk to the device */ | 2590 | /* Read the regs to test if we can talk to the device */ |
2584 | for (i = 0; i < 0x40; i++) { | 2591 | for (i = 0; i < 0x40; i++) { |
2585 | if (!intel_sdvo_read_byte(intel_sdvo, i, &ch[i])) { | 2592 | u8 byte; |
2593 | |||
2594 | if (!intel_sdvo_read_byte(intel_sdvo, i, &byte)) { | ||
2586 | DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n", | 2595 | DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n", |
2587 | IS_SDVOB(sdvo_reg) ? 'B' : 'C'); | 2596 | IS_SDVOB(sdvo_reg) ? 'B' : 'C'); |
2588 | goto err_i2c; | 2597 | goto err; |
2589 | } | 2598 | } |
2590 | } | 2599 | } |
2591 | 2600 | ||
2592 | /* setup the DDC bus. */ | 2601 | if (IS_SDVOB(sdvo_reg)) |
2593 | if (IS_SDVOB(sdvo_reg)) { | ||
2594 | intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOB DDC BUS"); | ||
2595 | intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg, | ||
2596 | "SDVOB/VGA DDC BUS"); | ||
2597 | dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; | 2602 | dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; |
2598 | } else { | 2603 | else |
2599 | intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOC DDC BUS"); | ||
2600 | intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg, | ||
2601 | "SDVOC/VGA DDC BUS"); | ||
2602 | dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; | 2604 | dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; |
2603 | } | ||
2604 | if (intel_encoder->ddc_bus == NULL || intel_sdvo->analog_ddc_bus == NULL) | ||
2605 | goto err_i2c; | ||
2606 | |||
2607 | /* Wrap with our custom algo which switches to DDC mode */ | ||
2608 | intel_encoder->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; | ||
2609 | 2605 | ||
2610 | /* encoder type will be decided later */ | 2606 | drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); |
2611 | drm_encoder_init(dev, &intel_encoder->enc, &intel_sdvo_enc_funcs, 0); | ||
2612 | drm_encoder_helper_add(&intel_encoder->enc, &intel_sdvo_helper_funcs); | ||
2613 | 2607 | ||
2614 | /* In default case sdvo lvds is false */ | 2608 | /* In default case sdvo lvds is false */ |
2615 | if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) | 2609 | if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) |
2616 | goto err_enc; | 2610 | goto err; |
2617 | 2611 | ||
2618 | if (intel_sdvo_output_setup(intel_sdvo, | 2612 | if (intel_sdvo_output_setup(intel_sdvo, |
2619 | intel_sdvo->caps.output_flags) != true) { | 2613 | intel_sdvo->caps.output_flags) != true) { |
2620 | DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", | 2614 | DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", |
2621 | IS_SDVOB(sdvo_reg) ? 'B' : 'C'); | 2615 | IS_SDVOB(sdvo_reg) ? 'B' : 'C'); |
2622 | goto err_enc; | 2616 | goto err; |
2623 | } | 2617 | } |
2624 | 2618 | ||
2625 | intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); | 2619 | intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); |
2626 | 2620 | ||
2627 | /* Set the input timing to the screen. Assume always input 0. */ | 2621 | /* Set the input timing to the screen. Assume always input 0. */ |
2628 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 2622 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
2629 | goto err_enc; | 2623 | goto err; |
2630 | 2624 | ||
2631 | if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, | 2625 | if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, |
2632 | &intel_sdvo->pixel_clock_min, | 2626 | &intel_sdvo->pixel_clock_min, |
2633 | &intel_sdvo->pixel_clock_max)) | 2627 | &intel_sdvo->pixel_clock_max)) |
2634 | goto err_enc; | 2628 | goto err; |
2635 | 2629 | ||
2636 | DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " | 2630 | DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " |
2637 | "clock range %dMHz - %dMHz, " | 2631 | "clock range %dMHz - %dMHz, " |
@@ -2651,16 +2645,9 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) | |||
2651 | (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); | 2645 | (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); |
2652 | return true; | 2646 | return true; |
2653 | 2647 | ||
2654 | err_enc: | 2648 | err: |
2655 | drm_encoder_cleanup(&intel_encoder->enc); | 2649 | drm_encoder_cleanup(&intel_encoder->base); |
2656 | err_i2c: | 2650 | i2c_del_adapter(&intel_sdvo->ddc); |
2657 | if (intel_sdvo->analog_ddc_bus != NULL) | ||
2658 | intel_i2c_destroy(intel_sdvo->analog_ddc_bus); | ||
2659 | if (intel_encoder->ddc_bus != NULL) | ||
2660 | intel_i2c_destroy(intel_encoder->ddc_bus); | ||
2661 | if (intel_encoder->i2c_bus != NULL) | ||
2662 | intel_i2c_destroy(intel_encoder->i2c_bus); | ||
2663 | err_inteloutput: | ||
2664 | kfree(intel_sdvo); | 2651 | kfree(intel_sdvo); |
2665 | 2652 | ||
2666 | return false; | 2653 | return false; |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 4a117e318a73..2f7681989316 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -48,7 +48,7 @@ struct intel_tv { | |||
48 | struct intel_encoder base; | 48 | struct intel_encoder base; |
49 | 49 | ||
50 | int type; | 50 | int type; |
51 | char *tv_format; | 51 | const char *tv_format; |
52 | int margin[4]; | 52 | int margin[4]; |
53 | u32 save_TV_H_CTL_1; | 53 | u32 save_TV_H_CTL_1; |
54 | u32 save_TV_H_CTL_2; | 54 | u32 save_TV_H_CTL_2; |
@@ -350,7 +350,7 @@ static const struct video_levels component_levels = { | |||
350 | 350 | ||
351 | 351 | ||
352 | struct tv_mode { | 352 | struct tv_mode { |
353 | char *name; | 353 | const char *name; |
354 | int clock; | 354 | int clock; |
355 | int refresh; /* in millihertz (for precision) */ | 355 | int refresh; /* in millihertz (for precision) */ |
356 | u32 oversample; | 356 | u32 oversample; |
@@ -900,7 +900,14 @@ static const struct tv_mode tv_modes[] = { | |||
900 | 900 | ||
901 | static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder) | 901 | static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder) |
902 | { | 902 | { |
903 | return container_of(enc_to_intel_encoder(encoder), struct intel_tv, base); | 903 | return container_of(encoder, struct intel_tv, base.base); |
904 | } | ||
905 | |||
906 | static struct intel_tv *intel_attached_tv(struct drm_connector *connector) | ||
907 | { | ||
908 | return container_of(intel_attached_encoder(connector), | ||
909 | struct intel_tv, | ||
910 | base); | ||
904 | } | 911 | } |
905 | 912 | ||
906 | static void | 913 | static void |
@@ -922,7 +929,7 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode) | |||
922 | } | 929 | } |
923 | 930 | ||
924 | static const struct tv_mode * | 931 | static const struct tv_mode * |
925 | intel_tv_mode_lookup (char *tv_format) | 932 | intel_tv_mode_lookup(const char *tv_format) |
926 | { | 933 | { |
927 | int i; | 934 | int i; |
928 | 935 | ||
@@ -936,22 +943,23 @@ intel_tv_mode_lookup (char *tv_format) | |||
936 | } | 943 | } |
937 | 944 | ||
938 | static const struct tv_mode * | 945 | static const struct tv_mode * |
939 | intel_tv_mode_find (struct intel_tv *intel_tv) | 946 | intel_tv_mode_find(struct intel_tv *intel_tv) |
940 | { | 947 | { |
941 | return intel_tv_mode_lookup(intel_tv->tv_format); | 948 | return intel_tv_mode_lookup(intel_tv->tv_format); |
942 | } | 949 | } |
943 | 950 | ||
944 | static enum drm_mode_status | 951 | static enum drm_mode_status |
945 | intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) | 952 | intel_tv_mode_valid(struct drm_connector *connector, |
953 | struct drm_display_mode *mode) | ||
946 | { | 954 | { |
947 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 955 | struct intel_tv *intel_tv = intel_attached_tv(connector); |
948 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | ||
949 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); | 956 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); |
950 | 957 | ||
951 | /* Ensure TV refresh is close to desired refresh */ | 958 | /* Ensure TV refresh is close to desired refresh */ |
952 | if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000) | 959 | if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000) |
953 | < 1000) | 960 | < 1000) |
954 | return MODE_OK; | 961 | return MODE_OK; |
962 | |||
955 | return MODE_CLOCK_RANGE; | 963 | return MODE_CLOCK_RANGE; |
956 | } | 964 | } |
957 | 965 | ||
@@ -1131,7 +1139,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
1131 | color_conversion->av); | 1139 | color_conversion->av); |
1132 | } | 1140 | } |
1133 | 1141 | ||
1134 | if (IS_I965G(dev)) | 1142 | if (INTEL_INFO(dev)->gen >= 4) |
1135 | I915_WRITE(TV_CLR_KNOBS, 0x00404000); | 1143 | I915_WRITE(TV_CLR_KNOBS, 0x00404000); |
1136 | else | 1144 | else |
1137 | I915_WRITE(TV_CLR_KNOBS, 0x00606000); | 1145 | I915_WRITE(TV_CLR_KNOBS, 0x00606000); |
@@ -1157,12 +1165,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
1157 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); | 1165 | I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); |
1158 | 1166 | ||
1159 | /* Wait for vblank for the disable to take effect */ | 1167 | /* Wait for vblank for the disable to take effect */ |
1160 | if (!IS_I9XX(dev)) | 1168 | if (IS_GEN2(dev)) |
1161 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 1169 | intel_wait_for_vblank(dev, intel_crtc->pipe); |
1162 | 1170 | ||
1163 | I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); | 1171 | I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); |
1164 | /* Wait for vblank for the disable to take effect. */ | 1172 | /* Wait for vblank for the disable to take effect. */ |
1165 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 1173 | intel_wait_for_pipe_off(dev, intel_crtc->pipe); |
1166 | 1174 | ||
1167 | /* Filter ctl must be set before TV_WIN_SIZE */ | 1175 | /* Filter ctl must be set before TV_WIN_SIZE */ |
1168 | I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); | 1176 | I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); |
@@ -1196,7 +1204,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
1196 | I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); | 1204 | I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); |
1197 | for (i = 0; i < 43; i++) | 1205 | for (i = 0; i < 43; i++) |
1198 | I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); | 1206 | I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); |
1199 | I915_WRITE(TV_DAC, 0); | 1207 | I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE); |
1200 | I915_WRITE(TV_CTL, tv_ctl); | 1208 | I915_WRITE(TV_CTL, tv_ctl); |
1201 | } | 1209 | } |
1202 | 1210 | ||
@@ -1228,15 +1236,13 @@ static const struct drm_display_mode reported_modes[] = { | |||
1228 | static int | 1236 | static int |
1229 | intel_tv_detect_type (struct intel_tv *intel_tv) | 1237 | intel_tv_detect_type (struct intel_tv *intel_tv) |
1230 | { | 1238 | { |
1231 | struct drm_encoder *encoder = &intel_tv->base.enc; | 1239 | struct drm_encoder *encoder = &intel_tv->base.base; |
1232 | struct drm_device *dev = encoder->dev; | 1240 | struct drm_device *dev = encoder->dev; |
1233 | struct drm_i915_private *dev_priv = dev->dev_private; | 1241 | struct drm_i915_private *dev_priv = dev->dev_private; |
1234 | unsigned long irqflags; | 1242 | unsigned long irqflags; |
1235 | u32 tv_ctl, save_tv_ctl; | 1243 | u32 tv_ctl, save_tv_ctl; |
1236 | u32 tv_dac, save_tv_dac; | 1244 | u32 tv_dac, save_tv_dac; |
1237 | int type = DRM_MODE_CONNECTOR_Unknown; | 1245 | int type; |
1238 | |||
1239 | tv_dac = I915_READ(TV_DAC); | ||
1240 | 1246 | ||
1241 | /* Disable TV interrupts around load detect or we'll recurse */ | 1247 | /* Disable TV interrupts around load detect or we'll recurse */ |
1242 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1248 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
@@ -1244,19 +1250,14 @@ intel_tv_detect_type (struct intel_tv *intel_tv) | |||
1244 | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); | 1250 | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); |
1245 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); | 1251 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); |
1246 | 1252 | ||
1247 | /* | 1253 | save_tv_dac = tv_dac = I915_READ(TV_DAC); |
1248 | * Detect TV by polling) | 1254 | save_tv_ctl = tv_ctl = I915_READ(TV_CTL); |
1249 | */ | 1255 | |
1250 | save_tv_dac = tv_dac; | 1256 | /* Poll for TV detection */ |
1251 | tv_ctl = I915_READ(TV_CTL); | 1257 | tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK); |
1252 | save_tv_ctl = tv_ctl; | ||
1253 | tv_ctl &= ~TV_ENC_ENABLE; | ||
1254 | tv_ctl &= ~TV_TEST_MODE_MASK; | ||
1255 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; | 1258 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; |
1256 | tv_dac &= ~TVDAC_SENSE_MASK; | 1259 | |
1257 | tv_dac &= ~DAC_A_MASK; | 1260 | tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK); |
1258 | tv_dac &= ~DAC_B_MASK; | ||
1259 | tv_dac &= ~DAC_C_MASK; | ||
1260 | tv_dac |= (TVDAC_STATE_CHG_EN | | 1261 | tv_dac |= (TVDAC_STATE_CHG_EN | |
1261 | TVDAC_A_SENSE_CTL | | 1262 | TVDAC_A_SENSE_CTL | |
1262 | TVDAC_B_SENSE_CTL | | 1263 | TVDAC_B_SENSE_CTL | |
@@ -1265,37 +1266,40 @@ intel_tv_detect_type (struct intel_tv *intel_tv) | |||
1265 | DAC_A_0_7_V | | 1266 | DAC_A_0_7_V | |
1266 | DAC_B_0_7_V | | 1267 | DAC_B_0_7_V | |
1267 | DAC_C_0_7_V); | 1268 | DAC_C_0_7_V); |
1269 | |||
1268 | I915_WRITE(TV_CTL, tv_ctl); | 1270 | I915_WRITE(TV_CTL, tv_ctl); |
1269 | I915_WRITE(TV_DAC, tv_dac); | 1271 | I915_WRITE(TV_DAC, tv_dac); |
1270 | POSTING_READ(TV_DAC); | 1272 | POSTING_READ(TV_DAC); |
1271 | msleep(20); | ||
1272 | 1273 | ||
1273 | tv_dac = I915_READ(TV_DAC); | 1274 | intel_wait_for_vblank(intel_tv->base.base.dev, |
1274 | I915_WRITE(TV_DAC, save_tv_dac); | 1275 | to_intel_crtc(intel_tv->base.base.crtc)->pipe); |
1275 | I915_WRITE(TV_CTL, save_tv_ctl); | ||
1276 | POSTING_READ(TV_CTL); | ||
1277 | msleep(20); | ||
1278 | 1276 | ||
1279 | /* | 1277 | type = -1; |
1280 | * A B C | 1278 | if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) { |
1281 | * 0 1 1 Composite | 1279 | DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac); |
1282 | * 1 0 X svideo | 1280 | /* |
1283 | * 0 0 0 Component | 1281 | * A B C |
1284 | */ | 1282 | * 0 1 1 Composite |
1285 | if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { | 1283 | * 1 0 X svideo |
1286 | DRM_DEBUG_KMS("Detected Composite TV connection\n"); | 1284 | * 0 0 0 Component |
1287 | type = DRM_MODE_CONNECTOR_Composite; | 1285 | */ |
1288 | } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { | 1286 | if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { |
1289 | DRM_DEBUG_KMS("Detected S-Video TV connection\n"); | 1287 | DRM_DEBUG_KMS("Detected Composite TV connection\n"); |
1290 | type = DRM_MODE_CONNECTOR_SVIDEO; | 1288 | type = DRM_MODE_CONNECTOR_Composite; |
1291 | } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { | 1289 | } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { |
1292 | DRM_DEBUG_KMS("Detected Component TV connection\n"); | 1290 | DRM_DEBUG_KMS("Detected S-Video TV connection\n"); |
1293 | type = DRM_MODE_CONNECTOR_Component; | 1291 | type = DRM_MODE_CONNECTOR_SVIDEO; |
1294 | } else { | 1292 | } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { |
1295 | DRM_DEBUG_KMS("No TV connection detected\n"); | 1293 | DRM_DEBUG_KMS("Detected Component TV connection\n"); |
1296 | type = -1; | 1294 | type = DRM_MODE_CONNECTOR_Component; |
1295 | } else { | ||
1296 | DRM_DEBUG_KMS("Unrecognised TV connection\n"); | ||
1297 | } | ||
1297 | } | 1298 | } |
1298 | 1299 | ||
1300 | I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN); | ||
1301 | I915_WRITE(TV_CTL, save_tv_ctl); | ||
1302 | |||
1299 | /* Restore interrupt config */ | 1303 | /* Restore interrupt config */ |
1300 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1304 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
1301 | i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | | 1305 | i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | |
@@ -1311,8 +1315,7 @@ intel_tv_detect_type (struct intel_tv *intel_tv) | |||
1311 | */ | 1315 | */ |
1312 | static void intel_tv_find_better_format(struct drm_connector *connector) | 1316 | static void intel_tv_find_better_format(struct drm_connector *connector) |
1313 | { | 1317 | { |
1314 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1318 | struct intel_tv *intel_tv = intel_attached_tv(connector); |
1315 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | ||
1316 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); | 1319 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); |
1317 | int i; | 1320 | int i; |
1318 | 1321 | ||
@@ -1344,14 +1347,13 @@ static enum drm_connector_status | |||
1344 | intel_tv_detect(struct drm_connector *connector, bool force) | 1347 | intel_tv_detect(struct drm_connector *connector, bool force) |
1345 | { | 1348 | { |
1346 | struct drm_display_mode mode; | 1349 | struct drm_display_mode mode; |
1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1350 | struct intel_tv *intel_tv = intel_attached_tv(connector); |
1348 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | ||
1349 | int type; | 1351 | int type; |
1350 | 1352 | ||
1351 | mode = reported_modes[0]; | 1353 | mode = reported_modes[0]; |
1352 | drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); | 1354 | drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); |
1353 | 1355 | ||
1354 | if (encoder->crtc && encoder->crtc->enabled) { | 1356 | if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { |
1355 | type = intel_tv_detect_type(intel_tv); | 1357 | type = intel_tv_detect_type(intel_tv); |
1356 | } else if (force) { | 1358 | } else if (force) { |
1357 | struct drm_crtc *crtc; | 1359 | struct drm_crtc *crtc; |
@@ -1375,11 +1377,10 @@ intel_tv_detect(struct drm_connector *connector, bool force) | |||
1375 | return connector_status_connected; | 1377 | return connector_status_connected; |
1376 | } | 1378 | } |
1377 | 1379 | ||
1378 | static struct input_res { | 1380 | static const struct input_res { |
1379 | char *name; | 1381 | const char *name; |
1380 | int w, h; | 1382 | int w, h; |
1381 | } input_res_table[] = | 1383 | } input_res_table[] = { |
1382 | { | ||
1383 | {"640x480", 640, 480}, | 1384 | {"640x480", 640, 480}, |
1384 | {"800x600", 800, 600}, | 1385 | {"800x600", 800, 600}, |
1385 | {"1024x768", 1024, 768}, | 1386 | {"1024x768", 1024, 768}, |
@@ -1396,8 +1397,7 @@ static void | |||
1396 | intel_tv_chose_preferred_modes(struct drm_connector *connector, | 1397 | intel_tv_chose_preferred_modes(struct drm_connector *connector, |
1397 | struct drm_display_mode *mode_ptr) | 1398 | struct drm_display_mode *mode_ptr) |
1398 | { | 1399 | { |
1399 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1400 | struct intel_tv *intel_tv = intel_attached_tv(connector); |
1400 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | ||
1401 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); | 1401 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); |
1402 | 1402 | ||
1403 | if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480) | 1403 | if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480) |
@@ -1422,15 +1422,14 @@ static int | |||
1422 | intel_tv_get_modes(struct drm_connector *connector) | 1422 | intel_tv_get_modes(struct drm_connector *connector) |
1423 | { | 1423 | { |
1424 | struct drm_display_mode *mode_ptr; | 1424 | struct drm_display_mode *mode_ptr; |
1425 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1425 | struct intel_tv *intel_tv = intel_attached_tv(connector); |
1426 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | ||
1427 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); | 1426 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); |
1428 | int j, count = 0; | 1427 | int j, count = 0; |
1429 | u64 tmp; | 1428 | u64 tmp; |
1430 | 1429 | ||
1431 | for (j = 0; j < ARRAY_SIZE(input_res_table); | 1430 | for (j = 0; j < ARRAY_SIZE(input_res_table); |
1432 | j++) { | 1431 | j++) { |
1433 | struct input_res *input = &input_res_table[j]; | 1432 | const struct input_res *input = &input_res_table[j]; |
1434 | unsigned int hactive_s = input->w; | 1433 | unsigned int hactive_s = input->w; |
1435 | unsigned int vactive_s = input->h; | 1434 | unsigned int vactive_s = input->h; |
1436 | 1435 | ||
@@ -1488,9 +1487,8 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop | |||
1488 | uint64_t val) | 1487 | uint64_t val) |
1489 | { | 1488 | { |
1490 | struct drm_device *dev = connector->dev; | 1489 | struct drm_device *dev = connector->dev; |
1491 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1490 | struct intel_tv *intel_tv = intel_attached_tv(connector); |
1492 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | 1491 | struct drm_crtc *crtc = intel_tv->base.base.crtc; |
1493 | struct drm_crtc *crtc = encoder->crtc; | ||
1494 | int ret = 0; | 1492 | int ret = 0; |
1495 | bool changed = false; | 1493 | bool changed = false; |
1496 | 1494 | ||
@@ -1555,7 +1553,7 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = { | |||
1555 | static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = { | 1553 | static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = { |
1556 | .mode_valid = intel_tv_mode_valid, | 1554 | .mode_valid = intel_tv_mode_valid, |
1557 | .get_modes = intel_tv_get_modes, | 1555 | .get_modes = intel_tv_get_modes, |
1558 | .best_encoder = intel_attached_encoder, | 1556 | .best_encoder = intel_best_encoder, |
1559 | }; | 1557 | }; |
1560 | 1558 | ||
1561 | static const struct drm_encoder_funcs intel_tv_enc_funcs = { | 1559 | static const struct drm_encoder_funcs intel_tv_enc_funcs = { |
@@ -1607,7 +1605,7 @@ intel_tv_init(struct drm_device *dev) | |||
1607 | struct intel_encoder *intel_encoder; | 1605 | struct intel_encoder *intel_encoder; |
1608 | struct intel_connector *intel_connector; | 1606 | struct intel_connector *intel_connector; |
1609 | u32 tv_dac_on, tv_dac_off, save_tv_dac; | 1607 | u32 tv_dac_on, tv_dac_off, save_tv_dac; |
1610 | char **tv_format_names; | 1608 | char *tv_format_names[ARRAY_SIZE(tv_modes)]; |
1611 | int i, initial_mode = 0; | 1609 | int i, initial_mode = 0; |
1612 | 1610 | ||
1613 | if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) | 1611 | if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) |
@@ -1661,15 +1659,15 @@ intel_tv_init(struct drm_device *dev) | |||
1661 | drm_connector_init(dev, connector, &intel_tv_connector_funcs, | 1659 | drm_connector_init(dev, connector, &intel_tv_connector_funcs, |
1662 | DRM_MODE_CONNECTOR_SVIDEO); | 1660 | DRM_MODE_CONNECTOR_SVIDEO); |
1663 | 1661 | ||
1664 | drm_encoder_init(dev, &intel_encoder->enc, &intel_tv_enc_funcs, | 1662 | drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs, |
1665 | DRM_MODE_ENCODER_TVDAC); | 1663 | DRM_MODE_ENCODER_TVDAC); |
1666 | 1664 | ||
1667 | drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc); | 1665 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
1668 | intel_encoder->type = INTEL_OUTPUT_TVOUT; | 1666 | intel_encoder->type = INTEL_OUTPUT_TVOUT; |
1669 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 1667 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
1670 | intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT); | 1668 | intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT); |
1671 | intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1)); | 1669 | intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); |
1672 | intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT); | 1670 | intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT); |
1673 | intel_tv->type = DRM_MODE_CONNECTOR_Unknown; | 1671 | intel_tv->type = DRM_MODE_CONNECTOR_Unknown; |
1674 | 1672 | ||
1675 | /* BIOS margin values */ | 1673 | /* BIOS margin values */ |
@@ -1678,21 +1676,19 @@ intel_tv_init(struct drm_device *dev) | |||
1678 | intel_tv->margin[TV_MARGIN_RIGHT] = 46; | 1676 | intel_tv->margin[TV_MARGIN_RIGHT] = 46; |
1679 | intel_tv->margin[TV_MARGIN_BOTTOM] = 37; | 1677 | intel_tv->margin[TV_MARGIN_BOTTOM] = 37; |
1680 | 1678 | ||
1681 | intel_tv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL); | 1679 | intel_tv->tv_format = tv_modes[initial_mode].name; |
1682 | 1680 | ||
1683 | drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs); | 1681 | drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs); |
1684 | drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); | 1682 | drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); |
1685 | connector->interlace_allowed = false; | 1683 | connector->interlace_allowed = false; |
1686 | connector->doublescan_allowed = false; | 1684 | connector->doublescan_allowed = false; |
1687 | 1685 | ||
1688 | /* Create TV properties then attach current values */ | 1686 | /* Create TV properties then attach current values */ |
1689 | tv_format_names = kmalloc(sizeof(char *) * ARRAY_SIZE(tv_modes), | ||
1690 | GFP_KERNEL); | ||
1691 | if (!tv_format_names) | ||
1692 | goto out; | ||
1693 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) | 1687 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) |
1694 | tv_format_names[i] = tv_modes[i].name; | 1688 | tv_format_names[i] = (char *)tv_modes[i].name; |
1695 | drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names); | 1689 | drm_mode_create_tv_properties(dev, |
1690 | ARRAY_SIZE(tv_modes), | ||
1691 | tv_format_names); | ||
1696 | 1692 | ||
1697 | drm_connector_attach_property(connector, dev->mode_config.tv_mode_property, | 1693 | drm_connector_attach_property(connector, dev->mode_config.tv_mode_property, |
1698 | initial_mode); | 1694 | initial_mode); |
@@ -1708,6 +1704,5 @@ intel_tv_init(struct drm_device *dev) | |||
1708 | drm_connector_attach_property(connector, | 1704 | drm_connector_attach_property(connector, |
1709 | dev->mode_config.tv_bottom_margin_property, | 1705 | dev->mode_config.tv_bottom_margin_property, |
1710 | intel_tv->margin[TV_MARGIN_BOTTOM]); | 1706 | intel_tv->margin[TV_MARGIN_BOTTOM]); |
1711 | out: | ||
1712 | drm_sysfs_connector_add(connector); | 1707 | drm_sysfs_connector_add(connector); |
1713 | } | 1708 | } |
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 26d0d8ced80d..65ea42cf1795 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c | |||
@@ -60,8 +60,6 @@ static struct drm_driver driver = { | |||
60 | .irq_uninstall = mga_driver_irq_uninstall, | 60 | .irq_uninstall = mga_driver_irq_uninstall, |
61 | .irq_handler = mga_driver_irq_handler, | 61 | .irq_handler = mga_driver_irq_handler, |
62 | .reclaim_buffers = drm_core_reclaim_buffers, | 62 | .reclaim_buffers = drm_core_reclaim_buffers, |
63 | .get_map_ofs = drm_core_get_map_ofs, | ||
64 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
65 | .ioctls = mga_ioctls, | 63 | .ioctls = mga_ioctls, |
66 | .dma_ioctl = mga_dma_buffers, | 64 | .dma_ioctl = mga_dma_buffers, |
67 | .fops = { | 65 | .fops = { |
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index d2d28048efb2..72730e9ca06c 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig | |||
@@ -10,6 +10,7 @@ config DRM_NOUVEAU | |||
10 | select FB | 10 | select FB |
11 | select FRAMEBUFFER_CONSOLE if !EMBEDDED | 11 | select FRAMEBUFFER_CONSOLE if !EMBEDDED |
12 | select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT | 12 | select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT |
13 | select ACPI_VIDEO if ACPI | ||
13 | help | 14 | help |
14 | Choose this option for open-source nVidia support. | 15 | Choose this option for open-source nVidia support. |
15 | 16 | ||
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index e9b06e4ef2a2..23fa82d667d6 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -9,7 +9,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
9 | nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ | 9 | nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ |
10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ | 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ |
11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ | 11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ |
12 | nouveau_dp.o \ | 12 | nouveau_dp.o nouveau_ramht.o \ |
13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ | ||
13 | nv04_timer.o \ | 14 | nv04_timer.o \ |
14 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 15 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ | 16 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ |
@@ -23,7 +24,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ | 24 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ |
24 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ | 25 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ |
25 | nv10_gpio.o nv50_gpio.o \ | 26 | nv10_gpio.o nv50_gpio.o \ |
26 | nv50_calc.o | 27 | nv50_calc.o \ |
28 | nv04_pm.o nv50_pm.o nva3_pm.o | ||
27 | 29 | ||
28 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o | 30 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o |
29 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o | 31 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index c17a055ee3e5..119152606e4c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -292,6 +292,6 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) | |||
292 | if (ret < 0) | 292 | if (ret < 0) |
293 | return ret; | 293 | return ret; |
294 | 294 | ||
295 | nv_connector->edid = edid; | 295 | nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); |
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 974b0f8ae048..53f4eba65cb9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -43,9 +43,6 @@ | |||
43 | #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg) | 43 | #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg) |
44 | #define LOG_OLD_VALUE(x) | 44 | #define LOG_OLD_VALUE(x) |
45 | 45 | ||
46 | #define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) | ||
47 | #define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) | ||
48 | |||
49 | struct init_exec { | 46 | struct init_exec { |
50 | bool execute; | 47 | bool execute; |
51 | bool repeat; | 48 | bool repeat; |
@@ -272,12 +269,6 @@ struct init_tbl_entry { | |||
272 | int (*handler)(struct nvbios *, uint16_t, struct init_exec *); | 269 | int (*handler)(struct nvbios *, uint16_t, struct init_exec *); |
273 | }; | 270 | }; |
274 | 271 | ||
275 | struct bit_entry { | ||
276 | uint8_t id[2]; | ||
277 | uint16_t length; | ||
278 | uint16_t offset; | ||
279 | }; | ||
280 | |||
281 | static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *); | 272 | static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *); |
282 | 273 | ||
283 | #define MACRO_INDEX_SIZE 2 | 274 | #define MACRO_INDEX_SIZE 2 |
@@ -1231,7 +1222,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1231 | return 3; | 1222 | return 3; |
1232 | } | 1223 | } |
1233 | 1224 | ||
1234 | if (cond & 1) | 1225 | if (!(cond & 1)) |
1235 | iexec->execute = false; | 1226 | iexec->execute = false; |
1236 | } | 1227 | } |
1237 | break; | 1228 | break; |
@@ -4675,6 +4666,92 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i | |||
4675 | return 0; | 4666 | return 0; |
4676 | } | 4667 | } |
4677 | 4668 | ||
4669 | struct pll_mapping { | ||
4670 | u8 type; | ||
4671 | u32 reg; | ||
4672 | }; | ||
4673 | |||
4674 | static struct pll_mapping nv04_pll_mapping[] = { | ||
4675 | { PLL_CORE , NV_PRAMDAC_NVPLL_COEFF }, | ||
4676 | { PLL_MEMORY, NV_PRAMDAC_MPLL_COEFF }, | ||
4677 | { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, | ||
4678 | { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, | ||
4679 | {} | ||
4680 | }; | ||
4681 | |||
4682 | static struct pll_mapping nv40_pll_mapping[] = { | ||
4683 | { PLL_CORE , 0x004000 }, | ||
4684 | { PLL_MEMORY, 0x004020 }, | ||
4685 | { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, | ||
4686 | { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, | ||
4687 | {} | ||
4688 | }; | ||
4689 | |||
4690 | static struct pll_mapping nv50_pll_mapping[] = { | ||
4691 | { PLL_CORE , 0x004028 }, | ||
4692 | { PLL_SHADER, 0x004020 }, | ||
4693 | { PLL_UNK03 , 0x004000 }, | ||
4694 | { PLL_MEMORY, 0x004008 }, | ||
4695 | { PLL_UNK40 , 0x00e810 }, | ||
4696 | { PLL_UNK41 , 0x00e818 }, | ||
4697 | { PLL_UNK42 , 0x00e824 }, | ||
4698 | { PLL_VPLL0 , 0x614100 }, | ||
4699 | { PLL_VPLL1 , 0x614900 }, | ||
4700 | {} | ||
4701 | }; | ||
4702 | |||
4703 | static struct pll_mapping nv84_pll_mapping[] = { | ||
4704 | { PLL_CORE , 0x004028 }, | ||
4705 | { PLL_SHADER, 0x004020 }, | ||
4706 | { PLL_MEMORY, 0x004008 }, | ||
4707 | { PLL_UNK05 , 0x004030 }, | ||
4708 | { PLL_UNK41 , 0x00e818 }, | ||
4709 | { PLL_VPLL0 , 0x614100 }, | ||
4710 | { PLL_VPLL1 , 0x614900 }, | ||
4711 | {} | ||
4712 | }; | ||
4713 | |||
4714 | u32 | ||
4715 | get_pll_register(struct drm_device *dev, enum pll_types type) | ||
4716 | { | ||
4717 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
4718 | struct nvbios *bios = &dev_priv->vbios; | ||
4719 | struct pll_mapping *map; | ||
4720 | int i; | ||
4721 | |||
4722 | if (dev_priv->card_type < NV_40) | ||
4723 | map = nv04_pll_mapping; | ||
4724 | else | ||
4725 | if (dev_priv->card_type < NV_50) | ||
4726 | map = nv40_pll_mapping; | ||
4727 | else { | ||
4728 | u8 *plim = &bios->data[bios->pll_limit_tbl_ptr]; | ||
4729 | |||
4730 | if (plim[0] >= 0x30) { | ||
4731 | u8 *entry = plim + plim[1]; | ||
4732 | for (i = 0; i < plim[3]; i++, entry += plim[2]) { | ||
4733 | if (entry[0] == type) | ||
4734 | return ROM32(entry[3]); | ||
4735 | } | ||
4736 | |||
4737 | return 0; | ||
4738 | } | ||
4739 | |||
4740 | if (dev_priv->chipset == 0x50) | ||
4741 | map = nv50_pll_mapping; | ||
4742 | else | ||
4743 | map = nv84_pll_mapping; | ||
4744 | } | ||
4745 | |||
4746 | while (map->reg) { | ||
4747 | if (map->type == type) | ||
4748 | return map->reg; | ||
4749 | map++; | ||
4750 | } | ||
4751 | |||
4752 | return 0; | ||
4753 | } | ||
4754 | |||
4678 | int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) | 4755 | int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) |
4679 | { | 4756 | { |
4680 | /* | 4757 | /* |
@@ -4750,6 +4827,17 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4750 | /* initialize all members to zero */ | 4827 | /* initialize all members to zero */ |
4751 | memset(pll_lim, 0, sizeof(struct pll_lims)); | 4828 | memset(pll_lim, 0, sizeof(struct pll_lims)); |
4752 | 4829 | ||
4830 | /* if we were passed a type rather than a register, figure | ||
4831 | * out the register and store it | ||
4832 | */ | ||
4833 | if (limit_match > PLL_MAX) | ||
4834 | pll_lim->reg = limit_match; | ||
4835 | else { | ||
4836 | pll_lim->reg = get_pll_register(dev, limit_match); | ||
4837 | if (!pll_lim->reg) | ||
4838 | return -ENOENT; | ||
4839 | } | ||
4840 | |||
4753 | if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { | 4841 | if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { |
4754 | uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; | 4842 | uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; |
4755 | 4843 | ||
@@ -4785,7 +4873,6 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4785 | pll_lim->max_usable_log2p = 0x6; | 4873 | pll_lim->max_usable_log2p = 0x6; |
4786 | } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { | 4874 | } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { |
4787 | uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; | 4875 | uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; |
4788 | uint32_t reg = 0; /* default match */ | ||
4789 | uint8_t *pll_rec; | 4876 | uint8_t *pll_rec; |
4790 | int i; | 4877 | int i; |
4791 | 4878 | ||
@@ -4797,37 +4884,22 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4797 | NV_WARN(dev, "Default PLL limit entry has non-zero " | 4884 | NV_WARN(dev, "Default PLL limit entry has non-zero " |
4798 | "register field\n"); | 4885 | "register field\n"); |
4799 | 4886 | ||
4800 | if (limit_match > MAX_PLL_TYPES) | ||
4801 | /* we've been passed a reg as the match */ | ||
4802 | reg = limit_match; | ||
4803 | else /* limit match is a pll type */ | ||
4804 | for (i = 1; i < entries && !reg; i++) { | ||
4805 | uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]); | ||
4806 | |||
4807 | if (limit_match == NVPLL && | ||
4808 | (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000)) | ||
4809 | reg = cmpreg; | ||
4810 | if (limit_match == MPLL && | ||
4811 | (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020)) | ||
4812 | reg = cmpreg; | ||
4813 | if (limit_match == VPLL1 && | ||
4814 | (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010)) | ||
4815 | reg = cmpreg; | ||
4816 | if (limit_match == VPLL2 && | ||
4817 | (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018)) | ||
4818 | reg = cmpreg; | ||
4819 | } | ||
4820 | |||
4821 | for (i = 1; i < entries; i++) | 4887 | for (i = 1; i < entries; i++) |
4822 | if (ROM32(bios->data[plloffs + recordlen * i]) == reg) { | 4888 | if (ROM32(bios->data[plloffs + recordlen * i]) == pll_lim->reg) { |
4823 | pllindex = i; | 4889 | pllindex = i; |
4824 | break; | 4890 | break; |
4825 | } | 4891 | } |
4826 | 4892 | ||
4893 | if ((dev_priv->card_type >= NV_50) && (pllindex == 0)) { | ||
4894 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | ||
4895 | "limits table", pll_lim->reg); | ||
4896 | return -ENOENT; | ||
4897 | } | ||
4898 | |||
4827 | pll_rec = &bios->data[plloffs + recordlen * pllindex]; | 4899 | pll_rec = &bios->data[plloffs + recordlen * pllindex]; |
4828 | 4900 | ||
4829 | BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", | 4901 | BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", |
4830 | pllindex ? reg : 0); | 4902 | pllindex ? pll_lim->reg : 0); |
4831 | 4903 | ||
4832 | /* | 4904 | /* |
4833 | * Frequencies are stored in tables in MHz, kHz are more | 4905 | * Frequencies are stored in tables in MHz, kHz are more |
@@ -4877,8 +4949,8 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4877 | if (cv == 0x51 && !pll_lim->refclk) { | 4949 | if (cv == 0x51 && !pll_lim->refclk) { |
4878 | uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); | 4950 | uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); |
4879 | 4951 | ||
4880 | if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) || | 4952 | if ((pll_lim->reg == NV_PRAMDAC_VPLL_COEFF && sel_clk & 0x20) || |
4881 | ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) { | 4953 | (pll_lim->reg == NV_RAMDAC_VPLL2 && sel_clk & 0x80)) { |
4882 | if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) | 4954 | if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) |
4883 | pll_lim->refclk = 200000; | 4955 | pll_lim->refclk = 200000; |
4884 | else | 4956 | else |
@@ -4891,10 +4963,10 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4891 | int i; | 4963 | int i; |
4892 | 4964 | ||
4893 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", | 4965 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", |
4894 | limit_match); | 4966 | pll_lim->reg); |
4895 | 4967 | ||
4896 | for (i = 0; i < entries; i++, entry += recordlen) { | 4968 | for (i = 0; i < entries; i++, entry += recordlen) { |
4897 | if (ROM32(entry[3]) == limit_match) { | 4969 | if (ROM32(entry[3]) == pll_lim->reg) { |
4898 | record = &bios->data[ROM16(entry[1])]; | 4970 | record = &bios->data[ROM16(entry[1])]; |
4899 | break; | 4971 | break; |
4900 | } | 4972 | } |
@@ -4902,7 +4974,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4902 | 4974 | ||
4903 | if (!record) { | 4975 | if (!record) { |
4904 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | 4976 | NV_ERROR(dev, "Register 0x%08x not found in PLL " |
4905 | "limits table", limit_match); | 4977 | "limits table", pll_lim->reg); |
4906 | return -ENOENT; | 4978 | return -ENOENT; |
4907 | } | 4979 | } |
4908 | 4980 | ||
@@ -4931,10 +5003,10 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4931 | int i; | 5003 | int i; |
4932 | 5004 | ||
4933 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", | 5005 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", |
4934 | limit_match); | 5006 | pll_lim->reg); |
4935 | 5007 | ||
4936 | for (i = 0; i < entries; i++, entry += recordlen) { | 5008 | for (i = 0; i < entries; i++, entry += recordlen) { |
4937 | if (ROM32(entry[3]) == limit_match) { | 5009 | if (ROM32(entry[3]) == pll_lim->reg) { |
4938 | record = &bios->data[ROM16(entry[1])]; | 5010 | record = &bios->data[ROM16(entry[1])]; |
4939 | break; | 5011 | break; |
4940 | } | 5012 | } |
@@ -4942,7 +5014,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4942 | 5014 | ||
4943 | if (!record) { | 5015 | if (!record) { |
4944 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | 5016 | NV_ERROR(dev, "Register 0x%08x not found in PLL " |
4945 | "limits table", limit_match); | 5017 | "limits table", pll_lim->reg); |
4946 | return -ENOENT; | 5018 | return -ENOENT; |
4947 | } | 5019 | } |
4948 | 5020 | ||
@@ -5293,7 +5365,7 @@ parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios, | |||
5293 | if (bitentry->length < 0x5) | 5365 | if (bitentry->length < 0x5) |
5294 | return 0; | 5366 | return 0; |
5295 | 5367 | ||
5296 | if (bitentry->id[1] < 2) { | 5368 | if (bitentry->version < 2) { |
5297 | bios->ram_restrict_group_count = bios->data[bitentry->offset + 2]; | 5369 | bios->ram_restrict_group_count = bios->data[bitentry->offset + 2]; |
5298 | bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]); | 5370 | bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]); |
5299 | } else { | 5371 | } else { |
@@ -5403,27 +5475,40 @@ struct bit_table { | |||
5403 | 5475 | ||
5404 | #define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry }) | 5476 | #define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry }) |
5405 | 5477 | ||
5478 | int | ||
5479 | bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) | ||
5480 | { | ||
5481 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
5482 | struct nvbios *bios = &dev_priv->vbios; | ||
5483 | u8 entries, *entry; | ||
5484 | |||
5485 | entries = bios->data[bios->offset + 10]; | ||
5486 | entry = &bios->data[bios->offset + 12]; | ||
5487 | while (entries--) { | ||
5488 | if (entry[0] == id) { | ||
5489 | bit->id = entry[0]; | ||
5490 | bit->version = entry[1]; | ||
5491 | bit->length = ROM16(entry[2]); | ||
5492 | bit->offset = ROM16(entry[4]); | ||
5493 | bit->data = ROMPTR(bios, entry[4]); | ||
5494 | return 0; | ||
5495 | } | ||
5496 | |||
5497 | entry += bios->data[bios->offset + 9]; | ||
5498 | } | ||
5499 | |||
5500 | return -ENOENT; | ||
5501 | } | ||
5502 | |||
5406 | static int | 5503 | static int |
5407 | parse_bit_table(struct nvbios *bios, const uint16_t bitoffset, | 5504 | parse_bit_table(struct nvbios *bios, const uint16_t bitoffset, |
5408 | struct bit_table *table) | 5505 | struct bit_table *table) |
5409 | { | 5506 | { |
5410 | struct drm_device *dev = bios->dev; | 5507 | struct drm_device *dev = bios->dev; |
5411 | uint8_t maxentries = bios->data[bitoffset + 4]; | ||
5412 | int i, offset; | ||
5413 | struct bit_entry bitentry; | 5508 | struct bit_entry bitentry; |
5414 | 5509 | ||
5415 | for (i = 0, offset = bitoffset + 6; i < maxentries; i++, offset += 6) { | 5510 | if (bit_table(dev, table->id, &bitentry) == 0) |
5416 | bitentry.id[0] = bios->data[offset]; | ||
5417 | |||
5418 | if (bitentry.id[0] != table->id) | ||
5419 | continue; | ||
5420 | |||
5421 | bitentry.id[1] = bios->data[offset + 1]; | ||
5422 | bitentry.length = ROM16(bios->data[offset + 2]); | ||
5423 | bitentry.offset = ROM16(bios->data[offset + 4]); | ||
5424 | |||
5425 | return table->parse_fn(dev, bios, &bitentry); | 5511 | return table->parse_fn(dev, bios, &bitentry); |
5426 | } | ||
5427 | 5512 | ||
5428 | NV_INFO(dev, "BIT table '%c' not found\n", table->id); | 5513 | NV_INFO(dev, "BIT table '%c' not found\n", table->id); |
5429 | return -ENOSYS; | 5514 | return -ENOSYS; |
@@ -5683,8 +5768,14 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) | |||
5683 | static struct dcb_gpio_entry * | 5768 | static struct dcb_gpio_entry * |
5684 | new_gpio_entry(struct nvbios *bios) | 5769 | new_gpio_entry(struct nvbios *bios) |
5685 | { | 5770 | { |
5771 | struct drm_device *dev = bios->dev; | ||
5686 | struct dcb_gpio_table *gpio = &bios->dcb.gpio; | 5772 | struct dcb_gpio_table *gpio = &bios->dcb.gpio; |
5687 | 5773 | ||
5774 | if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) { | ||
5775 | NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n"); | ||
5776 | return NULL; | ||
5777 | } | ||
5778 | |||
5688 | return &gpio->entry[gpio->entries++]; | 5779 | return &gpio->entry[gpio->entries++]; |
5689 | } | 5780 | } |
5690 | 5781 | ||
@@ -5706,113 +5797,90 @@ nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag) | |||
5706 | } | 5797 | } |
5707 | 5798 | ||
5708 | static void | 5799 | static void |
5709 | parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset) | ||
5710 | { | ||
5711 | struct dcb_gpio_entry *gpio; | ||
5712 | uint16_t ent = ROM16(bios->data[offset]); | ||
5713 | uint8_t line = ent & 0x1f, | ||
5714 | tag = ent >> 5 & 0x3f, | ||
5715 | flags = ent >> 11 & 0x1f; | ||
5716 | |||
5717 | if (tag == 0x3f) | ||
5718 | return; | ||
5719 | |||
5720 | gpio = new_gpio_entry(bios); | ||
5721 | |||
5722 | gpio->tag = tag; | ||
5723 | gpio->line = line; | ||
5724 | gpio->invert = flags != 4; | ||
5725 | gpio->entry = ent; | ||
5726 | } | ||
5727 | |||
5728 | static void | ||
5729 | parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset) | ||
5730 | { | ||
5731 | uint32_t entry = ROM32(bios->data[offset]); | ||
5732 | struct dcb_gpio_entry *gpio; | ||
5733 | |||
5734 | if ((entry & 0x0000ff00) == 0x0000ff00) | ||
5735 | return; | ||
5736 | |||
5737 | gpio = new_gpio_entry(bios); | ||
5738 | gpio->tag = (entry & 0x0000ff00) >> 8; | ||
5739 | gpio->line = (entry & 0x0000001f) >> 0; | ||
5740 | gpio->state_default = (entry & 0x01000000) >> 24; | ||
5741 | gpio->state[0] = (entry & 0x18000000) >> 27; | ||
5742 | gpio->state[1] = (entry & 0x60000000) >> 29; | ||
5743 | gpio->entry = entry; | ||
5744 | } | ||
5745 | |||
5746 | static void | ||
5747 | parse_dcb_gpio_table(struct nvbios *bios) | 5800 | parse_dcb_gpio_table(struct nvbios *bios) |
5748 | { | 5801 | { |
5749 | struct drm_device *dev = bios->dev; | 5802 | struct drm_device *dev = bios->dev; |
5750 | uint16_t gpio_table_ptr = bios->dcb.gpio_table_ptr; | 5803 | struct dcb_gpio_entry *e; |
5751 | uint8_t *gpio_table = &bios->data[gpio_table_ptr]; | 5804 | u8 headerlen, entries, recordlen; |
5752 | int header_len = gpio_table[1], | 5805 | u8 *dcb, *gpio = NULL, *entry; |
5753 | entries = gpio_table[2], | ||
5754 | entry_len = gpio_table[3]; | ||
5755 | void (*parse_entry)(struct nvbios *, uint16_t) = NULL; | ||
5756 | int i; | 5806 | int i; |
5757 | 5807 | ||
5758 | if (bios->dcb.version >= 0x40) { | 5808 | dcb = ROMPTR(bios, bios->data[0x36]); |
5759 | if (gpio_table_ptr && entry_len != 4) { | 5809 | if (dcb[0] >= 0x30) { |
5760 | NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); | 5810 | gpio = ROMPTR(bios, dcb[10]); |
5761 | return; | 5811 | if (!gpio) |
5762 | } | 5812 | goto no_table; |
5763 | 5813 | ||
5764 | parse_entry = parse_dcb40_gpio_entry; | 5814 | headerlen = gpio[1]; |
5815 | entries = gpio[2]; | ||
5816 | recordlen = gpio[3]; | ||
5817 | } else | ||
5818 | if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) { | ||
5819 | gpio = ROMPTR(bios, dcb[-15]); | ||
5820 | if (!gpio) | ||
5821 | goto no_table; | ||
5822 | |||
5823 | headerlen = 3; | ||
5824 | entries = gpio[2]; | ||
5825 | recordlen = gpio[1]; | ||
5826 | } else | ||
5827 | if (dcb[0] >= 0x22) { | ||
5828 | /* No GPIO table present, parse the TVDAC GPIO data. */ | ||
5829 | uint8_t *tvdac_gpio = &dcb[-5]; | ||
5765 | 5830 | ||
5766 | } else if (bios->dcb.version >= 0x30) { | 5831 | if (tvdac_gpio[0] & 1) { |
5767 | if (gpio_table_ptr && entry_len != 2) { | 5832 | e = new_gpio_entry(bios); |
5768 | NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); | 5833 | e->tag = DCB_GPIO_TVDAC0; |
5769 | return; | 5834 | e->line = tvdac_gpio[1] >> 4; |
5835 | e->invert = tvdac_gpio[0] & 2; | ||
5770 | } | 5836 | } |
5771 | 5837 | ||
5772 | parse_entry = parse_dcb30_gpio_entry; | 5838 | goto no_table; |
5773 | 5839 | } else { | |
5774 | } else if (bios->dcb.version >= 0x22) { | 5840 | NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]); |
5775 | /* | 5841 | goto no_table; |
5776 | * DCBs older than v3.0 don't really have a GPIO | 5842 | } |
5777 | * table, instead they keep some GPIO info at fixed | ||
5778 | * locations. | ||
5779 | */ | ||
5780 | uint16_t dcbptr = ROM16(bios->data[0x36]); | ||
5781 | uint8_t *tvdac_gpio = &bios->data[dcbptr - 5]; | ||
5782 | 5843 | ||
5783 | if (tvdac_gpio[0] & 1) { | 5844 | entry = gpio + headerlen; |
5784 | struct dcb_gpio_entry *gpio = new_gpio_entry(bios); | 5845 | for (i = 0; i < entries; i++, entry += recordlen) { |
5846 | e = new_gpio_entry(bios); | ||
5847 | if (!e) | ||
5848 | break; | ||
5785 | 5849 | ||
5786 | gpio->tag = DCB_GPIO_TVDAC0; | 5850 | if (gpio[0] < 0x40) { |
5787 | gpio->line = tvdac_gpio[1] >> 4; | 5851 | e->entry = ROM16(entry[0]); |
5788 | gpio->invert = tvdac_gpio[0] & 2; | 5852 | e->tag = (e->entry & 0x07e0) >> 5; |
5789 | } | 5853 | if (e->tag == 0x3f) { |
5790 | } else { | 5854 | bios->dcb.gpio.entries--; |
5791 | /* | 5855 | continue; |
5792 | * No systematic way to store GPIO info on pre-v2.2 | 5856 | } |
5793 | * DCBs, try to match the PCI device IDs. | ||
5794 | */ | ||
5795 | 5857 | ||
5796 | /* Apple iMac G4 NV18 */ | 5858 | e->line = (e->entry & 0x001f); |
5797 | if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { | 5859 | e->invert = ((e->entry & 0xf800) >> 11) != 4; |
5798 | struct dcb_gpio_entry *gpio = new_gpio_entry(bios); | 5860 | } else { |
5861 | e->entry = ROM32(entry[0]); | ||
5862 | e->tag = (e->entry & 0x0000ff00) >> 8; | ||
5863 | if (e->tag == 0xff) { | ||
5864 | bios->dcb.gpio.entries--; | ||
5865 | continue; | ||
5866 | } | ||
5799 | 5867 | ||
5800 | gpio->tag = DCB_GPIO_TVDAC0; | 5868 | e->line = (e->entry & 0x0000001f) >> 0; |
5801 | gpio->line = 4; | 5869 | e->state_default = (e->entry & 0x01000000) >> 24; |
5870 | e->state[0] = (e->entry & 0x18000000) >> 27; | ||
5871 | e->state[1] = (e->entry & 0x60000000) >> 29; | ||
5802 | } | 5872 | } |
5803 | |||
5804 | } | 5873 | } |
5805 | 5874 | ||
5806 | if (!gpio_table_ptr) | 5875 | no_table: |
5807 | return; | 5876 | /* Apple iMac G4 NV18 */ |
5808 | 5877 | if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { | |
5809 | if (entries > DCB_MAX_NUM_GPIO_ENTRIES) { | 5878 | e = new_gpio_entry(bios); |
5810 | NV_WARN(dev, "Too many entries in the DCB GPIO table.\n"); | 5879 | if (e) { |
5811 | entries = DCB_MAX_NUM_GPIO_ENTRIES; | 5880 | e->tag = DCB_GPIO_TVDAC0; |
5881 | e->line = 4; | ||
5882 | } | ||
5812 | } | 5883 | } |
5813 | |||
5814 | for (i = 0; i < entries; i++) | ||
5815 | parse_entry(bios, gpio_table_ptr + header_len + entry_len * i); | ||
5816 | } | 5884 | } |
5817 | 5885 | ||
5818 | struct dcb_connector_table_entry * | 5886 | struct dcb_connector_table_entry * |
@@ -6680,6 +6748,8 @@ static int nouveau_parse_vbios_struct(struct drm_device *dev) | |||
6680 | bit_signature, sizeof(bit_signature)); | 6748 | bit_signature, sizeof(bit_signature)); |
6681 | if (offset) { | 6749 | if (offset) { |
6682 | NV_TRACE(dev, "BIT BIOS found\n"); | 6750 | NV_TRACE(dev, "BIT BIOS found\n"); |
6751 | bios->type = NVBIOS_BIT; | ||
6752 | bios->offset = offset; | ||
6683 | return parse_bit_structure(bios, offset + 6); | 6753 | return parse_bit_structure(bios, offset + 6); |
6684 | } | 6754 | } |
6685 | 6755 | ||
@@ -6687,6 +6757,8 @@ static int nouveau_parse_vbios_struct(struct drm_device *dev) | |||
6687 | bmp_signature, sizeof(bmp_signature)); | 6757 | bmp_signature, sizeof(bmp_signature)); |
6688 | if (offset) { | 6758 | if (offset) { |
6689 | NV_TRACE(dev, "BMP BIOS found\n"); | 6759 | NV_TRACE(dev, "BMP BIOS found\n"); |
6760 | bios->type = NVBIOS_BMP; | ||
6761 | bios->offset = offset; | ||
6690 | return parse_bmp_structure(dev, bios, offset); | 6762 | return parse_bmp_structure(dev, bios, offset); |
6691 | } | 6763 | } |
6692 | 6764 | ||
@@ -6806,6 +6878,8 @@ nouveau_bios_init(struct drm_device *dev) | |||
6806 | "running VBIOS init tables.\n"); | 6878 | "running VBIOS init tables.\n"); |
6807 | bios->execute = true; | 6879 | bios->execute = true; |
6808 | } | 6880 | } |
6881 | if (nouveau_force_post) | ||
6882 | bios->execute = true; | ||
6809 | 6883 | ||
6810 | ret = nouveau_run_vbios_init(dev); | 6884 | ret = nouveau_run_vbios_init(dev); |
6811 | if (ret) | 6885 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index c1de2f3fcb0e..50a648e01c49 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -34,6 +34,20 @@ | |||
34 | 34 | ||
35 | #define DCB_LOC_ON_CHIP 0 | 35 | #define DCB_LOC_ON_CHIP 0 |
36 | 36 | ||
37 | #define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) | ||
38 | #define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) | ||
39 | #define ROMPTR(bios, x) (ROM16(x) ? &(bios)->data[ROM16(x)] : NULL) | ||
40 | |||
41 | struct bit_entry { | ||
42 | uint8_t id; | ||
43 | uint8_t version; | ||
44 | uint16_t length; | ||
45 | uint16_t offset; | ||
46 | uint8_t *data; | ||
47 | }; | ||
48 | |||
49 | int bit_table(struct drm_device *, u8 id, struct bit_entry *); | ||
50 | |||
37 | struct dcb_i2c_entry { | 51 | struct dcb_i2c_entry { |
38 | uint32_t entry; | 52 | uint32_t entry; |
39 | uint8_t port_type; | 53 | uint8_t port_type; |
@@ -170,16 +184,28 @@ enum LVDS_script { | |||
170 | LVDS_PANEL_OFF | 184 | LVDS_PANEL_OFF |
171 | }; | 185 | }; |
172 | 186 | ||
173 | /* changing these requires matching changes to reg tables in nv_get_clock */ | 187 | /* these match types in pll limits table version 0x40, |
174 | #define MAX_PLL_TYPES 4 | 188 | * nouveau uses them on all chipsets internally where a |
189 | * specific pll needs to be referenced, but the exact | ||
190 | * register isn't known. | ||
191 | */ | ||
175 | enum pll_types { | 192 | enum pll_types { |
176 | NVPLL, | 193 | PLL_CORE = 0x01, |
177 | MPLL, | 194 | PLL_SHADER = 0x02, |
178 | VPLL1, | 195 | PLL_UNK03 = 0x03, |
179 | VPLL2 | 196 | PLL_MEMORY = 0x04, |
197 | PLL_UNK05 = 0x05, | ||
198 | PLL_UNK40 = 0x40, | ||
199 | PLL_UNK41 = 0x41, | ||
200 | PLL_UNK42 = 0x42, | ||
201 | PLL_VPLL0 = 0x80, | ||
202 | PLL_VPLL1 = 0x81, | ||
203 | PLL_MAX = 0xff | ||
180 | }; | 204 | }; |
181 | 205 | ||
182 | struct pll_lims { | 206 | struct pll_lims { |
207 | u32 reg; | ||
208 | |||
183 | struct { | 209 | struct { |
184 | int minfreq; | 210 | int minfreq; |
185 | int maxfreq; | 211 | int maxfreq; |
@@ -212,6 +238,11 @@ struct pll_lims { | |||
212 | 238 | ||
213 | struct nvbios { | 239 | struct nvbios { |
214 | struct drm_device *dev; | 240 | struct drm_device *dev; |
241 | enum { | ||
242 | NVBIOS_BMP, | ||
243 | NVBIOS_BIT | ||
244 | } type; | ||
245 | uint16_t offset; | ||
215 | 246 | ||
216 | uint8_t chip_version; | 247 | uint8_t chip_version; |
217 | 248 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index f6f44779d82f..80353e2b8409 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -36,21 +36,6 @@ | |||
36 | #include <linux/log2.h> | 36 | #include <linux/log2.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | 38 | ||
39 | int | ||
40 | nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan) | ||
41 | { | ||
42 | struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; | ||
43 | int ret; | ||
44 | |||
45 | if (!prev_fence || nouveau_fence_channel(prev_fence) == chan) | ||
46 | return 0; | ||
47 | |||
48 | spin_lock(&nvbo->bo.lock); | ||
49 | ret = ttm_bo_wait(&nvbo->bo, false, false, false); | ||
50 | spin_unlock(&nvbo->bo.lock); | ||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static void | 39 | static void |
55 | nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | 40 | nouveau_bo_del_ttm(struct ttm_buffer_object *bo) |
56 | { | 41 | { |
@@ -58,8 +43,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | |||
58 | struct drm_device *dev = dev_priv->dev; | 43 | struct drm_device *dev = dev_priv->dev; |
59 | struct nouveau_bo *nvbo = nouveau_bo(bo); | 44 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
60 | 45 | ||
61 | ttm_bo_kunmap(&nvbo->kmap); | ||
62 | |||
63 | if (unlikely(nvbo->gem)) | 46 | if (unlikely(nvbo->gem)) |
64 | DRM_ERROR("bo %p still attached to GEM object\n", bo); | 47 | DRM_ERROR("bo %p still attached to GEM object\n", bo); |
65 | 48 | ||
@@ -164,8 +147,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
164 | nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); | 147 | nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); |
165 | align >>= PAGE_SHIFT; | 148 | align >>= PAGE_SHIFT; |
166 | 149 | ||
167 | nvbo->placement.fpfn = 0; | ||
168 | nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0; | ||
169 | nouveau_bo_placement_set(nvbo, flags, 0); | 150 | nouveau_bo_placement_set(nvbo, flags, 0); |
170 | 151 | ||
171 | nvbo->channel = chan; | 152 | nvbo->channel = chan; |
@@ -305,7 +286,8 @@ nouveau_bo_map(struct nouveau_bo *nvbo) | |||
305 | void | 286 | void |
306 | nouveau_bo_unmap(struct nouveau_bo *nvbo) | 287 | nouveau_bo_unmap(struct nouveau_bo *nvbo) |
307 | { | 288 | { |
308 | ttm_bo_kunmap(&nvbo->kmap); | 289 | if (nvbo) |
290 | ttm_bo_kunmap(&nvbo->kmap); | ||
309 | } | 291 | } |
310 | 292 | ||
311 | u16 | 293 | u16 |
@@ -399,14 +381,19 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
399 | man->default_caching = TTM_PL_FLAG_CACHED; | 381 | man->default_caching = TTM_PL_FLAG_CACHED; |
400 | break; | 382 | break; |
401 | case TTM_PL_VRAM: | 383 | case TTM_PL_VRAM: |
384 | man->func = &ttm_bo_manager_func; | ||
402 | man->flags = TTM_MEMTYPE_FLAG_FIXED | | 385 | man->flags = TTM_MEMTYPE_FLAG_FIXED | |
403 | TTM_MEMTYPE_FLAG_MAPPABLE; | 386 | TTM_MEMTYPE_FLAG_MAPPABLE; |
404 | man->available_caching = TTM_PL_FLAG_UNCACHED | | 387 | man->available_caching = TTM_PL_FLAG_UNCACHED | |
405 | TTM_PL_FLAG_WC; | 388 | TTM_PL_FLAG_WC; |
406 | man->default_caching = TTM_PL_FLAG_WC; | 389 | man->default_caching = TTM_PL_FLAG_WC; |
407 | man->gpu_offset = dev_priv->vm_vram_base; | 390 | if (dev_priv->card_type == NV_50) |
391 | man->gpu_offset = 0x40000000; | ||
392 | else | ||
393 | man->gpu_offset = 0; | ||
408 | break; | 394 | break; |
409 | case TTM_PL_TT: | 395 | case TTM_PL_TT: |
396 | man->func = &ttm_bo_manager_func; | ||
410 | switch (dev_priv->gart_info.type) { | 397 | switch (dev_priv->gart_info.type) { |
411 | case NOUVEAU_GART_AGP: | 398 | case NOUVEAU_GART_AGP: |
412 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; | 399 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; |
@@ -469,19 +456,26 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
469 | if (ret) | 456 | if (ret) |
470 | return ret; | 457 | return ret; |
471 | 458 | ||
472 | ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, | 459 | if (nvbo->channel) { |
473 | evict || (nvbo->channel && | 460 | ret = nouveau_fence_sync(fence, nvbo->channel); |
474 | nvbo->channel != chan), | 461 | if (ret) |
462 | goto out; | ||
463 | } | ||
464 | |||
465 | ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict, | ||
475 | no_wait_reserve, no_wait_gpu, new_mem); | 466 | no_wait_reserve, no_wait_gpu, new_mem); |
467 | out: | ||
476 | nouveau_fence_unref((void *)&fence); | 468 | nouveau_fence_unref((void *)&fence); |
477 | return ret; | 469 | return ret; |
478 | } | 470 | } |
479 | 471 | ||
480 | static inline uint32_t | 472 | static inline uint32_t |
481 | nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, | 473 | nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, |
482 | struct ttm_mem_reg *mem) | 474 | struct nouveau_channel *chan, struct ttm_mem_reg *mem) |
483 | { | 475 | { |
484 | if (chan == nouveau_bdev(nvbo->bo.bdev)->channel) { | 476 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
477 | |||
478 | if (nvbo->no_vm) { | ||
485 | if (mem->mem_type == TTM_PL_TT) | 479 | if (mem->mem_type == TTM_PL_TT) |
486 | return NvDmaGART; | 480 | return NvDmaGART; |
487 | return NvDmaVRAM; | 481 | return NvDmaVRAM; |
@@ -493,86 +487,181 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, | |||
493 | } | 487 | } |
494 | 488 | ||
495 | static int | 489 | static int |
496 | nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, | 490 | nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, |
497 | bool no_wait_reserve, bool no_wait_gpu, | 491 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) |
498 | struct ttm_mem_reg *new_mem) | ||
499 | { | 492 | { |
500 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
501 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | 493 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); |
502 | struct ttm_mem_reg *old_mem = &bo->mem; | 494 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
503 | struct nouveau_channel *chan; | 495 | u64 length = (new_mem->num_pages << PAGE_SHIFT); |
504 | uint64_t src_offset, dst_offset; | 496 | u64 src_offset, dst_offset; |
505 | uint32_t page_count; | ||
506 | int ret; | 497 | int ret; |
507 | 498 | ||
508 | chan = nvbo->channel; | 499 | src_offset = old_mem->start << PAGE_SHIFT; |
509 | if (!chan || nvbo->tile_flags || nvbo->no_vm) | 500 | dst_offset = new_mem->start << PAGE_SHIFT; |
510 | chan = dev_priv->channel; | 501 | if (!nvbo->no_vm) { |
511 | 502 | if (old_mem->mem_type == TTM_PL_VRAM) | |
512 | src_offset = old_mem->mm_node->start << PAGE_SHIFT; | ||
513 | dst_offset = new_mem->mm_node->start << PAGE_SHIFT; | ||
514 | if (chan != dev_priv->channel) { | ||
515 | if (old_mem->mem_type == TTM_PL_TT) | ||
516 | src_offset += dev_priv->vm_gart_base; | ||
517 | else | ||
518 | src_offset += dev_priv->vm_vram_base; | 503 | src_offset += dev_priv->vm_vram_base; |
519 | |||
520 | if (new_mem->mem_type == TTM_PL_TT) | ||
521 | dst_offset += dev_priv->vm_gart_base; | ||
522 | else | 504 | else |
505 | src_offset += dev_priv->vm_gart_base; | ||
506 | |||
507 | if (new_mem->mem_type == TTM_PL_VRAM) | ||
523 | dst_offset += dev_priv->vm_vram_base; | 508 | dst_offset += dev_priv->vm_vram_base; |
509 | else | ||
510 | dst_offset += dev_priv->vm_gart_base; | ||
524 | } | 511 | } |
525 | 512 | ||
526 | ret = RING_SPACE(chan, 3); | 513 | ret = RING_SPACE(chan, 3); |
527 | if (ret) | 514 | if (ret) |
528 | return ret; | 515 | return ret; |
529 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); | ||
530 | OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, old_mem)); | ||
531 | OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, new_mem)); | ||
532 | 516 | ||
533 | if (dev_priv->card_type >= NV_50) { | 517 | BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); |
534 | ret = RING_SPACE(chan, 4); | 518 | OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); |
519 | OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); | ||
520 | |||
521 | while (length) { | ||
522 | u32 amount, stride, height; | ||
523 | |||
524 | amount = min(length, (u64)(4 * 1024 * 1024)); | ||
525 | stride = 16 * 4; | ||
526 | height = amount / stride; | ||
527 | |||
528 | if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { | ||
529 | ret = RING_SPACE(chan, 8); | ||
530 | if (ret) | ||
531 | return ret; | ||
532 | |||
533 | BEGIN_RING(chan, NvSubM2MF, 0x0200, 7); | ||
534 | OUT_RING (chan, 0); | ||
535 | OUT_RING (chan, 0); | ||
536 | OUT_RING (chan, stride); | ||
537 | OUT_RING (chan, height); | ||
538 | OUT_RING (chan, 1); | ||
539 | OUT_RING (chan, 0); | ||
540 | OUT_RING (chan, 0); | ||
541 | } else { | ||
542 | ret = RING_SPACE(chan, 2); | ||
543 | if (ret) | ||
544 | return ret; | ||
545 | |||
546 | BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); | ||
547 | OUT_RING (chan, 1); | ||
548 | } | ||
549 | if (old_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { | ||
550 | ret = RING_SPACE(chan, 8); | ||
551 | if (ret) | ||
552 | return ret; | ||
553 | |||
554 | BEGIN_RING(chan, NvSubM2MF, 0x021c, 7); | ||
555 | OUT_RING (chan, 0); | ||
556 | OUT_RING (chan, 0); | ||
557 | OUT_RING (chan, stride); | ||
558 | OUT_RING (chan, height); | ||
559 | OUT_RING (chan, 1); | ||
560 | OUT_RING (chan, 0); | ||
561 | OUT_RING (chan, 0); | ||
562 | } else { | ||
563 | ret = RING_SPACE(chan, 2); | ||
564 | if (ret) | ||
565 | return ret; | ||
566 | |||
567 | BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); | ||
568 | OUT_RING (chan, 1); | ||
569 | } | ||
570 | |||
571 | ret = RING_SPACE(chan, 14); | ||
535 | if (ret) | 572 | if (ret) |
536 | return ret; | 573 | return ret; |
537 | BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); | 574 | |
538 | OUT_RING(chan, 1); | 575 | BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); |
539 | BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); | 576 | OUT_RING (chan, upper_32_bits(src_offset)); |
540 | OUT_RING(chan, 1); | 577 | OUT_RING (chan, upper_32_bits(dst_offset)); |
578 | BEGIN_RING(chan, NvSubM2MF, 0x030c, 8); | ||
579 | OUT_RING (chan, lower_32_bits(src_offset)); | ||
580 | OUT_RING (chan, lower_32_bits(dst_offset)); | ||
581 | OUT_RING (chan, stride); | ||
582 | OUT_RING (chan, stride); | ||
583 | OUT_RING (chan, stride); | ||
584 | OUT_RING (chan, height); | ||
585 | OUT_RING (chan, 0x00000101); | ||
586 | OUT_RING (chan, 0x00000000); | ||
587 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); | ||
588 | OUT_RING (chan, 0); | ||
589 | |||
590 | length -= amount; | ||
591 | src_offset += amount; | ||
592 | dst_offset += amount; | ||
541 | } | 593 | } |
542 | 594 | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int | ||
599 | nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | ||
600 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) | ||
601 | { | ||
602 | u32 src_offset = old_mem->start << PAGE_SHIFT; | ||
603 | u32 dst_offset = new_mem->start << PAGE_SHIFT; | ||
604 | u32 page_count = new_mem->num_pages; | ||
605 | int ret; | ||
606 | |||
607 | ret = RING_SPACE(chan, 3); | ||
608 | if (ret) | ||
609 | return ret; | ||
610 | |||
611 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); | ||
612 | OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); | ||
613 | OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); | ||
614 | |||
543 | page_count = new_mem->num_pages; | 615 | page_count = new_mem->num_pages; |
544 | while (page_count) { | 616 | while (page_count) { |
545 | int line_count = (page_count > 2047) ? 2047 : page_count; | 617 | int line_count = (page_count > 2047) ? 2047 : page_count; |
546 | 618 | ||
547 | if (dev_priv->card_type >= NV_50) { | ||
548 | ret = RING_SPACE(chan, 3); | ||
549 | if (ret) | ||
550 | return ret; | ||
551 | BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); | ||
552 | OUT_RING(chan, upper_32_bits(src_offset)); | ||
553 | OUT_RING(chan, upper_32_bits(dst_offset)); | ||
554 | } | ||
555 | ret = RING_SPACE(chan, 11); | 619 | ret = RING_SPACE(chan, 11); |
556 | if (ret) | 620 | if (ret) |
557 | return ret; | 621 | return ret; |
622 | |||
558 | BEGIN_RING(chan, NvSubM2MF, | 623 | BEGIN_RING(chan, NvSubM2MF, |
559 | NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); | 624 | NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); |
560 | OUT_RING(chan, lower_32_bits(src_offset)); | 625 | OUT_RING (chan, src_offset); |
561 | OUT_RING(chan, lower_32_bits(dst_offset)); | 626 | OUT_RING (chan, dst_offset); |
562 | OUT_RING(chan, PAGE_SIZE); /* src_pitch */ | 627 | OUT_RING (chan, PAGE_SIZE); /* src_pitch */ |
563 | OUT_RING(chan, PAGE_SIZE); /* dst_pitch */ | 628 | OUT_RING (chan, PAGE_SIZE); /* dst_pitch */ |
564 | OUT_RING(chan, PAGE_SIZE); /* line_length */ | 629 | OUT_RING (chan, PAGE_SIZE); /* line_length */ |
565 | OUT_RING(chan, line_count); | 630 | OUT_RING (chan, line_count); |
566 | OUT_RING(chan, (1<<8)|(1<<0)); | 631 | OUT_RING (chan, 0x00000101); |
567 | OUT_RING(chan, 0); | 632 | OUT_RING (chan, 0x00000000); |
568 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); | 633 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); |
569 | OUT_RING(chan, 0); | 634 | OUT_RING (chan, 0); |
570 | 635 | ||
571 | page_count -= line_count; | 636 | page_count -= line_count; |
572 | src_offset += (PAGE_SIZE * line_count); | 637 | src_offset += (PAGE_SIZE * line_count); |
573 | dst_offset += (PAGE_SIZE * line_count); | 638 | dst_offset += (PAGE_SIZE * line_count); |
574 | } | 639 | } |
575 | 640 | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int | ||
645 | nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, | ||
646 | bool no_wait_reserve, bool no_wait_gpu, | ||
647 | struct ttm_mem_reg *new_mem) | ||
648 | { | ||
649 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | ||
650 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
651 | struct nouveau_channel *chan; | ||
652 | int ret; | ||
653 | |||
654 | chan = nvbo->channel; | ||
655 | if (!chan || nvbo->no_vm) | ||
656 | chan = dev_priv->channel; | ||
657 | |||
658 | if (dev_priv->card_type < NV_50) | ||
659 | ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); | ||
660 | else | ||
661 | ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem); | ||
662 | if (ret) | ||
663 | return ret; | ||
664 | |||
576 | return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); | 665 | return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); |
577 | } | 666 | } |
578 | 667 | ||
@@ -606,12 +695,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
606 | 695 | ||
607 | ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); | 696 | ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); |
608 | out: | 697 | out: |
609 | if (tmp_mem.mm_node) { | 698 | ttm_bo_mem_put(bo, &tmp_mem); |
610 | spin_lock(&bo->bdev->glob->lru_lock); | ||
611 | drm_mm_put_block(tmp_mem.mm_node); | ||
612 | spin_unlock(&bo->bdev->glob->lru_lock); | ||
613 | } | ||
614 | |||
615 | return ret; | 699 | return ret; |
616 | } | 700 | } |
617 | 701 | ||
@@ -644,12 +728,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
644 | goto out; | 728 | goto out; |
645 | 729 | ||
646 | out: | 730 | out: |
647 | if (tmp_mem.mm_node) { | 731 | ttm_bo_mem_put(bo, &tmp_mem); |
648 | spin_lock(&bo->bdev->glob->lru_lock); | ||
649 | drm_mm_put_block(tmp_mem.mm_node); | ||
650 | spin_unlock(&bo->bdev->glob->lru_lock); | ||
651 | } | ||
652 | |||
653 | return ret; | 732 | return ret; |
654 | } | 733 | } |
655 | 734 | ||
@@ -669,7 +748,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, | |||
669 | return 0; | 748 | return 0; |
670 | } | 749 | } |
671 | 750 | ||
672 | offset = new_mem->mm_node->start << PAGE_SHIFT; | 751 | offset = new_mem->start << PAGE_SHIFT; |
673 | 752 | ||
674 | if (dev_priv->card_type == NV_50) { | 753 | if (dev_priv->card_type == NV_50) { |
675 | ret = nv50_mem_vm_bind_linear(dev, | 754 | ret = nv50_mem_vm_bind_linear(dev, |
@@ -719,12 +798,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
719 | if (ret) | 798 | if (ret) |
720 | return ret; | 799 | return ret; |
721 | 800 | ||
722 | /* Software copy if the card isn't up and running yet. */ | ||
723 | if (!dev_priv->channel) { | ||
724 | ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); | ||
725 | goto out; | ||
726 | } | ||
727 | |||
728 | /* Fake bo copy. */ | 801 | /* Fake bo copy. */ |
729 | if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { | 802 | if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { |
730 | BUG_ON(bo->mem.mm_node != NULL); | 803 | BUG_ON(bo->mem.mm_node != NULL); |
@@ -733,6 +806,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
733 | goto out; | 806 | goto out; |
734 | } | 807 | } |
735 | 808 | ||
809 | /* Software copy if the card isn't up and running yet. */ | ||
810 | if (!dev_priv->channel) { | ||
811 | ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); | ||
812 | goto out; | ||
813 | } | ||
814 | |||
736 | /* Hardware assisted copy. */ | 815 | /* Hardware assisted copy. */ |
737 | if (new_mem->mem_type == TTM_PL_SYSTEM) | 816 | if (new_mem->mem_type == TTM_PL_SYSTEM) |
738 | ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); | 817 | ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); |
@@ -783,14 +862,14 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
783 | case TTM_PL_TT: | 862 | case TTM_PL_TT: |
784 | #if __OS_HAS_AGP | 863 | #if __OS_HAS_AGP |
785 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { | 864 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { |
786 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; | 865 | mem->bus.offset = mem->start << PAGE_SHIFT; |
787 | mem->bus.base = dev_priv->gart_info.aper_base; | 866 | mem->bus.base = dev_priv->gart_info.aper_base; |
788 | mem->bus.is_iomem = true; | 867 | mem->bus.is_iomem = true; |
789 | } | 868 | } |
790 | #endif | 869 | #endif |
791 | break; | 870 | break; |
792 | case TTM_PL_VRAM: | 871 | case TTM_PL_VRAM: |
793 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; | 872 | mem->bus.offset = mem->start << PAGE_SHIFT; |
794 | mem->bus.base = pci_resource_start(dev->pdev, 1); | 873 | mem->bus.base = pci_resource_start(dev->pdev, 1); |
795 | mem->bus.is_iomem = true; | 874 | mem->bus.is_iomem = true; |
796 | break; | 875 | break; |
@@ -808,7 +887,26 @@ nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
808 | static int | 887 | static int |
809 | nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) | 888 | nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) |
810 | { | 889 | { |
811 | return 0; | 890 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); |
891 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
892 | |||
893 | /* as long as the bo isn't in vram, and isn't tiled, we've got | ||
894 | * nothing to do here. | ||
895 | */ | ||
896 | if (bo->mem.mem_type != TTM_PL_VRAM) { | ||
897 | if (dev_priv->card_type < NV_50 || !nvbo->tile_flags) | ||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | /* make sure bo is in mappable vram */ | ||
902 | if (bo->mem.start + bo->mem.num_pages < dev_priv->fb_mappable_pages) | ||
903 | return 0; | ||
904 | |||
905 | |||
906 | nvbo->placement.fpfn = 0; | ||
907 | nvbo->placement.lpfn = dev_priv->fb_mappable_pages; | ||
908 | nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0); | ||
909 | return ttm_bo_validate(bo, &nvbo->placement, false, true, false); | ||
812 | } | 910 | } |
813 | 911 | ||
814 | struct ttm_bo_driver nouveau_bo_driver = { | 912 | struct ttm_bo_driver nouveau_bo_driver = { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c index ca85da784846..dad96cce5e39 100644 --- a/drivers/gpu/drm/nouveau/nouveau_calc.c +++ b/drivers/gpu/drm/nouveau/nouveau_calc.c | |||
@@ -198,8 +198,8 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, | |||
198 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 198 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
199 | struct nv_fifo_info fifo_data; | 199 | struct nv_fifo_info fifo_data; |
200 | struct nv_sim_state sim_data; | 200 | struct nv_sim_state sim_data; |
201 | int MClk = nouveau_hw_get_clock(dev, MPLL); | 201 | int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY); |
202 | int NVClk = nouveau_hw_get_clock(dev, NVPLL); | 202 | int NVClk = nouveau_hw_get_clock(dev, PLL_CORE); |
203 | uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); | 203 | uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); |
204 | 204 | ||
205 | sim_data.pclk_khz = VClk; | 205 | sim_data.pclk_khz = VClk; |
@@ -234,7 +234,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, | |||
234 | } | 234 | } |
235 | 235 | ||
236 | static void | 236 | static void |
237 | nv30_update_arb(int *burst, int *lwm) | 237 | nv20_update_arb(int *burst, int *lwm) |
238 | { | 238 | { |
239 | unsigned int fifo_size, burst_size, graphics_lwm; | 239 | unsigned int fifo_size, burst_size, graphics_lwm; |
240 | 240 | ||
@@ -251,14 +251,14 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm | |||
251 | { | 251 | { |
252 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
253 | 253 | ||
254 | if (dev_priv->card_type < NV_30) | 254 | if (dev_priv->card_type < NV_20) |
255 | nv04_update_arb(dev, vclk, bpp, burst, lwm); | 255 | nv04_update_arb(dev, vclk, bpp, burst, lwm); |
256 | else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || | 256 | else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || |
257 | (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { | 257 | (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { |
258 | *burst = 128; | 258 | *burst = 128; |
259 | *lwm = 0x0480; | 259 | *lwm = 0x0480; |
260 | } else | 260 | } else |
261 | nv30_update_arb(burst, lwm); | 261 | nv20_update_arb(burst, lwm); |
262 | } | 262 | } |
263 | 263 | ||
264 | static int | 264 | static int |
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 0480f064f2c1..373950e34814 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
@@ -48,14 +48,14 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) | |||
48 | dev_priv->gart_info.aper_size, | 48 | dev_priv->gart_info.aper_size, |
49 | NV_DMA_ACCESS_RO, &pushbuf, | 49 | NV_DMA_ACCESS_RO, &pushbuf, |
50 | NULL); | 50 | NULL); |
51 | chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; | 51 | chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; |
52 | } else | 52 | } else |
53 | if (dev_priv->card_type != NV_04) { | 53 | if (dev_priv->card_type != NV_04) { |
54 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, | 54 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, |
55 | dev_priv->fb_available_size, | 55 | dev_priv->fb_available_size, |
56 | NV_DMA_ACCESS_RO, | 56 | NV_DMA_ACCESS_RO, |
57 | NV_DMA_TARGET_VIDMEM, &pushbuf); | 57 | NV_DMA_TARGET_VIDMEM, &pushbuf); |
58 | chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; | 58 | chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; |
59 | } else { | 59 | } else { |
60 | /* NV04 cmdbuf hack, from original ddx.. not sure of it's | 60 | /* NV04 cmdbuf hack, from original ddx.. not sure of it's |
61 | * exact reason for existing :) PCI access to cmdbuf in | 61 | * exact reason for existing :) PCI access to cmdbuf in |
@@ -67,17 +67,11 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) | |||
67 | dev_priv->fb_available_size, | 67 | dev_priv->fb_available_size, |
68 | NV_DMA_ACCESS_RO, | 68 | NV_DMA_ACCESS_RO, |
69 | NV_DMA_TARGET_PCI, &pushbuf); | 69 | NV_DMA_TARGET_PCI, &pushbuf); |
70 | chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; | 70 | chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; |
71 | } | ||
72 | |||
73 | ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf); | ||
74 | if (ret) { | ||
75 | NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret); | ||
76 | if (pushbuf != dev_priv->gart_info.sg_ctxdma) | ||
77 | nouveau_gpuobj_del(dev, &pushbuf); | ||
78 | return ret; | ||
79 | } | 71 | } |
80 | 72 | ||
73 | nouveau_gpuobj_ref(pushbuf, &chan->pushbuf); | ||
74 | nouveau_gpuobj_ref(NULL, &pushbuf); | ||
81 | return 0; | 75 | return 0; |
82 | } | 76 | } |
83 | 77 | ||
@@ -229,7 +223,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, | |||
229 | 223 | ||
230 | ret = nouveau_dma_init(chan); | 224 | ret = nouveau_dma_init(chan); |
231 | if (!ret) | 225 | if (!ret) |
232 | ret = nouveau_fence_init(chan); | 226 | ret = nouveau_fence_channel_init(chan); |
233 | if (ret) { | 227 | if (ret) { |
234 | nouveau_channel_free(chan); | 228 | nouveau_channel_free(chan); |
235 | return ret; | 229 | return ret; |
@@ -276,7 +270,7 @@ nouveau_channel_free(struct nouveau_channel *chan) | |||
276 | * above attempts at idling were OK, but if we failed this'll tell TTM | 270 | * above attempts at idling were OK, but if we failed this'll tell TTM |
277 | * we're done with the buffers. | 271 | * we're done with the buffers. |
278 | */ | 272 | */ |
279 | nouveau_fence_fini(chan); | 273 | nouveau_fence_channel_fini(chan); |
280 | 274 | ||
281 | /* This will prevent pfifo from switching channels. */ | 275 | /* This will prevent pfifo from switching channels. */ |
282 | pfifo->reassign(dev, false); | 276 | pfifo->reassign(dev, false); |
@@ -308,8 +302,9 @@ nouveau_channel_free(struct nouveau_channel *chan) | |||
308 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | 302 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
309 | 303 | ||
310 | /* Release the channel's resources */ | 304 | /* Release the channel's resources */ |
311 | nouveau_gpuobj_ref_del(dev, &chan->pushbuf); | 305 | nouveau_gpuobj_ref(NULL, &chan->pushbuf); |
312 | if (chan->pushbuf_bo) { | 306 | if (chan->pushbuf_bo) { |
307 | nouveau_bo_unmap(chan->pushbuf_bo); | ||
313 | nouveau_bo_unpin(chan->pushbuf_bo); | 308 | nouveau_bo_unpin(chan->pushbuf_bo); |
314 | nouveau_bo_ref(NULL, &chan->pushbuf_bo); | 309 | nouveau_bo_ref(NULL, &chan->pushbuf_bo); |
315 | } | 310 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index fc737037f751..0871495096fa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -76,6 +76,22 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) | |||
76 | return NULL; | 76 | return NULL; |
77 | } | 77 | } |
78 | 78 | ||
79 | /*TODO: This could use improvement, and learn to handle the fixed | ||
80 | * BIOS tables etc. It's fine currently, for its only user. | ||
81 | */ | ||
82 | int | ||
83 | nouveau_connector_bpp(struct drm_connector *connector) | ||
84 | { | ||
85 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
86 | |||
87 | if (nv_connector->edid && nv_connector->edid->revision >= 4) { | ||
88 | u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4; | ||
89 | if (bpc > 4) | ||
90 | return bpc; | ||
91 | } | ||
92 | |||
93 | return 18; | ||
94 | } | ||
79 | 95 | ||
80 | static void | 96 | static void |
81 | nouveau_connector_destroy(struct drm_connector *drm_connector) | 97 | nouveau_connector_destroy(struct drm_connector *drm_connector) |
@@ -130,6 +146,36 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
130 | return NULL; | 146 | return NULL; |
131 | } | 147 | } |
132 | 148 | ||
149 | static struct nouveau_encoder * | ||
150 | nouveau_connector_of_detect(struct drm_connector *connector) | ||
151 | { | ||
152 | #ifdef __powerpc__ | ||
153 | struct drm_device *dev = connector->dev; | ||
154 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
155 | struct nouveau_encoder *nv_encoder; | ||
156 | struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); | ||
157 | |||
158 | if (!dn || | ||
159 | !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || | ||
160 | (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) | ||
161 | return NULL; | ||
162 | |||
163 | for_each_child_of_node(dn, cn) { | ||
164 | const char *name = of_get_property(cn, "name", NULL); | ||
165 | const void *edid = of_get_property(cn, "EDID", NULL); | ||
166 | int idx = name ? name[strlen(name) - 1] - 'A' : 0; | ||
167 | |||
168 | if (nv_encoder->dcb->i2c_index == idx && edid) { | ||
169 | nv_connector->edid = | ||
170 | kmemdup(edid, EDID_LENGTH, GFP_KERNEL); | ||
171 | of_node_put(cn); | ||
172 | return nv_encoder; | ||
173 | } | ||
174 | } | ||
175 | #endif | ||
176 | return NULL; | ||
177 | } | ||
178 | |||
133 | static void | 179 | static void |
134 | nouveau_connector_set_encoder(struct drm_connector *connector, | 180 | nouveau_connector_set_encoder(struct drm_connector *connector, |
135 | struct nouveau_encoder *nv_encoder) | 181 | struct nouveau_encoder *nv_encoder) |
@@ -225,6 +271,12 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
225 | return connector_status_connected; | 271 | return connector_status_connected; |
226 | } | 272 | } |
227 | 273 | ||
274 | nv_encoder = nouveau_connector_of_detect(connector); | ||
275 | if (nv_encoder) { | ||
276 | nouveau_connector_set_encoder(connector, nv_encoder); | ||
277 | return connector_status_connected; | ||
278 | } | ||
279 | |||
228 | detect_analog: | 280 | detect_analog: |
229 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); | 281 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); |
230 | if (!nv_encoder && !nouveau_tv_disable) | 282 | if (!nv_encoder && !nouveau_tv_disable) |
@@ -630,7 +682,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
630 | else | 682 | else |
631 | max_clock = nv_encoder->dp.link_nr * 162000; | 683 | max_clock = nv_encoder->dp.link_nr * 162000; |
632 | 684 | ||
633 | clock *= 3; | 685 | clock = clock * nouveau_connector_bpp(connector) / 8; |
634 | break; | 686 | break; |
635 | default: | 687 | default: |
636 | BUG_ON(1); | 688 | BUG_ON(1); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index 0d2e668ccfe5..c21ed6b16f88 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h | |||
@@ -55,4 +55,7 @@ nouveau_connector_create(struct drm_device *, int index); | |||
55 | void | 55 | void |
56 | nouveau_connector_set_polling(struct drm_connector *); | 56 | nouveau_connector_set_polling(struct drm_connector *); |
57 | 57 | ||
58 | int | ||
59 | nouveau_connector_bpp(struct drm_connector *); | ||
60 | |||
58 | #endif /* __NOUVEAU_CONNECTOR_H__ */ | 61 | #endif /* __NOUVEAU_CONNECTOR_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 7933de4aff2e..8e1592368cce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c | |||
@@ -157,7 +157,23 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data) | |||
157 | return 0; | 157 | return 0; |
158 | } | 158 | } |
159 | 159 | ||
160 | static int | ||
161 | nouveau_debugfs_evict_vram(struct seq_file *m, void *data) | ||
162 | { | ||
163 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
164 | struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private; | ||
165 | int ret; | ||
166 | |||
167 | ret = ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); | ||
168 | if (ret) | ||
169 | seq_printf(m, "failed: %d", ret); | ||
170 | else | ||
171 | seq_printf(m, "succeeded\n"); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
160 | static struct drm_info_list nouveau_debugfs_list[] = { | 175 | static struct drm_info_list nouveau_debugfs_list[] = { |
176 | { "evict_vram", nouveau_debugfs_evict_vram, 0, NULL }, | ||
161 | { "chipset", nouveau_debugfs_chipset_info, 0, NULL }, | 177 | { "chipset", nouveau_debugfs_chipset_info, 0, NULL }, |
162 | { "memory", nouveau_debugfs_memory_info, 0, NULL }, | 178 | { "memory", nouveau_debugfs_memory_info, 0, NULL }, |
163 | { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, | 179 | { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 2e3c6caa97ee..82581e600dcd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
30 | #include "nouveau_dma.h" | 30 | #include "nouveau_dma.h" |
31 | #include "nouveau_ramht.h" | ||
31 | 32 | ||
32 | void | 33 | void |
33 | nouveau_dma_pre_init(struct nouveau_channel *chan) | 34 | nouveau_dma_pre_init(struct nouveau_channel *chan) |
@@ -58,26 +59,17 @@ nouveau_dma_init(struct nouveau_channel *chan) | |||
58 | { | 59 | { |
59 | struct drm_device *dev = chan->dev; | 60 | struct drm_device *dev = chan->dev; |
60 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 61 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
61 | struct nouveau_gpuobj *m2mf = NULL; | 62 | struct nouveau_gpuobj *obj = NULL; |
62 | struct nouveau_gpuobj *nvsw = NULL; | ||
63 | int ret, i; | 63 | int ret, i; |
64 | 64 | ||
65 | /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ | 65 | /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ |
66 | ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? | 66 | ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? |
67 | 0x0039 : 0x5039, &m2mf); | 67 | 0x0039 : 0x5039, &obj); |
68 | if (ret) | 68 | if (ret) |
69 | return ret; | 69 | return ret; |
70 | 70 | ||
71 | ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL); | 71 | ret = nouveau_ramht_insert(chan, NvM2MF, obj); |
72 | if (ret) | 72 | nouveau_gpuobj_ref(NULL, &obj); |
73 | return ret; | ||
74 | |||
75 | /* Create an NV_SW object for various sync purposes */ | ||
76 | ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw); | ||
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
80 | ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL); | ||
81 | if (ret) | 73 | if (ret) |
82 | return ret; | 74 | return ret; |
83 | 75 | ||
@@ -91,11 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan) | |||
91 | if (ret) | 83 | if (ret) |
92 | return ret; | 84 | return ret; |
93 | 85 | ||
94 | /* Map M2MF notifier object - fbcon. */ | ||
95 | ret = nouveau_bo_map(chan->notifier_bo); | ||
96 | if (ret) | ||
97 | return ret; | ||
98 | |||
99 | /* Insert NOPS for NOUVEAU_DMA_SKIPS */ | 86 | /* Insert NOPS for NOUVEAU_DMA_SKIPS */ |
100 | ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); | 87 | ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); |
101 | if (ret) | 88 | if (ret) |
@@ -113,13 +100,6 @@ nouveau_dma_init(struct nouveau_channel *chan) | |||
113 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); | 100 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); |
114 | OUT_RING(chan, NvNotify0); | 101 | OUT_RING(chan, NvNotify0); |
115 | 102 | ||
116 | /* Initialise NV_SW */ | ||
117 | ret = RING_SPACE(chan, 2); | ||
118 | if (ret) | ||
119 | return ret; | ||
120 | BEGIN_RING(chan, NvSubSw, 0, 1); | ||
121 | OUT_RING(chan, NvSw); | ||
122 | |||
123 | /* Sit back and pray the channel works.. */ | 103 | /* Sit back and pray the channel works.. */ |
124 | FIRE_RING(chan); | 104 | FIRE_RING(chan); |
125 | 105 | ||
@@ -217,7 +197,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) | |||
217 | 197 | ||
218 | chan->dma.ib_free = get - chan->dma.ib_put; | 198 | chan->dma.ib_free = get - chan->dma.ib_put; |
219 | if (chan->dma.ib_free <= 0) | 199 | if (chan->dma.ib_free <= 0) |
220 | chan->dma.ib_free += chan->dma.ib_max + 1; | 200 | chan->dma.ib_free += chan->dma.ib_max; |
221 | } | 201 | } |
222 | 202 | ||
223 | return 0; | 203 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index 8b05c15866d5..d578c21d3c8d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h | |||
@@ -72,6 +72,7 @@ enum { | |||
72 | NvGdiRect = 0x8000000c, | 72 | NvGdiRect = 0x8000000c, |
73 | NvImageBlit = 0x8000000d, | 73 | NvImageBlit = 0x8000000d, |
74 | NvSw = 0x8000000e, | 74 | NvSw = 0x8000000e, |
75 | NvSema = 0x8000000f, | ||
75 | 76 | ||
76 | /* G80+ display objects */ | 77 | /* G80+ display objects */ |
77 | NvEvoVRAM = 0x01000000, | 78 | NvEvoVRAM = 0x01000000, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 8a1b188b4cd1..4562f309ae3d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -317,7 +317,8 @@ train: | |||
317 | return false; | 317 | return false; |
318 | 318 | ||
319 | config[0] = nv_encoder->dp.link_nr; | 319 | config[0] = nv_encoder->dp.link_nr; |
320 | if (nv_encoder->dp.dpcd_version >= 0x11) | 320 | if (nv_encoder->dp.dpcd_version >= 0x11 && |
321 | nv_encoder->dp.enhanced_frame) | ||
321 | config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | 322 | config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
322 | 323 | ||
323 | ret = nouveau_dp_lane_count_set(encoder, config[0]); | 324 | ret = nouveau_dp_lane_count_set(encoder, config[0]); |
@@ -468,10 +469,12 @@ nouveau_dp_detect(struct drm_encoder *encoder) | |||
468 | !nv_encoder->dcb->dpconf.link_bw) | 469 | !nv_encoder->dcb->dpconf.link_bw) |
469 | nv_encoder->dp.link_bw = DP_LINK_BW_1_62; | 470 | nv_encoder->dp.link_bw = DP_LINK_BW_1_62; |
470 | 471 | ||
471 | nv_encoder->dp.link_nr = dpcd[2] & 0xf; | 472 | nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; |
472 | if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) | 473 | if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) |
473 | nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; | 474 | nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; |
474 | 475 | ||
476 | nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); | ||
477 | |||
475 | return true; | 478 | return true; |
476 | } | 479 | } |
477 | 480 | ||
@@ -524,7 +527,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, | |||
524 | nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); | 527 | nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); |
525 | nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); | 528 | nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); |
526 | nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); | 529 | nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); |
527 | if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { | 530 | if (!nv_wait(dev, NV50_AUXCH_CTRL(index), |
531 | 0x00010000, 0x00000000)) { | ||
528 | NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", | 532 | NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", |
529 | nv_rd32(dev, NV50_AUXCH_CTRL(index))); | 533 | nv_rd32(dev, NV50_AUXCH_CTRL(index))); |
530 | ret = -EBUSY; | 534 | ret = -EBUSY; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 1de5eb53e016..edc4a9ab28d1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
@@ -31,13 +31,14 @@ | |||
31 | #include "nouveau_hw.h" | 31 | #include "nouveau_hw.h" |
32 | #include "nouveau_fb.h" | 32 | #include "nouveau_fb.h" |
33 | #include "nouveau_fbcon.h" | 33 | #include "nouveau_fbcon.h" |
34 | #include "nouveau_pm.h" | ||
34 | #include "nv50_display.h" | 35 | #include "nv50_display.h" |
35 | 36 | ||
36 | #include "drm_pciids.h" | 37 | #include "drm_pciids.h" |
37 | 38 | ||
38 | MODULE_PARM_DESC(noagp, "Disable AGP"); | 39 | MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); |
39 | int nouveau_noagp; | 40 | int nouveau_agpmode = -1; |
40 | module_param_named(noagp, nouveau_noagp, int, 0400); | 41 | module_param_named(agpmode, nouveau_agpmode, int, 0400); |
41 | 42 | ||
42 | MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); | 43 | MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); |
43 | static int nouveau_modeset = -1; /* kms */ | 44 | static int nouveau_modeset = -1; /* kms */ |
@@ -79,6 +80,10 @@ MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); | |||
79 | int nouveau_nofbaccel = 0; | 80 | int nouveau_nofbaccel = 0; |
80 | module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); | 81 | module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); |
81 | 82 | ||
83 | MODULE_PARM_DESC(force_post, "Force POST"); | ||
84 | int nouveau_force_post = 0; | ||
85 | module_param_named(force_post, nouveau_force_post, int, 0400); | ||
86 | |||
82 | MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); | 87 | MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); |
83 | int nouveau_override_conntype = 0; | 88 | int nouveau_override_conntype = 0; |
84 | module_param_named(override_conntype, nouveau_override_conntype, int, 0400); | 89 | module_param_named(override_conntype, nouveau_override_conntype, int, 0400); |
@@ -102,6 +107,14 @@ MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n" | |||
102 | int nouveau_reg_debug; | 107 | int nouveau_reg_debug; |
103 | module_param_named(reg_debug, nouveau_reg_debug, int, 0600); | 108 | module_param_named(reg_debug, nouveau_reg_debug, int, 0600); |
104 | 109 | ||
110 | MODULE_PARM_DESC(perflvl, "Performance level (default: boot)\n"); | ||
111 | char *nouveau_perflvl; | ||
112 | module_param_named(perflvl, nouveau_perflvl, charp, 0400); | ||
113 | |||
114 | MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n"); | ||
115 | int nouveau_perflvl_wr; | ||
116 | module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); | ||
117 | |||
105 | int nouveau_fbpercrtc; | 118 | int nouveau_fbpercrtc; |
106 | #if 0 | 119 | #if 0 |
107 | module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); | 120 | module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); |
@@ -271,6 +284,8 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
271 | if (ret) | 284 | if (ret) |
272 | return ret; | 285 | return ret; |
273 | 286 | ||
287 | nouveau_pm_resume(dev); | ||
288 | |||
274 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { | 289 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { |
275 | ret = nouveau_mem_init_agp(dev); | 290 | ret = nouveau_mem_init_agp(dev); |
276 | if (ret) { | 291 | if (ret) { |
@@ -379,8 +394,6 @@ static struct drm_driver driver = { | |||
379 | .irq_uninstall = nouveau_irq_uninstall, | 394 | .irq_uninstall = nouveau_irq_uninstall, |
380 | .irq_handler = nouveau_irq_handler, | 395 | .irq_handler = nouveau_irq_handler, |
381 | .reclaim_buffers = drm_core_reclaim_buffers, | 396 | .reclaim_buffers = drm_core_reclaim_buffers, |
382 | .get_map_ofs = drm_core_get_map_ofs, | ||
383 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
384 | .ioctls = nouveau_ioctls, | 397 | .ioctls = nouveau_ioctls, |
385 | .fops = { | 398 | .fops = { |
386 | .owner = THIS_MODULE, | 399 | .owner = THIS_MODULE, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b1be617373b6..3a07e580d27a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -133,22 +133,24 @@ enum nouveau_flags { | |||
133 | #define NVOBJ_ENGINE_DISPLAY 2 | 133 | #define NVOBJ_ENGINE_DISPLAY 2 |
134 | #define NVOBJ_ENGINE_INT 0xdeadbeef | 134 | #define NVOBJ_ENGINE_INT 0xdeadbeef |
135 | 135 | ||
136 | #define NVOBJ_FLAG_ALLOW_NO_REFS (1 << 0) | ||
137 | #define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) | 136 | #define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) |
138 | #define NVOBJ_FLAG_ZERO_FREE (1 << 2) | 137 | #define NVOBJ_FLAG_ZERO_FREE (1 << 2) |
139 | #define NVOBJ_FLAG_FAKE (1 << 3) | ||
140 | struct nouveau_gpuobj { | 138 | struct nouveau_gpuobj { |
139 | struct drm_device *dev; | ||
140 | struct kref refcount; | ||
141 | struct list_head list; | 141 | struct list_head list; |
142 | 142 | ||
143 | struct nouveau_channel *im_channel; | ||
144 | struct drm_mm_node *im_pramin; | 143 | struct drm_mm_node *im_pramin; |
145 | struct nouveau_bo *im_backing; | 144 | struct nouveau_bo *im_backing; |
146 | uint32_t im_backing_start; | ||
147 | uint32_t *im_backing_suspend; | 145 | uint32_t *im_backing_suspend; |
148 | int im_bound; | 146 | int im_bound; |
149 | 147 | ||
150 | uint32_t flags; | 148 | uint32_t flags; |
151 | int refcount; | 149 | |
150 | u32 size; | ||
151 | u32 pinst; | ||
152 | u32 cinst; | ||
153 | u64 vinst; | ||
152 | 154 | ||
153 | uint32_t engine; | 155 | uint32_t engine; |
154 | uint32_t class; | 156 | uint32_t class; |
@@ -157,16 +159,6 @@ struct nouveau_gpuobj { | |||
157 | void *priv; | 159 | void *priv; |
158 | }; | 160 | }; |
159 | 161 | ||
160 | struct nouveau_gpuobj_ref { | ||
161 | struct list_head list; | ||
162 | |||
163 | struct nouveau_gpuobj *gpuobj; | ||
164 | uint32_t instance; | ||
165 | |||
166 | struct nouveau_channel *channel; | ||
167 | int handle; | ||
168 | }; | ||
169 | |||
170 | struct nouveau_channel { | 162 | struct nouveau_channel { |
171 | struct drm_device *dev; | 163 | struct drm_device *dev; |
172 | int id; | 164 | int id; |
@@ -192,33 +184,32 @@ struct nouveau_channel { | |||
192 | } fence; | 184 | } fence; |
193 | 185 | ||
194 | /* DMA push buffer */ | 186 | /* DMA push buffer */ |
195 | struct nouveau_gpuobj_ref *pushbuf; | 187 | struct nouveau_gpuobj *pushbuf; |
196 | struct nouveau_bo *pushbuf_bo; | 188 | struct nouveau_bo *pushbuf_bo; |
197 | uint32_t pushbuf_base; | 189 | uint32_t pushbuf_base; |
198 | 190 | ||
199 | /* Notifier memory */ | 191 | /* Notifier memory */ |
200 | struct nouveau_bo *notifier_bo; | 192 | struct nouveau_bo *notifier_bo; |
201 | struct drm_mm notifier_heap; | 193 | struct drm_mm notifier_heap; |
202 | 194 | ||
203 | /* PFIFO context */ | 195 | /* PFIFO context */ |
204 | struct nouveau_gpuobj_ref *ramfc; | 196 | struct nouveau_gpuobj *ramfc; |
205 | struct nouveau_gpuobj_ref *cache; | 197 | struct nouveau_gpuobj *cache; |
206 | 198 | ||
207 | /* PGRAPH context */ | 199 | /* PGRAPH context */ |
208 | /* XXX may be merge 2 pointers as private data ??? */ | 200 | /* XXX may be merge 2 pointers as private data ??? */ |
209 | struct nouveau_gpuobj_ref *ramin_grctx; | 201 | struct nouveau_gpuobj *ramin_grctx; |
210 | void *pgraph_ctx; | 202 | void *pgraph_ctx; |
211 | 203 | ||
212 | /* NV50 VM */ | 204 | /* NV50 VM */ |
213 | struct nouveau_gpuobj *vm_pd; | 205 | struct nouveau_gpuobj *vm_pd; |
214 | struct nouveau_gpuobj_ref *vm_gart_pt; | 206 | struct nouveau_gpuobj *vm_gart_pt; |
215 | struct nouveau_gpuobj_ref *vm_vram_pt[NV50_VM_VRAM_NR]; | 207 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; |
216 | 208 | ||
217 | /* Objects */ | 209 | /* Objects */ |
218 | struct nouveau_gpuobj_ref *ramin; /* Private instmem */ | 210 | struct nouveau_gpuobj *ramin; /* Private instmem */ |
219 | struct drm_mm ramin_heap; /* Private PRAMIN heap */ | 211 | struct drm_mm ramin_heap; /* Private PRAMIN heap */ |
220 | struct nouveau_gpuobj_ref *ramht; /* Hash table */ | 212 | struct nouveau_ramht *ramht; /* Hash table */ |
221 | struct list_head ramht_refs; /* Objects referenced by RAMHT */ | ||
222 | 213 | ||
223 | /* GPU object info for stuff used in-kernel (mm_enabled) */ | 214 | /* GPU object info for stuff used in-kernel (mm_enabled) */ |
224 | uint32_t m2mf_ntfy; | 215 | uint32_t m2mf_ntfy; |
@@ -296,7 +287,7 @@ struct nouveau_fb_engine { | |||
296 | struct nouveau_fifo_engine { | 287 | struct nouveau_fifo_engine { |
297 | int channels; | 288 | int channels; |
298 | 289 | ||
299 | struct nouveau_gpuobj_ref *playlist[2]; | 290 | struct nouveau_gpuobj *playlist[2]; |
300 | int cur_playlist; | 291 | int cur_playlist; |
301 | 292 | ||
302 | int (*init)(struct drm_device *); | 293 | int (*init)(struct drm_device *); |
@@ -305,7 +296,6 @@ struct nouveau_fifo_engine { | |||
305 | void (*disable)(struct drm_device *); | 296 | void (*disable)(struct drm_device *); |
306 | void (*enable)(struct drm_device *); | 297 | void (*enable)(struct drm_device *); |
307 | bool (*reassign)(struct drm_device *, bool enable); | 298 | bool (*reassign)(struct drm_device *, bool enable); |
308 | bool (*cache_flush)(struct drm_device *dev); | ||
309 | bool (*cache_pull)(struct drm_device *dev, bool enable); | 299 | bool (*cache_pull)(struct drm_device *dev, bool enable); |
310 | 300 | ||
311 | int (*channel_id)(struct drm_device *); | 301 | int (*channel_id)(struct drm_device *); |
@@ -334,7 +324,7 @@ struct nouveau_pgraph_engine { | |||
334 | int grctx_size; | 324 | int grctx_size; |
335 | 325 | ||
336 | /* NV2x/NV3x context table (0x400780) */ | 326 | /* NV2x/NV3x context table (0x400780) */ |
337 | struct nouveau_gpuobj_ref *ctx_table; | 327 | struct nouveau_gpuobj *ctx_table; |
338 | 328 | ||
339 | int (*init)(struct drm_device *); | 329 | int (*init)(struct drm_device *); |
340 | void (*takedown)(struct drm_device *); | 330 | void (*takedown)(struct drm_device *); |
@@ -369,6 +359,91 @@ struct nouveau_gpio_engine { | |||
369 | void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); | 359 | void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); |
370 | }; | 360 | }; |
371 | 361 | ||
362 | struct nouveau_pm_voltage_level { | ||
363 | u8 voltage; | ||
364 | u8 vid; | ||
365 | }; | ||
366 | |||
367 | struct nouveau_pm_voltage { | ||
368 | bool supported; | ||
369 | u8 vid_mask; | ||
370 | |||
371 | struct nouveau_pm_voltage_level *level; | ||
372 | int nr_level; | ||
373 | }; | ||
374 | |||
375 | #define NOUVEAU_PM_MAX_LEVEL 8 | ||
376 | struct nouveau_pm_level { | ||
377 | struct device_attribute dev_attr; | ||
378 | char name[32]; | ||
379 | int id; | ||
380 | |||
381 | u32 core; | ||
382 | u32 memory; | ||
383 | u32 shader; | ||
384 | u32 unk05; | ||
385 | |||
386 | u8 voltage; | ||
387 | u8 fanspeed; | ||
388 | |||
389 | u16 memscript; | ||
390 | }; | ||
391 | |||
392 | struct nouveau_pm_temp_sensor_constants { | ||
393 | u16 offset_constant; | ||
394 | s16 offset_mult; | ||
395 | u16 offset_div; | ||
396 | u16 slope_mult; | ||
397 | u16 slope_div; | ||
398 | }; | ||
399 | |||
400 | struct nouveau_pm_threshold_temp { | ||
401 | s16 critical; | ||
402 | s16 down_clock; | ||
403 | s16 fan_boost; | ||
404 | }; | ||
405 | |||
406 | struct nouveau_pm_memtiming { | ||
407 | u32 reg_100220; | ||
408 | u32 reg_100224; | ||
409 | u32 reg_100228; | ||
410 | u32 reg_10022c; | ||
411 | u32 reg_100230; | ||
412 | u32 reg_100234; | ||
413 | u32 reg_100238; | ||
414 | u32 reg_10023c; | ||
415 | }; | ||
416 | |||
417 | struct nouveau_pm_memtimings { | ||
418 | bool supported; | ||
419 | struct nouveau_pm_memtiming *timing; | ||
420 | int nr_timing; | ||
421 | }; | ||
422 | |||
423 | struct nouveau_pm_engine { | ||
424 | struct nouveau_pm_voltage voltage; | ||
425 | struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; | ||
426 | int nr_perflvl; | ||
427 | struct nouveau_pm_memtimings memtimings; | ||
428 | struct nouveau_pm_temp_sensor_constants sensor_constants; | ||
429 | struct nouveau_pm_threshold_temp threshold_temp; | ||
430 | |||
431 | struct nouveau_pm_level boot; | ||
432 | struct nouveau_pm_level *cur; | ||
433 | |||
434 | struct device *hwmon; | ||
435 | |||
436 | int (*clock_get)(struct drm_device *, u32 id); | ||
437 | void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, | ||
438 | u32 id, int khz); | ||
439 | void (*clock_set)(struct drm_device *, void *); | ||
440 | int (*voltage_get)(struct drm_device *); | ||
441 | int (*voltage_set)(struct drm_device *, int voltage); | ||
442 | int (*fanspeed_get)(struct drm_device *); | ||
443 | int (*fanspeed_set)(struct drm_device *, int fanspeed); | ||
444 | int (*temp_get)(struct drm_device *); | ||
445 | }; | ||
446 | |||
372 | struct nouveau_engine { | 447 | struct nouveau_engine { |
373 | struct nouveau_instmem_engine instmem; | 448 | struct nouveau_instmem_engine instmem; |
374 | struct nouveau_mc_engine mc; | 449 | struct nouveau_mc_engine mc; |
@@ -378,6 +453,7 @@ struct nouveau_engine { | |||
378 | struct nouveau_fifo_engine fifo; | 453 | struct nouveau_fifo_engine fifo; |
379 | struct nouveau_display_engine display; | 454 | struct nouveau_display_engine display; |
380 | struct nouveau_gpio_engine gpio; | 455 | struct nouveau_gpio_engine gpio; |
456 | struct nouveau_pm_engine pm; | ||
381 | }; | 457 | }; |
382 | 458 | ||
383 | struct nouveau_pll_vals { | 459 | struct nouveau_pll_vals { |
@@ -522,8 +598,14 @@ struct drm_nouveau_private { | |||
522 | int flags; | 598 | int flags; |
523 | 599 | ||
524 | void __iomem *mmio; | 600 | void __iomem *mmio; |
601 | |||
602 | spinlock_t ramin_lock; | ||
525 | void __iomem *ramin; | 603 | void __iomem *ramin; |
526 | uint32_t ramin_size; | 604 | u32 ramin_size; |
605 | u32 ramin_base; | ||
606 | bool ramin_available; | ||
607 | struct drm_mm ramin_heap; | ||
608 | struct list_head gpuobj_list; | ||
527 | 609 | ||
528 | struct nouveau_bo *vga_ram; | 610 | struct nouveau_bo *vga_ram; |
529 | 611 | ||
@@ -540,6 +622,12 @@ struct drm_nouveau_private { | |||
540 | atomic_t validate_sequence; | 622 | atomic_t validate_sequence; |
541 | } ttm; | 623 | } ttm; |
542 | 624 | ||
625 | struct { | ||
626 | spinlock_t lock; | ||
627 | struct drm_mm heap; | ||
628 | struct nouveau_bo *bo; | ||
629 | } fence; | ||
630 | |||
543 | int fifo_alloc_count; | 631 | int fifo_alloc_count; |
544 | struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; | 632 | struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; |
545 | 633 | ||
@@ -550,15 +638,11 @@ struct drm_nouveau_private { | |||
550 | spinlock_t context_switch_lock; | 638 | spinlock_t context_switch_lock; |
551 | 639 | ||
552 | /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ | 640 | /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ |
553 | struct nouveau_gpuobj *ramht; | 641 | struct nouveau_ramht *ramht; |
642 | struct nouveau_gpuobj *ramfc; | ||
643 | struct nouveau_gpuobj *ramro; | ||
644 | |||
554 | uint32_t ramin_rsvd_vram; | 645 | uint32_t ramin_rsvd_vram; |
555 | uint32_t ramht_offset; | ||
556 | uint32_t ramht_size; | ||
557 | uint32_t ramht_bits; | ||
558 | uint32_t ramfc_offset; | ||
559 | uint32_t ramfc_size; | ||
560 | uint32_t ramro_offset; | ||
561 | uint32_t ramro_size; | ||
562 | 646 | ||
563 | struct { | 647 | struct { |
564 | enum { | 648 | enum { |
@@ -576,14 +660,12 @@ struct drm_nouveau_private { | |||
576 | } gart_info; | 660 | } gart_info; |
577 | 661 | ||
578 | /* nv10-nv40 tiling regions */ | 662 | /* nv10-nv40 tiling regions */ |
579 | struct { | 663 | struct nouveau_tile_reg tile[NOUVEAU_MAX_TILE_NR]; |
580 | struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR]; | ||
581 | spinlock_t lock; | ||
582 | } tile; | ||
583 | 664 | ||
584 | /* VRAM/fb configuration */ | 665 | /* VRAM/fb configuration */ |
585 | uint64_t vram_size; | 666 | uint64_t vram_size; |
586 | uint64_t vram_sys_base; | 667 | uint64_t vram_sys_base; |
668 | u32 vram_rblock_size; | ||
587 | 669 | ||
588 | uint64_t fb_phys; | 670 | uint64_t fb_phys; |
589 | uint64_t fb_available_size; | 671 | uint64_t fb_available_size; |
@@ -600,10 +682,6 @@ struct drm_nouveau_private { | |||
600 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; | 682 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; |
601 | int vm_vram_pt_nr; | 683 | int vm_vram_pt_nr; |
602 | 684 | ||
603 | struct drm_mm ramin_heap; | ||
604 | |||
605 | struct list_head gpuobj_list; | ||
606 | |||
607 | struct nvbios vbios; | 685 | struct nvbios vbios; |
608 | 686 | ||
609 | struct nv04_mode_state mode_reg; | 687 | struct nv04_mode_state mode_reg; |
@@ -634,6 +712,12 @@ struct drm_nouveau_private { | |||
634 | }; | 712 | }; |
635 | 713 | ||
636 | static inline struct drm_nouveau_private * | 714 | static inline struct drm_nouveau_private * |
715 | nouveau_private(struct drm_device *dev) | ||
716 | { | ||
717 | return dev->dev_private; | ||
718 | } | ||
719 | |||
720 | static inline struct drm_nouveau_private * | ||
637 | nouveau_bdev(struct ttm_bo_device *bd) | 721 | nouveau_bdev(struct ttm_bo_device *bd) |
638 | { | 722 | { |
639 | return container_of(bd, struct drm_nouveau_private, ttm.bdev); | 723 | return container_of(bd, struct drm_nouveau_private, ttm.bdev); |
@@ -669,7 +753,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) | |||
669 | } while (0) | 753 | } while (0) |
670 | 754 | ||
671 | /* nouveau_drv.c */ | 755 | /* nouveau_drv.c */ |
672 | extern int nouveau_noagp; | 756 | extern int nouveau_agpmode; |
673 | extern int nouveau_duallink; | 757 | extern int nouveau_duallink; |
674 | extern int nouveau_uscript_lvds; | 758 | extern int nouveau_uscript_lvds; |
675 | extern int nouveau_uscript_tmds; | 759 | extern int nouveau_uscript_tmds; |
@@ -683,7 +767,10 @@ extern char *nouveau_vbios; | |||
683 | extern int nouveau_ignorelid; | 767 | extern int nouveau_ignorelid; |
684 | extern int nouveau_nofbaccel; | 768 | extern int nouveau_nofbaccel; |
685 | extern int nouveau_noaccel; | 769 | extern int nouveau_noaccel; |
770 | extern int nouveau_force_post; | ||
686 | extern int nouveau_override_conntype; | 771 | extern int nouveau_override_conntype; |
772 | extern char *nouveau_perflvl; | ||
773 | extern int nouveau_perflvl_wr; | ||
687 | 774 | ||
688 | extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); | 775 | extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); |
689 | extern int nouveau_pci_resume(struct pci_dev *pdev); | 776 | extern int nouveau_pci_resume(struct pci_dev *pdev); |
@@ -704,8 +791,10 @@ extern bool nouveau_wait_for_idle(struct drm_device *); | |||
704 | extern int nouveau_card_init(struct drm_device *); | 791 | extern int nouveau_card_init(struct drm_device *); |
705 | 792 | ||
706 | /* nouveau_mem.c */ | 793 | /* nouveau_mem.c */ |
707 | extern int nouveau_mem_detect(struct drm_device *dev); | 794 | extern int nouveau_mem_vram_init(struct drm_device *); |
708 | extern int nouveau_mem_init(struct drm_device *); | 795 | extern void nouveau_mem_vram_fini(struct drm_device *); |
796 | extern int nouveau_mem_gart_init(struct drm_device *); | ||
797 | extern void nouveau_mem_gart_fini(struct drm_device *); | ||
709 | extern int nouveau_mem_init_agp(struct drm_device *); | 798 | extern int nouveau_mem_init_agp(struct drm_device *); |
710 | extern int nouveau_mem_reset_agp(struct drm_device *); | 799 | extern int nouveau_mem_reset_agp(struct drm_device *); |
711 | extern void nouveau_mem_close(struct drm_device *); | 800 | extern void nouveau_mem_close(struct drm_device *); |
@@ -749,7 +838,6 @@ extern void nouveau_channel_free(struct nouveau_channel *); | |||
749 | extern int nouveau_gpuobj_early_init(struct drm_device *); | 838 | extern int nouveau_gpuobj_early_init(struct drm_device *); |
750 | extern int nouveau_gpuobj_init(struct drm_device *); | 839 | extern int nouveau_gpuobj_init(struct drm_device *); |
751 | extern void nouveau_gpuobj_takedown(struct drm_device *); | 840 | extern void nouveau_gpuobj_takedown(struct drm_device *); |
752 | extern void nouveau_gpuobj_late_takedown(struct drm_device *); | ||
753 | extern int nouveau_gpuobj_suspend(struct drm_device *dev); | 841 | extern int nouveau_gpuobj_suspend(struct drm_device *dev); |
754 | extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev); | 842 | extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev); |
755 | extern void nouveau_gpuobj_resume(struct drm_device *dev); | 843 | extern void nouveau_gpuobj_resume(struct drm_device *dev); |
@@ -759,24 +847,11 @@ extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); | |||
759 | extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, | 847 | extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, |
760 | uint32_t size, int align, uint32_t flags, | 848 | uint32_t size, int align, uint32_t flags, |
761 | struct nouveau_gpuobj **); | 849 | struct nouveau_gpuobj **); |
762 | extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **); | 850 | extern void nouveau_gpuobj_ref(struct nouveau_gpuobj *, |
763 | extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, | 851 | struct nouveau_gpuobj **); |
764 | uint32_t handle, struct nouveau_gpuobj *, | 852 | extern int nouveau_gpuobj_new_fake(struct drm_device *, u32 pinst, u64 vinst, |
765 | struct nouveau_gpuobj_ref **); | 853 | u32 size, u32 flags, |
766 | extern int nouveau_gpuobj_ref_del(struct drm_device *, | 854 | struct nouveau_gpuobj **); |
767 | struct nouveau_gpuobj_ref **); | ||
768 | extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle, | ||
769 | struct nouveau_gpuobj_ref **ref_ret); | ||
770 | extern int nouveau_gpuobj_new_ref(struct drm_device *, | ||
771 | struct nouveau_channel *alloc_chan, | ||
772 | struct nouveau_channel *ref_chan, | ||
773 | uint32_t handle, uint32_t size, int align, | ||
774 | uint32_t flags, struct nouveau_gpuobj_ref **); | ||
775 | extern int nouveau_gpuobj_new_fake(struct drm_device *, | ||
776 | uint32_t p_offset, uint32_t b_offset, | ||
777 | uint32_t size, uint32_t flags, | ||
778 | struct nouveau_gpuobj **, | ||
779 | struct nouveau_gpuobj_ref**); | ||
780 | extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, | 855 | extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, |
781 | uint64_t offset, uint64_t size, int access, | 856 | uint64_t offset, uint64_t size, int access, |
782 | int target, struct nouveau_gpuobj **); | 857 | int target, struct nouveau_gpuobj **); |
@@ -879,6 +954,7 @@ extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, | |||
879 | enum dcb_gpio_tag); | 954 | enum dcb_gpio_tag); |
880 | extern struct dcb_connector_table_entry * | 955 | extern struct dcb_connector_table_entry * |
881 | nouveau_bios_connector_entry(struct drm_device *, int index); | 956 | nouveau_bios_connector_entry(struct drm_device *, int index); |
957 | extern u32 get_pll_register(struct drm_device *, enum pll_types); | ||
882 | extern int get_pll_limits(struct drm_device *, uint32_t limit_match, | 958 | extern int get_pll_limits(struct drm_device *, uint32_t limit_match, |
883 | struct pll_lims *); | 959 | struct pll_lims *); |
884 | extern int nouveau_bios_run_display_table(struct drm_device *, | 960 | extern int nouveau_bios_run_display_table(struct drm_device *, |
@@ -925,10 +1001,10 @@ extern int nv40_fb_init(struct drm_device *); | |||
925 | extern void nv40_fb_takedown(struct drm_device *); | 1001 | extern void nv40_fb_takedown(struct drm_device *); |
926 | extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, | 1002 | extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, |
927 | uint32_t, uint32_t); | 1003 | uint32_t, uint32_t); |
928 | |||
929 | /* nv50_fb.c */ | 1004 | /* nv50_fb.c */ |
930 | extern int nv50_fb_init(struct drm_device *); | 1005 | extern int nv50_fb_init(struct drm_device *); |
931 | extern void nv50_fb_takedown(struct drm_device *); | 1006 | extern void nv50_fb_takedown(struct drm_device *); |
1007 | extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *); | ||
932 | 1008 | ||
933 | /* nvc0_fb.c */ | 1009 | /* nvc0_fb.c */ |
934 | extern int nvc0_fb_init(struct drm_device *); | 1010 | extern int nvc0_fb_init(struct drm_device *); |
@@ -939,7 +1015,6 @@ extern int nv04_fifo_init(struct drm_device *); | |||
939 | extern void nv04_fifo_disable(struct drm_device *); | 1015 | extern void nv04_fifo_disable(struct drm_device *); |
940 | extern void nv04_fifo_enable(struct drm_device *); | 1016 | extern void nv04_fifo_enable(struct drm_device *); |
941 | extern bool nv04_fifo_reassign(struct drm_device *, bool); | 1017 | extern bool nv04_fifo_reassign(struct drm_device *, bool); |
942 | extern bool nv04_fifo_cache_flush(struct drm_device *); | ||
943 | extern bool nv04_fifo_cache_pull(struct drm_device *, bool); | 1018 | extern bool nv04_fifo_cache_pull(struct drm_device *, bool); |
944 | extern int nv04_fifo_channel_id(struct drm_device *); | 1019 | extern int nv04_fifo_channel_id(struct drm_device *); |
945 | extern int nv04_fifo_create_context(struct nouveau_channel *); | 1020 | extern int nv04_fifo_create_context(struct nouveau_channel *); |
@@ -977,7 +1052,6 @@ extern void nvc0_fifo_takedown(struct drm_device *); | |||
977 | extern void nvc0_fifo_disable(struct drm_device *); | 1052 | extern void nvc0_fifo_disable(struct drm_device *); |
978 | extern void nvc0_fifo_enable(struct drm_device *); | 1053 | extern void nvc0_fifo_enable(struct drm_device *); |
979 | extern bool nvc0_fifo_reassign(struct drm_device *, bool); | 1054 | extern bool nvc0_fifo_reassign(struct drm_device *, bool); |
980 | extern bool nvc0_fifo_cache_flush(struct drm_device *); | ||
981 | extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); | 1055 | extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); |
982 | extern int nvc0_fifo_channel_id(struct drm_device *); | 1056 | extern int nvc0_fifo_channel_id(struct drm_device *); |
983 | extern int nvc0_fifo_create_context(struct nouveau_channel *); | 1057 | extern int nvc0_fifo_create_context(struct nouveau_channel *); |
@@ -1169,15 +1243,21 @@ extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); | |||
1169 | 1243 | ||
1170 | /* nouveau_fence.c */ | 1244 | /* nouveau_fence.c */ |
1171 | struct nouveau_fence; | 1245 | struct nouveau_fence; |
1172 | extern int nouveau_fence_init(struct nouveau_channel *); | 1246 | extern int nouveau_fence_init(struct drm_device *); |
1173 | extern void nouveau_fence_fini(struct nouveau_channel *); | 1247 | extern void nouveau_fence_fini(struct drm_device *); |
1248 | extern int nouveau_fence_channel_init(struct nouveau_channel *); | ||
1249 | extern void nouveau_fence_channel_fini(struct nouveau_channel *); | ||
1174 | extern void nouveau_fence_update(struct nouveau_channel *); | 1250 | extern void nouveau_fence_update(struct nouveau_channel *); |
1175 | extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **, | 1251 | extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **, |
1176 | bool emit); | 1252 | bool emit); |
1177 | extern int nouveau_fence_emit(struct nouveau_fence *); | 1253 | extern int nouveau_fence_emit(struct nouveau_fence *); |
1254 | extern void nouveau_fence_work(struct nouveau_fence *fence, | ||
1255 | void (*work)(void *priv, bool signalled), | ||
1256 | void *priv); | ||
1178 | struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); | 1257 | struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); |
1179 | extern bool nouveau_fence_signalled(void *obj, void *arg); | 1258 | extern bool nouveau_fence_signalled(void *obj, void *arg); |
1180 | extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); | 1259 | extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); |
1260 | extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); | ||
1181 | extern int nouveau_fence_flush(void *obj, void *arg); | 1261 | extern int nouveau_fence_flush(void *obj, void *arg); |
1182 | extern void nouveau_fence_unref(void **obj); | 1262 | extern void nouveau_fence_unref(void **obj); |
1183 | extern void *nouveau_fence_ref(void *obj); | 1263 | extern void *nouveau_fence_ref(void *obj); |
@@ -1255,12 +1335,11 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val) | |||
1255 | iowrite32_native(val, dev_priv->mmio + reg); | 1335 | iowrite32_native(val, dev_priv->mmio + reg); |
1256 | } | 1336 | } |
1257 | 1337 | ||
1258 | static inline void nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) | 1338 | static inline u32 nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) |
1259 | { | 1339 | { |
1260 | u32 tmp = nv_rd32(dev, reg); | 1340 | u32 tmp = nv_rd32(dev, reg); |
1261 | tmp &= ~mask; | 1341 | nv_wr32(dev, reg, (tmp & ~mask) | val); |
1262 | tmp |= val; | 1342 | return tmp; |
1263 | nv_wr32(dev, reg, tmp); | ||
1264 | } | 1343 | } |
1265 | 1344 | ||
1266 | static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) | 1345 | static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) |
@@ -1275,7 +1354,7 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val) | |||
1275 | iowrite8(val, dev_priv->mmio + reg); | 1354 | iowrite8(val, dev_priv->mmio + reg); |
1276 | } | 1355 | } |
1277 | 1356 | ||
1278 | #define nv_wait(reg, mask, val) \ | 1357 | #define nv_wait(dev, reg, mask, val) \ |
1279 | nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) | 1358 | nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) |
1280 | 1359 | ||
1281 | /* PRAMIN access */ | 1360 | /* PRAMIN access */ |
@@ -1292,17 +1371,8 @@ static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val) | |||
1292 | } | 1371 | } |
1293 | 1372 | ||
1294 | /* object access */ | 1373 | /* object access */ |
1295 | static inline u32 nv_ro32(struct drm_device *dev, struct nouveau_gpuobj *obj, | 1374 | extern u32 nv_ro32(struct nouveau_gpuobj *, u32 offset); |
1296 | unsigned index) | 1375 | extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val); |
1297 | { | ||
1298 | return nv_ri32(dev, obj->im_pramin->start + index * 4); | ||
1299 | } | ||
1300 | |||
1301 | static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj, | ||
1302 | unsigned index, u32 val) | ||
1303 | { | ||
1304 | nv_wi32(dev, obj->im_pramin->start + index * 4, val); | ||
1305 | } | ||
1306 | 1376 | ||
1307 | /* | 1377 | /* |
1308 | * Logging | 1378 | * Logging |
@@ -1403,6 +1473,7 @@ nv_match_device(struct drm_device *dev, unsigned device, | |||
1403 | #define NV_SW_SEMAPHORE_OFFSET 0x00000064 | 1473 | #define NV_SW_SEMAPHORE_OFFSET 0x00000064 |
1404 | #define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 | 1474 | #define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 |
1405 | #define NV_SW_SEMAPHORE_RELEASE 0x0000006c | 1475 | #define NV_SW_SEMAPHORE_RELEASE 0x0000006c |
1476 | #define NV_SW_YIELD 0x00000080 | ||
1406 | #define NV_SW_DMA_VBLSEM 0x0000018c | 1477 | #define NV_SW_DMA_VBLSEM 0x0000018c |
1407 | #define NV_SW_VBLSEM_OFFSET 0x00000400 | 1478 | #define NV_SW_VBLSEM_OFFSET 0x00000400 |
1408 | #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 | 1479 | #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 7c82d68bc155..ae69b61d93db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
@@ -55,6 +55,7 @@ struct nouveau_encoder { | |||
55 | int dpcd_version; | 55 | int dpcd_version; |
56 | int link_nr; | 56 | int link_nr; |
57 | int link_bw; | 57 | int link_bw; |
58 | bool enhanced_frame; | ||
58 | } dp; | 59 | } dp; |
59 | }; | 60 | }; |
60 | }; | 61 | }; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index dbd30b2e43fd..02a4d1fd4845 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -104,6 +104,8 @@ static struct fb_ops nouveau_fbcon_ops = { | |||
104 | .fb_pan_display = drm_fb_helper_pan_display, | 104 | .fb_pan_display = drm_fb_helper_pan_display, |
105 | .fb_blank = drm_fb_helper_blank, | 105 | .fb_blank = drm_fb_helper_blank, |
106 | .fb_setcmap = drm_fb_helper_setcmap, | 106 | .fb_setcmap = drm_fb_helper_setcmap, |
107 | .fb_debug_enter = drm_fb_helper_debug_enter, | ||
108 | .fb_debug_leave = drm_fb_helper_debug_leave, | ||
107 | }; | 109 | }; |
108 | 110 | ||
109 | static struct fb_ops nv04_fbcon_ops = { | 111 | static struct fb_ops nv04_fbcon_ops = { |
@@ -117,6 +119,8 @@ static struct fb_ops nv04_fbcon_ops = { | |||
117 | .fb_pan_display = drm_fb_helper_pan_display, | 119 | .fb_pan_display = drm_fb_helper_pan_display, |
118 | .fb_blank = drm_fb_helper_blank, | 120 | .fb_blank = drm_fb_helper_blank, |
119 | .fb_setcmap = drm_fb_helper_setcmap, | 121 | .fb_setcmap = drm_fb_helper_setcmap, |
122 | .fb_debug_enter = drm_fb_helper_debug_enter, | ||
123 | .fb_debug_leave = drm_fb_helper_debug_leave, | ||
120 | }; | 124 | }; |
121 | 125 | ||
122 | static struct fb_ops nv50_fbcon_ops = { | 126 | static struct fb_ops nv50_fbcon_ops = { |
@@ -130,6 +134,8 @@ static struct fb_ops nv50_fbcon_ops = { | |||
130 | .fb_pan_display = drm_fb_helper_pan_display, | 134 | .fb_pan_display = drm_fb_helper_pan_display, |
131 | .fb_blank = drm_fb_helper_blank, | 135 | .fb_blank = drm_fb_helper_blank, |
132 | .fb_setcmap = drm_fb_helper_setcmap, | 136 | .fb_setcmap = drm_fb_helper_setcmap, |
137 | .fb_debug_enter = drm_fb_helper_debug_enter, | ||
138 | .fb_debug_leave = drm_fb_helper_debug_leave, | ||
133 | }; | 139 | }; |
134 | 140 | ||
135 | static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | 141 | static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 87ac21ec23d2..441b12420bb1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -28,9 +28,11 @@ | |||
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | 29 | ||
30 | #include "nouveau_drv.h" | 30 | #include "nouveau_drv.h" |
31 | #include "nouveau_ramht.h" | ||
31 | #include "nouveau_dma.h" | 32 | #include "nouveau_dma.h" |
32 | 33 | ||
33 | #define USE_REFCNT (dev_priv->card_type >= NV_10) | 34 | #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) |
35 | #define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) | ||
34 | 36 | ||
35 | struct nouveau_fence { | 37 | struct nouveau_fence { |
36 | struct nouveau_channel *channel; | 38 | struct nouveau_channel *channel; |
@@ -39,6 +41,15 @@ struct nouveau_fence { | |||
39 | 41 | ||
40 | uint32_t sequence; | 42 | uint32_t sequence; |
41 | bool signalled; | 43 | bool signalled; |
44 | |||
45 | void (*work)(void *priv, bool signalled); | ||
46 | void *priv; | ||
47 | }; | ||
48 | |||
49 | struct nouveau_semaphore { | ||
50 | struct kref ref; | ||
51 | struct drm_device *dev; | ||
52 | struct drm_mm_node *mem; | ||
42 | }; | 53 | }; |
43 | 54 | ||
44 | static inline struct nouveau_fence * | 55 | static inline struct nouveau_fence * |
@@ -59,14 +70,13 @@ nouveau_fence_del(struct kref *ref) | |||
59 | void | 70 | void |
60 | nouveau_fence_update(struct nouveau_channel *chan) | 71 | nouveau_fence_update(struct nouveau_channel *chan) |
61 | { | 72 | { |
62 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 73 | struct drm_device *dev = chan->dev; |
63 | struct list_head *entry, *tmp; | 74 | struct nouveau_fence *tmp, *fence; |
64 | struct nouveau_fence *fence; | ||
65 | uint32_t sequence; | 75 | uint32_t sequence; |
66 | 76 | ||
67 | spin_lock(&chan->fence.lock); | 77 | spin_lock(&chan->fence.lock); |
68 | 78 | ||
69 | if (USE_REFCNT) | 79 | if (USE_REFCNT(dev)) |
70 | sequence = nvchan_rd32(chan, 0x48); | 80 | sequence = nvchan_rd32(chan, 0x48); |
71 | else | 81 | else |
72 | sequence = atomic_read(&chan->fence.last_sequence_irq); | 82 | sequence = atomic_read(&chan->fence.last_sequence_irq); |
@@ -75,12 +85,14 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
75 | goto out; | 85 | goto out; |
76 | chan->fence.sequence_ack = sequence; | 86 | chan->fence.sequence_ack = sequence; |
77 | 87 | ||
78 | list_for_each_safe(entry, tmp, &chan->fence.pending) { | 88 | list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { |
79 | fence = list_entry(entry, struct nouveau_fence, entry); | ||
80 | |||
81 | sequence = fence->sequence; | 89 | sequence = fence->sequence; |
82 | fence->signalled = true; | 90 | fence->signalled = true; |
83 | list_del(&fence->entry); | 91 | list_del(&fence->entry); |
92 | |||
93 | if (unlikely(fence->work)) | ||
94 | fence->work(fence->priv, true); | ||
95 | |||
84 | kref_put(&fence->refcount, nouveau_fence_del); | 96 | kref_put(&fence->refcount, nouveau_fence_del); |
85 | 97 | ||
86 | if (sequence == chan->fence.sequence_ack) | 98 | if (sequence == chan->fence.sequence_ack) |
@@ -121,8 +133,8 @@ nouveau_fence_channel(struct nouveau_fence *fence) | |||
121 | int | 133 | int |
122 | nouveau_fence_emit(struct nouveau_fence *fence) | 134 | nouveau_fence_emit(struct nouveau_fence *fence) |
123 | { | 135 | { |
124 | struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; | ||
125 | struct nouveau_channel *chan = fence->channel; | 136 | struct nouveau_channel *chan = fence->channel; |
137 | struct drm_device *dev = chan->dev; | ||
126 | int ret; | 138 | int ret; |
127 | 139 | ||
128 | ret = RING_SPACE(chan, 2); | 140 | ret = RING_SPACE(chan, 2); |
@@ -143,7 +155,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
143 | list_add_tail(&fence->entry, &chan->fence.pending); | 155 | list_add_tail(&fence->entry, &chan->fence.pending); |
144 | spin_unlock(&chan->fence.lock); | 156 | spin_unlock(&chan->fence.lock); |
145 | 157 | ||
146 | BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); | 158 | BEGIN_RING(chan, NvSubSw, USE_REFCNT(dev) ? 0x0050 : 0x0150, 1); |
147 | OUT_RING(chan, fence->sequence); | 159 | OUT_RING(chan, fence->sequence); |
148 | FIRE_RING(chan); | 160 | FIRE_RING(chan); |
149 | 161 | ||
@@ -151,6 +163,25 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
151 | } | 163 | } |
152 | 164 | ||
153 | void | 165 | void |
166 | nouveau_fence_work(struct nouveau_fence *fence, | ||
167 | void (*work)(void *priv, bool signalled), | ||
168 | void *priv) | ||
169 | { | ||
170 | BUG_ON(fence->work); | ||
171 | |||
172 | spin_lock(&fence->channel->fence.lock); | ||
173 | |||
174 | if (fence->signalled) { | ||
175 | work(priv, true); | ||
176 | } else { | ||
177 | fence->work = work; | ||
178 | fence->priv = priv; | ||
179 | } | ||
180 | |||
181 | spin_unlock(&fence->channel->fence.lock); | ||
182 | } | ||
183 | |||
184 | void | ||
154 | nouveau_fence_unref(void **sync_obj) | 185 | nouveau_fence_unref(void **sync_obj) |
155 | { | 186 | { |
156 | struct nouveau_fence *fence = nouveau_fence(*sync_obj); | 187 | struct nouveau_fence *fence = nouveau_fence(*sync_obj); |
@@ -213,6 +244,162 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | |||
213 | return ret; | 244 | return ret; |
214 | } | 245 | } |
215 | 246 | ||
247 | static struct nouveau_semaphore * | ||
248 | alloc_semaphore(struct drm_device *dev) | ||
249 | { | ||
250 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
251 | struct nouveau_semaphore *sema; | ||
252 | |||
253 | if (!USE_SEMA(dev)) | ||
254 | return NULL; | ||
255 | |||
256 | sema = kmalloc(sizeof(*sema), GFP_KERNEL); | ||
257 | if (!sema) | ||
258 | goto fail; | ||
259 | |||
260 | spin_lock(&dev_priv->fence.lock); | ||
261 | sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); | ||
262 | if (sema->mem) | ||
263 | sema->mem = drm_mm_get_block(sema->mem, 4, 0); | ||
264 | spin_unlock(&dev_priv->fence.lock); | ||
265 | |||
266 | if (!sema->mem) | ||
267 | goto fail; | ||
268 | |||
269 | kref_init(&sema->ref); | ||
270 | sema->dev = dev; | ||
271 | nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0); | ||
272 | |||
273 | return sema; | ||
274 | fail: | ||
275 | kfree(sema); | ||
276 | return NULL; | ||
277 | } | ||
278 | |||
279 | static void | ||
280 | free_semaphore(struct kref *ref) | ||
281 | { | ||
282 | struct nouveau_semaphore *sema = | ||
283 | container_of(ref, struct nouveau_semaphore, ref); | ||
284 | struct drm_nouveau_private *dev_priv = sema->dev->dev_private; | ||
285 | |||
286 | spin_lock(&dev_priv->fence.lock); | ||
287 | drm_mm_put_block(sema->mem); | ||
288 | spin_unlock(&dev_priv->fence.lock); | ||
289 | |||
290 | kfree(sema); | ||
291 | } | ||
292 | |||
293 | static void | ||
294 | semaphore_work(void *priv, bool signalled) | ||
295 | { | ||
296 | struct nouveau_semaphore *sema = priv; | ||
297 | struct drm_nouveau_private *dev_priv = sema->dev->dev_private; | ||
298 | |||
299 | if (unlikely(!signalled)) | ||
300 | nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); | ||
301 | |||
302 | kref_put(&sema->ref, free_semaphore); | ||
303 | } | ||
304 | |||
305 | static int | ||
306 | emit_semaphore(struct nouveau_channel *chan, int method, | ||
307 | struct nouveau_semaphore *sema) | ||
308 | { | ||
309 | struct drm_nouveau_private *dev_priv = sema->dev->dev_private; | ||
310 | struct nouveau_fence *fence; | ||
311 | bool smart = (dev_priv->card_type >= NV_50); | ||
312 | int ret; | ||
313 | |||
314 | ret = RING_SPACE(chan, smart ? 8 : 4); | ||
315 | if (ret) | ||
316 | return ret; | ||
317 | |||
318 | if (smart) { | ||
319 | BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); | ||
320 | OUT_RING(chan, NvSema); | ||
321 | } | ||
322 | BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); | ||
323 | OUT_RING(chan, sema->mem->start); | ||
324 | |||
325 | if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) { | ||
326 | /* | ||
327 | * NV50 tries to be too smart and context-switch | ||
328 | * between semaphores instead of doing a "first come, | ||
329 | * first served" strategy like previous cards | ||
330 | * do. | ||
331 | * | ||
332 | * That's bad because the ACQUIRE latency can get as | ||
333 | * large as the PFIFO context time slice in the | ||
334 | * typical DRI2 case where you have several | ||
335 | * outstanding semaphores at the same moment. | ||
336 | * | ||
337 | * If we're going to ACQUIRE, force the card to | ||
338 | * context switch before, just in case the matching | ||
339 | * RELEASE is already scheduled to be executed in | ||
340 | * another channel. | ||
341 | */ | ||
342 | BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); | ||
343 | OUT_RING(chan, 0); | ||
344 | } | ||
345 | |||
346 | BEGIN_RING(chan, NvSubSw, method, 1); | ||
347 | OUT_RING(chan, 1); | ||
348 | |||
349 | if (smart && method == NV_SW_SEMAPHORE_RELEASE) { | ||
350 | /* | ||
351 | * Force the card to context switch, there may be | ||
352 | * another channel waiting for the semaphore we just | ||
353 | * released. | ||
354 | */ | ||
355 | BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); | ||
356 | OUT_RING(chan, 0); | ||
357 | } | ||
358 | |||
359 | /* Delay semaphore destruction until its work is done */ | ||
360 | ret = nouveau_fence_new(chan, &fence, true); | ||
361 | if (ret) | ||
362 | return ret; | ||
363 | |||
364 | kref_get(&sema->ref); | ||
365 | nouveau_fence_work(fence, semaphore_work, sema); | ||
366 | nouveau_fence_unref((void *)&fence); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | int | ||
372 | nouveau_fence_sync(struct nouveau_fence *fence, | ||
373 | struct nouveau_channel *wchan) | ||
374 | { | ||
375 | struct nouveau_channel *chan = nouveau_fence_channel(fence); | ||
376 | struct drm_device *dev = wchan->dev; | ||
377 | struct nouveau_semaphore *sema; | ||
378 | int ret; | ||
379 | |||
380 | if (likely(!fence || chan == wchan || | ||
381 | nouveau_fence_signalled(fence, NULL))) | ||
382 | return 0; | ||
383 | |||
384 | sema = alloc_semaphore(dev); | ||
385 | if (!sema) { | ||
386 | /* Early card or broken userspace, fall back to | ||
387 | * software sync. */ | ||
388 | return nouveau_fence_wait(fence, NULL, false, false); | ||
389 | } | ||
390 | |||
391 | /* Make wchan wait until it gets signalled */ | ||
392 | ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); | ||
393 | if (ret) | ||
394 | goto out; | ||
395 | |||
396 | /* Signal the semaphore from chan */ | ||
397 | ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); | ||
398 | out: | ||
399 | kref_put(&sema->ref, free_semaphore); | ||
400 | return ret; | ||
401 | } | ||
402 | |||
216 | int | 403 | int |
217 | nouveau_fence_flush(void *sync_obj, void *sync_arg) | 404 | nouveau_fence_flush(void *sync_obj, void *sync_arg) |
218 | { | 405 | { |
@@ -220,26 +407,123 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg) | |||
220 | } | 407 | } |
221 | 408 | ||
222 | int | 409 | int |
223 | nouveau_fence_init(struct nouveau_channel *chan) | 410 | nouveau_fence_channel_init(struct nouveau_channel *chan) |
224 | { | 411 | { |
412 | struct drm_device *dev = chan->dev; | ||
413 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
414 | struct nouveau_gpuobj *obj = NULL; | ||
415 | int ret; | ||
416 | |||
417 | /* Create an NV_SW object for various sync purposes */ | ||
418 | ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj); | ||
419 | if (ret) | ||
420 | return ret; | ||
421 | |||
422 | ret = nouveau_ramht_insert(chan, NvSw, obj); | ||
423 | nouveau_gpuobj_ref(NULL, &obj); | ||
424 | if (ret) | ||
425 | return ret; | ||
426 | |||
427 | ret = RING_SPACE(chan, 2); | ||
428 | if (ret) | ||
429 | return ret; | ||
430 | BEGIN_RING(chan, NvSubSw, 0, 1); | ||
431 | OUT_RING(chan, NvSw); | ||
432 | |||
433 | /* Create a DMA object for the shared cross-channel sync area. */ | ||
434 | if (USE_SEMA(dev)) { | ||
435 | struct drm_mm_node *mem = dev_priv->fence.bo->bo.mem.mm_node; | ||
436 | |||
437 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, | ||
438 | mem->start << PAGE_SHIFT, | ||
439 | mem->size << PAGE_SHIFT, | ||
440 | NV_DMA_ACCESS_RW, | ||
441 | NV_DMA_TARGET_VIDMEM, &obj); | ||
442 | if (ret) | ||
443 | return ret; | ||
444 | |||
445 | ret = nouveau_ramht_insert(chan, NvSema, obj); | ||
446 | nouveau_gpuobj_ref(NULL, &obj); | ||
447 | if (ret) | ||
448 | return ret; | ||
449 | |||
450 | ret = RING_SPACE(chan, 2); | ||
451 | if (ret) | ||
452 | return ret; | ||
453 | BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); | ||
454 | OUT_RING(chan, NvSema); | ||
455 | } | ||
456 | |||
457 | FIRE_RING(chan); | ||
458 | |||
225 | INIT_LIST_HEAD(&chan->fence.pending); | 459 | INIT_LIST_HEAD(&chan->fence.pending); |
226 | spin_lock_init(&chan->fence.lock); | 460 | spin_lock_init(&chan->fence.lock); |
227 | atomic_set(&chan->fence.last_sequence_irq, 0); | 461 | atomic_set(&chan->fence.last_sequence_irq, 0); |
462 | |||
228 | return 0; | 463 | return 0; |
229 | } | 464 | } |
230 | 465 | ||
231 | void | 466 | void |
232 | nouveau_fence_fini(struct nouveau_channel *chan) | 467 | nouveau_fence_channel_fini(struct nouveau_channel *chan) |
233 | { | 468 | { |
234 | struct list_head *entry, *tmp; | 469 | struct nouveau_fence *tmp, *fence; |
235 | struct nouveau_fence *fence; | ||
236 | |||
237 | list_for_each_safe(entry, tmp, &chan->fence.pending) { | ||
238 | fence = list_entry(entry, struct nouveau_fence, entry); | ||
239 | 470 | ||
471 | list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { | ||
240 | fence->signalled = true; | 472 | fence->signalled = true; |
241 | list_del(&fence->entry); | 473 | list_del(&fence->entry); |
474 | |||
475 | if (unlikely(fence->work)) | ||
476 | fence->work(fence->priv, false); | ||
477 | |||
242 | kref_put(&fence->refcount, nouveau_fence_del); | 478 | kref_put(&fence->refcount, nouveau_fence_del); |
243 | } | 479 | } |
244 | } | 480 | } |
245 | 481 | ||
482 | int | ||
483 | nouveau_fence_init(struct drm_device *dev) | ||
484 | { | ||
485 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
486 | int ret; | ||
487 | |||
488 | /* Create a shared VRAM heap for cross-channel sync. */ | ||
489 | if (USE_SEMA(dev)) { | ||
490 | ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, | ||
491 | 0, 0, false, true, &dev_priv->fence.bo); | ||
492 | if (ret) | ||
493 | return ret; | ||
494 | |||
495 | ret = nouveau_bo_pin(dev_priv->fence.bo, TTM_PL_FLAG_VRAM); | ||
496 | if (ret) | ||
497 | goto fail; | ||
498 | |||
499 | ret = nouveau_bo_map(dev_priv->fence.bo); | ||
500 | if (ret) | ||
501 | goto fail; | ||
502 | |||
503 | ret = drm_mm_init(&dev_priv->fence.heap, 0, | ||
504 | dev_priv->fence.bo->bo.mem.size); | ||
505 | if (ret) | ||
506 | goto fail; | ||
507 | |||
508 | spin_lock_init(&dev_priv->fence.lock); | ||
509 | } | ||
510 | |||
511 | return 0; | ||
512 | fail: | ||
513 | nouveau_bo_unmap(dev_priv->fence.bo); | ||
514 | nouveau_bo_ref(NULL, &dev_priv->fence.bo); | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | void | ||
519 | nouveau_fence_fini(struct drm_device *dev) | ||
520 | { | ||
521 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
522 | |||
523 | if (USE_SEMA(dev)) { | ||
524 | drm_mm_takedown(&dev_priv->fence.heap); | ||
525 | nouveau_bo_unmap(dev_priv->fence.bo); | ||
526 | nouveau_bo_unpin(dev_priv->fence.bo); | ||
527 | nouveau_bo_ref(NULL, &dev_priv->fence.bo); | ||
528 | } | ||
529 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 19620a6709f5..5c4c929d7f74 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -362,7 +362,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, | |||
362 | list_for_each_entry(nvbo, list, entry) { | 362 | list_for_each_entry(nvbo, list, entry) { |
363 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; | 363 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; |
364 | 364 | ||
365 | ret = nouveau_bo_sync_gpu(nvbo, chan); | 365 | ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); |
366 | if (unlikely(ret)) { | 366 | if (unlikely(ret)) { |
367 | NV_ERROR(dev, "fail pre-validate sync\n"); | 367 | NV_ERROR(dev, "fail pre-validate sync\n"); |
368 | return ret; | 368 | return ret; |
@@ -385,7 +385,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, | |||
385 | return ret; | 385 | return ret; |
386 | } | 386 | } |
387 | 387 | ||
388 | ret = nouveau_bo_sync_gpu(nvbo, chan); | 388 | ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); |
389 | if (unlikely(ret)) { | 389 | if (unlikely(ret)) { |
390 | NV_ERROR(dev, "fail post-validate sync\n"); | 390 | NV_ERROR(dev, "fail post-validate sync\n"); |
391 | return ret; | 391 | return ret; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h index 5d39c4ce8006..4a8ad1307fa4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_grctx.h +++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h | |||
@@ -126,7 +126,7 @@ gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) | |||
126 | reg = (reg - 0x00400000) / 4; | 126 | reg = (reg - 0x00400000) / 4; |
127 | reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; | 127 | reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; |
128 | 128 | ||
129 | nv_wo32(ctx->dev, ctx->data, reg, val); | 129 | nv_wo32(ctx->data, reg * 4, val); |
130 | } | 130 | } |
131 | #endif | 131 | #endif |
132 | 132 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index 7b613682e400..bed669a54a2d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c | |||
@@ -305,7 +305,7 @@ setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg, | |||
305 | bool mpll = Preg == 0x4020; | 305 | bool mpll = Preg == 0x4020; |
306 | uint32_t oldPval = nvReadMC(dev, Preg); | 306 | uint32_t oldPval = nvReadMC(dev, Preg); |
307 | uint32_t NMNM = pv->NM2 << 16 | pv->NM1; | 307 | uint32_t NMNM = pv->NM2 << 16 | pv->NM1; |
308 | uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) | | 308 | uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | |
309 | 0xc << 28 | pv->log2P << 16; | 309 | 0xc << 28 | pv->log2P << 16; |
310 | uint32_t saved4600 = 0; | 310 | uint32_t saved4600 = 0; |
311 | /* some cards have different maskc040s */ | 311 | /* some cards have different maskc040s */ |
@@ -427,22 +427,12 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype, | |||
427 | struct nouveau_pll_vals *pllvals) | 427 | struct nouveau_pll_vals *pllvals) |
428 | { | 428 | { |
429 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 429 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
430 | const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF, | 430 | uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; |
431 | NV_PRAMDAC_MPLL_COEFF, | ||
432 | NV_PRAMDAC_VPLL_COEFF, | ||
433 | NV_RAMDAC_VPLL2 }; | ||
434 | const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000, | ||
435 | 0x4020, | ||
436 | NV_PRAMDAC_VPLL_COEFF, | ||
437 | NV_RAMDAC_VPLL2 }; | ||
438 | uint32_t reg1, pll1, pll2 = 0; | ||
439 | struct pll_lims pll_lim; | 431 | struct pll_lims pll_lim; |
440 | int ret; | 432 | int ret; |
441 | 433 | ||
442 | if (dev_priv->card_type < NV_40) | 434 | if (reg1 == 0) |
443 | reg1 = nv04_regs[plltype]; | 435 | return -ENOENT; |
444 | else | ||
445 | reg1 = nv40_regs[plltype]; | ||
446 | 436 | ||
447 | pll1 = nvReadMC(dev, reg1); | 437 | pll1 = nvReadMC(dev, reg1); |
448 | 438 | ||
@@ -491,8 +481,10 @@ int | |||
491 | nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) | 481 | nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) |
492 | { | 482 | { |
493 | struct nouveau_pll_vals pllvals; | 483 | struct nouveau_pll_vals pllvals; |
484 | int ret; | ||
494 | 485 | ||
495 | if (plltype == MPLL && (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { | 486 | if (plltype == PLL_MEMORY && |
487 | (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { | ||
496 | uint32_t mpllP; | 488 | uint32_t mpllP; |
497 | 489 | ||
498 | pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); | 490 | pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); |
@@ -501,14 +493,17 @@ nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) | |||
501 | 493 | ||
502 | return 400000 / mpllP; | 494 | return 400000 / mpllP; |
503 | } else | 495 | } else |
504 | if (plltype == MPLL && (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { | 496 | if (plltype == PLL_MEMORY && |
497 | (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { | ||
505 | uint32_t clock; | 498 | uint32_t clock; |
506 | 499 | ||
507 | pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); | 500 | pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); |
508 | return clock; | 501 | return clock; |
509 | } | 502 | } |
510 | 503 | ||
511 | nouveau_hw_get_pllvals(dev, plltype, &pllvals); | 504 | ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals); |
505 | if (ret) | ||
506 | return ret; | ||
512 | 507 | ||
513 | return nouveau_hw_pllvals_to_clk(&pllvals); | 508 | return nouveau_hw_pllvals_to_clk(&pllvals); |
514 | } | 509 | } |
@@ -526,9 +521,9 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | |||
526 | struct nouveau_pll_vals pv; | 521 | struct nouveau_pll_vals pv; |
527 | uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; | 522 | uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; |
528 | 523 | ||
529 | if (get_pll_limits(dev, head ? VPLL2 : VPLL1, &pll_lim)) | 524 | if (get_pll_limits(dev, pllreg, &pll_lim)) |
530 | return; | 525 | return; |
531 | nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &pv); | 526 | nouveau_hw_get_pllvals(dev, pllreg, &pv); |
532 | 527 | ||
533 | if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && | 528 | if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && |
534 | pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && | 529 | pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && |
@@ -661,7 +656,7 @@ nv_save_state_ramdac(struct drm_device *dev, int head, | |||
661 | if (dev_priv->card_type >= NV_10) | 656 | if (dev_priv->card_type >= NV_10) |
662 | regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); | 657 | regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); |
663 | 658 | ||
664 | nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, ®p->pllvals); | 659 | nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, ®p->pllvals); |
665 | state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); | 660 | state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); |
666 | if (nv_two_heads(dev)) | 661 | if (nv_two_heads(dev)) |
667 | state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); | 662 | state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); |
@@ -866,10 +861,11 @@ nv_save_state_ext(struct drm_device *dev, int head, | |||
866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 861 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); | 862 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); |
868 | 863 | ||
869 | if (dev_priv->card_type >= NV_30) { | 864 | if (dev_priv->card_type >= NV_20) |
870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); | 865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); |
866 | |||
867 | if (dev_priv->card_type >= NV_30) | ||
871 | rd_cio_state(dev, head, regp, 0x9f); | 868 | rd_cio_state(dev, head, regp, 0x9f); |
872 | } | ||
873 | 869 | ||
874 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); | 870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); |
875 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 871 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
@@ -976,10 +972,11 @@ nv_load_state_ext(struct drm_device *dev, int head, | |||
976 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 972 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 973 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
978 | 974 | ||
979 | if (dev_priv->card_type >= NV_30) { | 975 | if (dev_priv->card_type >= NV_20) |
980 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); | 976 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); |
977 | |||
978 | if (dev_priv->card_type >= NV_30) | ||
981 | wr_cio_state(dev, head, regp, 0x9f); | 979 | wr_cio_state(dev, head, regp, 0x9f); |
982 | } | ||
983 | 980 | ||
984 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); | 981 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); |
985 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 982 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 84614858728b..fdd7e3de79c8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -299,7 +299,10 @@ nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) | |||
299 | 299 | ||
300 | int | 300 | int |
301 | nouveau_i2c_identify(struct drm_device *dev, const char *what, | 301 | nouveau_i2c_identify(struct drm_device *dev, const char *what, |
302 | struct i2c_board_info *info, int index) | 302 | struct i2c_board_info *info, |
303 | bool (*match)(struct nouveau_i2c_chan *, | ||
304 | struct i2c_board_info *), | ||
305 | int index) | ||
303 | { | 306 | { |
304 | struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); | 307 | struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); |
305 | int i; | 308 | int i; |
@@ -307,7 +310,8 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, | |||
307 | NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); | 310 | NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); |
308 | 311 | ||
309 | for (i = 0; info[i].addr; i++) { | 312 | for (i = 0; info[i].addr; i++) { |
310 | if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { | 313 | if (nouveau_probe_i2c_addr(i2c, info[i].addr) && |
314 | (!match || match(i2c, &info[i]))) { | ||
311 | NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); | 315 | NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); |
312 | return i; | 316 | return i; |
313 | } | 317 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index f71cb32f7571..c77a6ba66b7c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h | |||
@@ -44,7 +44,10 @@ void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); | |||
44 | struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); | 44 | struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); |
45 | bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | 45 | bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); |
46 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | 46 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, |
47 | struct i2c_board_info *info, int index); | 47 | struct i2c_board_info *info, |
48 | bool (*match)(struct nouveau_i2c_chan *, | ||
49 | struct i2c_board_info *), | ||
50 | int index); | ||
48 | 51 | ||
49 | extern const struct i2c_algorithm nouveau_dp_i2c_algo; | 52 | extern const struct i2c_algorithm nouveau_dp_i2c_algo; |
50 | 53 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 794b0ee30cf6..6fd51a51c608 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "nouveau_drm.h" | 35 | #include "nouveau_drm.h" |
36 | #include "nouveau_drv.h" | 36 | #include "nouveau_drv.h" |
37 | #include "nouveau_reg.h" | 37 | #include "nouveau_reg.h" |
38 | #include "nouveau_ramht.h" | ||
38 | #include <linux/ratelimit.h> | 39 | #include <linux/ratelimit.h> |
39 | 40 | ||
40 | /* needed for hotplug irq */ | 41 | /* needed for hotplug irq */ |
@@ -106,15 +107,16 @@ nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) | |||
106 | const int mthd = addr & 0x1ffc; | 107 | const int mthd = addr & 0x1ffc; |
107 | 108 | ||
108 | if (mthd == 0x0000) { | 109 | if (mthd == 0x0000) { |
109 | struct nouveau_gpuobj_ref *ref = NULL; | 110 | struct nouveau_gpuobj *gpuobj; |
110 | 111 | ||
111 | if (nouveau_gpuobj_ref_find(chan, data, &ref)) | 112 | gpuobj = nouveau_ramht_find(chan, data); |
113 | if (!gpuobj) | ||
112 | return false; | 114 | return false; |
113 | 115 | ||
114 | if (ref->gpuobj->engine != NVOBJ_ENGINE_SW) | 116 | if (gpuobj->engine != NVOBJ_ENGINE_SW) |
115 | return false; | 117 | return false; |
116 | 118 | ||
117 | chan->sw_subchannel[subc] = ref->gpuobj->class; | 119 | chan->sw_subchannel[subc] = gpuobj->class; |
118 | nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, | 120 | nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, |
119 | NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); | 121 | NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); |
120 | return true; | 122 | return true; |
@@ -200,16 +202,45 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
200 | } | 202 | } |
201 | 203 | ||
202 | if (status & NV_PFIFO_INTR_DMA_PUSHER) { | 204 | if (status & NV_PFIFO_INTR_DMA_PUSHER) { |
203 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d\n", chid); | 205 | u32 get = nv_rd32(dev, 0x003244); |
206 | u32 put = nv_rd32(dev, 0x003240); | ||
207 | u32 push = nv_rd32(dev, 0x003220); | ||
208 | u32 state = nv_rd32(dev, 0x003228); | ||
209 | |||
210 | if (dev_priv->card_type == NV_50) { | ||
211 | u32 ho_get = nv_rd32(dev, 0x003328); | ||
212 | u32 ho_put = nv_rd32(dev, 0x003320); | ||
213 | u32 ib_get = nv_rd32(dev, 0x003334); | ||
214 | u32 ib_put = nv_rd32(dev, 0x003330); | ||
215 | |||
216 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " | ||
217 | "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " | ||
218 | "State 0x%08x Push 0x%08x\n", | ||
219 | chid, ho_get, get, ho_put, put, ib_get, ib_put, | ||
220 | state, push); | ||
221 | |||
222 | /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ | ||
223 | nv_wr32(dev, 0x003364, 0x00000000); | ||
224 | if (get != put || ho_get != ho_put) { | ||
225 | nv_wr32(dev, 0x003244, put); | ||
226 | nv_wr32(dev, 0x003328, ho_put); | ||
227 | } else | ||
228 | if (ib_get != ib_put) { | ||
229 | nv_wr32(dev, 0x003334, ib_put); | ||
230 | } | ||
231 | } else { | ||
232 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " | ||
233 | "Put 0x%08x State 0x%08x Push 0x%08x\n", | ||
234 | chid, get, put, state, push); | ||
204 | 235 | ||
205 | status &= ~NV_PFIFO_INTR_DMA_PUSHER; | 236 | if (get != put) |
206 | nv_wr32(dev, NV03_PFIFO_INTR_0, | 237 | nv_wr32(dev, 0x003244, put); |
207 | NV_PFIFO_INTR_DMA_PUSHER); | 238 | } |
208 | 239 | ||
209 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); | 240 | nv_wr32(dev, 0x003228, 0x00000000); |
210 | if (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT) != get) | 241 | nv_wr32(dev, 0x003220, 0x00000001); |
211 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, | 242 | nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); |
212 | get + 4); | 243 | status &= ~NV_PFIFO_INTR_DMA_PUSHER; |
213 | } | 244 | } |
214 | 245 | ||
215 | if (status & NV_PFIFO_INTR_SEMAPHORE) { | 246 | if (status & NV_PFIFO_INTR_SEMAPHORE) { |
@@ -226,6 +257,14 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
226 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); | 257 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); |
227 | } | 258 | } |
228 | 259 | ||
260 | if (dev_priv->card_type == NV_50) { | ||
261 | if (status & 0x00000010) { | ||
262 | nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); | ||
263 | status &= ~0x00000010; | ||
264 | nv_wr32(dev, 0x002100, 0x00000010); | ||
265 | } | ||
266 | } | ||
267 | |||
229 | if (status) { | 268 | if (status) { |
230 | NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", | 269 | NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", |
231 | status, chid); | 270 | status, chid); |
@@ -357,7 +396,7 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev) | |||
357 | if (!chan || !chan->ramin_grctx) | 396 | if (!chan || !chan->ramin_grctx) |
358 | continue; | 397 | continue; |
359 | 398 | ||
360 | if (inst == chan->ramin_grctx->instance) | 399 | if (inst == chan->ramin_grctx->pinst) |
361 | break; | 400 | break; |
362 | } | 401 | } |
363 | } else { | 402 | } else { |
@@ -369,7 +408,7 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev) | |||
369 | if (!chan || !chan->ramin) | 408 | if (!chan || !chan->ramin) |
370 | continue; | 409 | continue; |
371 | 410 | ||
372 | if (inst == chan->ramin->instance) | 411 | if (inst == chan->ramin->vinst) |
373 | break; | 412 | break; |
374 | } | 413 | } |
375 | } | 414 | } |
@@ -605,40 +644,6 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) | |||
605 | nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); | 644 | nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); |
606 | } | 645 | } |
607 | 646 | ||
608 | static void | ||
609 | nv50_pfb_vm_trap(struct drm_device *dev, int display, const char *name) | ||
610 | { | ||
611 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
612 | uint32_t trap[6]; | ||
613 | int i, ch; | ||
614 | uint32_t idx = nv_rd32(dev, 0x100c90); | ||
615 | if (idx & 0x80000000) { | ||
616 | idx &= 0xffffff; | ||
617 | if (display) { | ||
618 | for (i = 0; i < 6; i++) { | ||
619 | nv_wr32(dev, 0x100c90, idx | i << 24); | ||
620 | trap[i] = nv_rd32(dev, 0x100c94); | ||
621 | } | ||
622 | for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { | ||
623 | struct nouveau_channel *chan = dev_priv->fifos[ch]; | ||
624 | |||
625 | if (!chan || !chan->ramin) | ||
626 | continue; | ||
627 | |||
628 | if (trap[1] == chan->ramin->instance >> 12) | ||
629 | break; | ||
630 | } | ||
631 | NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x %08x channel %d\n", | ||
632 | name, (trap[5]&0x100?"read":"write"), | ||
633 | trap[5]&0xff, trap[4]&0xffff, | ||
634 | trap[3]&0xffff, trap[0], trap[2], ch); | ||
635 | } | ||
636 | nv_wr32(dev, 0x100c90, idx | 0x80000000); | ||
637 | } else if (display) { | ||
638 | NV_INFO(dev, "%s - no VM fault?\n", name); | ||
639 | } | ||
640 | } | ||
641 | |||
642 | static struct nouveau_enum_names nv50_mp_exec_error_names[] = | 647 | static struct nouveau_enum_names nv50_mp_exec_error_names[] = |
643 | { | 648 | { |
644 | { 3, "STACK_UNDERFLOW" }, | 649 | { 3, "STACK_UNDERFLOW" }, |
@@ -711,7 +716,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, | |||
711 | tps++; | 716 | tps++; |
712 | switch (type) { | 717 | switch (type) { |
713 | case 6: /* texture error... unknown for now */ | 718 | case 6: /* texture error... unknown for now */ |
714 | nv50_pfb_vm_trap(dev, display, name); | 719 | nv50_fb_vm_trap(dev, display, name); |
715 | if (display) { | 720 | if (display) { |
716 | NV_ERROR(dev, "magic set %d:\n", i); | 721 | NV_ERROR(dev, "magic set %d:\n", i); |
717 | for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) | 722 | for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) |
@@ -734,7 +739,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, | |||
734 | uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); | 739 | uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); |
735 | uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); | 740 | uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); |
736 | uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); | 741 | uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); |
737 | nv50_pfb_vm_trap(dev, display, name); | 742 | nv50_fb_vm_trap(dev, display, name); |
738 | /* 2d engine destination */ | 743 | /* 2d engine destination */ |
739 | if (ustatus & 0x00000010) { | 744 | if (ustatus & 0x00000010) { |
740 | if (display) { | 745 | if (display) { |
@@ -817,7 +822,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
817 | 822 | ||
818 | /* Known to be triggered by screwed up NOTIFY and COND... */ | 823 | /* Known to be triggered by screwed up NOTIFY and COND... */ |
819 | if (ustatus & 0x00000001) { | 824 | if (ustatus & 0x00000001) { |
820 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); | 825 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); |
821 | nv_wr32(dev, 0x400500, 0); | 826 | nv_wr32(dev, 0x400500, 0); |
822 | if (nv_rd32(dev, 0x400808) & 0x80000000) { | 827 | if (nv_rd32(dev, 0x400808) & 0x80000000) { |
823 | if (display) { | 828 | if (display) { |
@@ -842,7 +847,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
842 | ustatus &= ~0x00000001; | 847 | ustatus &= ~0x00000001; |
843 | } | 848 | } |
844 | if (ustatus & 0x00000002) { | 849 | if (ustatus & 0x00000002) { |
845 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); | 850 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); |
846 | nv_wr32(dev, 0x400500, 0); | 851 | nv_wr32(dev, 0x400500, 0); |
847 | if (nv_rd32(dev, 0x40084c) & 0x80000000) { | 852 | if (nv_rd32(dev, 0x40084c) & 0x80000000) { |
848 | if (display) { | 853 | if (display) { |
@@ -884,15 +889,15 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
884 | NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); | 889 | NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); |
885 | } | 890 | } |
886 | if (ustatus & 0x00000001) { | 891 | if (ustatus & 0x00000001) { |
887 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); | 892 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); |
888 | ustatus &= ~0x00000001; | 893 | ustatus &= ~0x00000001; |
889 | } | 894 | } |
890 | if (ustatus & 0x00000002) { | 895 | if (ustatus & 0x00000002) { |
891 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); | 896 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); |
892 | ustatus &= ~0x00000002; | 897 | ustatus &= ~0x00000002; |
893 | } | 898 | } |
894 | if (ustatus & 0x00000004) { | 899 | if (ustatus & 0x00000004) { |
895 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); | 900 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); |
896 | ustatus &= ~0x00000004; | 901 | ustatus &= ~0x00000004; |
897 | } | 902 | } |
898 | NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", | 903 | NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", |
@@ -917,7 +922,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
917 | NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); | 922 | NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); |
918 | } | 923 | } |
919 | if (ustatus & 0x00000001) { | 924 | if (ustatus & 0x00000001) { |
920 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); | 925 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); |
921 | NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", | 926 | NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", |
922 | nv_rd32(dev, 0x400c00), | 927 | nv_rd32(dev, 0x400c00), |
923 | nv_rd32(dev, 0x400c08), | 928 | nv_rd32(dev, 0x400c08), |
@@ -939,7 +944,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
939 | NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); | 944 | NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); |
940 | } | 945 | } |
941 | if (ustatus & 0x00000001) { | 946 | if (ustatus & 0x00000001) { |
942 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); | 947 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); |
943 | NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", | 948 | NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", |
944 | nv_rd32(dev, 0x401804), | 949 | nv_rd32(dev, 0x401804), |
945 | nv_rd32(dev, 0x401808), | 950 | nv_rd32(dev, 0x401808), |
@@ -964,7 +969,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
964 | NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); | 969 | NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); |
965 | } | 970 | } |
966 | if (ustatus & 0x00000001) { | 971 | if (ustatus & 0x00000001) { |
967 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); | 972 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); |
968 | NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", | 973 | NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", |
969 | nv_rd32(dev, 0x405800), | 974 | nv_rd32(dev, 0x405800), |
970 | nv_rd32(dev, 0x405804), | 975 | nv_rd32(dev, 0x405804), |
@@ -986,7 +991,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) | |||
986 | * remaining, so try to handle it anyway. Perhaps related to that | 991 | * remaining, so try to handle it anyway. Perhaps related to that |
987 | * unknown DMA slot on tesla? */ | 992 | * unknown DMA slot on tesla? */ |
988 | if (status & 0x20) { | 993 | if (status & 0x20) { |
989 | nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); | 994 | nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); |
990 | ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; | 995 | ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; |
991 | if (display) | 996 | if (display) |
992 | NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); | 997 | NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 9689d4147686..a163c7c612e7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include "drm_sarea.h" | 35 | #include "drm_sarea.h" |
36 | #include "nouveau_drv.h" | 36 | #include "nouveau_drv.h" |
37 | 37 | ||
38 | #define MIN(a,b) a < b ? a : b | ||
39 | |||
38 | /* | 40 | /* |
39 | * NV10-NV40 tiling helpers | 41 | * NV10-NV40 tiling helpers |
40 | */ | 42 | */ |
@@ -47,18 +49,14 @@ nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, | |||
47 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; | 49 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; |
48 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | 50 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; |
49 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 51 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
50 | struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; | 52 | struct nouveau_tile_reg *tile = &dev_priv->tile[i]; |
51 | 53 | ||
52 | tile->addr = addr; | 54 | tile->addr = addr; |
53 | tile->size = size; | 55 | tile->size = size; |
54 | tile->used = !!pitch; | 56 | tile->used = !!pitch; |
55 | nouveau_fence_unref((void **)&tile->fence); | 57 | nouveau_fence_unref((void **)&tile->fence); |
56 | 58 | ||
57 | if (!pfifo->cache_flush(dev)) | ||
58 | return; | ||
59 | |||
60 | pfifo->reassign(dev, false); | 59 | pfifo->reassign(dev, false); |
61 | pfifo->cache_flush(dev); | ||
62 | pfifo->cache_pull(dev, false); | 60 | pfifo->cache_pull(dev, false); |
63 | 61 | ||
64 | nouveau_wait_for_idle(dev); | 62 | nouveau_wait_for_idle(dev); |
@@ -76,34 +74,36 @@ nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, | |||
76 | { | 74 | { |
77 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 75 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
78 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | 76 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; |
79 | struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL; | 77 | struct nouveau_tile_reg *found = NULL; |
80 | int i; | 78 | unsigned long i, flags; |
81 | 79 | ||
82 | spin_lock(&dev_priv->tile.lock); | 80 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
83 | 81 | ||
84 | for (i = 0; i < pfb->num_tiles; i++) { | 82 | for (i = 0; i < pfb->num_tiles; i++) { |
85 | if (tile[i].used) | 83 | struct nouveau_tile_reg *tile = &dev_priv->tile[i]; |
84 | |||
85 | if (tile->used) | ||
86 | /* Tile region in use. */ | 86 | /* Tile region in use. */ |
87 | continue; | 87 | continue; |
88 | 88 | ||
89 | if (tile[i].fence && | 89 | if (tile->fence && |
90 | !nouveau_fence_signalled(tile[i].fence, NULL)) | 90 | !nouveau_fence_signalled(tile->fence, NULL)) |
91 | /* Pending tile region. */ | 91 | /* Pending tile region. */ |
92 | continue; | 92 | continue; |
93 | 93 | ||
94 | if (max(tile[i].addr, addr) < | 94 | if (max(tile->addr, addr) < |
95 | min(tile[i].addr + tile[i].size, addr + size)) | 95 | min(tile->addr + tile->size, addr + size)) |
96 | /* Kill an intersecting tile region. */ | 96 | /* Kill an intersecting tile region. */ |
97 | nv10_mem_set_region_tiling(dev, i, 0, 0, 0); | 97 | nv10_mem_set_region_tiling(dev, i, 0, 0, 0); |
98 | 98 | ||
99 | if (pitch && !found) { | 99 | if (pitch && !found) { |
100 | /* Free tile region. */ | 100 | /* Free tile region. */ |
101 | nv10_mem_set_region_tiling(dev, i, addr, size, pitch); | 101 | nv10_mem_set_region_tiling(dev, i, addr, size, pitch); |
102 | found = &tile[i]; | 102 | found = tile; |
103 | } | 103 | } |
104 | } | 104 | } |
105 | 105 | ||
106 | spin_unlock(&dev_priv->tile.lock); | 106 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
107 | 107 | ||
108 | return found; | 108 | return found; |
109 | } | 109 | } |
@@ -169,8 +169,9 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, | |||
169 | virt += (end - pte); | 169 | virt += (end - pte); |
170 | 170 | ||
171 | while (pte < end) { | 171 | while (pte < end) { |
172 | nv_wo32(dev, pgt, pte++, offset_l); | 172 | nv_wo32(pgt, (pte * 4) + 0, offset_l); |
173 | nv_wo32(dev, pgt, pte++, offset_h); | 173 | nv_wo32(pgt, (pte * 4) + 4, offset_h); |
174 | pte += 2; | ||
174 | } | 175 | } |
175 | } | 176 | } |
176 | } | 177 | } |
@@ -203,8 +204,10 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) | |||
203 | pages -= (end - pte); | 204 | pages -= (end - pte); |
204 | virt += (end - pte) << 15; | 205 | virt += (end - pte) << 15; |
205 | 206 | ||
206 | while (pte < end) | 207 | while (pte < end) { |
207 | nv_wo32(dev, pgt, pte++, 0); | 208 | nv_wo32(pgt, (pte * 4), 0); |
209 | pte++; | ||
210 | } | ||
208 | } | 211 | } |
209 | dev_priv->engine.instmem.flush(dev); | 212 | dev_priv->engine.instmem.flush(dev); |
210 | 213 | ||
@@ -218,7 +221,7 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) | |||
218 | * Cleanup everything | 221 | * Cleanup everything |
219 | */ | 222 | */ |
220 | void | 223 | void |
221 | nouveau_mem_close(struct drm_device *dev) | 224 | nouveau_mem_vram_fini(struct drm_device *dev) |
222 | { | 225 | { |
223 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 226 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
224 | 227 | ||
@@ -229,6 +232,19 @@ nouveau_mem_close(struct drm_device *dev) | |||
229 | 232 | ||
230 | nouveau_ttm_global_release(dev_priv); | 233 | nouveau_ttm_global_release(dev_priv); |
231 | 234 | ||
235 | if (dev_priv->fb_mtrr >= 0) { | ||
236 | drm_mtrr_del(dev_priv->fb_mtrr, | ||
237 | pci_resource_start(dev->pdev, 1), | ||
238 | pci_resource_len(dev->pdev, 1), DRM_MTRR_WC); | ||
239 | dev_priv->fb_mtrr = -1; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | void | ||
244 | nouveau_mem_gart_fini(struct drm_device *dev) | ||
245 | { | ||
246 | nouveau_sgdma_takedown(dev); | ||
247 | |||
232 | if (drm_core_has_AGP(dev) && dev->agp) { | 248 | if (drm_core_has_AGP(dev) && dev->agp) { |
233 | struct drm_agp_mem *entry, *tempe; | 249 | struct drm_agp_mem *entry, *tempe; |
234 | 250 | ||
@@ -248,13 +264,6 @@ nouveau_mem_close(struct drm_device *dev) | |||
248 | dev->agp->acquired = 0; | 264 | dev->agp->acquired = 0; |
249 | dev->agp->enabled = 0; | 265 | dev->agp->enabled = 0; |
250 | } | 266 | } |
251 | |||
252 | if (dev_priv->fb_mtrr) { | ||
253 | drm_mtrr_del(dev_priv->fb_mtrr, | ||
254 | pci_resource_start(dev->pdev, 1), | ||
255 | pci_resource_len(dev->pdev, 1), DRM_MTRR_WC); | ||
256 | dev_priv->fb_mtrr = -1; | ||
257 | } | ||
258 | } | 267 | } |
259 | 268 | ||
260 | static uint32_t | 269 | static uint32_t |
@@ -305,8 +314,62 @@ nouveau_mem_detect_nforce(struct drm_device *dev) | |||
305 | return 0; | 314 | return 0; |
306 | } | 315 | } |
307 | 316 | ||
308 | /* returns the amount of FB ram in bytes */ | 317 | static void |
309 | int | 318 | nv50_vram_preinit(struct drm_device *dev) |
319 | { | ||
320 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
321 | int i, parts, colbits, rowbitsa, rowbitsb, banks; | ||
322 | u64 rowsize, predicted; | ||
323 | u32 r0, r4, rt, ru; | ||
324 | |||
325 | r0 = nv_rd32(dev, 0x100200); | ||
326 | r4 = nv_rd32(dev, 0x100204); | ||
327 | rt = nv_rd32(dev, 0x100250); | ||
328 | ru = nv_rd32(dev, 0x001540); | ||
329 | NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); | ||
330 | |||
331 | for (i = 0, parts = 0; i < 8; i++) { | ||
332 | if (ru & (0x00010000 << i)) | ||
333 | parts++; | ||
334 | } | ||
335 | |||
336 | colbits = (r4 & 0x0000f000) >> 12; | ||
337 | rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; | ||
338 | rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; | ||
339 | banks = ((r4 & 0x01000000) ? 8 : 4); | ||
340 | |||
341 | rowsize = parts * banks * (1 << colbits) * 8; | ||
342 | predicted = rowsize << rowbitsa; | ||
343 | if (r0 & 0x00000004) | ||
344 | predicted += rowsize << rowbitsb; | ||
345 | |||
346 | if (predicted != dev_priv->vram_size) { | ||
347 | NV_WARN(dev, "memory controller reports %dMiB VRAM\n", | ||
348 | (u32)(dev_priv->vram_size >> 20)); | ||
349 | NV_WARN(dev, "we calculated %dMiB VRAM\n", | ||
350 | (u32)(predicted >> 20)); | ||
351 | } | ||
352 | |||
353 | dev_priv->vram_rblock_size = rowsize >> 12; | ||
354 | if (rt & 1) | ||
355 | dev_priv->vram_rblock_size *= 3; | ||
356 | |||
357 | NV_DEBUG(dev, "rblock %lld bytes\n", | ||
358 | (u64)dev_priv->vram_rblock_size << 12); | ||
359 | } | ||
360 | |||
361 | static void | ||
362 | nvaa_vram_preinit(struct drm_device *dev) | ||
363 | { | ||
364 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
365 | |||
366 | /* To our knowledge, there's no large scale reordering of pages | ||
367 | * that occurs on IGP chipsets. | ||
368 | */ | ||
369 | dev_priv->vram_rblock_size = 1; | ||
370 | } | ||
371 | |||
372 | static int | ||
310 | nouveau_mem_detect(struct drm_device *dev) | 373 | nouveau_mem_detect(struct drm_device *dev) |
311 | { | 374 | { |
312 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 375 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
@@ -325,9 +388,18 @@ nouveau_mem_detect(struct drm_device *dev) | |||
325 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 388 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
326 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; | 389 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; |
327 | dev_priv->vram_size &= 0xffffffff00ll; | 390 | dev_priv->vram_size &= 0xffffffff00ll; |
328 | if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { | 391 | |
392 | switch (dev_priv->chipset) { | ||
393 | case 0xaa: | ||
394 | case 0xac: | ||
395 | case 0xaf: | ||
329 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); | 396 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); |
330 | dev_priv->vram_sys_base <<= 12; | 397 | dev_priv->vram_sys_base <<= 12; |
398 | nvaa_vram_preinit(dev); | ||
399 | break; | ||
400 | default: | ||
401 | nv50_vram_preinit(dev); | ||
402 | break; | ||
331 | } | 403 | } |
332 | } else { | 404 | } else { |
333 | dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; | 405 | dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; |
@@ -345,6 +417,33 @@ nouveau_mem_detect(struct drm_device *dev) | |||
345 | return -ENOMEM; | 417 | return -ENOMEM; |
346 | } | 418 | } |
347 | 419 | ||
420 | #if __OS_HAS_AGP | ||
421 | static unsigned long | ||
422 | get_agp_mode(struct drm_device *dev, unsigned long mode) | ||
423 | { | ||
424 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
425 | |||
426 | /* | ||
427 | * FW seems to be broken on nv18, it makes the card lock up | ||
428 | * randomly. | ||
429 | */ | ||
430 | if (dev_priv->chipset == 0x18) | ||
431 | mode &= ~PCI_AGP_COMMAND_FW; | ||
432 | |||
433 | /* | ||
434 | * AGP mode set in the command line. | ||
435 | */ | ||
436 | if (nouveau_agpmode > 0) { | ||
437 | bool agpv3 = mode & 0x8; | ||
438 | int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; | ||
439 | |||
440 | mode = (mode & ~0x7) | (rate & 0x7); | ||
441 | } | ||
442 | |||
443 | return mode; | ||
444 | } | ||
445 | #endif | ||
446 | |||
348 | int | 447 | int |
349 | nouveau_mem_reset_agp(struct drm_device *dev) | 448 | nouveau_mem_reset_agp(struct drm_device *dev) |
350 | { | 449 | { |
@@ -355,7 +454,8 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
355 | /* First of all, disable fast writes, otherwise if it's | 454 | /* First of all, disable fast writes, otherwise if it's |
356 | * already enabled in the AGP bridge and we disable the card's | 455 | * already enabled in the AGP bridge and we disable the card's |
357 | * AGP controller we might be locking ourselves out of it. */ | 456 | * AGP controller we might be locking ourselves out of it. */ |
358 | if (nv_rd32(dev, NV04_PBUS_PCI_NV_19) & PCI_AGP_COMMAND_FW) { | 457 | if ((nv_rd32(dev, NV04_PBUS_PCI_NV_19) | |
458 | dev->agp->mode) & PCI_AGP_COMMAND_FW) { | ||
359 | struct drm_agp_info info; | 459 | struct drm_agp_info info; |
360 | struct drm_agp_mode mode; | 460 | struct drm_agp_mode mode; |
361 | 461 | ||
@@ -363,7 +463,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
363 | if (ret) | 463 | if (ret) |
364 | return ret; | 464 | return ret; |
365 | 465 | ||
366 | mode.mode = info.mode & ~PCI_AGP_COMMAND_FW; | 466 | mode.mode = get_agp_mode(dev, info.mode) & ~PCI_AGP_COMMAND_FW; |
367 | ret = drm_agp_enable(dev, mode); | 467 | ret = drm_agp_enable(dev, mode); |
368 | if (ret) | 468 | if (ret) |
369 | return ret; | 469 | return ret; |
@@ -418,7 +518,7 @@ nouveau_mem_init_agp(struct drm_device *dev) | |||
418 | } | 518 | } |
419 | 519 | ||
420 | /* see agp.h for the AGPSTAT_* modes available */ | 520 | /* see agp.h for the AGPSTAT_* modes available */ |
421 | mode.mode = info.mode; | 521 | mode.mode = get_agp_mode(dev, info.mode); |
422 | ret = drm_agp_enable(dev, mode); | 522 | ret = drm_agp_enable(dev, mode); |
423 | if (ret) { | 523 | if (ret) { |
424 | NV_ERROR(dev, "Unable to enable AGP: %d\n", ret); | 524 | NV_ERROR(dev, "Unable to enable AGP: %d\n", ret); |
@@ -433,24 +533,27 @@ nouveau_mem_init_agp(struct drm_device *dev) | |||
433 | } | 533 | } |
434 | 534 | ||
435 | int | 535 | int |
436 | nouveau_mem_init(struct drm_device *dev) | 536 | nouveau_mem_vram_init(struct drm_device *dev) |
437 | { | 537 | { |
438 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 538 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
439 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | 539 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; |
440 | int ret, dma_bits = 32; | 540 | int ret, dma_bits; |
441 | |||
442 | dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); | ||
443 | dev_priv->gart_info.type = NOUVEAU_GART_NONE; | ||
444 | 541 | ||
445 | if (dev_priv->card_type >= NV_50 && | 542 | if (dev_priv->card_type >= NV_50 && |
446 | pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) | 543 | pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) |
447 | dma_bits = 40; | 544 | dma_bits = 40; |
545 | else | ||
546 | dma_bits = 32; | ||
448 | 547 | ||
449 | ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); | 548 | ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); |
450 | if (ret) { | 549 | if (ret) |
451 | NV_ERROR(dev, "Error setting DMA mask: %d\n", ret); | ||
452 | return ret; | 550 | return ret; |
453 | } | 551 | |
552 | ret = nouveau_mem_detect(dev); | ||
553 | if (ret) | ||
554 | return ret; | ||
555 | |||
556 | dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); | ||
454 | 557 | ||
455 | ret = nouveau_ttm_global_init(dev_priv); | 558 | ret = nouveau_ttm_global_init(dev_priv); |
456 | if (ret) | 559 | if (ret) |
@@ -465,8 +568,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
465 | return ret; | 568 | return ret; |
466 | } | 569 | } |
467 | 570 | ||
468 | spin_lock_init(&dev_priv->tile.lock); | ||
469 | |||
470 | dev_priv->fb_available_size = dev_priv->vram_size; | 571 | dev_priv->fb_available_size = dev_priv->vram_size; |
471 | dev_priv->fb_mappable_pages = dev_priv->fb_available_size; | 572 | dev_priv->fb_mappable_pages = dev_priv->fb_available_size; |
472 | if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) | 573 | if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) |
@@ -474,7 +575,16 @@ nouveau_mem_init(struct drm_device *dev) | |||
474 | pci_resource_len(dev->pdev, 1); | 575 | pci_resource_len(dev->pdev, 1); |
475 | dev_priv->fb_mappable_pages >>= PAGE_SHIFT; | 576 | dev_priv->fb_mappable_pages >>= PAGE_SHIFT; |
476 | 577 | ||
477 | /* remove reserved space at end of vram from available amount */ | 578 | /* reserve space at end of VRAM for PRAMIN */ |
579 | if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || | ||
580 | dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) | ||
581 | dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); | ||
582 | else | ||
583 | if (dev_priv->card_type >= NV_40) | ||
584 | dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); | ||
585 | else | ||
586 | dev_priv->ramin_rsvd_vram = (512 * 1024); | ||
587 | |||
478 | dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; | 588 | dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; |
479 | dev_priv->fb_aper_free = dev_priv->fb_available_size; | 589 | dev_priv->fb_aper_free = dev_priv->fb_available_size; |
480 | 590 | ||
@@ -495,9 +605,23 @@ nouveau_mem_init(struct drm_device *dev) | |||
495 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); | 605 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); |
496 | } | 606 | } |
497 | 607 | ||
498 | /* GART */ | 608 | dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), |
609 | pci_resource_len(dev->pdev, 1), | ||
610 | DRM_MTRR_WC); | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | int | ||
615 | nouveau_mem_gart_init(struct drm_device *dev) | ||
616 | { | ||
617 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
618 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | ||
619 | int ret; | ||
620 | |||
621 | dev_priv->gart_info.type = NOUVEAU_GART_NONE; | ||
622 | |||
499 | #if !defined(__powerpc__) && !defined(__ia64__) | 623 | #if !defined(__powerpc__) && !defined(__ia64__) |
500 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { | 624 | if (drm_device_is_agp(dev) && dev->agp && nouveau_agpmode) { |
501 | ret = nouveau_mem_init_agp(dev); | 625 | ret = nouveau_mem_init_agp(dev); |
502 | if (ret) | 626 | if (ret) |
503 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); | 627 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); |
@@ -523,11 +647,150 @@ nouveau_mem_init(struct drm_device *dev) | |||
523 | return ret; | 647 | return ret; |
524 | } | 648 | } |
525 | 649 | ||
526 | dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), | ||
527 | pci_resource_len(dev->pdev, 1), | ||
528 | DRM_MTRR_WC); | ||
529 | |||
530 | return 0; | 650 | return 0; |
531 | } | 651 | } |
532 | 652 | ||
653 | void | ||
654 | nouveau_mem_timing_init(struct drm_device *dev) | ||
655 | { | ||
656 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
657 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
658 | struct nouveau_pm_memtimings *memtimings = &pm->memtimings; | ||
659 | struct nvbios *bios = &dev_priv->vbios; | ||
660 | struct bit_entry P; | ||
661 | u8 tUNK_0, tUNK_1, tUNK_2; | ||
662 | u8 tRP; /* Byte 3 */ | ||
663 | u8 tRAS; /* Byte 5 */ | ||
664 | u8 tRFC; /* Byte 7 */ | ||
665 | u8 tRC; /* Byte 9 */ | ||
666 | u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; | ||
667 | u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; | ||
668 | u8 *mem = NULL, *entry; | ||
669 | int i, recordlen, entries; | ||
670 | |||
671 | if (bios->type == NVBIOS_BIT) { | ||
672 | if (bit_table(dev, 'P', &P)) | ||
673 | return; | ||
674 | |||
675 | if (P.version == 1) | ||
676 | mem = ROMPTR(bios, P.data[4]); | ||
677 | else | ||
678 | if (P.version == 2) | ||
679 | mem = ROMPTR(bios, P.data[8]); | ||
680 | else { | ||
681 | NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); | ||
682 | } | ||
683 | } else { | ||
684 | NV_DEBUG(dev, "BMP version too old for memory\n"); | ||
685 | return; | ||
686 | } | ||
687 | |||
688 | if (!mem) { | ||
689 | NV_DEBUG(dev, "memory timing table pointer invalid\n"); | ||
690 | return; | ||
691 | } | ||
533 | 692 | ||
693 | if (mem[0] != 0x10) { | ||
694 | NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]); | ||
695 | return; | ||
696 | } | ||
697 | |||
698 | /* validate record length */ | ||
699 | entries = mem[2]; | ||
700 | recordlen = mem[3]; | ||
701 | if (recordlen < 15) { | ||
702 | NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]); | ||
703 | return; | ||
704 | } | ||
705 | |||
706 | /* parse vbios entries into common format */ | ||
707 | memtimings->timing = | ||
708 | kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); | ||
709 | if (!memtimings->timing) | ||
710 | return; | ||
711 | |||
712 | entry = mem + mem[1]; | ||
713 | for (i = 0; i < entries; i++, entry += recordlen) { | ||
714 | struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; | ||
715 | if (entry[0] == 0) | ||
716 | continue; | ||
717 | |||
718 | tUNK_18 = 1; | ||
719 | tUNK_19 = 1; | ||
720 | tUNK_20 = 0; | ||
721 | tUNK_21 = 0; | ||
722 | switch (MIN(recordlen,21)) { | ||
723 | case 21: | ||
724 | tUNK_21 = entry[21]; | ||
725 | case 20: | ||
726 | tUNK_20 = entry[20]; | ||
727 | case 19: | ||
728 | tUNK_19 = entry[19]; | ||
729 | case 18: | ||
730 | tUNK_18 = entry[18]; | ||
731 | default: | ||
732 | tUNK_0 = entry[0]; | ||
733 | tUNK_1 = entry[1]; | ||
734 | tUNK_2 = entry[2]; | ||
735 | tRP = entry[3]; | ||
736 | tRAS = entry[5]; | ||
737 | tRFC = entry[7]; | ||
738 | tRC = entry[9]; | ||
739 | tUNK_10 = entry[10]; | ||
740 | tUNK_11 = entry[11]; | ||
741 | tUNK_12 = entry[12]; | ||
742 | tUNK_13 = entry[13]; | ||
743 | tUNK_14 = entry[14]; | ||
744 | break; | ||
745 | } | ||
746 | |||
747 | timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP); | ||
748 | |||
749 | /* XXX: I don't trust the -1's and +1's... they must come | ||
750 | * from somewhere! */ | ||
751 | timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 | | ||
752 | tUNK_18 << 16 | | ||
753 | (tUNK_1 + tUNK_19 + 1) << 8 | | ||
754 | (tUNK_2 - 1)); | ||
755 | |||
756 | timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); | ||
757 | if(recordlen > 19) { | ||
758 | timing->reg_100228 += (tUNK_19 - 1) << 24; | ||
759 | } else { | ||
760 | timing->reg_100228 += tUNK_12 << 24; | ||
761 | } | ||
762 | |||
763 | /* XXX: reg_10022c */ | ||
764 | |||
765 | timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | | ||
766 | tUNK_13 << 8 | tUNK_13); | ||
767 | |||
768 | /* XXX: +6? */ | ||
769 | timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); | ||
770 | if(tUNK_10 > tUNK_11) { | ||
771 | timing->reg_100234 += tUNK_10 << 16; | ||
772 | } else { | ||
773 | timing->reg_100234 += tUNK_11 << 16; | ||
774 | } | ||
775 | |||
776 | /* XXX; reg_100238, reg_10023c */ | ||
777 | NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, | ||
778 | timing->reg_100220, timing->reg_100224, | ||
779 | timing->reg_100228, timing->reg_10022c); | ||
780 | NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", | ||
781 | timing->reg_100230, timing->reg_100234, | ||
782 | timing->reg_100238, timing->reg_10023c); | ||
783 | } | ||
784 | |||
785 | memtimings->nr_timing = entries; | ||
786 | memtimings->supported = true; | ||
787 | } | ||
788 | |||
789 | void | ||
790 | nouveau_mem_timing_fini(struct drm_device *dev) | ||
791 | { | ||
792 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
793 | struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; | ||
794 | |||
795 | kfree(mem->timing); | ||
796 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 3ec181ff50ce..2cc59f8c658b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "drmP.h" | 28 | #include "drmP.h" |
29 | #include "drm.h" | 29 | #include "drm.h" |
30 | #include "nouveau_drv.h" | 30 | #include "nouveau_drv.h" |
31 | #include "nouveau_ramht.h" | ||
31 | 32 | ||
32 | int | 33 | int |
33 | nouveau_notifier_init_channel(struct nouveau_channel *chan) | 34 | nouveau_notifier_init_channel(struct nouveau_channel *chan) |
@@ -112,7 +113,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
112 | return -ENOMEM; | 113 | return -ENOMEM; |
113 | } | 114 | } |
114 | 115 | ||
115 | offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT; | 116 | offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; |
116 | if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { | 117 | if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { |
117 | target = NV_DMA_TARGET_VIDMEM; | 118 | target = NV_DMA_TARGET_VIDMEM; |
118 | } else | 119 | } else |
@@ -146,11 +147,11 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
146 | nobj->dtor = nouveau_notifier_gpuobj_dtor; | 147 | nobj->dtor = nouveau_notifier_gpuobj_dtor; |
147 | nobj->priv = mem; | 148 | nobj->priv = mem; |
148 | 149 | ||
149 | ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); | 150 | ret = nouveau_ramht_insert(chan, handle, nobj); |
151 | nouveau_gpuobj_ref(NULL, &nobj); | ||
150 | if (ret) { | 152 | if (ret) { |
151 | nouveau_gpuobj_del(dev, &nobj); | ||
152 | drm_mm_put_block(mem); | 153 | drm_mm_put_block(mem); |
153 | NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); | 154 | NV_ERROR(dev, "Error adding notifier to ramht: %d\n", ret); |
154 | return ret; | 155 | return ret; |
155 | } | 156 | } |
156 | 157 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index b6bcb254f4ab..896cf8634144 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "drm.h" | 34 | #include "drm.h" |
35 | #include "nouveau_drv.h" | 35 | #include "nouveau_drv.h" |
36 | #include "nouveau_drm.h" | 36 | #include "nouveau_drm.h" |
37 | #include "nouveau_ramht.h" | ||
37 | 38 | ||
38 | /* NVidia uses context objects to drive drawing operations. | 39 | /* NVidia uses context objects to drive drawing operations. |
39 | 40 | ||
@@ -65,137 +66,6 @@ | |||
65 | The key into the hash table depends on the object handle and channel id and | 66 | The key into the hash table depends on the object handle and channel id and |
66 | is given as: | 67 | is given as: |
67 | */ | 68 | */ |
68 | static uint32_t | ||
69 | nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) | ||
70 | { | ||
71 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
72 | uint32_t hash = 0; | ||
73 | int i; | ||
74 | |||
75 | NV_DEBUG(dev, "ch%d handle=0x%08x\n", channel, handle); | ||
76 | |||
77 | for (i = 32; i > 0; i -= dev_priv->ramht_bits) { | ||
78 | hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); | ||
79 | handle >>= dev_priv->ramht_bits; | ||
80 | } | ||
81 | |||
82 | if (dev_priv->card_type < NV_50) | ||
83 | hash ^= channel << (dev_priv->ramht_bits - 4); | ||
84 | hash <<= 3; | ||
85 | |||
86 | NV_DEBUG(dev, "hash=0x%08x\n", hash); | ||
87 | return hash; | ||
88 | } | ||
89 | |||
90 | static int | ||
91 | nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, | ||
92 | uint32_t offset) | ||
93 | { | ||
94 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
95 | uint32_t ctx = nv_ro32(dev, ramht, (offset + 4)/4); | ||
96 | |||
97 | if (dev_priv->card_type < NV_40) | ||
98 | return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); | ||
99 | return (ctx != 0); | ||
100 | } | ||
101 | |||
102 | static int | ||
103 | nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) | ||
104 | { | ||
105 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
106 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; | ||
107 | struct nouveau_channel *chan = ref->channel; | ||
108 | struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; | ||
109 | uint32_t ctx, co, ho; | ||
110 | |||
111 | if (!ramht) { | ||
112 | NV_ERROR(dev, "No hash table!\n"); | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | |||
116 | if (dev_priv->card_type < NV_40) { | ||
117 | ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) | | ||
118 | (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | | ||
119 | (ref->gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); | ||
120 | } else | ||
121 | if (dev_priv->card_type < NV_50) { | ||
122 | ctx = (ref->instance >> 4) | | ||
123 | (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | | ||
124 | (ref->gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); | ||
125 | } else { | ||
126 | if (ref->gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { | ||
127 | ctx = (ref->instance << 10) | 2; | ||
128 | } else { | ||
129 | ctx = (ref->instance >> 4) | | ||
130 | ((ref->gpuobj->engine << | ||
131 | NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); | ||
136 | do { | ||
137 | if (!nouveau_ramht_entry_valid(dev, ramht, co)) { | ||
138 | NV_DEBUG(dev, | ||
139 | "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", | ||
140 | chan->id, co, ref->handle, ctx); | ||
141 | nv_wo32(dev, ramht, (co + 0)/4, ref->handle); | ||
142 | nv_wo32(dev, ramht, (co + 4)/4, ctx); | ||
143 | |||
144 | list_add_tail(&ref->list, &chan->ramht_refs); | ||
145 | instmem->flush(dev); | ||
146 | return 0; | ||
147 | } | ||
148 | NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", | ||
149 | chan->id, co, nv_ro32(dev, ramht, co/4)); | ||
150 | |||
151 | co += 8; | ||
152 | if (co >= dev_priv->ramht_size) | ||
153 | co = 0; | ||
154 | } while (co != ho); | ||
155 | |||
156 | NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); | ||
157 | return -ENOMEM; | ||
158 | } | ||
159 | |||
160 | static void | ||
161 | nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) | ||
162 | { | ||
163 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
164 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; | ||
165 | struct nouveau_channel *chan = ref->channel; | ||
166 | struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; | ||
167 | uint32_t co, ho; | ||
168 | |||
169 | if (!ramht) { | ||
170 | NV_ERROR(dev, "No hash table!\n"); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); | ||
175 | do { | ||
176 | if (nouveau_ramht_entry_valid(dev, ramht, co) && | ||
177 | (ref->handle == nv_ro32(dev, ramht, (co/4)))) { | ||
178 | NV_DEBUG(dev, | ||
179 | "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", | ||
180 | chan->id, co, ref->handle, | ||
181 | nv_ro32(dev, ramht, (co + 4))); | ||
182 | nv_wo32(dev, ramht, (co + 0)/4, 0x00000000); | ||
183 | nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); | ||
184 | |||
185 | list_del(&ref->list); | ||
186 | instmem->flush(dev); | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | co += 8; | ||
191 | if (co >= dev_priv->ramht_size) | ||
192 | co = 0; | ||
193 | } while (co != ho); | ||
194 | list_del(&ref->list); | ||
195 | |||
196 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", | ||
197 | chan->id, ref->handle); | ||
198 | } | ||
199 | 69 | ||
200 | int | 70 | int |
201 | nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | 71 | nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, |
@@ -205,7 +75,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
205 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 75 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
206 | struct nouveau_engine *engine = &dev_priv->engine; | 76 | struct nouveau_engine *engine = &dev_priv->engine; |
207 | struct nouveau_gpuobj *gpuobj; | 77 | struct nouveau_gpuobj *gpuobj; |
208 | struct drm_mm *pramin = NULL; | 78 | struct drm_mm_node *ramin = NULL; |
209 | int ret; | 79 | int ret; |
210 | 80 | ||
211 | NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", | 81 | NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", |
@@ -218,69 +88,102 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
218 | if (!gpuobj) | 88 | if (!gpuobj) |
219 | return -ENOMEM; | 89 | return -ENOMEM; |
220 | NV_DEBUG(dev, "gpuobj %p\n", gpuobj); | 90 | NV_DEBUG(dev, "gpuobj %p\n", gpuobj); |
91 | gpuobj->dev = dev; | ||
221 | gpuobj->flags = flags; | 92 | gpuobj->flags = flags; |
222 | gpuobj->im_channel = chan; | 93 | kref_init(&gpuobj->refcount); |
94 | gpuobj->size = size; | ||
223 | 95 | ||
96 | spin_lock(&dev_priv->ramin_lock); | ||
224 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); | 97 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); |
98 | spin_unlock(&dev_priv->ramin_lock); | ||
225 | 99 | ||
226 | /* Choose between global instmem heap, and per-channel private | ||
227 | * instmem heap. On <NV50 allow requests for private instmem | ||
228 | * to be satisfied from global heap if no per-channel area | ||
229 | * available. | ||
230 | */ | ||
231 | if (chan) { | 100 | if (chan) { |
232 | NV_DEBUG(dev, "channel heap\n"); | 101 | NV_DEBUG(dev, "channel heap\n"); |
233 | pramin = &chan->ramin_heap; | 102 | |
103 | ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); | ||
104 | if (ramin) | ||
105 | ramin = drm_mm_get_block(ramin, size, align); | ||
106 | |||
107 | if (!ramin) { | ||
108 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
109 | return -ENOMEM; | ||
110 | } | ||
234 | } else { | 111 | } else { |
235 | NV_DEBUG(dev, "global heap\n"); | 112 | NV_DEBUG(dev, "global heap\n"); |
236 | pramin = &dev_priv->ramin_heap; | ||
237 | 113 | ||
114 | /* allocate backing pages, sets vinst */ | ||
238 | ret = engine->instmem.populate(dev, gpuobj, &size); | 115 | ret = engine->instmem.populate(dev, gpuobj, &size); |
239 | if (ret) { | 116 | if (ret) { |
240 | nouveau_gpuobj_del(dev, &gpuobj); | 117 | nouveau_gpuobj_ref(NULL, &gpuobj); |
241 | return ret; | 118 | return ret; |
242 | } | 119 | } |
243 | } | ||
244 | 120 | ||
245 | /* Allocate a chunk of the PRAMIN aperture */ | 121 | /* try and get aperture space */ |
246 | gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0); | 122 | do { |
247 | if (gpuobj->im_pramin) | 123 | if (drm_mm_pre_get(&dev_priv->ramin_heap)) |
248 | gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align); | 124 | return -ENOMEM; |
125 | |||
126 | spin_lock(&dev_priv->ramin_lock); | ||
127 | ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, | ||
128 | align, 0); | ||
129 | if (ramin == NULL) { | ||
130 | spin_unlock(&dev_priv->ramin_lock); | ||
131 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
132 | return ret; | ||
133 | } | ||
249 | 134 | ||
250 | if (!gpuobj->im_pramin) { | 135 | ramin = drm_mm_get_block_atomic(ramin, size, align); |
251 | nouveau_gpuobj_del(dev, &gpuobj); | 136 | spin_unlock(&dev_priv->ramin_lock); |
252 | return -ENOMEM; | 137 | } while (ramin == NULL); |
138 | |||
139 | /* on nv50 it's ok to fail, we have a fallback path */ | ||
140 | if (!ramin && dev_priv->card_type < NV_50) { | ||
141 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
142 | return -ENOMEM; | ||
143 | } | ||
253 | } | 144 | } |
254 | 145 | ||
255 | if (!chan) { | 146 | /* if we got a chunk of the aperture, map pages into it */ |
147 | gpuobj->im_pramin = ramin; | ||
148 | if (!chan && gpuobj->im_pramin && dev_priv->ramin_available) { | ||
256 | ret = engine->instmem.bind(dev, gpuobj); | 149 | ret = engine->instmem.bind(dev, gpuobj); |
257 | if (ret) { | 150 | if (ret) { |
258 | nouveau_gpuobj_del(dev, &gpuobj); | 151 | nouveau_gpuobj_ref(NULL, &gpuobj); |
259 | return ret; | 152 | return ret; |
260 | } | 153 | } |
261 | } | 154 | } |
262 | 155 | ||
156 | /* calculate the various different addresses for the object */ | ||
157 | if (chan) { | ||
158 | gpuobj->pinst = chan->ramin->pinst; | ||
159 | if (gpuobj->pinst != ~0) | ||
160 | gpuobj->pinst += gpuobj->im_pramin->start; | ||
161 | |||
162 | if (dev_priv->card_type < NV_50) { | ||
163 | gpuobj->cinst = gpuobj->pinst; | ||
164 | } else { | ||
165 | gpuobj->cinst = gpuobj->im_pramin->start; | ||
166 | gpuobj->vinst = gpuobj->im_pramin->start + | ||
167 | chan->ramin->vinst; | ||
168 | } | ||
169 | } else { | ||
170 | if (gpuobj->im_pramin) | ||
171 | gpuobj->pinst = gpuobj->im_pramin->start; | ||
172 | else | ||
173 | gpuobj->pinst = ~0; | ||
174 | gpuobj->cinst = 0xdeadbeef; | ||
175 | } | ||
176 | |||
263 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { | 177 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { |
264 | int i; | 178 | int i; |
265 | 179 | ||
266 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) | 180 | for (i = 0; i < gpuobj->size; i += 4) |
267 | nv_wo32(dev, gpuobj, i/4, 0); | 181 | nv_wo32(gpuobj, i, 0); |
268 | engine->instmem.flush(dev); | 182 | engine->instmem.flush(dev); |
269 | } | 183 | } |
270 | 184 | ||
271 | *gpuobj_ret = gpuobj; | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | int | ||
276 | nouveau_gpuobj_early_init(struct drm_device *dev) | ||
277 | { | ||
278 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
279 | |||
280 | NV_DEBUG(dev, "\n"); | ||
281 | |||
282 | INIT_LIST_HEAD(&dev_priv->gpuobj_list); | ||
283 | 185 | ||
186 | *gpuobj_ret = gpuobj; | ||
284 | return 0; | 187 | return 0; |
285 | } | 188 | } |
286 | 189 | ||
@@ -288,18 +191,12 @@ int | |||
288 | nouveau_gpuobj_init(struct drm_device *dev) | 191 | nouveau_gpuobj_init(struct drm_device *dev) |
289 | { | 192 | { |
290 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 193 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
291 | int ret; | ||
292 | 194 | ||
293 | NV_DEBUG(dev, "\n"); | 195 | NV_DEBUG(dev, "\n"); |
294 | 196 | ||
295 | if (dev_priv->card_type < NV_50) { | 197 | INIT_LIST_HEAD(&dev_priv->gpuobj_list); |
296 | ret = nouveau_gpuobj_new_fake(dev, | 198 | spin_lock_init(&dev_priv->ramin_lock); |
297 | dev_priv->ramht_offset, ~0, dev_priv->ramht_size, | 199 | dev_priv->ramin_base = ~0; |
298 | NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ALLOW_NO_REFS, | ||
299 | &dev_priv->ramht, NULL); | ||
300 | if (ret) | ||
301 | return ret; | ||
302 | } | ||
303 | 200 | ||
304 | return 0; | 201 | return 0; |
305 | } | 202 | } |
@@ -311,297 +208,89 @@ nouveau_gpuobj_takedown(struct drm_device *dev) | |||
311 | 208 | ||
312 | NV_DEBUG(dev, "\n"); | 209 | NV_DEBUG(dev, "\n"); |
313 | 210 | ||
314 | nouveau_gpuobj_del(dev, &dev_priv->ramht); | 211 | BUG_ON(!list_empty(&dev_priv->gpuobj_list)); |
315 | } | 212 | } |
316 | 213 | ||
317 | void | ||
318 | nouveau_gpuobj_late_takedown(struct drm_device *dev) | ||
319 | { | ||
320 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
321 | struct nouveau_gpuobj *gpuobj = NULL; | ||
322 | struct list_head *entry, *tmp; | ||
323 | |||
324 | NV_DEBUG(dev, "\n"); | ||
325 | |||
326 | list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { | ||
327 | gpuobj = list_entry(entry, struct nouveau_gpuobj, list); | ||
328 | |||
329 | NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n", | ||
330 | gpuobj, gpuobj->refcount); | ||
331 | gpuobj->refcount = 0; | ||
332 | nouveau_gpuobj_del(dev, &gpuobj); | ||
333 | } | ||
334 | } | ||
335 | 214 | ||
336 | int | 215 | static void |
337 | nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) | 216 | nouveau_gpuobj_del(struct kref *ref) |
338 | { | 217 | { |
218 | struct nouveau_gpuobj *gpuobj = | ||
219 | container_of(ref, struct nouveau_gpuobj, refcount); | ||
220 | struct drm_device *dev = gpuobj->dev; | ||
339 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 221 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
340 | struct nouveau_engine *engine = &dev_priv->engine; | 222 | struct nouveau_engine *engine = &dev_priv->engine; |
341 | struct nouveau_gpuobj *gpuobj; | ||
342 | int i; | 223 | int i; |
343 | 224 | ||
344 | NV_DEBUG(dev, "gpuobj %p\n", pgpuobj ? *pgpuobj : NULL); | 225 | NV_DEBUG(dev, "gpuobj %p\n", gpuobj); |
345 | |||
346 | if (!dev_priv || !pgpuobj || !(*pgpuobj)) | ||
347 | return -EINVAL; | ||
348 | gpuobj = *pgpuobj; | ||
349 | |||
350 | if (gpuobj->refcount != 0) { | ||
351 | NV_ERROR(dev, "gpuobj refcount is %d\n", gpuobj->refcount); | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | 226 | ||
355 | if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { | 227 | if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { |
356 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) | 228 | for (i = 0; i < gpuobj->size; i += 4) |
357 | nv_wo32(dev, gpuobj, i/4, 0); | 229 | nv_wo32(gpuobj, i, 0); |
358 | engine->instmem.flush(dev); | 230 | engine->instmem.flush(dev); |
359 | } | 231 | } |
360 | 232 | ||
361 | if (gpuobj->dtor) | 233 | if (gpuobj->dtor) |
362 | gpuobj->dtor(dev, gpuobj); | 234 | gpuobj->dtor(dev, gpuobj); |
363 | 235 | ||
364 | if (gpuobj->im_backing && !(gpuobj->flags & NVOBJ_FLAG_FAKE)) | 236 | if (gpuobj->im_backing) |
365 | engine->instmem.clear(dev, gpuobj); | 237 | engine->instmem.clear(dev, gpuobj); |
366 | 238 | ||
367 | if (gpuobj->im_pramin) { | 239 | spin_lock(&dev_priv->ramin_lock); |
368 | if (gpuobj->flags & NVOBJ_FLAG_FAKE) | 240 | if (gpuobj->im_pramin) |
369 | kfree(gpuobj->im_pramin); | 241 | drm_mm_put_block(gpuobj->im_pramin); |
370 | else | ||
371 | drm_mm_put_block(gpuobj->im_pramin); | ||
372 | } | ||
373 | |||
374 | list_del(&gpuobj->list); | 242 | list_del(&gpuobj->list); |
243 | spin_unlock(&dev_priv->ramin_lock); | ||
375 | 244 | ||
376 | *pgpuobj = NULL; | ||
377 | kfree(gpuobj); | 245 | kfree(gpuobj); |
378 | return 0; | ||
379 | } | 246 | } |
380 | 247 | ||
381 | static int | 248 | void |
382 | nouveau_gpuobj_instance_get(struct drm_device *dev, | 249 | nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr) |
383 | struct nouveau_channel *chan, | ||
384 | struct nouveau_gpuobj *gpuobj, uint32_t *inst) | ||
385 | { | ||
386 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
387 | struct nouveau_gpuobj *cpramin; | ||
388 | |||
389 | /* <NV50 use PRAMIN address everywhere */ | ||
390 | if (dev_priv->card_type < NV_50) { | ||
391 | *inst = gpuobj->im_pramin->start; | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | if (chan && gpuobj->im_channel != chan) { | ||
396 | NV_ERROR(dev, "Channel mismatch: obj %d, ref %d\n", | ||
397 | gpuobj->im_channel->id, chan->id); | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | |||
401 | /* NV50 channel-local instance */ | ||
402 | if (chan) { | ||
403 | cpramin = chan->ramin->gpuobj; | ||
404 | *inst = gpuobj->im_pramin->start - cpramin->im_pramin->start; | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | /* NV50 global (VRAM) instance */ | ||
409 | if (!gpuobj->im_channel) { | ||
410 | /* ...from global heap */ | ||
411 | if (!gpuobj->im_backing) { | ||
412 | NV_ERROR(dev, "AII, no VRAM backing gpuobj\n"); | ||
413 | return -EINVAL; | ||
414 | } | ||
415 | *inst = gpuobj->im_backing_start; | ||
416 | return 0; | ||
417 | } else { | ||
418 | /* ...from local heap */ | ||
419 | cpramin = gpuobj->im_channel->ramin->gpuobj; | ||
420 | *inst = cpramin->im_backing_start + | ||
421 | (gpuobj->im_pramin->start - cpramin->im_pramin->start); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | int | ||
429 | nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan, | ||
430 | uint32_t handle, struct nouveau_gpuobj *gpuobj, | ||
431 | struct nouveau_gpuobj_ref **ref_ret) | ||
432 | { | ||
433 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
434 | struct nouveau_gpuobj_ref *ref; | ||
435 | uint32_t instance; | ||
436 | int ret; | ||
437 | |||
438 | NV_DEBUG(dev, "ch%d h=0x%08x gpuobj=%p\n", | ||
439 | chan ? chan->id : -1, handle, gpuobj); | ||
440 | |||
441 | if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL)) | ||
442 | return -EINVAL; | ||
443 | |||
444 | if (!chan && !ref_ret) | ||
445 | return -EINVAL; | ||
446 | |||
447 | if (gpuobj->engine == NVOBJ_ENGINE_SW && !gpuobj->im_pramin) { | ||
448 | /* sw object */ | ||
449 | instance = 0x40; | ||
450 | } else { | ||
451 | ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance); | ||
452 | if (ret) | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | ref = kzalloc(sizeof(*ref), GFP_KERNEL); | ||
457 | if (!ref) | ||
458 | return -ENOMEM; | ||
459 | INIT_LIST_HEAD(&ref->list); | ||
460 | ref->gpuobj = gpuobj; | ||
461 | ref->channel = chan; | ||
462 | ref->instance = instance; | ||
463 | |||
464 | if (!ref_ret) { | ||
465 | ref->handle = handle; | ||
466 | |||
467 | ret = nouveau_ramht_insert(dev, ref); | ||
468 | if (ret) { | ||
469 | kfree(ref); | ||
470 | return ret; | ||
471 | } | ||
472 | } else { | ||
473 | ref->handle = ~0; | ||
474 | *ref_ret = ref; | ||
475 | } | ||
476 | |||
477 | ref->gpuobj->refcount++; | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **pref) | ||
482 | { | ||
483 | struct nouveau_gpuobj_ref *ref; | ||
484 | |||
485 | NV_DEBUG(dev, "ref %p\n", pref ? *pref : NULL); | ||
486 | |||
487 | if (!dev || !pref || *pref == NULL) | ||
488 | return -EINVAL; | ||
489 | ref = *pref; | ||
490 | |||
491 | if (ref->handle != ~0) | ||
492 | nouveau_ramht_remove(dev, ref); | ||
493 | |||
494 | if (ref->gpuobj) { | ||
495 | ref->gpuobj->refcount--; | ||
496 | |||
497 | if (ref->gpuobj->refcount == 0) { | ||
498 | if (!(ref->gpuobj->flags & NVOBJ_FLAG_ALLOW_NO_REFS)) | ||
499 | nouveau_gpuobj_del(dev, &ref->gpuobj); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | *pref = NULL; | ||
504 | kfree(ref); | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | int | ||
509 | nouveau_gpuobj_new_ref(struct drm_device *dev, | ||
510 | struct nouveau_channel *oc, struct nouveau_channel *rc, | ||
511 | uint32_t handle, uint32_t size, int align, | ||
512 | uint32_t flags, struct nouveau_gpuobj_ref **ref) | ||
513 | { | ||
514 | struct nouveau_gpuobj *gpuobj = NULL; | ||
515 | int ret; | ||
516 | |||
517 | ret = nouveau_gpuobj_new(dev, oc, size, align, flags, &gpuobj); | ||
518 | if (ret) | ||
519 | return ret; | ||
520 | |||
521 | ret = nouveau_gpuobj_ref_add(dev, rc, handle, gpuobj, ref); | ||
522 | if (ret) { | ||
523 | nouveau_gpuobj_del(dev, &gpuobj); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | int | ||
531 | nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, | ||
532 | struct nouveau_gpuobj_ref **ref_ret) | ||
533 | { | 250 | { |
534 | struct nouveau_gpuobj_ref *ref; | 251 | if (ref) |
535 | struct list_head *entry, *tmp; | 252 | kref_get(&ref->refcount); |
536 | |||
537 | list_for_each_safe(entry, tmp, &chan->ramht_refs) { | ||
538 | ref = list_entry(entry, struct nouveau_gpuobj_ref, list); | ||
539 | 253 | ||
540 | if (ref->handle == handle) { | 254 | if (*ptr) |
541 | if (ref_ret) | 255 | kref_put(&(*ptr)->refcount, nouveau_gpuobj_del); |
542 | *ref_ret = ref; | ||
543 | return 0; | ||
544 | } | ||
545 | } | ||
546 | 256 | ||
547 | return -EINVAL; | 257 | *ptr = ref; |
548 | } | 258 | } |
549 | 259 | ||
550 | int | 260 | int |
551 | nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, | 261 | nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst, |
552 | uint32_t b_offset, uint32_t size, | 262 | u32 size, u32 flags, struct nouveau_gpuobj **pgpuobj) |
553 | uint32_t flags, struct nouveau_gpuobj **pgpuobj, | ||
554 | struct nouveau_gpuobj_ref **pref) | ||
555 | { | 263 | { |
556 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 264 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
557 | struct nouveau_gpuobj *gpuobj = NULL; | 265 | struct nouveau_gpuobj *gpuobj = NULL; |
558 | int i; | 266 | int i; |
559 | 267 | ||
560 | NV_DEBUG(dev, | 268 | NV_DEBUG(dev, |
561 | "p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n", | 269 | "pinst=0x%08x vinst=0x%010llx size=0x%08x flags=0x%08x\n", |
562 | p_offset, b_offset, size, flags); | 270 | pinst, vinst, size, flags); |
563 | 271 | ||
564 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); | 272 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); |
565 | if (!gpuobj) | 273 | if (!gpuobj) |
566 | return -ENOMEM; | 274 | return -ENOMEM; |
567 | NV_DEBUG(dev, "gpuobj %p\n", gpuobj); | 275 | NV_DEBUG(dev, "gpuobj %p\n", gpuobj); |
568 | gpuobj->im_channel = NULL; | 276 | gpuobj->dev = dev; |
569 | gpuobj->flags = flags | NVOBJ_FLAG_FAKE; | 277 | gpuobj->flags = flags; |
570 | 278 | kref_init(&gpuobj->refcount); | |
571 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); | 279 | gpuobj->size = size; |
572 | 280 | gpuobj->pinst = pinst; | |
573 | if (p_offset != ~0) { | 281 | gpuobj->cinst = 0xdeadbeef; |
574 | gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node), | 282 | gpuobj->vinst = vinst; |
575 | GFP_KERNEL); | ||
576 | if (!gpuobj->im_pramin) { | ||
577 | nouveau_gpuobj_del(dev, &gpuobj); | ||
578 | return -ENOMEM; | ||
579 | } | ||
580 | gpuobj->im_pramin->start = p_offset; | ||
581 | gpuobj->im_pramin->size = size; | ||
582 | } | ||
583 | |||
584 | if (b_offset != ~0) { | ||
585 | gpuobj->im_backing = (struct nouveau_bo *)-1; | ||
586 | gpuobj->im_backing_start = b_offset; | ||
587 | } | ||
588 | 283 | ||
589 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { | 284 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { |
590 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) | 285 | for (i = 0; i < gpuobj->size; i += 4) |
591 | nv_wo32(dev, gpuobj, i/4, 0); | 286 | nv_wo32(gpuobj, i, 0); |
592 | dev_priv->engine.instmem.flush(dev); | 287 | dev_priv->engine.instmem.flush(dev); |
593 | } | 288 | } |
594 | 289 | ||
595 | if (pref) { | 290 | spin_lock(&dev_priv->ramin_lock); |
596 | i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref); | 291 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); |
597 | if (i) { | 292 | spin_unlock(&dev_priv->ramin_lock); |
598 | nouveau_gpuobj_del(dev, &gpuobj); | 293 | *pgpuobj = gpuobj; |
599 | return i; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | if (pgpuobj) | ||
604 | *pgpuobj = gpuobj; | ||
605 | return 0; | 294 | return 0; |
606 | } | 295 | } |
607 | 296 | ||
@@ -685,14 +374,12 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, | |||
685 | adjust = offset & 0x00000fff; | 374 | adjust = offset & 0x00000fff; |
686 | frame = offset & ~0x00000fff; | 375 | frame = offset & ~0x00000fff; |
687 | 376 | ||
688 | nv_wo32(dev, *gpuobj, 0, ((1<<12) | (1<<13) | | 377 | nv_wo32(*gpuobj, 0, ((1<<12) | (1<<13) | (adjust << 20) | |
689 | (adjust << 20) | | 378 | (access << 14) | (target << 16) | |
690 | (access << 14) | | 379 | class)); |
691 | (target << 16) | | 380 | nv_wo32(*gpuobj, 4, size - 1); |
692 | class)); | 381 | nv_wo32(*gpuobj, 8, frame | pte_flags); |
693 | nv_wo32(dev, *gpuobj, 1, size - 1); | 382 | nv_wo32(*gpuobj, 12, frame | pte_flags); |
694 | nv_wo32(dev, *gpuobj, 2, frame | pte_flags); | ||
695 | nv_wo32(dev, *gpuobj, 3, frame | pte_flags); | ||
696 | } else { | 383 | } else { |
697 | uint64_t limit = offset + size - 1; | 384 | uint64_t limit = offset + size - 1; |
698 | uint32_t flags0, flags5; | 385 | uint32_t flags0, flags5; |
@@ -705,12 +392,12 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, | |||
705 | flags5 = 0x00080000; | 392 | flags5 = 0x00080000; |
706 | } | 393 | } |
707 | 394 | ||
708 | nv_wo32(dev, *gpuobj, 0, flags0 | class); | 395 | nv_wo32(*gpuobj, 0, flags0 | class); |
709 | nv_wo32(dev, *gpuobj, 1, lower_32_bits(limit)); | 396 | nv_wo32(*gpuobj, 4, lower_32_bits(limit)); |
710 | nv_wo32(dev, *gpuobj, 2, lower_32_bits(offset)); | 397 | nv_wo32(*gpuobj, 8, lower_32_bits(offset)); |
711 | nv_wo32(dev, *gpuobj, 3, ((upper_32_bits(limit) & 0xff) << 24) | | 398 | nv_wo32(*gpuobj, 12, ((upper_32_bits(limit) & 0xff) << 24) | |
712 | (upper_32_bits(offset) & 0xff)); | 399 | (upper_32_bits(offset) & 0xff)); |
713 | nv_wo32(dev, *gpuobj, 5, flags5); | 400 | nv_wo32(*gpuobj, 20, flags5); |
714 | } | 401 | } |
715 | 402 | ||
716 | instmem->flush(dev); | 403 | instmem->flush(dev); |
@@ -741,7 +428,7 @@ nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan, | |||
741 | *o_ret = 0; | 428 | *o_ret = 0; |
742 | } else | 429 | } else |
743 | if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { | 430 | if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { |
744 | *gpuobj = dev_priv->gart_info.sg_ctxdma; | 431 | nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, gpuobj); |
745 | if (offset & ~0xffffffffULL) { | 432 | if (offset & ~0xffffffffULL) { |
746 | NV_ERROR(dev, "obj offset exceeds 32-bits\n"); | 433 | NV_ERROR(dev, "obj offset exceeds 32-bits\n"); |
747 | return -EINVAL; | 434 | return -EINVAL; |
@@ -829,25 +516,25 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, | |||
829 | } | 516 | } |
830 | 517 | ||
831 | if (dev_priv->card_type >= NV_50) { | 518 | if (dev_priv->card_type >= NV_50) { |
832 | nv_wo32(dev, *gpuobj, 0, class); | 519 | nv_wo32(*gpuobj, 0, class); |
833 | nv_wo32(dev, *gpuobj, 5, 0x00010000); | 520 | nv_wo32(*gpuobj, 20, 0x00010000); |
834 | } else { | 521 | } else { |
835 | switch (class) { | 522 | switch (class) { |
836 | case NV_CLASS_NULL: | 523 | case NV_CLASS_NULL: |
837 | nv_wo32(dev, *gpuobj, 0, 0x00001030); | 524 | nv_wo32(*gpuobj, 0, 0x00001030); |
838 | nv_wo32(dev, *gpuobj, 1, 0xFFFFFFFF); | 525 | nv_wo32(*gpuobj, 4, 0xFFFFFFFF); |
839 | break; | 526 | break; |
840 | default: | 527 | default: |
841 | if (dev_priv->card_type >= NV_40) { | 528 | if (dev_priv->card_type >= NV_40) { |
842 | nv_wo32(dev, *gpuobj, 0, class); | 529 | nv_wo32(*gpuobj, 0, class); |
843 | #ifdef __BIG_ENDIAN | 530 | #ifdef __BIG_ENDIAN |
844 | nv_wo32(dev, *gpuobj, 2, 0x01000000); | 531 | nv_wo32(*gpuobj, 8, 0x01000000); |
845 | #endif | 532 | #endif |
846 | } else { | 533 | } else { |
847 | #ifdef __BIG_ENDIAN | 534 | #ifdef __BIG_ENDIAN |
848 | nv_wo32(dev, *gpuobj, 0, class | 0x00080000); | 535 | nv_wo32(*gpuobj, 0, class | 0x00080000); |
849 | #else | 536 | #else |
850 | nv_wo32(dev, *gpuobj, 0, class); | 537 | nv_wo32(*gpuobj, 0, class); |
851 | #endif | 538 | #endif |
852 | } | 539 | } |
853 | } | 540 | } |
@@ -873,10 +560,15 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, | |||
873 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); | 560 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); |
874 | if (!gpuobj) | 561 | if (!gpuobj) |
875 | return -ENOMEM; | 562 | return -ENOMEM; |
563 | gpuobj->dev = chan->dev; | ||
876 | gpuobj->engine = NVOBJ_ENGINE_SW; | 564 | gpuobj->engine = NVOBJ_ENGINE_SW; |
877 | gpuobj->class = class; | 565 | gpuobj->class = class; |
566 | kref_init(&gpuobj->refcount); | ||
567 | gpuobj->cinst = 0x40; | ||
878 | 568 | ||
569 | spin_lock(&dev_priv->ramin_lock); | ||
879 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); | 570 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); |
571 | spin_unlock(&dev_priv->ramin_lock); | ||
880 | *gpuobj_ret = gpuobj; | 572 | *gpuobj_ret = gpuobj; |
881 | return 0; | 573 | return 0; |
882 | } | 574 | } |
@@ -886,7 +578,6 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) | |||
886 | { | 578 | { |
887 | struct drm_device *dev = chan->dev; | 579 | struct drm_device *dev = chan->dev; |
888 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 580 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
889 | struct nouveau_gpuobj *pramin = NULL; | ||
890 | uint32_t size; | 581 | uint32_t size; |
891 | uint32_t base; | 582 | uint32_t base; |
892 | int ret; | 583 | int ret; |
@@ -911,18 +602,16 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) | |||
911 | size += 0x1000; | 602 | size += 0x1000; |
912 | } | 603 | } |
913 | 604 | ||
914 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, | 605 | ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); |
915 | &chan->ramin); | ||
916 | if (ret) { | 606 | if (ret) { |
917 | NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret); | 607 | NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret); |
918 | return ret; | 608 | return ret; |
919 | } | 609 | } |
920 | pramin = chan->ramin->gpuobj; | ||
921 | 610 | ||
922 | ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size); | 611 | ret = drm_mm_init(&chan->ramin_heap, base, size); |
923 | if (ret) { | 612 | if (ret) { |
924 | NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); | 613 | NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); |
925 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | 614 | nouveau_gpuobj_ref(NULL, &chan->ramin); |
926 | return ret; | 615 | return ret; |
927 | } | 616 | } |
928 | 617 | ||
@@ -939,8 +628,6 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
939 | struct nouveau_gpuobj *vram = NULL, *tt = NULL; | 628 | struct nouveau_gpuobj *vram = NULL, *tt = NULL; |
940 | int ret, i; | 629 | int ret, i; |
941 | 630 | ||
942 | INIT_LIST_HEAD(&chan->ramht_refs); | ||
943 | |||
944 | NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); | 631 | NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); |
945 | 632 | ||
946 | /* Allocate a chunk of memory for per-channel object storage */ | 633 | /* Allocate a chunk of memory for per-channel object storage */ |
@@ -956,41 +643,38 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
956 | * locations determined during init. | 643 | * locations determined during init. |
957 | */ | 644 | */ |
958 | if (dev_priv->card_type >= NV_50) { | 645 | if (dev_priv->card_type >= NV_50) { |
959 | uint32_t vm_offset, pde; | 646 | u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; |
647 | u64 vm_vinst = chan->ramin->vinst + pgd_offs; | ||
648 | u32 vm_pinst = chan->ramin->pinst; | ||
649 | u32 pde; | ||
960 | 650 | ||
961 | vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; | 651 | if (vm_pinst != ~0) |
962 | vm_offset += chan->ramin->gpuobj->im_pramin->start; | 652 | vm_pinst += pgd_offs; |
963 | 653 | ||
964 | ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, | 654 | ret = nouveau_gpuobj_new_fake(dev, vm_pinst, vm_vinst, 0x4000, |
965 | 0, &chan->vm_pd, NULL); | 655 | 0, &chan->vm_pd); |
966 | if (ret) | 656 | if (ret) |
967 | return ret; | 657 | return ret; |
968 | for (i = 0; i < 0x4000; i += 8) { | 658 | for (i = 0; i < 0x4000; i += 8) { |
969 | nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); | 659 | nv_wo32(chan->vm_pd, i + 0, 0x00000000); |
970 | nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); | 660 | nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); |
971 | } | 661 | } |
972 | 662 | ||
973 | pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 2; | 663 | nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, |
974 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, | 664 | &chan->vm_gart_pt); |
975 | dev_priv->gart_info.sg_ctxdma, | 665 | pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8; |
976 | &chan->vm_gart_pt); | 666 | nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->vinst | 3); |
977 | if (ret) | 667 | nv_wo32(chan->vm_pd, pde + 4, 0x00000000); |
978 | return ret; | ||
979 | nv_wo32(dev, chan->vm_pd, pde++, | ||
980 | chan->vm_gart_pt->instance | 0x03); | ||
981 | nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); | ||
982 | 668 | ||
983 | pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 2; | 669 | pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8; |
984 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { | 670 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { |
985 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, | 671 | nouveau_gpuobj_ref(dev_priv->vm_vram_pt[i], |
986 | dev_priv->vm_vram_pt[i], | 672 | &chan->vm_vram_pt[i]); |
987 | &chan->vm_vram_pt[i]); | ||
988 | if (ret) | ||
989 | return ret; | ||
990 | 673 | ||
991 | nv_wo32(dev, chan->vm_pd, pde++, | 674 | nv_wo32(chan->vm_pd, pde + 0, |
992 | chan->vm_vram_pt[i]->instance | 0x61); | 675 | chan->vm_vram_pt[i]->vinst | 0x61); |
993 | nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); | 676 | nv_wo32(chan->vm_pd, pde + 4, 0x00000000); |
677 | pde += 8; | ||
994 | } | 678 | } |
995 | 679 | ||
996 | instmem->flush(dev); | 680 | instmem->flush(dev); |
@@ -998,15 +682,17 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
998 | 682 | ||
999 | /* RAMHT */ | 683 | /* RAMHT */ |
1000 | if (dev_priv->card_type < NV_50) { | 684 | if (dev_priv->card_type < NV_50) { |
1001 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht, | 685 | nouveau_ramht_ref(dev_priv->ramht, &chan->ramht, NULL); |
1002 | &chan->ramht); | 686 | } else { |
687 | struct nouveau_gpuobj *ramht = NULL; | ||
688 | |||
689 | ret = nouveau_gpuobj_new(dev, chan, 0x8000, 16, | ||
690 | NVOBJ_FLAG_ZERO_ALLOC, &ramht); | ||
1003 | if (ret) | 691 | if (ret) |
1004 | return ret; | 692 | return ret; |
1005 | } else { | 693 | |
1006 | ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, | 694 | ret = nouveau_ramht_new(dev, ramht, &chan->ramht); |
1007 | 0x8000, 16, | 695 | nouveau_gpuobj_ref(NULL, &ramht); |
1008 | NVOBJ_FLAG_ZERO_ALLOC, | ||
1009 | &chan->ramht); | ||
1010 | if (ret) | 696 | if (ret) |
1011 | return ret; | 697 | return ret; |
1012 | } | 698 | } |
@@ -1023,24 +709,32 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
1023 | } | 709 | } |
1024 | } else { | 710 | } else { |
1025 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, | 711 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, |
1026 | 0, dev_priv->fb_available_size, | 712 | 0, dev_priv->fb_available_size, |
1027 | NV_DMA_ACCESS_RW, | 713 | NV_DMA_ACCESS_RW, |
1028 | NV_DMA_TARGET_VIDMEM, &vram); | 714 | NV_DMA_TARGET_VIDMEM, &vram); |
1029 | if (ret) { | 715 | if (ret) { |
1030 | NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); | 716 | NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); |
1031 | return ret; | 717 | return ret; |
1032 | } | 718 | } |
1033 | } | 719 | } |
1034 | 720 | ||
1035 | ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL); | 721 | ret = nouveau_ramht_insert(chan, vram_h, vram); |
722 | nouveau_gpuobj_ref(NULL, &vram); | ||
1036 | if (ret) { | 723 | if (ret) { |
1037 | NV_ERROR(dev, "Error referencing VRAM ctxdma: %d\n", ret); | 724 | NV_ERROR(dev, "Error adding VRAM ctxdma to RAMHT: %d\n", ret); |
1038 | return ret; | 725 | return ret; |
1039 | } | 726 | } |
1040 | 727 | ||
1041 | /* TT memory ctxdma */ | 728 | /* TT memory ctxdma */ |
1042 | if (dev_priv->card_type >= NV_50) { | 729 | if (dev_priv->card_type >= NV_50) { |
1043 | tt = vram; | 730 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, |
731 | 0, dev_priv->vm_end, | ||
732 | NV_DMA_ACCESS_RW, | ||
733 | NV_DMA_TARGET_AGP, &tt); | ||
734 | if (ret) { | ||
735 | NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); | ||
736 | return ret; | ||
737 | } | ||
1044 | } else | 738 | } else |
1045 | if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { | 739 | if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { |
1046 | ret = nouveau_gpuobj_gart_dma_new(chan, 0, | 740 | ret = nouveau_gpuobj_gart_dma_new(chan, 0, |
@@ -1056,9 +750,10 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
1056 | return ret; | 750 | return ret; |
1057 | } | 751 | } |
1058 | 752 | ||
1059 | ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL); | 753 | ret = nouveau_ramht_insert(chan, tt_h, tt); |
754 | nouveau_gpuobj_ref(NULL, &tt); | ||
1060 | if (ret) { | 755 | if (ret) { |
1061 | NV_ERROR(dev, "Error referencing TT ctxdma: %d\n", ret); | 756 | NV_ERROR(dev, "Error adding TT ctxdma to RAMHT: %d\n", ret); |
1062 | return ret; | 757 | return ret; |
1063 | } | 758 | } |
1064 | 759 | ||
@@ -1070,33 +765,23 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) | |||
1070 | { | 765 | { |
1071 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 766 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
1072 | struct drm_device *dev = chan->dev; | 767 | struct drm_device *dev = chan->dev; |
1073 | struct list_head *entry, *tmp; | ||
1074 | struct nouveau_gpuobj_ref *ref; | ||
1075 | int i; | 768 | int i; |
1076 | 769 | ||
1077 | NV_DEBUG(dev, "ch%d\n", chan->id); | 770 | NV_DEBUG(dev, "ch%d\n", chan->id); |
1078 | 771 | ||
1079 | if (!chan->ramht_refs.next) | 772 | if (!chan->ramht) |
1080 | return; | 773 | return; |
1081 | 774 | ||
1082 | list_for_each_safe(entry, tmp, &chan->ramht_refs) { | 775 | nouveau_ramht_ref(NULL, &chan->ramht, chan); |
1083 | ref = list_entry(entry, struct nouveau_gpuobj_ref, list); | ||
1084 | |||
1085 | nouveau_gpuobj_ref_del(dev, &ref); | ||
1086 | } | ||
1087 | |||
1088 | nouveau_gpuobj_ref_del(dev, &chan->ramht); | ||
1089 | 776 | ||
1090 | nouveau_gpuobj_del(dev, &chan->vm_pd); | 777 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); |
1091 | nouveau_gpuobj_ref_del(dev, &chan->vm_gart_pt); | 778 | nouveau_gpuobj_ref(NULL, &chan->vm_gart_pt); |
1092 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) | 779 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) |
1093 | nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); | 780 | nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); |
1094 | 781 | ||
1095 | if (chan->ramin_heap.free_stack.next) | 782 | if (chan->ramin_heap.free_stack.next) |
1096 | drm_mm_takedown(&chan->ramin_heap); | 783 | drm_mm_takedown(&chan->ramin_heap); |
1097 | if (chan->ramin) | 784 | nouveau_gpuobj_ref(NULL, &chan->ramin); |
1098 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | ||
1099 | |||
1100 | } | 785 | } |
1101 | 786 | ||
1102 | int | 787 | int |
@@ -1117,17 +802,17 @@ nouveau_gpuobj_suspend(struct drm_device *dev) | |||
1117 | } | 802 | } |
1118 | 803 | ||
1119 | list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { | 804 | list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { |
1120 | if (!gpuobj->im_backing || (gpuobj->flags & NVOBJ_FLAG_FAKE)) | 805 | if (!gpuobj->im_backing) |
1121 | continue; | 806 | continue; |
1122 | 807 | ||
1123 | gpuobj->im_backing_suspend = vmalloc(gpuobj->im_pramin->size); | 808 | gpuobj->im_backing_suspend = vmalloc(gpuobj->size); |
1124 | if (!gpuobj->im_backing_suspend) { | 809 | if (!gpuobj->im_backing_suspend) { |
1125 | nouveau_gpuobj_resume(dev); | 810 | nouveau_gpuobj_resume(dev); |
1126 | return -ENOMEM; | 811 | return -ENOMEM; |
1127 | } | 812 | } |
1128 | 813 | ||
1129 | for (i = 0; i < gpuobj->im_pramin->size / 4; i++) | 814 | for (i = 0; i < gpuobj->size; i += 4) |
1130 | gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); | 815 | gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i); |
1131 | } | 816 | } |
1132 | 817 | ||
1133 | return 0; | 818 | return 0; |
@@ -1172,8 +857,8 @@ nouveau_gpuobj_resume(struct drm_device *dev) | |||
1172 | if (!gpuobj->im_backing_suspend) | 857 | if (!gpuobj->im_backing_suspend) |
1173 | continue; | 858 | continue; |
1174 | 859 | ||
1175 | for (i = 0; i < gpuobj->im_pramin->size / 4; i++) | 860 | for (i = 0; i < gpuobj->size; i += 4) |
1176 | nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); | 861 | nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]); |
1177 | dev_priv->engine.instmem.flush(dev); | 862 | dev_priv->engine.instmem.flush(dev); |
1178 | } | 863 | } |
1179 | 864 | ||
@@ -1208,25 +893,24 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, | |||
1208 | return -EPERM; | 893 | return -EPERM; |
1209 | } | 894 | } |
1210 | 895 | ||
1211 | if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) | 896 | if (nouveau_ramht_find(chan, init->handle)) |
1212 | return -EEXIST; | 897 | return -EEXIST; |
1213 | 898 | ||
1214 | if (!grc->software) | 899 | if (!grc->software) |
1215 | ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); | 900 | ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); |
1216 | else | 901 | else |
1217 | ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); | 902 | ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); |
1218 | |||
1219 | if (ret) { | 903 | if (ret) { |
1220 | NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", | 904 | NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", |
1221 | ret, init->channel, init->handle); | 905 | ret, init->channel, init->handle); |
1222 | return ret; | 906 | return ret; |
1223 | } | 907 | } |
1224 | 908 | ||
1225 | ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL); | 909 | ret = nouveau_ramht_insert(chan, init->handle, gr); |
910 | nouveau_gpuobj_ref(NULL, &gr); | ||
1226 | if (ret) { | 911 | if (ret) { |
1227 | NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", | 912 | NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", |
1228 | ret, init->channel, init->handle); | 913 | ret, init->channel, init->handle); |
1229 | nouveau_gpuobj_del(dev, &gr); | ||
1230 | return ret; | 914 | return ret; |
1231 | } | 915 | } |
1232 | 916 | ||
@@ -1237,16 +921,62 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, | |||
1237 | struct drm_file *file_priv) | 921 | struct drm_file *file_priv) |
1238 | { | 922 | { |
1239 | struct drm_nouveau_gpuobj_free *objfree = data; | 923 | struct drm_nouveau_gpuobj_free *objfree = data; |
1240 | struct nouveau_gpuobj_ref *ref; | 924 | struct nouveau_gpuobj *gpuobj; |
1241 | struct nouveau_channel *chan; | 925 | struct nouveau_channel *chan; |
1242 | int ret; | ||
1243 | 926 | ||
1244 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); | 927 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); |
1245 | 928 | ||
1246 | ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref); | 929 | gpuobj = nouveau_ramht_find(chan, objfree->handle); |
1247 | if (ret) | 930 | if (!gpuobj) |
1248 | return ret; | 931 | return -ENOENT; |
1249 | nouveau_gpuobj_ref_del(dev, &ref); | ||
1250 | 932 | ||
933 | nouveau_ramht_remove(chan, objfree->handle); | ||
1251 | return 0; | 934 | return 0; |
1252 | } | 935 | } |
936 | |||
937 | u32 | ||
938 | nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) | ||
939 | { | ||
940 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; | ||
941 | struct drm_device *dev = gpuobj->dev; | ||
942 | |||
943 | if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { | ||
944 | u64 ptr = gpuobj->vinst + offset; | ||
945 | u32 base = ptr >> 16; | ||
946 | u32 val; | ||
947 | |||
948 | spin_lock(&dev_priv->ramin_lock); | ||
949 | if (dev_priv->ramin_base != base) { | ||
950 | dev_priv->ramin_base = base; | ||
951 | nv_wr32(dev, 0x001700, dev_priv->ramin_base); | ||
952 | } | ||
953 | val = nv_rd32(dev, 0x700000 + (ptr & 0xffff)); | ||
954 | spin_unlock(&dev_priv->ramin_lock); | ||
955 | return val; | ||
956 | } | ||
957 | |||
958 | return nv_ri32(dev, gpuobj->pinst + offset); | ||
959 | } | ||
960 | |||
961 | void | ||
962 | nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) | ||
963 | { | ||
964 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; | ||
965 | struct drm_device *dev = gpuobj->dev; | ||
966 | |||
967 | if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { | ||
968 | u64 ptr = gpuobj->vinst + offset; | ||
969 | u32 base = ptr >> 16; | ||
970 | |||
971 | spin_lock(&dev_priv->ramin_lock); | ||
972 | if (dev_priv->ramin_base != base) { | ||
973 | dev_priv->ramin_base = base; | ||
974 | nv_wr32(dev, 0x001700, dev_priv->ramin_base); | ||
975 | } | ||
976 | nv_wr32(dev, 0x700000 + (ptr & 0xffff), val); | ||
977 | spin_unlock(&dev_priv->ramin_lock); | ||
978 | return; | ||
979 | } | ||
980 | |||
981 | nv_wi32(dev, gpuobj->pinst + offset, val); | ||
982 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c new file mode 100644 index 000000000000..ac62a1b8c4fc --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | static void | ||
31 | legacy_perf_init(struct drm_device *dev) | ||
32 | { | ||
33 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
34 | struct nvbios *bios = &dev_priv->vbios; | ||
35 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
36 | char *perf, *entry, *bmp = &bios->data[bios->offset]; | ||
37 | int headerlen, use_straps; | ||
38 | |||
39 | if (bmp[5] < 0x5 || bmp[6] < 0x14) { | ||
40 | NV_DEBUG(dev, "BMP version too old for perf\n"); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | perf = ROMPTR(bios, bmp[0x73]); | ||
45 | if (!perf) { | ||
46 | NV_DEBUG(dev, "No memclock table pointer found.\n"); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | switch (perf[0]) { | ||
51 | case 0x12: | ||
52 | case 0x14: | ||
53 | case 0x18: | ||
54 | use_straps = 0; | ||
55 | headerlen = 1; | ||
56 | break; | ||
57 | case 0x01: | ||
58 | use_straps = perf[1] & 1; | ||
59 | headerlen = (use_straps ? 8 : 2); | ||
60 | break; | ||
61 | default: | ||
62 | NV_WARN(dev, "Unknown memclock table version %x.\n", perf[0]); | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | entry = perf + headerlen; | ||
67 | if (use_straps) | ||
68 | entry += (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; | ||
69 | |||
70 | sprintf(pm->perflvl[0].name, "performance_level_0"); | ||
71 | pm->perflvl[0].memory = ROM16(entry[0]) * 20; | ||
72 | pm->nr_perflvl = 1; | ||
73 | } | ||
74 | |||
75 | void | ||
76 | nouveau_perf_init(struct drm_device *dev) | ||
77 | { | ||
78 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
79 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
80 | struct nvbios *bios = &dev_priv->vbios; | ||
81 | struct bit_entry P; | ||
82 | u8 version, headerlen, recordlen, entries; | ||
83 | u8 *perf, *entry; | ||
84 | int vid, i; | ||
85 | |||
86 | if (bios->type == NVBIOS_BIT) { | ||
87 | if (bit_table(dev, 'P', &P)) | ||
88 | return; | ||
89 | |||
90 | if (P.version != 1 && P.version != 2) { | ||
91 | NV_WARN(dev, "unknown perf for BIT P %d\n", P.version); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | perf = ROMPTR(bios, P.data[0]); | ||
96 | version = perf[0]; | ||
97 | headerlen = perf[1]; | ||
98 | if (version < 0x40) { | ||
99 | recordlen = perf[3] + (perf[4] * perf[5]); | ||
100 | entries = perf[2]; | ||
101 | } else { | ||
102 | recordlen = perf[2] + (perf[3] * perf[4]); | ||
103 | entries = perf[5]; | ||
104 | } | ||
105 | } else { | ||
106 | if (bios->data[bios->offset + 6] < 0x25) { | ||
107 | legacy_perf_init(dev); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | perf = ROMPTR(bios, bios->data[bios->offset + 0x94]); | ||
112 | if (!perf) { | ||
113 | NV_DEBUG(dev, "perf table pointer invalid\n"); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | version = perf[1]; | ||
118 | headerlen = perf[0]; | ||
119 | recordlen = perf[3]; | ||
120 | entries = perf[2]; | ||
121 | } | ||
122 | |||
123 | entry = perf + headerlen; | ||
124 | for (i = 0; i < entries; i++) { | ||
125 | struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; | ||
126 | |||
127 | if (entry[0] == 0xff) { | ||
128 | entry += recordlen; | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | switch (version) { | ||
133 | case 0x12: | ||
134 | case 0x13: | ||
135 | case 0x15: | ||
136 | perflvl->fanspeed = entry[55]; | ||
137 | perflvl->voltage = entry[56]; | ||
138 | perflvl->core = ROM32(entry[1]) * 10; | ||
139 | perflvl->memory = ROM32(entry[5]) * 20; | ||
140 | break; | ||
141 | case 0x21: | ||
142 | case 0x23: | ||
143 | case 0x24: | ||
144 | perflvl->fanspeed = entry[4]; | ||
145 | perflvl->voltage = entry[5]; | ||
146 | perflvl->core = ROM16(entry[6]) * 1000; | ||
147 | |||
148 | if (dev_priv->chipset == 0x49 || | ||
149 | dev_priv->chipset == 0x4b) | ||
150 | perflvl->memory = ROM16(entry[11]) * 1000; | ||
151 | else | ||
152 | perflvl->memory = ROM16(entry[11]) * 2000; | ||
153 | |||
154 | break; | ||
155 | case 0x25: | ||
156 | perflvl->fanspeed = entry[4]; | ||
157 | perflvl->voltage = entry[5]; | ||
158 | perflvl->core = ROM16(entry[6]) * 1000; | ||
159 | perflvl->shader = ROM16(entry[10]) * 1000; | ||
160 | perflvl->memory = ROM16(entry[12]) * 1000; | ||
161 | break; | ||
162 | case 0x30: | ||
163 | perflvl->memscript = ROM16(entry[2]); | ||
164 | case 0x35: | ||
165 | perflvl->fanspeed = entry[6]; | ||
166 | perflvl->voltage = entry[7]; | ||
167 | perflvl->core = ROM16(entry[8]) * 1000; | ||
168 | perflvl->shader = ROM16(entry[10]) * 1000; | ||
169 | perflvl->memory = ROM16(entry[12]) * 1000; | ||
170 | /*XXX: confirm on 0x35 */ | ||
171 | perflvl->unk05 = ROM16(entry[16]) * 1000; | ||
172 | break; | ||
173 | case 0x40: | ||
174 | #define subent(n) entry[perf[2] + ((n) * perf[3])] | ||
175 | perflvl->fanspeed = 0; /*XXX*/ | ||
176 | perflvl->voltage = entry[2]; | ||
177 | perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000; | ||
178 | perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000; | ||
179 | perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000; | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | /* make sure vid is valid */ | ||
184 | if (pm->voltage.supported && perflvl->voltage) { | ||
185 | vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); | ||
186 | if (vid < 0) { | ||
187 | NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); | ||
188 | entry += recordlen; | ||
189 | continue; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | snprintf(perflvl->name, sizeof(perflvl->name), | ||
194 | "performance_level_%d", i); | ||
195 | perflvl->id = i; | ||
196 | pm->nr_perflvl++; | ||
197 | |||
198 | entry += recordlen; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | void | ||
203 | nouveau_perf_fini(struct drm_device *dev) | ||
204 | { | ||
205 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c new file mode 100644 index 000000000000..1c99c55d6d46 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -0,0 +1,518 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | #include <linux/hwmon.h> | ||
31 | #include <linux/hwmon-sysfs.h> | ||
32 | |||
33 | static int | ||
34 | nouveau_pm_clock_set(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||
35 | u8 id, u32 khz) | ||
36 | { | ||
37 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
38 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
39 | void *pre_state; | ||
40 | |||
41 | if (khz == 0) | ||
42 | return 0; | ||
43 | |||
44 | pre_state = pm->clock_pre(dev, perflvl, id, khz); | ||
45 | if (IS_ERR(pre_state)) | ||
46 | return PTR_ERR(pre_state); | ||
47 | |||
48 | if (pre_state) | ||
49 | pm->clock_set(dev, pre_state); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int | ||
54 | nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||
55 | { | ||
56 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
57 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
58 | int ret; | ||
59 | |||
60 | if (perflvl == pm->cur) | ||
61 | return 0; | ||
62 | |||
63 | if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { | ||
64 | ret = pm->voltage_set(dev, perflvl->voltage); | ||
65 | if (ret) { | ||
66 | NV_ERROR(dev, "voltage_set %d failed: %d\n", | ||
67 | perflvl->voltage, ret); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); | ||
72 | nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); | ||
73 | nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); | ||
74 | nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); | ||
75 | |||
76 | pm->cur = perflvl; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int | ||
81 | nouveau_pm_profile_set(struct drm_device *dev, const char *profile) | ||
82 | { | ||
83 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
84 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
85 | struct nouveau_pm_level *perflvl = NULL; | ||
86 | |||
87 | /* safety precaution, for now */ | ||
88 | if (nouveau_perflvl_wr != 7777) | ||
89 | return -EPERM; | ||
90 | |||
91 | if (!pm->clock_set) | ||
92 | return -EINVAL; | ||
93 | |||
94 | if (!strncmp(profile, "boot", 4)) | ||
95 | perflvl = &pm->boot; | ||
96 | else { | ||
97 | int pl = simple_strtol(profile, NULL, 10); | ||
98 | int i; | ||
99 | |||
100 | for (i = 0; i < pm->nr_perflvl; i++) { | ||
101 | if (pm->perflvl[i].id == pl) { | ||
102 | perflvl = &pm->perflvl[i]; | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | if (!perflvl) | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | |||
111 | NV_INFO(dev, "setting performance level: %s\n", profile); | ||
112 | return nouveau_pm_perflvl_set(dev, perflvl); | ||
113 | } | ||
114 | |||
115 | static int | ||
116 | nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||
117 | { | ||
118 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
119 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
120 | int ret; | ||
121 | |||
122 | if (!pm->clock_get) | ||
123 | return -EINVAL; | ||
124 | |||
125 | memset(perflvl, 0, sizeof(*perflvl)); | ||
126 | |||
127 | ret = pm->clock_get(dev, PLL_CORE); | ||
128 | if (ret > 0) | ||
129 | perflvl->core = ret; | ||
130 | |||
131 | ret = pm->clock_get(dev, PLL_MEMORY); | ||
132 | if (ret > 0) | ||
133 | perflvl->memory = ret; | ||
134 | |||
135 | ret = pm->clock_get(dev, PLL_SHADER); | ||
136 | if (ret > 0) | ||
137 | perflvl->shader = ret; | ||
138 | |||
139 | ret = pm->clock_get(dev, PLL_UNK05); | ||
140 | if (ret > 0) | ||
141 | perflvl->unk05 = ret; | ||
142 | |||
143 | if (pm->voltage.supported && pm->voltage_get) { | ||
144 | ret = pm->voltage_get(dev); | ||
145 | if (ret > 0) | ||
146 | perflvl->voltage = ret; | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void | ||
153 | nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) | ||
154 | { | ||
155 | char c[16], s[16], v[16], f[16]; | ||
156 | |||
157 | c[0] = '\0'; | ||
158 | if (perflvl->core) | ||
159 | snprintf(c, sizeof(c), " core %dMHz", perflvl->core / 1000); | ||
160 | |||
161 | s[0] = '\0'; | ||
162 | if (perflvl->shader) | ||
163 | snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); | ||
164 | |||
165 | v[0] = '\0'; | ||
166 | if (perflvl->voltage) | ||
167 | snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); | ||
168 | |||
169 | f[0] = '\0'; | ||
170 | if (perflvl->fanspeed) | ||
171 | snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed); | ||
172 | |||
173 | snprintf(ptr, len, "memory %dMHz%s%s%s%s\n", perflvl->memory / 1000, | ||
174 | c, s, v, f); | ||
175 | } | ||
176 | |||
177 | static ssize_t | ||
178 | nouveau_pm_get_perflvl_info(struct device *d, | ||
179 | struct device_attribute *a, char *buf) | ||
180 | { | ||
181 | struct nouveau_pm_level *perflvl = (struct nouveau_pm_level *)a; | ||
182 | char *ptr = buf; | ||
183 | int len = PAGE_SIZE; | ||
184 | |||
185 | snprintf(ptr, len, "%d: ", perflvl->id); | ||
186 | ptr += strlen(buf); | ||
187 | len -= strlen(buf); | ||
188 | |||
189 | nouveau_pm_perflvl_info(perflvl, ptr, len); | ||
190 | return strlen(buf); | ||
191 | } | ||
192 | |||
193 | static ssize_t | ||
194 | nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) | ||
195 | { | ||
196 | struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); | ||
197 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
198 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
199 | struct nouveau_pm_level cur; | ||
200 | int len = PAGE_SIZE, ret; | ||
201 | char *ptr = buf; | ||
202 | |||
203 | if (!pm->cur) | ||
204 | snprintf(ptr, len, "setting: boot\n"); | ||
205 | else if (pm->cur == &pm->boot) | ||
206 | snprintf(ptr, len, "setting: boot\nc: "); | ||
207 | else | ||
208 | snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); | ||
209 | ptr += strlen(buf); | ||
210 | len -= strlen(buf); | ||
211 | |||
212 | ret = nouveau_pm_perflvl_get(dev, &cur); | ||
213 | if (ret == 0) | ||
214 | nouveau_pm_perflvl_info(&cur, ptr, len); | ||
215 | return strlen(buf); | ||
216 | } | ||
217 | |||
218 | static ssize_t | ||
219 | nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a, | ||
220 | const char *buf, size_t count) | ||
221 | { | ||
222 | struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); | ||
223 | int ret; | ||
224 | |||
225 | ret = nouveau_pm_profile_set(dev, buf); | ||
226 | if (ret) | ||
227 | return ret; | ||
228 | return strlen(buf); | ||
229 | } | ||
230 | |||
231 | static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR, | ||
232 | nouveau_pm_get_perflvl, nouveau_pm_set_perflvl); | ||
233 | |||
234 | static int | ||
235 | nouveau_sysfs_init(struct drm_device *dev) | ||
236 | { | ||
237 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
238 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
239 | struct device *d = &dev->pdev->dev; | ||
240 | int ret, i; | ||
241 | |||
242 | ret = device_create_file(d, &dev_attr_performance_level); | ||
243 | if (ret) | ||
244 | return ret; | ||
245 | |||
246 | for (i = 0; i < pm->nr_perflvl; i++) { | ||
247 | struct nouveau_pm_level *perflvl = &pm->perflvl[i]; | ||
248 | |||
249 | perflvl->dev_attr.attr.name = perflvl->name; | ||
250 | perflvl->dev_attr.attr.mode = S_IRUGO; | ||
251 | perflvl->dev_attr.show = nouveau_pm_get_perflvl_info; | ||
252 | perflvl->dev_attr.store = NULL; | ||
253 | sysfs_attr_init(&perflvl->dev_attr.attr); | ||
254 | |||
255 | ret = device_create_file(d, &perflvl->dev_attr); | ||
256 | if (ret) { | ||
257 | NV_ERROR(dev, "failed pervlvl %d sysfs: %d\n", | ||
258 | perflvl->id, i); | ||
259 | perflvl->dev_attr.attr.name = NULL; | ||
260 | nouveau_pm_fini(dev); | ||
261 | return ret; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static void | ||
269 | nouveau_sysfs_fini(struct drm_device *dev) | ||
270 | { | ||
271 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
272 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
273 | struct device *d = &dev->pdev->dev; | ||
274 | int i; | ||
275 | |||
276 | device_remove_file(d, &dev_attr_performance_level); | ||
277 | for (i = 0; i < pm->nr_perflvl; i++) { | ||
278 | struct nouveau_pm_level *pl = &pm->perflvl[i]; | ||
279 | |||
280 | if (!pl->dev_attr.attr.name) | ||
281 | break; | ||
282 | |||
283 | device_remove_file(d, &pl->dev_attr); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | static ssize_t | ||
288 | nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | ||
289 | { | ||
290 | struct drm_device *dev = dev_get_drvdata(d); | ||
291 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
292 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
293 | |||
294 | return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000); | ||
295 | } | ||
296 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, | ||
297 | NULL, 0); | ||
298 | |||
299 | static ssize_t | ||
300 | nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) | ||
301 | { | ||
302 | struct drm_device *dev = dev_get_drvdata(d); | ||
303 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
304 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
305 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||
306 | |||
307 | return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000); | ||
308 | } | ||
309 | static ssize_t | ||
310 | nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, | ||
311 | const char *buf, size_t count) | ||
312 | { | ||
313 | struct drm_device *dev = dev_get_drvdata(d); | ||
314 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
315 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
316 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||
317 | long value; | ||
318 | |||
319 | if (strict_strtol(buf, 10, &value) == -EINVAL) | ||
320 | return count; | ||
321 | |||
322 | temp->down_clock = value/1000; | ||
323 | |||
324 | nouveau_temp_safety_checks(dev); | ||
325 | |||
326 | return count; | ||
327 | } | ||
328 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp, | ||
329 | nouveau_hwmon_set_max_temp, | ||
330 | 0); | ||
331 | |||
332 | static ssize_t | ||
333 | nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, | ||
334 | char *buf) | ||
335 | { | ||
336 | struct drm_device *dev = dev_get_drvdata(d); | ||
337 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
338 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
339 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||
340 | |||
341 | return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000); | ||
342 | } | ||
343 | static ssize_t | ||
344 | nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, | ||
345 | const char *buf, | ||
346 | size_t count) | ||
347 | { | ||
348 | struct drm_device *dev = dev_get_drvdata(d); | ||
349 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
350 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
351 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||
352 | long value; | ||
353 | |||
354 | if (strict_strtol(buf, 10, &value) == -EINVAL) | ||
355 | return count; | ||
356 | |||
357 | temp->critical = value/1000; | ||
358 | |||
359 | nouveau_temp_safety_checks(dev); | ||
360 | |||
361 | return count; | ||
362 | } | ||
363 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, | ||
364 | nouveau_hwmon_critical_temp, | ||
365 | nouveau_hwmon_set_critical_temp, | ||
366 | 0); | ||
367 | |||
368 | static ssize_t nouveau_hwmon_show_name(struct device *dev, | ||
369 | struct device_attribute *attr, | ||
370 | char *buf) | ||
371 | { | ||
372 | return sprintf(buf, "nouveau\n"); | ||
373 | } | ||
374 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0); | ||
375 | |||
376 | static ssize_t nouveau_hwmon_show_update_rate(struct device *dev, | ||
377 | struct device_attribute *attr, | ||
378 | char *buf) | ||
379 | { | ||
380 | return sprintf(buf, "1000\n"); | ||
381 | } | ||
382 | static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO, | ||
383 | nouveau_hwmon_show_update_rate, | ||
384 | NULL, 0); | ||
385 | |||
386 | static struct attribute *hwmon_attributes[] = { | ||
387 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
388 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
389 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
390 | &sensor_dev_attr_name.dev_attr.attr, | ||
391 | &sensor_dev_attr_update_rate.dev_attr.attr, | ||
392 | NULL | ||
393 | }; | ||
394 | |||
395 | static const struct attribute_group hwmon_attrgroup = { | ||
396 | .attrs = hwmon_attributes, | ||
397 | }; | ||
398 | |||
399 | static int | ||
400 | nouveau_hwmon_init(struct drm_device *dev) | ||
401 | { | ||
402 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
403 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
404 | struct device *hwmon_dev; | ||
405 | int ret; | ||
406 | |||
407 | if (!pm->temp_get) | ||
408 | return -ENODEV; | ||
409 | |||
410 | hwmon_dev = hwmon_device_register(&dev->pdev->dev); | ||
411 | if (IS_ERR(hwmon_dev)) { | ||
412 | ret = PTR_ERR(hwmon_dev); | ||
413 | NV_ERROR(dev, | ||
414 | "Unable to register hwmon device: %d\n", ret); | ||
415 | return ret; | ||
416 | } | ||
417 | dev_set_drvdata(hwmon_dev, dev); | ||
418 | ret = sysfs_create_group(&hwmon_dev->kobj, | ||
419 | &hwmon_attrgroup); | ||
420 | if (ret) { | ||
421 | NV_ERROR(dev, | ||
422 | "Unable to create hwmon sysfs file: %d\n", ret); | ||
423 | hwmon_device_unregister(hwmon_dev); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | pm->hwmon = hwmon_dev; | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static void | ||
433 | nouveau_hwmon_fini(struct drm_device *dev) | ||
434 | { | ||
435 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
436 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
437 | |||
438 | if (pm->hwmon) { | ||
439 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); | ||
440 | hwmon_device_unregister(pm->hwmon); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | int | ||
445 | nouveau_pm_init(struct drm_device *dev) | ||
446 | { | ||
447 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
448 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
449 | char info[256]; | ||
450 | int ret, i; | ||
451 | |||
452 | nouveau_volt_init(dev); | ||
453 | nouveau_perf_init(dev); | ||
454 | nouveau_temp_init(dev); | ||
455 | nouveau_mem_timing_init(dev); | ||
456 | |||
457 | NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); | ||
458 | for (i = 0; i < pm->nr_perflvl; i++) { | ||
459 | nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); | ||
460 | NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info); | ||
461 | } | ||
462 | |||
463 | /* determine current ("boot") performance level */ | ||
464 | ret = nouveau_pm_perflvl_get(dev, &pm->boot); | ||
465 | if (ret == 0) { | ||
466 | pm->cur = &pm->boot; | ||
467 | |||
468 | nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); | ||
469 | NV_INFO(dev, "c: %s", info); | ||
470 | } | ||
471 | |||
472 | /* switch performance levels now if requested */ | ||
473 | if (nouveau_perflvl != NULL) { | ||
474 | ret = nouveau_pm_profile_set(dev, nouveau_perflvl); | ||
475 | if (ret) { | ||
476 | NV_ERROR(dev, "error setting perflvl \"%s\": %d\n", | ||
477 | nouveau_perflvl, ret); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | nouveau_sysfs_init(dev); | ||
482 | nouveau_hwmon_init(dev); | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | void | ||
488 | nouveau_pm_fini(struct drm_device *dev) | ||
489 | { | ||
490 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
491 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
492 | |||
493 | if (pm->cur != &pm->boot) | ||
494 | nouveau_pm_perflvl_set(dev, &pm->boot); | ||
495 | |||
496 | nouveau_mem_timing_fini(dev); | ||
497 | nouveau_temp_fini(dev); | ||
498 | nouveau_perf_fini(dev); | ||
499 | nouveau_volt_fini(dev); | ||
500 | |||
501 | nouveau_hwmon_fini(dev); | ||
502 | nouveau_sysfs_fini(dev); | ||
503 | } | ||
504 | |||
505 | void | ||
506 | nouveau_pm_resume(struct drm_device *dev) | ||
507 | { | ||
508 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
509 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
510 | struct nouveau_pm_level *perflvl; | ||
511 | |||
512 | if (pm->cur == &pm->boot) | ||
513 | return; | ||
514 | |||
515 | perflvl = pm->cur; | ||
516 | pm->cur = &pm->boot; | ||
517 | nouveau_pm_perflvl_set(dev, perflvl); | ||
518 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h new file mode 100644 index 000000000000..4a9838ddacec --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #ifndef __NOUVEAU_PM_H__ | ||
26 | #define __NOUVEAU_PM_H__ | ||
27 | |||
28 | /* nouveau_pm.c */ | ||
29 | int nouveau_pm_init(struct drm_device *dev); | ||
30 | void nouveau_pm_fini(struct drm_device *dev); | ||
31 | void nouveau_pm_resume(struct drm_device *dev); | ||
32 | |||
33 | /* nouveau_volt.c */ | ||
34 | void nouveau_volt_init(struct drm_device *); | ||
35 | void nouveau_volt_fini(struct drm_device *); | ||
36 | int nouveau_volt_vid_lookup(struct drm_device *, int voltage); | ||
37 | int nouveau_volt_lvl_lookup(struct drm_device *, int vid); | ||
38 | int nouveau_voltage_gpio_get(struct drm_device *); | ||
39 | int nouveau_voltage_gpio_set(struct drm_device *, int voltage); | ||
40 | |||
41 | /* nouveau_perf.c */ | ||
42 | void nouveau_perf_init(struct drm_device *); | ||
43 | void nouveau_perf_fini(struct drm_device *); | ||
44 | |||
45 | /* nouveau_mem.c */ | ||
46 | void nouveau_mem_timing_init(struct drm_device *); | ||
47 | void nouveau_mem_timing_fini(struct drm_device *); | ||
48 | |||
49 | /* nv04_pm.c */ | ||
50 | int nv04_pm_clock_get(struct drm_device *, u32 id); | ||
51 | void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | ||
52 | u32 id, int khz); | ||
53 | void nv04_pm_clock_set(struct drm_device *, void *); | ||
54 | |||
55 | /* nv50_pm.c */ | ||
56 | int nv50_pm_clock_get(struct drm_device *, u32 id); | ||
57 | void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | ||
58 | u32 id, int khz); | ||
59 | void nv50_pm_clock_set(struct drm_device *, void *); | ||
60 | |||
61 | /* nva3_pm.c */ | ||
62 | int nva3_pm_clock_get(struct drm_device *, u32 id); | ||
63 | void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | ||
64 | u32 id, int khz); | ||
65 | void nva3_pm_clock_set(struct drm_device *, void *); | ||
66 | |||
67 | /* nouveau_temp.c */ | ||
68 | void nouveau_temp_init(struct drm_device *dev); | ||
69 | void nouveau_temp_fini(struct drm_device *dev); | ||
70 | void nouveau_temp_safety_checks(struct drm_device *dev); | ||
71 | int nv40_temp_get(struct drm_device *dev); | ||
72 | int nv84_temp_get(struct drm_device *dev); | ||
73 | |||
74 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c new file mode 100644 index 000000000000..7f16697cc96c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c | |||
@@ -0,0 +1,289 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | #include "nouveau_ramht.h" | ||
29 | |||
30 | static u32 | ||
31 | nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle) | ||
32 | { | ||
33 | struct drm_device *dev = chan->dev; | ||
34 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
35 | struct nouveau_ramht *ramht = chan->ramht; | ||
36 | u32 hash = 0; | ||
37 | int i; | ||
38 | |||
39 | NV_DEBUG(dev, "ch%d handle=0x%08x\n", chan->id, handle); | ||
40 | |||
41 | for (i = 32; i > 0; i -= ramht->bits) { | ||
42 | hash ^= (handle & ((1 << ramht->bits) - 1)); | ||
43 | handle >>= ramht->bits; | ||
44 | } | ||
45 | |||
46 | if (dev_priv->card_type < NV_50) | ||
47 | hash ^= chan->id << (ramht->bits - 4); | ||
48 | hash <<= 3; | ||
49 | |||
50 | NV_DEBUG(dev, "hash=0x%08x\n", hash); | ||
51 | return hash; | ||
52 | } | ||
53 | |||
54 | static int | ||
55 | nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, | ||
56 | u32 offset) | ||
57 | { | ||
58 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
59 | u32 ctx = nv_ro32(ramht, offset + 4); | ||
60 | |||
61 | if (dev_priv->card_type < NV_40) | ||
62 | return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); | ||
63 | return (ctx != 0); | ||
64 | } | ||
65 | |||
66 | static int | ||
67 | nouveau_ramht_entry_same_channel(struct nouveau_channel *chan, | ||
68 | struct nouveau_gpuobj *ramht, u32 offset) | ||
69 | { | ||
70 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | ||
71 | u32 ctx = nv_ro32(ramht, offset + 4); | ||
72 | |||
73 | if (dev_priv->card_type >= NV_50) | ||
74 | return true; | ||
75 | else if (dev_priv->card_type >= NV_40) | ||
76 | return chan->id == | ||
77 | ((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); | ||
78 | else | ||
79 | return chan->id == | ||
80 | ((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); | ||
81 | } | ||
82 | |||
83 | int | ||
84 | nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, | ||
85 | struct nouveau_gpuobj *gpuobj) | ||
86 | { | ||
87 | struct drm_device *dev = chan->dev; | ||
88 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
89 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; | ||
90 | struct nouveau_ramht_entry *entry; | ||
91 | struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; | ||
92 | unsigned long flags; | ||
93 | u32 ctx, co, ho; | ||
94 | |||
95 | if (nouveau_ramht_find(chan, handle)) | ||
96 | return -EEXIST; | ||
97 | |||
98 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
99 | if (!entry) | ||
100 | return -ENOMEM; | ||
101 | entry->channel = chan; | ||
102 | entry->gpuobj = NULL; | ||
103 | entry->handle = handle; | ||
104 | nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); | ||
105 | |||
106 | if (dev_priv->card_type < NV_40) { | ||
107 | ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->cinst >> 4) | | ||
108 | (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | | ||
109 | (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); | ||
110 | } else | ||
111 | if (dev_priv->card_type < NV_50) { | ||
112 | ctx = (gpuobj->cinst >> 4) | | ||
113 | (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | | ||
114 | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); | ||
115 | } else { | ||
116 | if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { | ||
117 | ctx = (gpuobj->cinst << 10) | 2; | ||
118 | } else { | ||
119 | ctx = (gpuobj->cinst >> 4) | | ||
120 | ((gpuobj->engine << | ||
121 | NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | spin_lock_irqsave(&chan->ramht->lock, flags); | ||
126 | list_add(&entry->head, &chan->ramht->entries); | ||
127 | |||
128 | co = ho = nouveau_ramht_hash_handle(chan, handle); | ||
129 | do { | ||
130 | if (!nouveau_ramht_entry_valid(dev, ramht, co)) { | ||
131 | NV_DEBUG(dev, | ||
132 | "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", | ||
133 | chan->id, co, handle, ctx); | ||
134 | nv_wo32(ramht, co + 0, handle); | ||
135 | nv_wo32(ramht, co + 4, ctx); | ||
136 | |||
137 | spin_unlock_irqrestore(&chan->ramht->lock, flags); | ||
138 | instmem->flush(dev); | ||
139 | return 0; | ||
140 | } | ||
141 | NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", | ||
142 | chan->id, co, nv_ro32(ramht, co)); | ||
143 | |||
144 | co += 8; | ||
145 | if (co >= ramht->size) | ||
146 | co = 0; | ||
147 | } while (co != ho); | ||
148 | |||
149 | NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); | ||
150 | list_del(&entry->head); | ||
151 | spin_unlock_irqrestore(&chan->ramht->lock, flags); | ||
152 | kfree(entry); | ||
153 | return -ENOMEM; | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle) | ||
158 | { | ||
159 | struct drm_device *dev = chan->dev; | ||
160 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
161 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; | ||
162 | struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; | ||
163 | struct nouveau_ramht_entry *entry, *tmp; | ||
164 | u32 co, ho; | ||
165 | |||
166 | list_for_each_entry_safe(entry, tmp, &chan->ramht->entries, head) { | ||
167 | if (entry->channel != chan || entry->handle != handle) | ||
168 | continue; | ||
169 | |||
170 | nouveau_gpuobj_ref(NULL, &entry->gpuobj); | ||
171 | list_del(&entry->head); | ||
172 | kfree(entry); | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | co = ho = nouveau_ramht_hash_handle(chan, handle); | ||
177 | do { | ||
178 | if (nouveau_ramht_entry_valid(dev, ramht, co) && | ||
179 | nouveau_ramht_entry_same_channel(chan, ramht, co) && | ||
180 | (handle == nv_ro32(ramht, co))) { | ||
181 | NV_DEBUG(dev, | ||
182 | "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", | ||
183 | chan->id, co, handle, nv_ro32(ramht, co + 4)); | ||
184 | nv_wo32(ramht, co + 0, 0x00000000); | ||
185 | nv_wo32(ramht, co + 4, 0x00000000); | ||
186 | instmem->flush(dev); | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | co += 8; | ||
191 | if (co >= ramht->size) | ||
192 | co = 0; | ||
193 | } while (co != ho); | ||
194 | |||
195 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", | ||
196 | chan->id, handle); | ||
197 | } | ||
198 | |||
199 | void | ||
200 | nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) | ||
201 | { | ||
202 | struct nouveau_ramht *ramht = chan->ramht; | ||
203 | unsigned long flags; | ||
204 | |||
205 | spin_lock_irqsave(&ramht->lock, flags); | ||
206 | nouveau_ramht_remove_locked(chan, handle); | ||
207 | spin_unlock_irqrestore(&ramht->lock, flags); | ||
208 | } | ||
209 | |||
210 | struct nouveau_gpuobj * | ||
211 | nouveau_ramht_find(struct nouveau_channel *chan, u32 handle) | ||
212 | { | ||
213 | struct nouveau_ramht *ramht = chan->ramht; | ||
214 | struct nouveau_ramht_entry *entry; | ||
215 | struct nouveau_gpuobj *gpuobj = NULL; | ||
216 | unsigned long flags; | ||
217 | |||
218 | if (unlikely(!chan->ramht)) | ||
219 | return NULL; | ||
220 | |||
221 | spin_lock_irqsave(&ramht->lock, flags); | ||
222 | list_for_each_entry(entry, &chan->ramht->entries, head) { | ||
223 | if (entry->channel == chan && entry->handle == handle) { | ||
224 | gpuobj = entry->gpuobj; | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | spin_unlock_irqrestore(&ramht->lock, flags); | ||
229 | |||
230 | return gpuobj; | ||
231 | } | ||
232 | |||
233 | int | ||
234 | nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | ||
235 | struct nouveau_ramht **pramht) | ||
236 | { | ||
237 | struct nouveau_ramht *ramht; | ||
238 | |||
239 | ramht = kzalloc(sizeof(*ramht), GFP_KERNEL); | ||
240 | if (!ramht) | ||
241 | return -ENOMEM; | ||
242 | |||
243 | ramht->dev = dev; | ||
244 | kref_init(&ramht->refcount); | ||
245 | ramht->bits = drm_order(gpuobj->size / 8); | ||
246 | INIT_LIST_HEAD(&ramht->entries); | ||
247 | spin_lock_init(&ramht->lock); | ||
248 | nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj); | ||
249 | |||
250 | *pramht = ramht; | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static void | ||
255 | nouveau_ramht_del(struct kref *ref) | ||
256 | { | ||
257 | struct nouveau_ramht *ramht = | ||
258 | container_of(ref, struct nouveau_ramht, refcount); | ||
259 | |||
260 | nouveau_gpuobj_ref(NULL, &ramht->gpuobj); | ||
261 | kfree(ramht); | ||
262 | } | ||
263 | |||
264 | void | ||
265 | nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, | ||
266 | struct nouveau_channel *chan) | ||
267 | { | ||
268 | struct nouveau_ramht_entry *entry, *tmp; | ||
269 | struct nouveau_ramht *ramht; | ||
270 | unsigned long flags; | ||
271 | |||
272 | if (ref) | ||
273 | kref_get(&ref->refcount); | ||
274 | |||
275 | ramht = *ptr; | ||
276 | if (ramht) { | ||
277 | spin_lock_irqsave(&ramht->lock, flags); | ||
278 | list_for_each_entry_safe(entry, tmp, &ramht->entries, head) { | ||
279 | if (entry->channel != chan) | ||
280 | continue; | ||
281 | |||
282 | nouveau_ramht_remove_locked(chan, entry->handle); | ||
283 | } | ||
284 | spin_unlock_irqrestore(&ramht->lock, flags); | ||
285 | |||
286 | kref_put(&ramht->refcount, nouveau_ramht_del); | ||
287 | } | ||
288 | *ptr = ref; | ||
289 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.h b/drivers/gpu/drm/nouveau/nouveau_ramht.h new file mode 100644 index 000000000000..b79cb5e1a8f1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_ramht.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #ifndef __NOUVEAU_RAMHT_H__ | ||
26 | #define __NOUVEAU_RAMHT_H__ | ||
27 | |||
28 | struct nouveau_ramht_entry { | ||
29 | struct list_head head; | ||
30 | struct nouveau_channel *channel; | ||
31 | struct nouveau_gpuobj *gpuobj; | ||
32 | u32 handle; | ||
33 | }; | ||
34 | |||
35 | struct nouveau_ramht { | ||
36 | struct drm_device *dev; | ||
37 | struct kref refcount; | ||
38 | spinlock_t lock; | ||
39 | struct nouveau_gpuobj *gpuobj; | ||
40 | struct list_head entries; | ||
41 | int bits; | ||
42 | }; | ||
43 | |||
44 | extern int nouveau_ramht_new(struct drm_device *, struct nouveau_gpuobj *, | ||
45 | struct nouveau_ramht **); | ||
46 | extern void nouveau_ramht_ref(struct nouveau_ramht *, struct nouveau_ramht **, | ||
47 | struct nouveau_channel *unref_channel); | ||
48 | |||
49 | extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, | ||
50 | struct nouveau_gpuobj *); | ||
51 | extern void nouveau_ramht_remove(struct nouveau_channel *, u32 handle); | ||
52 | extern struct nouveau_gpuobj * | ||
53 | nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); | ||
54 | |||
55 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 21a6e453b975..1b42541ca9e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -551,6 +551,8 @@ | |||
551 | #define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C | 551 | #define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C |
552 | #define NV03_PFIFO_CACHE1_PULL0 0x00003240 | 552 | #define NV03_PFIFO_CACHE1_PULL0 0x00003240 |
553 | #define NV04_PFIFO_CACHE1_PULL0 0x00003250 | 553 | #define NV04_PFIFO_CACHE1_PULL0 0x00003250 |
554 | # define NV04_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000010 | ||
555 | # define NV04_PFIFO_CACHE1_PULL0_HASH_BUSY 0x00001000 | ||
554 | #define NV03_PFIFO_CACHE1_PULL1 0x00003250 | 556 | #define NV03_PFIFO_CACHE1_PULL1 0x00003250 |
555 | #define NV04_PFIFO_CACHE1_PULL1 0x00003254 | 557 | #define NV04_PFIFO_CACHE1_PULL1 0x00003254 |
556 | #define NV04_PFIFO_CACHE1_HASH 0x00003258 | 558 | #define NV04_PFIFO_CACHE1_HASH 0x00003258 |
@@ -785,15 +787,12 @@ | |||
785 | #define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) | 787 | #define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) |
786 | #define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8) | 788 | #define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8) |
787 | #define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8) | 789 | #define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8) |
790 | #define NV50_PDISPLAY_EXT_MODE_CTRL_P(i) (0x00610b80 + (i) * 0x8) | ||
791 | #define NV50_PDISPLAY_EXT_MODE_CTRL_C(i) (0x00610b84 + (i) * 0x8) | ||
788 | #define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8) | 792 | #define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8) |
789 | #define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8) | 793 | #define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8) |
790 | |||
791 | #define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8) | 794 | #define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8) |
792 | #define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8) | 795 | #define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8) |
793 | #define NV90_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8) | ||
794 | #define NV90_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) | ||
795 | #define NV90_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610b80 + (i) * 0x8) | ||
796 | #define NV90_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610b84 + (i) * 0x8) | ||
797 | 796 | ||
798 | #define NV50_PDISPLAY_CRTC_CLK 0x00614000 | 797 | #define NV50_PDISPLAY_CRTC_CLK 0x00614000 |
799 | #define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100) | 798 | #define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 6b9187d7f67d..288bacac7e5a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c | |||
@@ -95,9 +95,9 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | |||
95 | struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; | 95 | struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; |
96 | unsigned i, j, pte; | 96 | unsigned i, j, pte; |
97 | 97 | ||
98 | NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); | 98 | NV_DEBUG(dev, "pg=0x%lx\n", mem->start); |
99 | 99 | ||
100 | pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); | 100 | pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT); |
101 | nvbe->pte_start = pte; | 101 | nvbe->pte_start = pte; |
102 | for (i = 0; i < nvbe->nr_pages; i++) { | 102 | for (i = 0; i < nvbe->nr_pages; i++) { |
103 | dma_addr_t dma_offset = nvbe->pages[i]; | 103 | dma_addr_t dma_offset = nvbe->pages[i]; |
@@ -105,11 +105,13 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | |||
105 | uint32_t offset_h = upper_32_bits(dma_offset); | 105 | uint32_t offset_h = upper_32_bits(dma_offset); |
106 | 106 | ||
107 | for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { | 107 | for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { |
108 | if (dev_priv->card_type < NV_50) | 108 | if (dev_priv->card_type < NV_50) { |
109 | nv_wo32(dev, gpuobj, pte++, offset_l | 3); | 109 | nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); |
110 | else { | 110 | pte += 1; |
111 | nv_wo32(dev, gpuobj, pte++, offset_l | 0x21); | 111 | } else { |
112 | nv_wo32(dev, gpuobj, pte++, offset_h & 0xff); | 112 | nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21); |
113 | nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff); | ||
114 | pte += 2; | ||
113 | } | 115 | } |
114 | 116 | ||
115 | dma_offset += NV_CTXDMA_PAGE_SIZE; | 117 | dma_offset += NV_CTXDMA_PAGE_SIZE; |
@@ -145,11 +147,13 @@ nouveau_sgdma_unbind(struct ttm_backend *be) | |||
145 | dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; | 147 | dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; |
146 | 148 | ||
147 | for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { | 149 | for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { |
148 | if (dev_priv->card_type < NV_50) | 150 | if (dev_priv->card_type < NV_50) { |
149 | nv_wo32(dev, gpuobj, pte++, dma_offset | 3); | 151 | nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3); |
150 | else { | 152 | pte += 1; |
151 | nv_wo32(dev, gpuobj, pte++, dma_offset | 0x21); | 153 | } else { |
152 | nv_wo32(dev, gpuobj, pte++, 0x00000000); | 154 | nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); |
155 | nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000); | ||
156 | pte += 2; | ||
153 | } | 157 | } |
154 | 158 | ||
155 | dma_offset += NV_CTXDMA_PAGE_SIZE; | 159 | dma_offset += NV_CTXDMA_PAGE_SIZE; |
@@ -230,7 +234,6 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
230 | } | 234 | } |
231 | 235 | ||
232 | ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, | 236 | ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, |
233 | NVOBJ_FLAG_ALLOW_NO_REFS | | ||
234 | NVOBJ_FLAG_ZERO_ALLOC | | 237 | NVOBJ_FLAG_ZERO_ALLOC | |
235 | NVOBJ_FLAG_ZERO_FREE, &gpuobj); | 238 | NVOBJ_FLAG_ZERO_FREE, &gpuobj); |
236 | if (ret) { | 239 | if (ret) { |
@@ -239,9 +242,9 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
239 | } | 242 | } |
240 | 243 | ||
241 | dev_priv->gart_info.sg_dummy_page = | 244 | dev_priv->gart_info.sg_dummy_page = |
242 | alloc_page(GFP_KERNEL|__GFP_DMA32); | 245 | alloc_page(GFP_KERNEL|__GFP_DMA32|__GFP_ZERO); |
243 | if (!dev_priv->gart_info.sg_dummy_page) { | 246 | if (!dev_priv->gart_info.sg_dummy_page) { |
244 | nouveau_gpuobj_del(dev, &gpuobj); | 247 | nouveau_gpuobj_ref(NULL, &gpuobj); |
245 | return -ENOMEM; | 248 | return -ENOMEM; |
246 | } | 249 | } |
247 | 250 | ||
@@ -250,29 +253,34 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
250 | pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, | 253 | pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, |
251 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 254 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
252 | if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { | 255 | if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { |
253 | nouveau_gpuobj_del(dev, &gpuobj); | 256 | nouveau_gpuobj_ref(NULL, &gpuobj); |
254 | return -EFAULT; | 257 | return -EFAULT; |
255 | } | 258 | } |
256 | 259 | ||
257 | if (dev_priv->card_type < NV_50) { | 260 | if (dev_priv->card_type < NV_50) { |
261 | /* special case, allocated from global instmem heap so | ||
262 | * cinst is invalid, we use it on all channels though so | ||
263 | * cinst needs to be valid, set it the same as pinst | ||
264 | */ | ||
265 | gpuobj->cinst = gpuobj->pinst; | ||
266 | |||
258 | /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and | 267 | /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and |
259 | * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE | 268 | * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE |
260 | * on those cards? */ | 269 | * on those cards? */ |
261 | nv_wo32(dev, gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | | 270 | nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | |
262 | (1 << 12) /* PT present */ | | 271 | (1 << 12) /* PT present */ | |
263 | (0 << 13) /* PT *not* linear */ | | 272 | (0 << 13) /* PT *not* linear */ | |
264 | (NV_DMA_ACCESS_RW << 14) | | 273 | (NV_DMA_ACCESS_RW << 14) | |
265 | (NV_DMA_TARGET_PCI << 16)); | 274 | (NV_DMA_TARGET_PCI << 16)); |
266 | nv_wo32(dev, gpuobj, 1, aper_size - 1); | 275 | nv_wo32(gpuobj, 4, aper_size - 1); |
267 | for (i = 2; i < 2 + (aper_size >> 12); i++) { | 276 | for (i = 2; i < 2 + (aper_size >> 12); i++) { |
268 | nv_wo32(dev, gpuobj, i, | 277 | nv_wo32(gpuobj, i * 4, |
269 | dev_priv->gart_info.sg_dummy_bus | 3); | 278 | dev_priv->gart_info.sg_dummy_bus | 3); |
270 | } | 279 | } |
271 | } else { | 280 | } else { |
272 | for (i = 0; i < obj_size; i += 8) { | 281 | for (i = 0; i < obj_size; i += 8) { |
273 | nv_wo32(dev, gpuobj, (i+0)/4, | 282 | nv_wo32(gpuobj, i + 0, 0x00000000); |
274 | dev_priv->gart_info.sg_dummy_bus | 0x21); | 283 | nv_wo32(gpuobj, i + 4, 0x00000000); |
275 | nv_wo32(dev, gpuobj, (i+4)/4, 0); | ||
276 | } | 284 | } |
277 | } | 285 | } |
278 | dev_priv->engine.instmem.flush(dev); | 286 | dev_priv->engine.instmem.flush(dev); |
@@ -298,7 +306,7 @@ nouveau_sgdma_takedown(struct drm_device *dev) | |||
298 | dev_priv->gart_info.sg_dummy_bus = 0; | 306 | dev_priv->gart_info.sg_dummy_bus = 0; |
299 | } | 307 | } |
300 | 308 | ||
301 | nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma); | 309 | nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); |
302 | } | 310 | } |
303 | 311 | ||
304 | int | 312 | int |
@@ -308,9 +316,9 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) | |||
308 | struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; | 316 | struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; |
309 | int pte; | 317 | int pte; |
310 | 318 | ||
311 | pte = (offset >> NV_CTXDMA_PAGE_SHIFT); | 319 | pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2; |
312 | if (dev_priv->card_type < NV_50) { | 320 | if (dev_priv->card_type < NV_50) { |
313 | *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; | 321 | *page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK; |
314 | return 0; | 322 | return 0; |
315 | } | 323 | } |
316 | 324 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 989322be3728..ed7757f14083 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include "nouveau_drv.h" | 35 | #include "nouveau_drv.h" |
36 | #include "nouveau_drm.h" | 36 | #include "nouveau_drm.h" |
37 | #include "nouveau_fbcon.h" | 37 | #include "nouveau_fbcon.h" |
38 | #include "nouveau_ramht.h" | ||
39 | #include "nouveau_pm.h" | ||
38 | #include "nv50_display.h" | 40 | #include "nv50_display.h" |
39 | 41 | ||
40 | static void nouveau_stub_takedown(struct drm_device *dev) {} | 42 | static void nouveau_stub_takedown(struct drm_device *dev) {} |
@@ -78,7 +80,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
78 | engine->fifo.disable = nv04_fifo_disable; | 80 | engine->fifo.disable = nv04_fifo_disable; |
79 | engine->fifo.enable = nv04_fifo_enable; | 81 | engine->fifo.enable = nv04_fifo_enable; |
80 | engine->fifo.reassign = nv04_fifo_reassign; | 82 | engine->fifo.reassign = nv04_fifo_reassign; |
81 | engine->fifo.cache_flush = nv04_fifo_cache_flush; | ||
82 | engine->fifo.cache_pull = nv04_fifo_cache_pull; | 83 | engine->fifo.cache_pull = nv04_fifo_cache_pull; |
83 | engine->fifo.channel_id = nv04_fifo_channel_id; | 84 | engine->fifo.channel_id = nv04_fifo_channel_id; |
84 | engine->fifo.create_context = nv04_fifo_create_context; | 85 | engine->fifo.create_context = nv04_fifo_create_context; |
@@ -95,6 +96,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
95 | engine->gpio.get = NULL; | 96 | engine->gpio.get = NULL; |
96 | engine->gpio.set = NULL; | 97 | engine->gpio.set = NULL; |
97 | engine->gpio.irq_enable = NULL; | 98 | engine->gpio.irq_enable = NULL; |
99 | engine->pm.clock_get = nv04_pm_clock_get; | ||
100 | engine->pm.clock_pre = nv04_pm_clock_pre; | ||
101 | engine->pm.clock_set = nv04_pm_clock_set; | ||
98 | break; | 102 | break; |
99 | case 0x10: | 103 | case 0x10: |
100 | engine->instmem.init = nv04_instmem_init; | 104 | engine->instmem.init = nv04_instmem_init; |
@@ -130,7 +134,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
130 | engine->fifo.disable = nv04_fifo_disable; | 134 | engine->fifo.disable = nv04_fifo_disable; |
131 | engine->fifo.enable = nv04_fifo_enable; | 135 | engine->fifo.enable = nv04_fifo_enable; |
132 | engine->fifo.reassign = nv04_fifo_reassign; | 136 | engine->fifo.reassign = nv04_fifo_reassign; |
133 | engine->fifo.cache_flush = nv04_fifo_cache_flush; | ||
134 | engine->fifo.cache_pull = nv04_fifo_cache_pull; | 137 | engine->fifo.cache_pull = nv04_fifo_cache_pull; |
135 | engine->fifo.channel_id = nv10_fifo_channel_id; | 138 | engine->fifo.channel_id = nv10_fifo_channel_id; |
136 | engine->fifo.create_context = nv10_fifo_create_context; | 139 | engine->fifo.create_context = nv10_fifo_create_context; |
@@ -147,6 +150,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
147 | engine->gpio.get = nv10_gpio_get; | 150 | engine->gpio.get = nv10_gpio_get; |
148 | engine->gpio.set = nv10_gpio_set; | 151 | engine->gpio.set = nv10_gpio_set; |
149 | engine->gpio.irq_enable = NULL; | 152 | engine->gpio.irq_enable = NULL; |
153 | engine->pm.clock_get = nv04_pm_clock_get; | ||
154 | engine->pm.clock_pre = nv04_pm_clock_pre; | ||
155 | engine->pm.clock_set = nv04_pm_clock_set; | ||
150 | break; | 156 | break; |
151 | case 0x20: | 157 | case 0x20: |
152 | engine->instmem.init = nv04_instmem_init; | 158 | engine->instmem.init = nv04_instmem_init; |
@@ -182,7 +188,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
182 | engine->fifo.disable = nv04_fifo_disable; | 188 | engine->fifo.disable = nv04_fifo_disable; |
183 | engine->fifo.enable = nv04_fifo_enable; | 189 | engine->fifo.enable = nv04_fifo_enable; |
184 | engine->fifo.reassign = nv04_fifo_reassign; | 190 | engine->fifo.reassign = nv04_fifo_reassign; |
185 | engine->fifo.cache_flush = nv04_fifo_cache_flush; | ||
186 | engine->fifo.cache_pull = nv04_fifo_cache_pull; | 191 | engine->fifo.cache_pull = nv04_fifo_cache_pull; |
187 | engine->fifo.channel_id = nv10_fifo_channel_id; | 192 | engine->fifo.channel_id = nv10_fifo_channel_id; |
188 | engine->fifo.create_context = nv10_fifo_create_context; | 193 | engine->fifo.create_context = nv10_fifo_create_context; |
@@ -199,6 +204,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
199 | engine->gpio.get = nv10_gpio_get; | 204 | engine->gpio.get = nv10_gpio_get; |
200 | engine->gpio.set = nv10_gpio_set; | 205 | engine->gpio.set = nv10_gpio_set; |
201 | engine->gpio.irq_enable = NULL; | 206 | engine->gpio.irq_enable = NULL; |
207 | engine->pm.clock_get = nv04_pm_clock_get; | ||
208 | engine->pm.clock_pre = nv04_pm_clock_pre; | ||
209 | engine->pm.clock_set = nv04_pm_clock_set; | ||
202 | break; | 210 | break; |
203 | case 0x30: | 211 | case 0x30: |
204 | engine->instmem.init = nv04_instmem_init; | 212 | engine->instmem.init = nv04_instmem_init; |
@@ -234,7 +242,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
234 | engine->fifo.disable = nv04_fifo_disable; | 242 | engine->fifo.disable = nv04_fifo_disable; |
235 | engine->fifo.enable = nv04_fifo_enable; | 243 | engine->fifo.enable = nv04_fifo_enable; |
236 | engine->fifo.reassign = nv04_fifo_reassign; | 244 | engine->fifo.reassign = nv04_fifo_reassign; |
237 | engine->fifo.cache_flush = nv04_fifo_cache_flush; | ||
238 | engine->fifo.cache_pull = nv04_fifo_cache_pull; | 245 | engine->fifo.cache_pull = nv04_fifo_cache_pull; |
239 | engine->fifo.channel_id = nv10_fifo_channel_id; | 246 | engine->fifo.channel_id = nv10_fifo_channel_id; |
240 | engine->fifo.create_context = nv10_fifo_create_context; | 247 | engine->fifo.create_context = nv10_fifo_create_context; |
@@ -251,6 +258,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
251 | engine->gpio.get = nv10_gpio_get; | 258 | engine->gpio.get = nv10_gpio_get; |
252 | engine->gpio.set = nv10_gpio_set; | 259 | engine->gpio.set = nv10_gpio_set; |
253 | engine->gpio.irq_enable = NULL; | 260 | engine->gpio.irq_enable = NULL; |
261 | engine->pm.clock_get = nv04_pm_clock_get; | ||
262 | engine->pm.clock_pre = nv04_pm_clock_pre; | ||
263 | engine->pm.clock_set = nv04_pm_clock_set; | ||
264 | engine->pm.voltage_get = nouveau_voltage_gpio_get; | ||
265 | engine->pm.voltage_set = nouveau_voltage_gpio_set; | ||
254 | break; | 266 | break; |
255 | case 0x40: | 267 | case 0x40: |
256 | case 0x60: | 268 | case 0x60: |
@@ -287,7 +299,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
287 | engine->fifo.disable = nv04_fifo_disable; | 299 | engine->fifo.disable = nv04_fifo_disable; |
288 | engine->fifo.enable = nv04_fifo_enable; | 300 | engine->fifo.enable = nv04_fifo_enable; |
289 | engine->fifo.reassign = nv04_fifo_reassign; | 301 | engine->fifo.reassign = nv04_fifo_reassign; |
290 | engine->fifo.cache_flush = nv04_fifo_cache_flush; | ||
291 | engine->fifo.cache_pull = nv04_fifo_cache_pull; | 302 | engine->fifo.cache_pull = nv04_fifo_cache_pull; |
292 | engine->fifo.channel_id = nv10_fifo_channel_id; | 303 | engine->fifo.channel_id = nv10_fifo_channel_id; |
293 | engine->fifo.create_context = nv40_fifo_create_context; | 304 | engine->fifo.create_context = nv40_fifo_create_context; |
@@ -304,6 +315,12 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
304 | engine->gpio.get = nv10_gpio_get; | 315 | engine->gpio.get = nv10_gpio_get; |
305 | engine->gpio.set = nv10_gpio_set; | 316 | engine->gpio.set = nv10_gpio_set; |
306 | engine->gpio.irq_enable = NULL; | 317 | engine->gpio.irq_enable = NULL; |
318 | engine->pm.clock_get = nv04_pm_clock_get; | ||
319 | engine->pm.clock_pre = nv04_pm_clock_pre; | ||
320 | engine->pm.clock_set = nv04_pm_clock_set; | ||
321 | engine->pm.voltage_get = nouveau_voltage_gpio_get; | ||
322 | engine->pm.voltage_set = nouveau_voltage_gpio_set; | ||
323 | engine->pm.temp_get = nv40_temp_get; | ||
307 | break; | 324 | break; |
308 | case 0x50: | 325 | case 0x50: |
309 | case 0x80: /* gotta love NVIDIA's consistency.. */ | 326 | case 0x80: /* gotta love NVIDIA's consistency.. */ |
@@ -358,6 +375,27 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
358 | engine->gpio.get = nv50_gpio_get; | 375 | engine->gpio.get = nv50_gpio_get; |
359 | engine->gpio.set = nv50_gpio_set; | 376 | engine->gpio.set = nv50_gpio_set; |
360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | 377 | engine->gpio.irq_enable = nv50_gpio_irq_enable; |
378 | switch (dev_priv->chipset) { | ||
379 | case 0xa3: | ||
380 | case 0xa5: | ||
381 | case 0xa8: | ||
382 | case 0xaf: | ||
383 | engine->pm.clock_get = nva3_pm_clock_get; | ||
384 | engine->pm.clock_pre = nva3_pm_clock_pre; | ||
385 | engine->pm.clock_set = nva3_pm_clock_set; | ||
386 | break; | ||
387 | default: | ||
388 | engine->pm.clock_get = nv50_pm_clock_get; | ||
389 | engine->pm.clock_pre = nv50_pm_clock_pre; | ||
390 | engine->pm.clock_set = nv50_pm_clock_set; | ||
391 | break; | ||
392 | } | ||
393 | engine->pm.voltage_get = nouveau_voltage_gpio_get; | ||
394 | engine->pm.voltage_set = nouveau_voltage_gpio_set; | ||
395 | if (dev_priv->chipset >= 0x84) | ||
396 | engine->pm.temp_get = nv84_temp_get; | ||
397 | else | ||
398 | engine->pm.temp_get = nv40_temp_get; | ||
361 | break; | 399 | break; |
362 | case 0xC0: | 400 | case 0xC0: |
363 | engine->instmem.init = nvc0_instmem_init; | 401 | engine->instmem.init = nvc0_instmem_init; |
@@ -437,16 +475,14 @@ static int | |||
437 | nouveau_card_init_channel(struct drm_device *dev) | 475 | nouveau_card_init_channel(struct drm_device *dev) |
438 | { | 476 | { |
439 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 477 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
440 | struct nouveau_gpuobj *gpuobj; | 478 | struct nouveau_gpuobj *gpuobj = NULL; |
441 | int ret; | 479 | int ret; |
442 | 480 | ||
443 | ret = nouveau_channel_alloc(dev, &dev_priv->channel, | 481 | ret = nouveau_channel_alloc(dev, &dev_priv->channel, |
444 | (struct drm_file *)-2, | 482 | (struct drm_file *)-2, NvDmaFB, NvDmaTT); |
445 | NvDmaFB, NvDmaTT); | ||
446 | if (ret) | 483 | if (ret) |
447 | return ret; | 484 | return ret; |
448 | 485 | ||
449 | gpuobj = NULL; | ||
450 | ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, | 486 | ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, |
451 | 0, dev_priv->vram_size, | 487 | 0, dev_priv->vram_size, |
452 | NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, | 488 | NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, |
@@ -454,26 +490,25 @@ nouveau_card_init_channel(struct drm_device *dev) | |||
454 | if (ret) | 490 | if (ret) |
455 | goto out_err; | 491 | goto out_err; |
456 | 492 | ||
457 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, | 493 | ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj); |
458 | gpuobj, NULL); | 494 | nouveau_gpuobj_ref(NULL, &gpuobj); |
459 | if (ret) | 495 | if (ret) |
460 | goto out_err; | 496 | goto out_err; |
461 | 497 | ||
462 | gpuobj = NULL; | ||
463 | ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, | 498 | ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, |
464 | dev_priv->gart_info.aper_size, | 499 | dev_priv->gart_info.aper_size, |
465 | NV_DMA_ACCESS_RW, &gpuobj, NULL); | 500 | NV_DMA_ACCESS_RW, &gpuobj, NULL); |
466 | if (ret) | 501 | if (ret) |
467 | goto out_err; | 502 | goto out_err; |
468 | 503 | ||
469 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, | 504 | ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj); |
470 | gpuobj, NULL); | 505 | nouveau_gpuobj_ref(NULL, &gpuobj); |
471 | if (ret) | 506 | if (ret) |
472 | goto out_err; | 507 | goto out_err; |
473 | 508 | ||
474 | return 0; | 509 | return 0; |
510 | |||
475 | out_err: | 511 | out_err: |
476 | nouveau_gpuobj_del(dev, &gpuobj); | ||
477 | nouveau_channel_free(dev_priv->channel); | 512 | nouveau_channel_free(dev_priv->channel); |
478 | dev_priv->channel = NULL; | 513 | dev_priv->channel = NULL; |
479 | return ret; | 514 | return ret; |
@@ -534,35 +569,28 @@ nouveau_card_init(struct drm_device *dev) | |||
534 | if (ret) | 569 | if (ret) |
535 | goto out_display_early; | 570 | goto out_display_early; |
536 | 571 | ||
537 | ret = nouveau_mem_detect(dev); | 572 | nouveau_pm_init(dev); |
573 | |||
574 | ret = nouveau_mem_vram_init(dev); | ||
538 | if (ret) | 575 | if (ret) |
539 | goto out_bios; | 576 | goto out_bios; |
540 | 577 | ||
541 | ret = nouveau_gpuobj_early_init(dev); | 578 | ret = nouveau_gpuobj_init(dev); |
542 | if (ret) | 579 | if (ret) |
543 | goto out_bios; | 580 | goto out_vram; |
544 | 581 | ||
545 | /* Initialise instance memory, must happen before mem_init so we | ||
546 | * know exactly how much VRAM we're able to use for "normal" | ||
547 | * purposes. | ||
548 | */ | ||
549 | ret = engine->instmem.init(dev); | 582 | ret = engine->instmem.init(dev); |
550 | if (ret) | 583 | if (ret) |
551 | goto out_gpuobj_early; | 584 | goto out_gpuobj; |
552 | 585 | ||
553 | /* Setup the memory manager */ | 586 | ret = nouveau_mem_gart_init(dev); |
554 | ret = nouveau_mem_init(dev); | ||
555 | if (ret) | 587 | if (ret) |
556 | goto out_instmem; | 588 | goto out_instmem; |
557 | 589 | ||
558 | ret = nouveau_gpuobj_init(dev); | ||
559 | if (ret) | ||
560 | goto out_mem; | ||
561 | |||
562 | /* PMC */ | 590 | /* PMC */ |
563 | ret = engine->mc.init(dev); | 591 | ret = engine->mc.init(dev); |
564 | if (ret) | 592 | if (ret) |
565 | goto out_gpuobj; | 593 | goto out_gart; |
566 | 594 | ||
567 | /* PGPIO */ | 595 | /* PGPIO */ |
568 | ret = engine->gpio.init(dev); | 596 | ret = engine->gpio.init(dev); |
@@ -611,9 +639,13 @@ nouveau_card_init(struct drm_device *dev) | |||
611 | /* what about PVIDEO/PCRTC/PRAMDAC etc? */ | 639 | /* what about PVIDEO/PCRTC/PRAMDAC etc? */ |
612 | 640 | ||
613 | if (!engine->graph.accel_blocked) { | 641 | if (!engine->graph.accel_blocked) { |
614 | ret = nouveau_card_init_channel(dev); | 642 | ret = nouveau_fence_init(dev); |
615 | if (ret) | 643 | if (ret) |
616 | goto out_irq; | 644 | goto out_irq; |
645 | |||
646 | ret = nouveau_card_init_channel(dev); | ||
647 | if (ret) | ||
648 | goto out_fence; | ||
617 | } | 649 | } |
618 | 650 | ||
619 | ret = nouveau_backlight_init(dev); | 651 | ret = nouveau_backlight_init(dev); |
@@ -624,6 +656,8 @@ nouveau_card_init(struct drm_device *dev) | |||
624 | drm_kms_helper_poll_init(dev); | 656 | drm_kms_helper_poll_init(dev); |
625 | return 0; | 657 | return 0; |
626 | 658 | ||
659 | out_fence: | ||
660 | nouveau_fence_fini(dev); | ||
627 | out_irq: | 661 | out_irq: |
628 | drm_irq_uninstall(dev); | 662 | drm_irq_uninstall(dev); |
629 | out_display: | 663 | out_display: |
@@ -642,16 +676,16 @@ out_gpio: | |||
642 | engine->gpio.takedown(dev); | 676 | engine->gpio.takedown(dev); |
643 | out_mc: | 677 | out_mc: |
644 | engine->mc.takedown(dev); | 678 | engine->mc.takedown(dev); |
645 | out_gpuobj: | 679 | out_gart: |
646 | nouveau_gpuobj_takedown(dev); | 680 | nouveau_mem_gart_fini(dev); |
647 | out_mem: | ||
648 | nouveau_sgdma_takedown(dev); | ||
649 | nouveau_mem_close(dev); | ||
650 | out_instmem: | 681 | out_instmem: |
651 | engine->instmem.takedown(dev); | 682 | engine->instmem.takedown(dev); |
652 | out_gpuobj_early: | 683 | out_gpuobj: |
653 | nouveau_gpuobj_late_takedown(dev); | 684 | nouveau_gpuobj_takedown(dev); |
685 | out_vram: | ||
686 | nouveau_mem_vram_fini(dev); | ||
654 | out_bios: | 687 | out_bios: |
688 | nouveau_pm_fini(dev); | ||
655 | nouveau_bios_takedown(dev); | 689 | nouveau_bios_takedown(dev); |
656 | out_display_early: | 690 | out_display_early: |
657 | engine->display.late_takedown(dev); | 691 | engine->display.late_takedown(dev); |
@@ -667,7 +701,8 @@ static void nouveau_card_takedown(struct drm_device *dev) | |||
667 | 701 | ||
668 | nouveau_backlight_exit(dev); | 702 | nouveau_backlight_exit(dev); |
669 | 703 | ||
670 | if (dev_priv->channel) { | 704 | if (!engine->graph.accel_blocked) { |
705 | nouveau_fence_fini(dev); | ||
671 | nouveau_channel_free(dev_priv->channel); | 706 | nouveau_channel_free(dev_priv->channel); |
672 | dev_priv->channel = NULL; | 707 | dev_priv->channel = NULL; |
673 | } | 708 | } |
@@ -686,15 +721,15 @@ static void nouveau_card_takedown(struct drm_device *dev) | |||
686 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); | 721 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); |
687 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); | 722 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); |
688 | mutex_unlock(&dev->struct_mutex); | 723 | mutex_unlock(&dev->struct_mutex); |
689 | nouveau_sgdma_takedown(dev); | 724 | nouveau_mem_gart_fini(dev); |
690 | 725 | ||
691 | nouveau_gpuobj_takedown(dev); | ||
692 | nouveau_mem_close(dev); | ||
693 | engine->instmem.takedown(dev); | 726 | engine->instmem.takedown(dev); |
727 | nouveau_gpuobj_takedown(dev); | ||
728 | nouveau_mem_vram_fini(dev); | ||
694 | 729 | ||
695 | drm_irq_uninstall(dev); | 730 | drm_irq_uninstall(dev); |
696 | 731 | ||
697 | nouveau_gpuobj_late_takedown(dev); | 732 | nouveau_pm_fini(dev); |
698 | nouveau_bios_takedown(dev); | 733 | nouveau_bios_takedown(dev); |
699 | 734 | ||
700 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 735 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
@@ -1057,7 +1092,7 @@ bool nouveau_wait_until(struct drm_device *dev, uint64_t timeout, | |||
1057 | /* Waits for PGRAPH to go completely idle */ | 1092 | /* Waits for PGRAPH to go completely idle */ |
1058 | bool nouveau_wait_for_idle(struct drm_device *dev) | 1093 | bool nouveau_wait_for_idle(struct drm_device *dev) |
1059 | { | 1094 | { |
1060 | if (!nv_wait(NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { | 1095 | if (!nv_wait(dev, NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { |
1061 | NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", | 1096 | NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", |
1062 | nv_rd32(dev, NV04_PGRAPH_STATUS)); | 1097 | nv_rd32(dev, NV04_PGRAPH_STATUS)); |
1063 | return false; | 1098 | return false; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c new file mode 100644 index 000000000000..16bbbf1eff63 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * Copyright 2010 PathScale inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Martin Peres | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | static void | ||
31 | nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) | ||
32 | { | ||
33 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
34 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
35 | struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||
36 | struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | ||
37 | int i, headerlen, recordlen, entries; | ||
38 | |||
39 | if (!temp) { | ||
40 | NV_DEBUG(dev, "temperature table pointer invalid\n"); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | /* Set the default sensor's contants */ | ||
45 | sensor->offset_constant = 0; | ||
46 | sensor->offset_mult = 1; | ||
47 | sensor->offset_div = 1; | ||
48 | sensor->slope_mult = 1; | ||
49 | sensor->slope_div = 1; | ||
50 | |||
51 | /* Set the default temperature thresholds */ | ||
52 | temps->critical = 110; | ||
53 | temps->down_clock = 100; | ||
54 | temps->fan_boost = 90; | ||
55 | |||
56 | /* Set the known default values to setup the temperature sensor */ | ||
57 | if (dev_priv->card_type >= NV_40) { | ||
58 | switch (dev_priv->chipset) { | ||
59 | case 0x43: | ||
60 | sensor->offset_mult = 32060; | ||
61 | sensor->offset_div = 1000; | ||
62 | sensor->slope_mult = 792; | ||
63 | sensor->slope_div = 1000; | ||
64 | break; | ||
65 | |||
66 | case 0x44: | ||
67 | case 0x47: | ||
68 | case 0x4a: | ||
69 | sensor->offset_mult = 27839; | ||
70 | sensor->offset_div = 1000; | ||
71 | sensor->slope_mult = 780; | ||
72 | sensor->slope_div = 1000; | ||
73 | break; | ||
74 | |||
75 | case 0x46: | ||
76 | sensor->offset_mult = -24775; | ||
77 | sensor->offset_div = 100; | ||
78 | sensor->slope_mult = 467; | ||
79 | sensor->slope_div = 10000; | ||
80 | break; | ||
81 | |||
82 | case 0x49: | ||
83 | sensor->offset_mult = -25051; | ||
84 | sensor->offset_div = 100; | ||
85 | sensor->slope_mult = 458; | ||
86 | sensor->slope_div = 10000; | ||
87 | break; | ||
88 | |||
89 | case 0x4b: | ||
90 | sensor->offset_mult = -24088; | ||
91 | sensor->offset_div = 100; | ||
92 | sensor->slope_mult = 442; | ||
93 | sensor->slope_div = 10000; | ||
94 | break; | ||
95 | |||
96 | case 0x50: | ||
97 | sensor->offset_mult = -22749; | ||
98 | sensor->offset_div = 100; | ||
99 | sensor->slope_mult = 431; | ||
100 | sensor->slope_div = 10000; | ||
101 | break; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | headerlen = temp[1]; | ||
106 | recordlen = temp[2]; | ||
107 | entries = temp[3]; | ||
108 | temp = temp + headerlen; | ||
109 | |||
110 | /* Read the entries from the table */ | ||
111 | for (i = 0; i < entries; i++) { | ||
112 | u16 value = ROM16(temp[1]); | ||
113 | |||
114 | switch (temp[0]) { | ||
115 | case 0x01: | ||
116 | if ((value & 0x8f) == 0) | ||
117 | sensor->offset_constant = (value >> 9) & 0x7f; | ||
118 | break; | ||
119 | |||
120 | case 0x04: | ||
121 | if ((value & 0xf00f) == 0xa000) /* core */ | ||
122 | temps->critical = (value&0x0ff0) >> 4; | ||
123 | break; | ||
124 | |||
125 | case 0x07: | ||
126 | if ((value & 0xf00f) == 0xa000) /* core */ | ||
127 | temps->down_clock = (value&0x0ff0) >> 4; | ||
128 | break; | ||
129 | |||
130 | case 0x08: | ||
131 | if ((value & 0xf00f) == 0xa000) /* core */ | ||
132 | temps->fan_boost = (value&0x0ff0) >> 4; | ||
133 | break; | ||
134 | |||
135 | case 0x10: | ||
136 | sensor->offset_mult = value; | ||
137 | break; | ||
138 | |||
139 | case 0x11: | ||
140 | sensor->offset_div = value; | ||
141 | break; | ||
142 | |||
143 | case 0x12: | ||
144 | sensor->slope_mult = value; | ||
145 | break; | ||
146 | |||
147 | case 0x13: | ||
148 | sensor->slope_div = value; | ||
149 | break; | ||
150 | } | ||
151 | temp += recordlen; | ||
152 | } | ||
153 | |||
154 | nouveau_temp_safety_checks(dev); | ||
155 | } | ||
156 | |||
157 | static int | ||
158 | nv40_sensor_setup(struct drm_device *dev) | ||
159 | { | ||
160 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
161 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
162 | struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||
163 | u32 offset = sensor->offset_mult / sensor->offset_div; | ||
164 | u32 sensor_calibration; | ||
165 | |||
166 | /* set up the sensors */ | ||
167 | sensor_calibration = 120 - offset - sensor->offset_constant; | ||
168 | sensor_calibration = sensor_calibration * sensor->slope_div / | ||
169 | sensor->slope_mult; | ||
170 | |||
171 | if (dev_priv->chipset >= 0x46) | ||
172 | sensor_calibration |= 0x80000000; | ||
173 | else | ||
174 | sensor_calibration |= 0x10000000; | ||
175 | |||
176 | nv_wr32(dev, 0x0015b0, sensor_calibration); | ||
177 | |||
178 | /* Wait for the sensor to update */ | ||
179 | msleep(5); | ||
180 | |||
181 | /* read */ | ||
182 | return nv_rd32(dev, 0x0015b4) & 0x1fff; | ||
183 | } | ||
184 | |||
185 | int | ||
186 | nv40_temp_get(struct drm_device *dev) | ||
187 | { | ||
188 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
189 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
190 | struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||
191 | int offset = sensor->offset_mult / sensor->offset_div; | ||
192 | int core_temp; | ||
193 | |||
194 | if (dev_priv->chipset >= 0x50) { | ||
195 | core_temp = nv_rd32(dev, 0x20008); | ||
196 | } else { | ||
197 | core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; | ||
198 | /* Setup the sensor if the temperature is 0 */ | ||
199 | if (core_temp == 0) | ||
200 | core_temp = nv40_sensor_setup(dev); | ||
201 | } | ||
202 | |||
203 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; | ||
204 | core_temp = core_temp + offset + sensor->offset_constant; | ||
205 | |||
206 | return core_temp; | ||
207 | } | ||
208 | |||
209 | int | ||
210 | nv84_temp_get(struct drm_device *dev) | ||
211 | { | ||
212 | return nv_rd32(dev, 0x20400); | ||
213 | } | ||
214 | |||
215 | void | ||
216 | nouveau_temp_safety_checks(struct drm_device *dev) | ||
217 | { | ||
218 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
219 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
220 | struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | ||
221 | |||
222 | if (temps->critical > 120) | ||
223 | temps->critical = 120; | ||
224 | else if (temps->critical < 80) | ||
225 | temps->critical = 80; | ||
226 | |||
227 | if (temps->down_clock > 110) | ||
228 | temps->down_clock = 110; | ||
229 | else if (temps->down_clock < 60) | ||
230 | temps->down_clock = 60; | ||
231 | |||
232 | if (temps->fan_boost > 100) | ||
233 | temps->fan_boost = 100; | ||
234 | else if (temps->fan_boost < 40) | ||
235 | temps->fan_boost = 40; | ||
236 | } | ||
237 | |||
238 | static bool | ||
239 | probe_monitoring_device(struct nouveau_i2c_chan *i2c, | ||
240 | struct i2c_board_info *info) | ||
241 | { | ||
242 | char modalias[16] = "i2c:"; | ||
243 | struct i2c_client *client; | ||
244 | |||
245 | strlcat(modalias, info->type, sizeof(modalias)); | ||
246 | request_module(modalias); | ||
247 | |||
248 | client = i2c_new_device(&i2c->adapter, info); | ||
249 | if (!client) | ||
250 | return false; | ||
251 | |||
252 | if (!client->driver || client->driver->detect(client, info)) { | ||
253 | i2c_unregister_device(client); | ||
254 | return false; | ||
255 | } | ||
256 | |||
257 | return true; | ||
258 | } | ||
259 | |||
260 | static void | ||
261 | nouveau_temp_probe_i2c(struct drm_device *dev) | ||
262 | { | ||
263 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
264 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | ||
265 | struct i2c_board_info info[] = { | ||
266 | { I2C_BOARD_INFO("w83l785ts", 0x2d) }, | ||
267 | { I2C_BOARD_INFO("w83781d", 0x2d) }, | ||
268 | { I2C_BOARD_INFO("f75375", 0x2e) }, | ||
269 | { I2C_BOARD_INFO("adt7473", 0x2e) }, | ||
270 | { I2C_BOARD_INFO("lm99", 0x4c) }, | ||
271 | { } | ||
272 | }; | ||
273 | int idx = (dcb->version >= 0x40 ? | ||
274 | dcb->i2c_default_indices & 0xf : 2); | ||
275 | |||
276 | nouveau_i2c_identify(dev, "monitoring device", info, | ||
277 | probe_monitoring_device, idx); | ||
278 | } | ||
279 | |||
280 | void | ||
281 | nouveau_temp_init(struct drm_device *dev) | ||
282 | { | ||
283 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
284 | struct nvbios *bios = &dev_priv->vbios; | ||
285 | struct bit_entry P; | ||
286 | u8 *temp = NULL; | ||
287 | |||
288 | if (bios->type == NVBIOS_BIT) { | ||
289 | if (bit_table(dev, 'P', &P)) | ||
290 | return; | ||
291 | |||
292 | if (P.version == 1) | ||
293 | temp = ROMPTR(bios, P.data[12]); | ||
294 | else if (P.version == 2) | ||
295 | temp = ROMPTR(bios, P.data[16]); | ||
296 | else | ||
297 | NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); | ||
298 | |||
299 | nouveau_temp_vbios_parse(dev, temp); | ||
300 | } | ||
301 | |||
302 | nouveau_temp_probe_i2c(dev); | ||
303 | } | ||
304 | |||
305 | void | ||
306 | nouveau_temp_fini(struct drm_device *dev) | ||
307 | { | ||
308 | |||
309 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c new file mode 100644 index 000000000000..04fdc00a67d5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_volt.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; | ||
31 | static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); | ||
32 | |||
33 | int | ||
34 | nouveau_voltage_gpio_get(struct drm_device *dev) | ||
35 | { | ||
36 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
37 | struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; | ||
38 | struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | ||
39 | u8 vid = 0; | ||
40 | int i; | ||
41 | |||
42 | for (i = 0; i < nr_vidtag; i++) { | ||
43 | if (!(volt->vid_mask & (1 << i))) | ||
44 | continue; | ||
45 | |||
46 | vid |= gpio->get(dev, vidtag[i]) << i; | ||
47 | } | ||
48 | |||
49 | return nouveau_volt_lvl_lookup(dev, vid); | ||
50 | } | ||
51 | |||
52 | int | ||
53 | nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) | ||
54 | { | ||
55 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
56 | struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; | ||
57 | struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | ||
58 | int vid, i; | ||
59 | |||
60 | vid = nouveau_volt_vid_lookup(dev, voltage); | ||
61 | if (vid < 0) | ||
62 | return vid; | ||
63 | |||
64 | for (i = 0; i < nr_vidtag; i++) { | ||
65 | if (!(volt->vid_mask & (1 << i))) | ||
66 | continue; | ||
67 | |||
68 | gpio->set(dev, vidtag[i], !!(vid & (1 << i))); | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | int | ||
75 | nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) | ||
76 | { | ||
77 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
78 | struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | ||
79 | int i; | ||
80 | |||
81 | for (i = 0; i < volt->nr_level; i++) { | ||
82 | if (volt->level[i].voltage == voltage) | ||
83 | return volt->level[i].vid; | ||
84 | } | ||
85 | |||
86 | return -ENOENT; | ||
87 | } | ||
88 | |||
89 | int | ||
90 | nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) | ||
91 | { | ||
92 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
93 | struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; i < volt->nr_level; i++) { | ||
97 | if (volt->level[i].vid == vid) | ||
98 | return volt->level[i].voltage; | ||
99 | } | ||
100 | |||
101 | return -ENOENT; | ||
102 | } | ||
103 | |||
104 | void | ||
105 | nouveau_volt_init(struct drm_device *dev) | ||
106 | { | ||
107 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
108 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | ||
109 | struct nouveau_pm_voltage *voltage = &pm->voltage; | ||
110 | struct nvbios *bios = &dev_priv->vbios; | ||
111 | struct bit_entry P; | ||
112 | u8 *volt = NULL, *entry; | ||
113 | int i, headerlen, recordlen, entries, vidmask, vidshift; | ||
114 | |||
115 | if (bios->type == NVBIOS_BIT) { | ||
116 | if (bit_table(dev, 'P', &P)) | ||
117 | return; | ||
118 | |||
119 | if (P.version == 1) | ||
120 | volt = ROMPTR(bios, P.data[16]); | ||
121 | else | ||
122 | if (P.version == 2) | ||
123 | volt = ROMPTR(bios, P.data[12]); | ||
124 | else { | ||
125 | NV_WARN(dev, "unknown volt for BIT P %d\n", P.version); | ||
126 | } | ||
127 | } else { | ||
128 | if (bios->data[bios->offset + 6] < 0x27) { | ||
129 | NV_DEBUG(dev, "BMP version too old for voltage\n"); | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | volt = ROMPTR(bios, bios->data[bios->offset + 0x98]); | ||
134 | } | ||
135 | |||
136 | if (!volt) { | ||
137 | NV_DEBUG(dev, "voltage table pointer invalid\n"); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | switch (volt[0]) { | ||
142 | case 0x10: | ||
143 | case 0x11: | ||
144 | case 0x12: | ||
145 | headerlen = 5; | ||
146 | recordlen = volt[1]; | ||
147 | entries = volt[2]; | ||
148 | vidshift = 0; | ||
149 | vidmask = volt[4]; | ||
150 | break; | ||
151 | case 0x20: | ||
152 | headerlen = volt[1]; | ||
153 | recordlen = volt[3]; | ||
154 | entries = volt[2]; | ||
155 | vidshift = 0; /* could be vidshift like 0x30? */ | ||
156 | vidmask = volt[5]; | ||
157 | break; | ||
158 | case 0x30: | ||
159 | headerlen = volt[1]; | ||
160 | recordlen = volt[2]; | ||
161 | entries = volt[3]; | ||
162 | vidshift = hweight8(volt[5]); | ||
163 | vidmask = volt[4]; | ||
164 | break; | ||
165 | default: | ||
166 | NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | /* validate vid mask */ | ||
171 | voltage->vid_mask = vidmask; | ||
172 | if (!voltage->vid_mask) | ||
173 | return; | ||
174 | |||
175 | i = 0; | ||
176 | while (vidmask) { | ||
177 | if (i > nr_vidtag) { | ||
178 | NV_DEBUG(dev, "vid bit %d unknown\n", i); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | if (!nouveau_bios_gpio_entry(dev, vidtag[i])) { | ||
183 | NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | vidmask >>= 1; | ||
188 | i++; | ||
189 | } | ||
190 | |||
191 | /* parse vbios entries into common format */ | ||
192 | voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); | ||
193 | if (!voltage->level) | ||
194 | return; | ||
195 | |||
196 | entry = volt + headerlen; | ||
197 | for (i = 0; i < entries; i++, entry += recordlen) { | ||
198 | voltage->level[i].voltage = entry[0]; | ||
199 | voltage->level[i].vid = entry[1] >> vidshift; | ||
200 | } | ||
201 | voltage->nr_level = entries; | ||
202 | voltage->supported = true; | ||
203 | } | ||
204 | |||
205 | void | ||
206 | nouveau_volt_fini(struct drm_device *dev) | ||
207 | { | ||
208 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
209 | struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | ||
210 | |||
211 | kfree(volt->level); | ||
212 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 497df8765f28..17f7cf0c11a8 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "nouveau_fb.h" | 33 | #include "nouveau_fb.h" |
34 | #include "nouveau_hw.h" | 34 | #include "nouveau_hw.h" |
35 | #include "nvreg.h" | 35 | #include "nvreg.h" |
36 | #include "nouveau_fbcon.h" | ||
36 | 37 | ||
37 | static int | 38 | static int |
38 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 39 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
@@ -109,7 +110,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod | |||
109 | struct nouveau_pll_vals *pv = ®p->pllvals; | 110 | struct nouveau_pll_vals *pv = ®p->pllvals; |
110 | struct pll_lims pll_lim; | 111 | struct pll_lims pll_lim; |
111 | 112 | ||
112 | if (get_pll_limits(dev, nv_crtc->index ? VPLL2 : VPLL1, &pll_lim)) | 113 | if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) |
113 | return; | 114 | return; |
114 | 115 | ||
115 | /* NM2 == 0 is used to determine single stage mode on two stage plls */ | 116 | /* NM2 == 0 is used to determine single stage mode on two stage plls */ |
@@ -718,6 +719,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) | |||
718 | 719 | ||
719 | drm_crtc_cleanup(crtc); | 720 | drm_crtc_cleanup(crtc); |
720 | 721 | ||
722 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); | ||
721 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); | 723 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); |
722 | kfree(nv_crtc); | 724 | kfree(nv_crtc); |
723 | } | 725 | } |
@@ -768,8 +770,9 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, | |||
768 | } | 770 | } |
769 | 771 | ||
770 | static int | 772 | static int |
771 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 773 | nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, |
772 | struct drm_framebuffer *old_fb) | 774 | struct drm_framebuffer *passed_fb, |
775 | int x, int y, bool atomic) | ||
773 | { | 776 | { |
774 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 777 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
775 | struct drm_device *dev = crtc->dev; | 778 | struct drm_device *dev = crtc->dev; |
@@ -780,13 +783,26 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
780 | int arb_burst, arb_lwm; | 783 | int arb_burst, arb_lwm; |
781 | int ret; | 784 | int ret; |
782 | 785 | ||
783 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | 786 | /* If atomic, we want to switch to the fb we were passed, so |
784 | if (ret) | 787 | * now we update pointers to do that. (We don't pin; just |
785 | return ret; | 788 | * assume we're already pinned and update the base address.) |
789 | */ | ||
790 | if (atomic) { | ||
791 | drm_fb = passed_fb; | ||
792 | fb = nouveau_framebuffer(passed_fb); | ||
793 | } | ||
794 | else { | ||
795 | /* If not atomic, we can go ahead and pin, and unpin the | ||
796 | * old fb we were passed. | ||
797 | */ | ||
798 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | ||
799 | if (ret) | ||
800 | return ret; | ||
786 | 801 | ||
787 | if (old_fb) { | 802 | if (passed_fb) { |
788 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb); | 803 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); |
789 | nouveau_bo_unpin(ofb->nvbo); | 804 | nouveau_bo_unpin(ofb->nvbo); |
805 | } | ||
790 | } | 806 | } |
791 | 807 | ||
792 | nv_crtc->fb.offset = fb->nvbo->bo.offset; | 808 | nv_crtc->fb.offset = fb->nvbo->bo.offset; |
@@ -826,7 +842,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
826 | crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); | 842 | crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); |
827 | crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); | 843 | crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); |
828 | 844 | ||
829 | if (dev_priv->card_type >= NV_30) { | 845 | if (dev_priv->card_type >= NV_20) { |
830 | regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; | 846 | regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; |
831 | crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); | 847 | crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); |
832 | } | 848 | } |
@@ -834,6 +850,29 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
834 | return 0; | 850 | return 0; |
835 | } | 851 | } |
836 | 852 | ||
853 | static int | ||
854 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | ||
855 | struct drm_framebuffer *old_fb) | ||
856 | { | ||
857 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); | ||
858 | } | ||
859 | |||
860 | static int | ||
861 | nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, | ||
862 | struct drm_framebuffer *fb, | ||
863 | int x, int y, int enter) | ||
864 | { | ||
865 | struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; | ||
866 | struct drm_device *dev = dev_priv->dev; | ||
867 | |||
868 | if (enter) | ||
869 | nouveau_fbcon_save_disable_accel(dev); | ||
870 | else | ||
871 | nouveau_fbcon_restore_accel(dev); | ||
872 | |||
873 | return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); | ||
874 | } | ||
875 | |||
837 | static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, | 876 | static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, |
838 | struct nouveau_bo *dst) | 877 | struct nouveau_bo *dst) |
839 | { | 878 | { |
@@ -962,6 +1001,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { | |||
962 | .mode_fixup = nv_crtc_mode_fixup, | 1001 | .mode_fixup = nv_crtc_mode_fixup, |
963 | .mode_set = nv_crtc_mode_set, | 1002 | .mode_set = nv_crtc_mode_set, |
964 | .mode_set_base = nv04_crtc_mode_set_base, | 1003 | .mode_set_base = nv04_crtc_mode_set_base, |
1004 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, | ||
965 | .load_lut = nv_crtc_gamma_load, | 1005 | .load_lut = nv_crtc_gamma_load, |
966 | }; | 1006 | }; |
967 | 1007 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index ea3627041ecf..ba6423f2ffcc 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c | |||
@@ -291,6 +291,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | |||
291 | msleep(5); | 291 | msleep(5); |
292 | 292 | ||
293 | sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); | 293 | sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); |
294 | /* do it again just in case it's a residual current */ | ||
295 | sample &= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); | ||
294 | 296 | ||
295 | temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); | 297 | temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); |
296 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, | 298 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, |
@@ -343,22 +345,13 @@ static void nv04_dac_prepare(struct drm_encoder *encoder) | |||
343 | { | 345 | { |
344 | struct drm_encoder_helper_funcs *helper = encoder->helper_private; | 346 | struct drm_encoder_helper_funcs *helper = encoder->helper_private; |
345 | struct drm_device *dev = encoder->dev; | 347 | struct drm_device *dev = encoder->dev; |
346 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
347 | int head = nouveau_crtc(encoder->crtc)->index; | 348 | int head = nouveau_crtc(encoder->crtc)->index; |
348 | struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg; | ||
349 | 349 | ||
350 | helper->dpms(encoder, DRM_MODE_DPMS_OFF); | 350 | helper->dpms(encoder, DRM_MODE_DPMS_OFF); |
351 | 351 | ||
352 | nv04_dfp_disable(dev, head); | 352 | nv04_dfp_disable(dev, head); |
353 | |||
354 | /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) | ||
355 | * at LCD__INDEX which we don't alter | ||
356 | */ | ||
357 | if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44)) | ||
358 | crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0; | ||
359 | } | 353 | } |
360 | 354 | ||
361 | |||
362 | static void nv04_dac_mode_set(struct drm_encoder *encoder, | 355 | static void nv04_dac_mode_set(struct drm_encoder *encoder, |
363 | struct drm_display_mode *mode, | 356 | struct drm_display_mode *mode, |
364 | struct drm_display_mode *adjusted_mode) | 357 | struct drm_display_mode *adjusted_mode) |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 0d3206a7046c..c936403b26e2 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -104,6 +104,8 @@ void nv04_dfp_disable(struct drm_device *dev, int head) | |||
104 | } | 104 | } |
105 | /* don't inadvertently turn it on when state written later */ | 105 | /* don't inadvertently turn it on when state written later */ |
106 | crtcstate[head].fp_control = FP_TG_CONTROL_OFF; | 106 | crtcstate[head].fp_control = FP_TG_CONTROL_OFF; |
107 | crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] &= | ||
108 | ~NV_CIO_CRE_LCD_ROUTE_MASK; | ||
107 | } | 109 | } |
108 | 110 | ||
109 | void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) | 111 | void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) |
@@ -253,26 +255,21 @@ static void nv04_dfp_prepare(struct drm_encoder *encoder) | |||
253 | 255 | ||
254 | nv04_dfp_prepare_sel_clk(dev, nv_encoder, head); | 256 | nv04_dfp_prepare_sel_clk(dev, nv_encoder, head); |
255 | 257 | ||
256 | /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) | 258 | *cr_lcd = (*cr_lcd & ~NV_CIO_CRE_LCD_ROUTE_MASK) | 0x3; |
257 | * at LCD__INDEX which we don't alter | 259 | |
258 | */ | 260 | if (nv_two_heads(dev)) { |
259 | if (!(*cr_lcd & 0x44)) { | 261 | if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) |
260 | *cr_lcd = 0x3; | 262 | *cr_lcd |= head ? 0x0 : 0x8; |
261 | 263 | else { | |
262 | if (nv_two_heads(dev)) { | 264 | *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; |
263 | if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) | 265 | if (nv_encoder->dcb->type == OUTPUT_LVDS) |
264 | *cr_lcd |= head ? 0x0 : 0x8; | 266 | *cr_lcd |= 0x30; |
265 | else { | 267 | if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { |
266 | *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; | 268 | /* avoid being connected to both crtcs */ |
267 | if (nv_encoder->dcb->type == OUTPUT_LVDS) | 269 | *cr_lcd_oth &= ~0x30; |
268 | *cr_lcd |= 0x30; | 270 | NVWriteVgaCrtc(dev, head ^ 1, |
269 | if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { | 271 | NV_CIO_CRE_LCD__INDEX, |
270 | /* avoid being connected to both crtcs */ | 272 | *cr_lcd_oth); |
271 | *cr_lcd_oth &= ~0x30; | ||
272 | NVWriteVgaCrtc(dev, head ^ 1, | ||
273 | NV_CIO_CRE_LCD__INDEX, | ||
274 | *cr_lcd_oth); | ||
275 | } | ||
276 | } | 273 | } |
277 | } | 274 | } |
278 | } | 275 | } |
@@ -640,7 +637,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) | |||
640 | get_tmds_slave(encoder)) | 637 | get_tmds_slave(encoder)) |
641 | return; | 638 | return; |
642 | 639 | ||
643 | type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); | 640 | type = nouveau_i2c_identify(dev, "TMDS transmitter", info, NULL, 2); |
644 | if (type < 0) | 641 | if (type < 0) |
645 | return; | 642 | return; |
646 | 643 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 1eeac4fae73d..33e4c9388bc1 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "drmP.h" | 25 | #include "drmP.h" |
26 | #include "nouveau_drv.h" | 26 | #include "nouveau_drv.h" |
27 | #include "nouveau_dma.h" | 27 | #include "nouveau_dma.h" |
28 | #include "nouveau_ramht.h" | ||
28 | #include "nouveau_fbcon.h" | 29 | #include "nouveau_fbcon.h" |
29 | 30 | ||
30 | void | 31 | void |
@@ -169,11 +170,9 @@ nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle) | |||
169 | if (ret) | 170 | if (ret) |
170 | return ret; | 171 | return ret; |
171 | 172 | ||
172 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, handle, obj, NULL); | 173 | ret = nouveau_ramht_insert(dev_priv->channel, handle, obj); |
173 | if (ret) | 174 | nouveau_gpuobj_ref(NULL, &obj); |
174 | return ret; | 175 | return ret; |
175 | |||
176 | return 0; | ||
177 | } | 176 | } |
178 | 177 | ||
179 | int | 178 | int |
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index 06cedd99c26a..708293b7ddcd 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c | |||
@@ -27,8 +27,9 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
30 | #include "nouveau_ramht.h" | ||
30 | 31 | ||
31 | #define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE)) | 32 | #define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE)) |
32 | #define NV04_RAMFC__SIZE 32 | 33 | #define NV04_RAMFC__SIZE 32 |
33 | #define NV04_RAMFC_DMA_PUT 0x00 | 34 | #define NV04_RAMFC_DMA_PUT 0x00 |
34 | #define NV04_RAMFC_DMA_GET 0x04 | 35 | #define NV04_RAMFC_DMA_GET 0x04 |
@@ -38,10 +39,8 @@ | |||
38 | #define NV04_RAMFC_ENGINE 0x14 | 39 | #define NV04_RAMFC_ENGINE 0x14 |
39 | #define NV04_RAMFC_PULL1_ENGINE 0x18 | 40 | #define NV04_RAMFC_PULL1_ENGINE 0x18 |
40 | 41 | ||
41 | #define RAMFC_WR(offset, val) nv_wo32(dev, chan->ramfc->gpuobj, \ | 42 | #define RAMFC_WR(offset, val) nv_wo32(chan->ramfc, NV04_RAMFC_##offset, (val)) |
42 | NV04_RAMFC_##offset/4, (val)) | 43 | #define RAMFC_RD(offset) nv_ro32(chan->ramfc, NV04_RAMFC_##offset) |
43 | #define RAMFC_RD(offset) nv_ro32(dev, chan->ramfc->gpuobj, \ | ||
44 | NV04_RAMFC_##offset/4) | ||
45 | 44 | ||
46 | void | 45 | void |
47 | nv04_fifo_disable(struct drm_device *dev) | 46 | nv04_fifo_disable(struct drm_device *dev) |
@@ -72,37 +71,32 @@ nv04_fifo_reassign(struct drm_device *dev, bool enable) | |||
72 | } | 71 | } |
73 | 72 | ||
74 | bool | 73 | bool |
75 | nv04_fifo_cache_flush(struct drm_device *dev) | ||
76 | { | ||
77 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
78 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | ||
79 | uint64_t start = ptimer->read(dev); | ||
80 | |||
81 | do { | ||
82 | if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) == | ||
83 | nv_rd32(dev, NV03_PFIFO_CACHE1_PUT)) | ||
84 | return true; | ||
85 | |||
86 | } while (ptimer->read(dev) - start < 100000000); | ||
87 | |||
88 | NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n"); | ||
89 | |||
90 | return false; | ||
91 | } | ||
92 | |||
93 | bool | ||
94 | nv04_fifo_cache_pull(struct drm_device *dev, bool enable) | 74 | nv04_fifo_cache_pull(struct drm_device *dev, bool enable) |
95 | { | 75 | { |
96 | uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0); | 76 | int pull = nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 1, enable); |
77 | |||
78 | if (!enable) { | ||
79 | /* In some cases the PFIFO puller may be left in an | ||
80 | * inconsistent state if you try to stop it when it's | ||
81 | * busy translating handles. Sometimes you get a | ||
82 | * PFIFO_CACHE_ERROR, sometimes it just fails silently | ||
83 | * sending incorrect instance offsets to PGRAPH after | ||
84 | * it's started up again. To avoid the latter we | ||
85 | * invalidate the most recently calculated instance. | ||
86 | */ | ||
87 | if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0, | ||
88 | NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0)) | ||
89 | NV_ERROR(dev, "Timeout idling the PFIFO puller.\n"); | ||
90 | |||
91 | if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) & | ||
92 | NV04_PFIFO_CACHE1_PULL0_HASH_FAILED) | ||
93 | nv_wr32(dev, NV03_PFIFO_INTR_0, | ||
94 | NV_PFIFO_INTR_CACHE_ERROR); | ||
97 | 95 | ||
98 | if (enable) { | ||
99 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1); | ||
100 | } else { | ||
101 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1); | ||
102 | nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); | 96 | nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); |
103 | } | 97 | } |
104 | 98 | ||
105 | return !!(pull & 1); | 99 | return pull & 1; |
106 | } | 100 | } |
107 | 101 | ||
108 | int | 102 | int |
@@ -130,7 +124,7 @@ nv04_fifo_create_context(struct nouveau_channel *chan) | |||
130 | NV04_RAMFC__SIZE, | 124 | NV04_RAMFC__SIZE, |
131 | NVOBJ_FLAG_ZERO_ALLOC | | 125 | NVOBJ_FLAG_ZERO_ALLOC | |
132 | NVOBJ_FLAG_ZERO_FREE, | 126 | NVOBJ_FLAG_ZERO_FREE, |
133 | NULL, &chan->ramfc); | 127 | &chan->ramfc); |
134 | if (ret) | 128 | if (ret) |
135 | return ret; | 129 | return ret; |
136 | 130 | ||
@@ -139,7 +133,7 @@ nv04_fifo_create_context(struct nouveau_channel *chan) | |||
139 | /* Setup initial state */ | 133 | /* Setup initial state */ |
140 | RAMFC_WR(DMA_PUT, chan->pushbuf_base); | 134 | RAMFC_WR(DMA_PUT, chan->pushbuf_base); |
141 | RAMFC_WR(DMA_GET, chan->pushbuf_base); | 135 | RAMFC_WR(DMA_GET, chan->pushbuf_base); |
142 | RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); | 136 | RAMFC_WR(DMA_INSTANCE, chan->pushbuf->pinst >> 4); |
143 | RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | | 137 | RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | |
144 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | | 138 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | |
145 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | | 139 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | |
@@ -161,7 +155,7 @@ nv04_fifo_destroy_context(struct nouveau_channel *chan) | |||
161 | nv_wr32(dev, NV04_PFIFO_MODE, | 155 | nv_wr32(dev, NV04_PFIFO_MODE, |
162 | nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); | 156 | nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); |
163 | 157 | ||
164 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | 158 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
165 | } | 159 | } |
166 | 160 | ||
167 | static void | 161 | static void |
@@ -264,10 +258,10 @@ nv04_fifo_init_ramxx(struct drm_device *dev) | |||
264 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 258 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
265 | 259 | ||
266 | nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | | 260 | nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | |
267 | ((dev_priv->ramht_bits - 9) << 16) | | 261 | ((dev_priv->ramht->bits - 9) << 16) | |
268 | (dev_priv->ramht_offset >> 8)); | 262 | (dev_priv->ramht->gpuobj->pinst >> 8)); |
269 | nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); | 263 | nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); |
270 | nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8); | 264 | nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); |
271 | } | 265 | } |
272 | 266 | ||
273 | static void | 267 | static void |
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index 4408232d33f1..0b5ae297abde 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "drmP.h" | 1 | #include "drmP.h" |
2 | #include "drm.h" | 2 | #include "drm.h" |
3 | #include "nouveau_drv.h" | 3 | #include "nouveau_drv.h" |
4 | #include "nouveau_ramht.h" | ||
4 | 5 | ||
5 | /* returns the size of fifo context */ | 6 | /* returns the size of fifo context */ |
6 | static int | 7 | static int |
@@ -17,102 +18,51 @@ nouveau_fifo_ctx_size(struct drm_device *dev) | |||
17 | return 32; | 18 | return 32; |
18 | } | 19 | } |
19 | 20 | ||
20 | static void | 21 | int nv04_instmem_init(struct drm_device *dev) |
21 | nv04_instmem_determine_amount(struct drm_device *dev) | ||
22 | { | 22 | { |
23 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 23 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
24 | int i; | 24 | struct nouveau_gpuobj *ramht = NULL; |
25 | u32 offset, length; | ||
26 | int ret; | ||
25 | 27 | ||
26 | /* Figure out how much instance memory we need */ | 28 | /* RAMIN always available */ |
27 | if (dev_priv->card_type >= NV_40) { | 29 | dev_priv->ramin_available = true; |
28 | /* We'll want more instance memory than this on some NV4x cards. | ||
29 | * There's a 16MB aperture to play with that maps onto the end | ||
30 | * of vram. For now, only reserve a small piece until we know | ||
31 | * more about what each chipset requires. | ||
32 | */ | ||
33 | switch (dev_priv->chipset) { | ||
34 | case 0x40: | ||
35 | case 0x47: | ||
36 | case 0x49: | ||
37 | case 0x4b: | ||
38 | dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); | ||
39 | break; | ||
40 | default: | ||
41 | dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); | ||
42 | break; | ||
43 | } | ||
44 | } else { | ||
45 | /*XXX: what *are* the limits on <NV40 cards? | ||
46 | */ | ||
47 | dev_priv->ramin_rsvd_vram = (512 * 1024); | ||
48 | } | ||
49 | NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); | ||
50 | 30 | ||
51 | /* Clear all of it, except the BIOS image that's in the first 64KiB */ | 31 | /* Setup shared RAMHT */ |
52 | for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) | 32 | ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, |
53 | nv_wi32(dev, i, 0x00000000); | 33 | NVOBJ_FLAG_ZERO_ALLOC, &ramht); |
54 | } | 34 | if (ret) |
35 | return ret; | ||
55 | 36 | ||
56 | static void | 37 | ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); |
57 | nv04_instmem_configure_fixed_tables(struct drm_device *dev) | 38 | nouveau_gpuobj_ref(NULL, &ramht); |
58 | { | 39 | if (ret) |
59 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 40 | return ret; |
60 | struct nouveau_engine *engine = &dev_priv->engine; | ||
61 | 41 | ||
62 | /* FIFO hash table (RAMHT) | 42 | /* And RAMRO */ |
63 | * use 4k hash table at RAMIN+0x10000 | 43 | ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, |
64 | * TODO: extend the hash table | 44 | NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); |
65 | */ | 45 | if (ret) |
66 | dev_priv->ramht_offset = 0x10000; | 46 | return ret; |
67 | dev_priv->ramht_bits = 9; | 47 | |
68 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits); /* nr entries */ | 48 | /* And RAMFC */ |
69 | dev_priv->ramht_size *= 8; /* 2 32-bit values per entry in RAMHT */ | 49 | length = dev_priv->engine.fifo.channels * nouveau_fifo_ctx_size(dev); |
70 | NV_DEBUG(dev, "RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset, | ||
71 | dev_priv->ramht_size); | ||
72 | |||
73 | /* FIFO runout table (RAMRO) - 512k at 0x11200 */ | ||
74 | dev_priv->ramro_offset = 0x11200; | ||
75 | dev_priv->ramro_size = 512; | ||
76 | NV_DEBUG(dev, "RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset, | ||
77 | dev_priv->ramro_size); | ||
78 | |||
79 | /* FIFO context table (RAMFC) | ||
80 | * NV40 : Not sure exactly how to position RAMFC on some cards, | ||
81 | * 0x30002 seems to position it at RAMIN+0x20000 on these | ||
82 | * cards. RAMFC is 4kb (32 fifos, 128byte entries). | ||
83 | * Others: Position RAMFC at RAMIN+0x11400 | ||
84 | */ | ||
85 | dev_priv->ramfc_size = engine->fifo.channels * | ||
86 | nouveau_fifo_ctx_size(dev); | ||
87 | switch (dev_priv->card_type) { | 50 | switch (dev_priv->card_type) { |
88 | case NV_40: | 51 | case NV_40: |
89 | dev_priv->ramfc_offset = 0x20000; | 52 | offset = 0x20000; |
90 | break; | 53 | break; |
91 | case NV_30: | ||
92 | case NV_20: | ||
93 | case NV_10: | ||
94 | case NV_04: | ||
95 | default: | 54 | default: |
96 | dev_priv->ramfc_offset = 0x11400; | 55 | offset = 0x11400; |
97 | break; | 56 | break; |
98 | } | 57 | } |
99 | NV_DEBUG(dev, "RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, | ||
100 | dev_priv->ramfc_size); | ||
101 | } | ||
102 | 58 | ||
103 | int nv04_instmem_init(struct drm_device *dev) | 59 | ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, |
104 | { | 60 | NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); |
105 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 61 | if (ret) |
106 | uint32_t offset; | 62 | return ret; |
107 | int ret; | ||
108 | |||
109 | nv04_instmem_determine_amount(dev); | ||
110 | nv04_instmem_configure_fixed_tables(dev); | ||
111 | 63 | ||
112 | /* Create a heap to manage RAMIN allocations, we don't allocate | 64 | /* Only allow space after RAMFC to be used for object allocation */ |
113 | * the space that was reserved for RAMHT/FC/RO. | 65 | offset += length; |
114 | */ | ||
115 | offset = dev_priv->ramfc_offset + dev_priv->ramfc_size; | ||
116 | 66 | ||
117 | /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 | 67 | /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 |
118 | * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 | 68 | * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 |
@@ -140,46 +90,34 @@ int nv04_instmem_init(struct drm_device *dev) | |||
140 | void | 90 | void |
141 | nv04_instmem_takedown(struct drm_device *dev) | 91 | nv04_instmem_takedown(struct drm_device *dev) |
142 | { | 92 | { |
93 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
94 | |||
95 | nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); | ||
96 | nouveau_gpuobj_ref(NULL, &dev_priv->ramro); | ||
97 | nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); | ||
143 | } | 98 | } |
144 | 99 | ||
145 | int | 100 | int |
146 | nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) | 101 | nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, |
102 | uint32_t *sz) | ||
147 | { | 103 | { |
148 | if (gpuobj->im_backing) | ||
149 | return -EINVAL; | ||
150 | |||
151 | return 0; | 104 | return 0; |
152 | } | 105 | } |
153 | 106 | ||
154 | void | 107 | void |
155 | nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | 108 | nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) |
156 | { | 109 | { |
157 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
158 | |||
159 | if (gpuobj && gpuobj->im_backing) { | ||
160 | if (gpuobj->im_bound) | ||
161 | dev_priv->engine.instmem.unbind(dev, gpuobj); | ||
162 | gpuobj->im_backing = NULL; | ||
163 | } | ||
164 | } | 110 | } |
165 | 111 | ||
166 | int | 112 | int |
167 | nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | 113 | nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) |
168 | { | 114 | { |
169 | if (!gpuobj->im_pramin || gpuobj->im_bound) | ||
170 | return -EINVAL; | ||
171 | |||
172 | gpuobj->im_bound = 1; | ||
173 | return 0; | 115 | return 0; |
174 | } | 116 | } |
175 | 117 | ||
176 | int | 118 | int |
177 | nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | 119 | nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) |
178 | { | 120 | { |
179 | if (gpuobj->im_bound == 0) | ||
180 | return -EINVAL; | ||
181 | |||
182 | gpuobj->im_bound = 0; | ||
183 | return 0; | 121 | return 0; |
184 | } | 122 | } |
185 | 123 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c new file mode 100644 index 000000000000..6a6eb697d38e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_pm.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | #include "nouveau_drv.h" | ||
27 | #include "nouveau_hw.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | struct nv04_pm_state { | ||
31 | struct pll_lims pll; | ||
32 | struct nouveau_pll_vals calc; | ||
33 | }; | ||
34 | |||
35 | int | ||
36 | nv04_pm_clock_get(struct drm_device *dev, u32 id) | ||
37 | { | ||
38 | return nouveau_hw_get_clock(dev, id); | ||
39 | } | ||
40 | |||
41 | void * | ||
42 | nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||
43 | u32 id, int khz) | ||
44 | { | ||
45 | struct nv04_pm_state *state; | ||
46 | int ret; | ||
47 | |||
48 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
49 | if (!state) | ||
50 | return ERR_PTR(-ENOMEM); | ||
51 | |||
52 | ret = get_pll_limits(dev, id, &state->pll); | ||
53 | if (ret) { | ||
54 | kfree(state); | ||
55 | return (ret == -ENOENT) ? NULL : ERR_PTR(ret); | ||
56 | } | ||
57 | |||
58 | ret = nouveau_calc_pll_mnp(dev, &state->pll, khz, &state->calc); | ||
59 | if (!ret) { | ||
60 | kfree(state); | ||
61 | return ERR_PTR(-EINVAL); | ||
62 | } | ||
63 | |||
64 | return state; | ||
65 | } | ||
66 | |||
67 | void | ||
68 | nv04_pm_clock_set(struct drm_device *dev, void *pre_state) | ||
69 | { | ||
70 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
71 | struct nv04_pm_state *state = pre_state; | ||
72 | u32 reg = state->pll.reg; | ||
73 | |||
74 | /* thank the insane nouveau_hw_setpll() interface for this */ | ||
75 | if (dev_priv->card_type >= NV_40) | ||
76 | reg += 4; | ||
77 | |||
78 | nouveau_hw_setpll(dev, reg, &state->calc); | ||
79 | kfree(state); | ||
80 | } | ||
81 | |||
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 0b5d012d7c28..3eb605ddfd03 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c | |||
@@ -49,8 +49,8 @@ static struct i2c_board_info nv04_tv_encoder_info[] = { | |||
49 | 49 | ||
50 | int nv04_tv_identify(struct drm_device *dev, int i2c_index) | 50 | int nv04_tv_identify(struct drm_device *dev, int i2c_index) |
51 | { | 51 | { |
52 | return nouveau_i2c_identify(dev, "TV encoder", | 52 | return nouveau_i2c_identify(dev, "TV encoder", nv04_tv_encoder_info, |
53 | nv04_tv_encoder_info, i2c_index); | 53 | NULL, i2c_index); |
54 | } | 54 | } |
55 | 55 | ||
56 | 56 | ||
@@ -99,12 +99,10 @@ static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) | |||
99 | 99 | ||
100 | state->tv_setup = 0; | 100 | state->tv_setup = 0; |
101 | 101 | ||
102 | if (bind) { | 102 | if (bind) |
103 | state->CRTC[NV_CIO_CRE_LCD__INDEX] = 0; | ||
104 | state->CRTC[NV_CIO_CRE_49] |= 0x10; | 103 | state->CRTC[NV_CIO_CRE_49] |= 0x10; |
105 | } else { | 104 | else |
106 | state->CRTC[NV_CIO_CRE_49] &= ~0x10; | 105 | state->CRTC[NV_CIO_CRE_49] &= ~0x10; |
107 | } | ||
108 | 106 | ||
109 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX, | 107 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX, |
110 | state->CRTC[NV_CIO_CRE_LCD__INDEX]); | 108 | state->CRTC[NV_CIO_CRE_LCD__INDEX]); |
diff --git a/drivers/gpu/drm/nouveau/nv10_fifo.c b/drivers/gpu/drm/nouveau/nv10_fifo.c index 7a4069cf5d0b..f1b03ad58fd5 100644 --- a/drivers/gpu/drm/nouveau/nv10_fifo.c +++ b/drivers/gpu/drm/nouveau/nv10_fifo.c | |||
@@ -27,8 +27,9 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
30 | #include "nouveau_ramht.h" | ||
30 | 31 | ||
31 | #define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE)) | 32 | #define NV10_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV10_RAMFC__SIZE)) |
32 | #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) | 33 | #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) |
33 | 34 | ||
34 | int | 35 | int |
@@ -48,7 +49,7 @@ nv10_fifo_create_context(struct nouveau_channel *chan) | |||
48 | 49 | ||
49 | ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0, | 50 | ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0, |
50 | NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | | 51 | NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | |
51 | NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc); | 52 | NVOBJ_FLAG_ZERO_FREE, &chan->ramfc); |
52 | if (ret) | 53 | if (ret) |
53 | return ret; | 54 | return ret; |
54 | 55 | ||
@@ -57,7 +58,7 @@ nv10_fifo_create_context(struct nouveau_channel *chan) | |||
57 | */ | 58 | */ |
58 | nv_wi32(dev, fc + 0, chan->pushbuf_base); | 59 | nv_wi32(dev, fc + 0, chan->pushbuf_base); |
59 | nv_wi32(dev, fc + 4, chan->pushbuf_base); | 60 | nv_wi32(dev, fc + 4, chan->pushbuf_base); |
60 | nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); | 61 | nv_wi32(dev, fc + 12, chan->pushbuf->pinst >> 4); |
61 | nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | | 62 | nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | |
62 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | | 63 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | |
63 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | | 64 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | |
@@ -80,7 +81,7 @@ nv10_fifo_destroy_context(struct nouveau_channel *chan) | |||
80 | nv_wr32(dev, NV04_PFIFO_MODE, | 81 | nv_wr32(dev, NV04_PFIFO_MODE, |
81 | nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); | 82 | nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); |
82 | 83 | ||
83 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | 84 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
84 | } | 85 | } |
85 | 86 | ||
86 | static void | 87 | static void |
@@ -202,14 +203,14 @@ nv10_fifo_init_ramxx(struct drm_device *dev) | |||
202 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 203 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
203 | 204 | ||
204 | nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | | 205 | nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | |
205 | ((dev_priv->ramht_bits - 9) << 16) | | 206 | ((dev_priv->ramht->bits - 9) << 16) | |
206 | (dev_priv->ramht_offset >> 8)); | 207 | (dev_priv->ramht->gpuobj->pinst >> 8)); |
207 | nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); | 208 | nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); |
208 | 209 | ||
209 | if (dev_priv->chipset < 0x17) { | 210 | if (dev_priv->chipset < 0x17) { |
210 | nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8); | 211 | nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8); |
211 | } else { | 212 | } else { |
212 | nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset >> 8) | | 213 | nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc->pinst >> 8) | |
213 | (1 << 16) /* 64 Bytes entry*/); | 214 | (1 << 16) /* 64 Bytes entry*/); |
214 | /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */ | 215 | /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */ |
215 | } | 216 | } |
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index b2f6a57c0cc5..8e68c9731159 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
@@ -803,7 +803,7 @@ nv10_graph_context_switch(struct drm_device *dev) | |||
803 | /* Load context for next channel */ | 803 | /* Load context for next channel */ |
804 | chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; | 804 | chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; |
805 | chan = dev_priv->fifos[chid]; | 805 | chan = dev_priv->fifos[chid]; |
806 | if (chan) | 806 | if (chan && chan->pgraph_ctx) |
807 | nv10_graph_load_context(chan); | 807 | nv10_graph_load_context(chan); |
808 | 808 | ||
809 | pgraph->fifo_access(dev, true); | 809 | pgraph->fifo_access(dev, true); |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 13cdc05b7c2d..28119fd19d03 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c | |||
@@ -193,55 +193,56 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
193 | } | 193 | } |
194 | } | 194 | } |
195 | 195 | ||
196 | static const struct { | 196 | static int nv17_tv_get_ld_modes(struct drm_encoder *encoder, |
197 | int hdisplay; | 197 | struct drm_connector *connector) |
198 | int vdisplay; | ||
199 | } modes[] = { | ||
200 | { 640, 400 }, | ||
201 | { 640, 480 }, | ||
202 | { 720, 480 }, | ||
203 | { 720, 576 }, | ||
204 | { 800, 600 }, | ||
205 | { 1024, 768 }, | ||
206 | { 1280, 720 }, | ||
207 | { 1280, 1024 }, | ||
208 | { 1920, 1080 } | ||
209 | }; | ||
210 | |||
211 | static int nv17_tv_get_modes(struct drm_encoder *encoder, | ||
212 | struct drm_connector *connector) | ||
213 | { | 198 | { |
214 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 199 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); |
215 | struct drm_display_mode *mode; | 200 | struct drm_display_mode *mode, *tv_mode; |
216 | struct drm_display_mode *output_mode; | ||
217 | int n = 0; | 201 | int n = 0; |
218 | int i; | ||
219 | |||
220 | if (tv_norm->kind != CTV_ENC_MODE) { | ||
221 | struct drm_display_mode *tv_mode; | ||
222 | 202 | ||
223 | for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { | 203 | for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { |
224 | mode = drm_mode_duplicate(encoder->dev, tv_mode); | 204 | mode = drm_mode_duplicate(encoder->dev, tv_mode); |
225 | 205 | ||
226 | mode->clock = tv_norm->tv_enc_mode.vrefresh * | 206 | mode->clock = tv_norm->tv_enc_mode.vrefresh * |
227 | mode->htotal / 1000 * | 207 | mode->htotal / 1000 * |
228 | mode->vtotal / 1000; | 208 | mode->vtotal / 1000; |
229 | 209 | ||
230 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 210 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
231 | mode->clock *= 2; | 211 | mode->clock *= 2; |
232 | 212 | ||
233 | if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay && | 213 | if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay && |
234 | mode->vdisplay == tv_norm->tv_enc_mode.vdisplay) | 214 | mode->vdisplay == tv_norm->tv_enc_mode.vdisplay) |
235 | mode->type |= DRM_MODE_TYPE_PREFERRED; | 215 | mode->type |= DRM_MODE_TYPE_PREFERRED; |
236 | 216 | ||
237 | drm_mode_probed_add(connector, mode); | 217 | drm_mode_probed_add(connector, mode); |
238 | n++; | 218 | n++; |
239 | } | ||
240 | return n; | ||
241 | } | 219 | } |
242 | 220 | ||
243 | /* tv_norm->kind == CTV_ENC_MODE */ | 221 | return n; |
244 | output_mode = &tv_norm->ctv_enc_mode.mode; | 222 | } |
223 | |||
224 | static int nv17_tv_get_hd_modes(struct drm_encoder *encoder, | ||
225 | struct drm_connector *connector) | ||
226 | { | ||
227 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | ||
228 | struct drm_display_mode *output_mode = &tv_norm->ctv_enc_mode.mode; | ||
229 | struct drm_display_mode *mode; | ||
230 | const struct { | ||
231 | int hdisplay; | ||
232 | int vdisplay; | ||
233 | } modes[] = { | ||
234 | { 640, 400 }, | ||
235 | { 640, 480 }, | ||
236 | { 720, 480 }, | ||
237 | { 720, 576 }, | ||
238 | { 800, 600 }, | ||
239 | { 1024, 768 }, | ||
240 | { 1280, 720 }, | ||
241 | { 1280, 1024 }, | ||
242 | { 1920, 1080 } | ||
243 | }; | ||
244 | int i, n = 0; | ||
245 | |||
245 | for (i = 0; i < ARRAY_SIZE(modes); i++) { | 246 | for (i = 0; i < ARRAY_SIZE(modes); i++) { |
246 | if (modes[i].hdisplay > output_mode->hdisplay || | 247 | if (modes[i].hdisplay > output_mode->hdisplay || |
247 | modes[i].vdisplay > output_mode->vdisplay) | 248 | modes[i].vdisplay > output_mode->vdisplay) |
@@ -251,11 +252,12 @@ static int nv17_tv_get_modes(struct drm_encoder *encoder, | |||
251 | modes[i].vdisplay == output_mode->vdisplay) { | 252 | modes[i].vdisplay == output_mode->vdisplay) { |
252 | mode = drm_mode_duplicate(encoder->dev, output_mode); | 253 | mode = drm_mode_duplicate(encoder->dev, output_mode); |
253 | mode->type |= DRM_MODE_TYPE_PREFERRED; | 254 | mode->type |= DRM_MODE_TYPE_PREFERRED; |
255 | |||
254 | } else { | 256 | } else { |
255 | mode = drm_cvt_mode(encoder->dev, modes[i].hdisplay, | 257 | mode = drm_cvt_mode(encoder->dev, modes[i].hdisplay, |
256 | modes[i].vdisplay, 60, false, | 258 | modes[i].vdisplay, 60, false, |
257 | output_mode->flags & DRM_MODE_FLAG_INTERLACE, | 259 | (output_mode->flags & |
258 | false); | 260 | DRM_MODE_FLAG_INTERLACE), false); |
259 | } | 261 | } |
260 | 262 | ||
261 | /* CVT modes are sometimes unsuitable... */ | 263 | /* CVT modes are sometimes unsuitable... */ |
@@ -266,6 +268,7 @@ static int nv17_tv_get_modes(struct drm_encoder *encoder, | |||
266 | - mode->hdisplay) * 9 / 10) & ~7; | 268 | - mode->hdisplay) * 9 / 10) & ~7; |
267 | mode->hsync_end = mode->hsync_start + 8; | 269 | mode->hsync_end = mode->hsync_start + 8; |
268 | } | 270 | } |
271 | |||
269 | if (output_mode->vdisplay >= 1024) { | 272 | if (output_mode->vdisplay >= 1024) { |
270 | mode->vtotal = output_mode->vtotal; | 273 | mode->vtotal = output_mode->vtotal; |
271 | mode->vsync_start = output_mode->vsync_start; | 274 | mode->vsync_start = output_mode->vsync_start; |
@@ -276,9 +279,21 @@ static int nv17_tv_get_modes(struct drm_encoder *encoder, | |||
276 | drm_mode_probed_add(connector, mode); | 279 | drm_mode_probed_add(connector, mode); |
277 | n++; | 280 | n++; |
278 | } | 281 | } |
282 | |||
279 | return n; | 283 | return n; |
280 | } | 284 | } |
281 | 285 | ||
286 | static int nv17_tv_get_modes(struct drm_encoder *encoder, | ||
287 | struct drm_connector *connector) | ||
288 | { | ||
289 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | ||
290 | |||
291 | if (tv_norm->kind == CTV_ENC_MODE) | ||
292 | return nv17_tv_get_hd_modes(encoder, connector); | ||
293 | else | ||
294 | return nv17_tv_get_ld_modes(encoder, connector); | ||
295 | } | ||
296 | |||
282 | static int nv17_tv_mode_valid(struct drm_encoder *encoder, | 297 | static int nv17_tv_mode_valid(struct drm_encoder *encoder, |
283 | struct drm_display_mode *mode) | 298 | struct drm_display_mode *mode) |
284 | { | 299 | { |
@@ -408,15 +423,8 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) | |||
408 | 423 | ||
409 | } | 424 | } |
410 | 425 | ||
411 | /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) | 426 | if (tv_norm->kind == CTV_ENC_MODE) |
412 | * at LCD__INDEX which we don't alter | 427 | *cr_lcd |= 0x1 | (head ? 0x0 : 0x8); |
413 | */ | ||
414 | if (!(*cr_lcd & 0x44)) { | ||
415 | if (tv_norm->kind == CTV_ENC_MODE) | ||
416 | *cr_lcd = 0x1 | (head ? 0x0 : 0x8); | ||
417 | else | ||
418 | *cr_lcd = 0; | ||
419 | } | ||
420 | 428 | ||
421 | /* Set the DACCLK register */ | 429 | /* Set the DACCLK register */ |
422 | dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; | 430 | dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/nv17_tv.h index c00977cedabd..6bf03840f9eb 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.h +++ b/drivers/gpu/drm/nouveau/nv17_tv.h | |||
@@ -127,7 +127,8 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder); | |||
127 | 127 | ||
128 | /* TV hardware access functions */ | 128 | /* TV hardware access functions */ |
129 | 129 | ||
130 | static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, uint32_t val) | 130 | static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, |
131 | uint32_t val) | ||
131 | { | 132 | { |
132 | nv_wr32(dev, reg, val); | 133 | nv_wr32(dev, reg, val); |
133 | } | 134 | } |
@@ -137,7 +138,8 @@ static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg) | |||
137 | return nv_rd32(dev, reg); | 138 | return nv_rd32(dev, reg); |
138 | } | 139 | } |
139 | 140 | ||
140 | static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, uint8_t val) | 141 | static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, |
142 | uint8_t val) | ||
141 | { | 143 | { |
142 | nv_write_ptv(dev, NV_PTV_TV_INDEX, reg); | 144 | nv_write_ptv(dev, NV_PTV_TV_INDEX, reg); |
143 | nv_write_ptv(dev, NV_PTV_TV_DATA, val); | 145 | nv_write_ptv(dev, NV_PTV_TV_DATA, val); |
@@ -149,8 +151,11 @@ static inline uint8_t nv_read_tv_enc(struct drm_device *dev, uint8_t reg) | |||
149 | return nv_read_ptv(dev, NV_PTV_TV_DATA); | 151 | return nv_read_ptv(dev, NV_PTV_TV_DATA); |
150 | } | 152 | } |
151 | 153 | ||
152 | #define nv_load_ptv(dev, state, reg) nv_write_ptv(dev, NV_PTV_OFFSET + 0x##reg, state->ptv_##reg) | 154 | #define nv_load_ptv(dev, state, reg) \ |
153 | #define nv_save_ptv(dev, state, reg) state->ptv_##reg = nv_read_ptv(dev, NV_PTV_OFFSET + 0x##reg) | 155 | nv_write_ptv(dev, NV_PTV_OFFSET + 0x##reg, state->ptv_##reg) |
154 | #define nv_load_tv_enc(dev, state, reg) nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg]) | 156 | #define nv_save_ptv(dev, state, reg) \ |
157 | state->ptv_##reg = nv_read_ptv(dev, NV_PTV_OFFSET + 0x##reg) | ||
158 | #define nv_load_tv_enc(dev, state, reg) \ | ||
159 | nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg]) | ||
155 | 160 | ||
156 | #endif | 161 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv_modes.c b/drivers/gpu/drm/nouveau/nv17_tv_modes.c index d64683d97e0d..9d3893c50a41 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv_modes.c +++ b/drivers/gpu/drm/nouveau/nv17_tv_modes.c | |||
@@ -336,12 +336,17 @@ static void tv_setup_filter(struct drm_encoder *encoder) | |||
336 | struct filter_params *p = &fparams[k][j]; | 336 | struct filter_params *p = &fparams[k][j]; |
337 | 337 | ||
338 | for (i = 0; i < 7; i++) { | 338 | for (i = 0; i < 7; i++) { |
339 | int64_t c = (p->k1 + p->ki*i + p->ki2*i*i + p->ki3*i*i*i) | 339 | int64_t c = (p->k1 + p->ki*i + p->ki2*i*i + |
340 | + (p->kr + p->kir*i + p->ki2r*i*i + p->ki3r*i*i*i)*rs[k] | 340 | p->ki3*i*i*i) |
341 | + (p->kf + p->kif*i + p->ki2f*i*i + p->ki3f*i*i*i)*flicker | 341 | + (p->kr + p->kir*i + p->ki2r*i*i + |
342 | + (p->krf + p->kirf*i + p->ki2rf*i*i + p->ki3rf*i*i*i)*flicker*rs[k]; | 342 | p->ki3r*i*i*i) * rs[k] |
343 | 343 | + (p->kf + p->kif*i + p->ki2f*i*i + | |
344 | (*filters[k])[j][i] = (c + id5/2) >> 39 & (0x1 << 31 | 0x7f << 9); | 344 | p->ki3f*i*i*i) * flicker |
345 | + (p->krf + p->kirf*i + p->ki2rf*i*i + | ||
346 | p->ki3rf*i*i*i) * flicker * rs[k]; | ||
347 | |||
348 | (*filters[k])[j][i] = (c + id5/2) >> 39 | ||
349 | & (0x1 << 31 | 0x7f << 9); | ||
345 | } | 350 | } |
346 | } | 351 | } |
347 | } | 352 | } |
@@ -349,7 +354,8 @@ static void tv_setup_filter(struct drm_encoder *encoder) | |||
349 | 354 | ||
350 | /* Hardware state saving/restoring */ | 355 | /* Hardware state saving/restoring */ |
351 | 356 | ||
352 | static void tv_save_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7]) | 357 | static void tv_save_filter(struct drm_device *dev, uint32_t base, |
358 | uint32_t regs[4][7]) | ||
353 | { | 359 | { |
354 | int i, j; | 360 | int i, j; |
355 | uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; | 361 | uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; |
@@ -360,7 +366,8 @@ static void tv_save_filter(struct drm_device *dev, uint32_t base, uint32_t regs[ | |||
360 | } | 366 | } |
361 | } | 367 | } |
362 | 368 | ||
363 | static void tv_load_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7]) | 369 | static void tv_load_filter(struct drm_device *dev, uint32_t base, |
370 | uint32_t regs[4][7]) | ||
364 | { | 371 | { |
365 | int i, j; | 372 | int i, j; |
366 | uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; | 373 | uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c }; |
@@ -504,10 +511,10 @@ void nv17_tv_update_properties(struct drm_encoder *encoder) | |||
504 | break; | 511 | break; |
505 | } | 512 | } |
506 | 513 | ||
507 | regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20], 255, | 514 | regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20], |
508 | tv_enc->saturation); | 515 | 255, tv_enc->saturation); |
509 | regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22], 255, | 516 | regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22], |
510 | tv_enc->saturation); | 517 | 255, tv_enc->saturation); |
511 | regs->tv_enc[0x25] = tv_enc->hue * 255 / 100; | 518 | regs->tv_enc[0x25] = tv_enc->hue * 255 / 100; |
512 | 519 | ||
513 | nv_load_ptv(dev, regs, 204); | 520 | nv_load_ptv(dev, regs, 204); |
@@ -541,7 +548,8 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder) | |||
541 | int head = nouveau_crtc(encoder->crtc)->index; | 548 | int head = nouveau_crtc(encoder->crtc)->index; |
542 | struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head]; | 549 | struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head]; |
543 | struct drm_display_mode *crtc_mode = &encoder->crtc->mode; | 550 | struct drm_display_mode *crtc_mode = &encoder->crtc->mode; |
544 | struct drm_display_mode *output_mode = &get_tv_norm(encoder)->ctv_enc_mode.mode; | 551 | struct drm_display_mode *output_mode = |
552 | &get_tv_norm(encoder)->ctv_enc_mode.mode; | ||
545 | int overscan, hmargin, vmargin, hratio, vratio; | 553 | int overscan, hmargin, vmargin, hratio, vratio; |
546 | 554 | ||
547 | /* The rescaler doesn't do the right thing for interlaced modes. */ | 555 | /* The rescaler doesn't do the right thing for interlaced modes. */ |
@@ -553,13 +561,15 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder) | |||
553 | hmargin = (output_mode->hdisplay - crtc_mode->hdisplay) / 2; | 561 | hmargin = (output_mode->hdisplay - crtc_mode->hdisplay) / 2; |
554 | vmargin = (output_mode->vdisplay - crtc_mode->vdisplay) / 2; | 562 | vmargin = (output_mode->vdisplay - crtc_mode->vdisplay) / 2; |
555 | 563 | ||
556 | hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20), hmargin, | 564 | hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20), |
557 | overscan); | 565 | hmargin, overscan); |
558 | vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20), vmargin, | 566 | vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20), |
559 | overscan); | 567 | vmargin, overscan); |
560 | 568 | ||
561 | hratio = crtc_mode->hdisplay * 0x800 / (output_mode->hdisplay - 2*hmargin); | 569 | hratio = crtc_mode->hdisplay * 0x800 / |
562 | vratio = crtc_mode->vdisplay * 0x800 / (output_mode->vdisplay - 2*vmargin) & ~3; | 570 | (output_mode->hdisplay - 2*hmargin); |
571 | vratio = crtc_mode->vdisplay * 0x800 / | ||
572 | (output_mode->vdisplay - 2*vmargin) & ~3; | ||
563 | 573 | ||
564 | regs->fp_horiz_regs[FP_VALID_START] = hmargin; | 574 | regs->fp_horiz_regs[FP_VALID_START] = hmargin; |
565 | regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1; | 575 | regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1; |
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index 17f309b36c91..12ab9cd56eca 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c | |||
@@ -37,49 +37,49 @@ nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) | |||
37 | { | 37 | { |
38 | int i; | 38 | int i; |
39 | 39 | ||
40 | nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); | 40 | nv_wo32(ctx, 0x033c, 0xffff0000); |
41 | nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); | 41 | nv_wo32(ctx, 0x03a0, 0x0fff0000); |
42 | nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); | 42 | nv_wo32(ctx, 0x03a4, 0x0fff0000); |
43 | nv_wo32(dev, ctx, 0x047c/4, 0x00000101); | 43 | nv_wo32(ctx, 0x047c, 0x00000101); |
44 | nv_wo32(dev, ctx, 0x0490/4, 0x00000111); | 44 | nv_wo32(ctx, 0x0490, 0x00000111); |
45 | nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); | 45 | nv_wo32(ctx, 0x04a8, 0x44400000); |
46 | for (i = 0x04d4; i <= 0x04e0; i += 4) | 46 | for (i = 0x04d4; i <= 0x04e0; i += 4) |
47 | nv_wo32(dev, ctx, i/4, 0x00030303); | 47 | nv_wo32(ctx, i, 0x00030303); |
48 | for (i = 0x04f4; i <= 0x0500; i += 4) | 48 | for (i = 0x04f4; i <= 0x0500; i += 4) |
49 | nv_wo32(dev, ctx, i/4, 0x00080000); | 49 | nv_wo32(ctx, i, 0x00080000); |
50 | for (i = 0x050c; i <= 0x0518; i += 4) | 50 | for (i = 0x050c; i <= 0x0518; i += 4) |
51 | nv_wo32(dev, ctx, i/4, 0x01012000); | 51 | nv_wo32(ctx, i, 0x01012000); |
52 | for (i = 0x051c; i <= 0x0528; i += 4) | 52 | for (i = 0x051c; i <= 0x0528; i += 4) |
53 | nv_wo32(dev, ctx, i/4, 0x000105b8); | 53 | nv_wo32(ctx, i, 0x000105b8); |
54 | for (i = 0x052c; i <= 0x0538; i += 4) | 54 | for (i = 0x052c; i <= 0x0538; i += 4) |
55 | nv_wo32(dev, ctx, i/4, 0x00080008); | 55 | nv_wo32(ctx, i, 0x00080008); |
56 | for (i = 0x055c; i <= 0x0598; i += 4) | 56 | for (i = 0x055c; i <= 0x0598; i += 4) |
57 | nv_wo32(dev, ctx, i/4, 0x07ff0000); | 57 | nv_wo32(ctx, i, 0x07ff0000); |
58 | nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); | 58 | nv_wo32(ctx, 0x05a4, 0x4b7fffff); |
59 | nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); | 59 | nv_wo32(ctx, 0x05fc, 0x00000001); |
60 | nv_wo32(dev, ctx, 0x0604/4, 0x00004000); | 60 | nv_wo32(ctx, 0x0604, 0x00004000); |
61 | nv_wo32(dev, ctx, 0x0610/4, 0x00000001); | 61 | nv_wo32(ctx, 0x0610, 0x00000001); |
62 | nv_wo32(dev, ctx, 0x0618/4, 0x00040000); | 62 | nv_wo32(ctx, 0x0618, 0x00040000); |
63 | nv_wo32(dev, ctx, 0x061c/4, 0x00010000); | 63 | nv_wo32(ctx, 0x061c, 0x00010000); |
64 | for (i = 0x1c1c; i <= 0x248c; i += 16) { | 64 | for (i = 0x1c1c; i <= 0x248c; i += 16) { |
65 | nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); | 65 | nv_wo32(ctx, (i + 0), 0x10700ff9); |
66 | nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); | 66 | nv_wo32(ctx, (i + 4), 0x0436086c); |
67 | nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); | 67 | nv_wo32(ctx, (i + 8), 0x000c001b); |
68 | } | 68 | } |
69 | nv_wo32(dev, ctx, 0x281c/4, 0x3f800000); | 69 | nv_wo32(ctx, 0x281c, 0x3f800000); |
70 | nv_wo32(dev, ctx, 0x2830/4, 0x3f800000); | 70 | nv_wo32(ctx, 0x2830, 0x3f800000); |
71 | nv_wo32(dev, ctx, 0x285c/4, 0x40000000); | 71 | nv_wo32(ctx, 0x285c, 0x40000000); |
72 | nv_wo32(dev, ctx, 0x2860/4, 0x3f800000); | 72 | nv_wo32(ctx, 0x2860, 0x3f800000); |
73 | nv_wo32(dev, ctx, 0x2864/4, 0x3f000000); | 73 | nv_wo32(ctx, 0x2864, 0x3f000000); |
74 | nv_wo32(dev, ctx, 0x286c/4, 0x40000000); | 74 | nv_wo32(ctx, 0x286c, 0x40000000); |
75 | nv_wo32(dev, ctx, 0x2870/4, 0x3f800000); | 75 | nv_wo32(ctx, 0x2870, 0x3f800000); |
76 | nv_wo32(dev, ctx, 0x2878/4, 0xbf800000); | 76 | nv_wo32(ctx, 0x2878, 0xbf800000); |
77 | nv_wo32(dev, ctx, 0x2880/4, 0xbf800000); | 77 | nv_wo32(ctx, 0x2880, 0xbf800000); |
78 | nv_wo32(dev, ctx, 0x34a4/4, 0x000fe000); | 78 | nv_wo32(ctx, 0x34a4, 0x000fe000); |
79 | nv_wo32(dev, ctx, 0x3530/4, 0x000003f8); | 79 | nv_wo32(ctx, 0x3530, 0x000003f8); |
80 | nv_wo32(dev, ctx, 0x3540/4, 0x002fe000); | 80 | nv_wo32(ctx, 0x3540, 0x002fe000); |
81 | for (i = 0x355c; i <= 0x3578; i += 4) | 81 | for (i = 0x355c; i <= 0x3578; i += 4) |
82 | nv_wo32(dev, ctx, i/4, 0x001c527c); | 82 | nv_wo32(ctx, i, 0x001c527c); |
83 | } | 83 | } |
84 | 84 | ||
85 | static void | 85 | static void |
@@ -87,58 +87,58 @@ nv25_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) | |||
87 | { | 87 | { |
88 | int i; | 88 | int i; |
89 | 89 | ||
90 | nv_wo32(dev, ctx, 0x035c/4, 0xffff0000); | 90 | nv_wo32(ctx, 0x035c, 0xffff0000); |
91 | nv_wo32(dev, ctx, 0x03c0/4, 0x0fff0000); | 91 | nv_wo32(ctx, 0x03c0, 0x0fff0000); |
92 | nv_wo32(dev, ctx, 0x03c4/4, 0x0fff0000); | 92 | nv_wo32(ctx, 0x03c4, 0x0fff0000); |
93 | nv_wo32(dev, ctx, 0x049c/4, 0x00000101); | 93 | nv_wo32(ctx, 0x049c, 0x00000101); |
94 | nv_wo32(dev, ctx, 0x04b0/4, 0x00000111); | 94 | nv_wo32(ctx, 0x04b0, 0x00000111); |
95 | nv_wo32(dev, ctx, 0x04c8/4, 0x00000080); | 95 | nv_wo32(ctx, 0x04c8, 0x00000080); |
96 | nv_wo32(dev, ctx, 0x04cc/4, 0xffff0000); | 96 | nv_wo32(ctx, 0x04cc, 0xffff0000); |
97 | nv_wo32(dev, ctx, 0x04d0/4, 0x00000001); | 97 | nv_wo32(ctx, 0x04d0, 0x00000001); |
98 | nv_wo32(dev, ctx, 0x04e4/4, 0x44400000); | 98 | nv_wo32(ctx, 0x04e4, 0x44400000); |
99 | nv_wo32(dev, ctx, 0x04fc/4, 0x4b800000); | 99 | nv_wo32(ctx, 0x04fc, 0x4b800000); |
100 | for (i = 0x0510; i <= 0x051c; i += 4) | 100 | for (i = 0x0510; i <= 0x051c; i += 4) |
101 | nv_wo32(dev, ctx, i/4, 0x00030303); | 101 | nv_wo32(ctx, i, 0x00030303); |
102 | for (i = 0x0530; i <= 0x053c; i += 4) | 102 | for (i = 0x0530; i <= 0x053c; i += 4) |
103 | nv_wo32(dev, ctx, i/4, 0x00080000); | 103 | nv_wo32(ctx, i, 0x00080000); |
104 | for (i = 0x0548; i <= 0x0554; i += 4) | 104 | for (i = 0x0548; i <= 0x0554; i += 4) |
105 | nv_wo32(dev, ctx, i/4, 0x01012000); | 105 | nv_wo32(ctx, i, 0x01012000); |
106 | for (i = 0x0558; i <= 0x0564; i += 4) | 106 | for (i = 0x0558; i <= 0x0564; i += 4) |
107 | nv_wo32(dev, ctx, i/4, 0x000105b8); | 107 | nv_wo32(ctx, i, 0x000105b8); |
108 | for (i = 0x0568; i <= 0x0574; i += 4) | 108 | for (i = 0x0568; i <= 0x0574; i += 4) |
109 | nv_wo32(dev, ctx, i/4, 0x00080008); | 109 | nv_wo32(ctx, i, 0x00080008); |
110 | for (i = 0x0598; i <= 0x05d4; i += 4) | 110 | for (i = 0x0598; i <= 0x05d4; i += 4) |
111 | nv_wo32(dev, ctx, i/4, 0x07ff0000); | 111 | nv_wo32(ctx, i, 0x07ff0000); |
112 | nv_wo32(dev, ctx, 0x05e0/4, 0x4b7fffff); | 112 | nv_wo32(ctx, 0x05e0, 0x4b7fffff); |
113 | nv_wo32(dev, ctx, 0x0620/4, 0x00000080); | 113 | nv_wo32(ctx, 0x0620, 0x00000080); |
114 | nv_wo32(dev, ctx, 0x0624/4, 0x30201000); | 114 | nv_wo32(ctx, 0x0624, 0x30201000); |
115 | nv_wo32(dev, ctx, 0x0628/4, 0x70605040); | 115 | nv_wo32(ctx, 0x0628, 0x70605040); |
116 | nv_wo32(dev, ctx, 0x062c/4, 0xb0a09080); | 116 | nv_wo32(ctx, 0x062c, 0xb0a09080); |
117 | nv_wo32(dev, ctx, 0x0630/4, 0xf0e0d0c0); | 117 | nv_wo32(ctx, 0x0630, 0xf0e0d0c0); |
118 | nv_wo32(dev, ctx, 0x0664/4, 0x00000001); | 118 | nv_wo32(ctx, 0x0664, 0x00000001); |
119 | nv_wo32(dev, ctx, 0x066c/4, 0x00004000); | 119 | nv_wo32(ctx, 0x066c, 0x00004000); |
120 | nv_wo32(dev, ctx, 0x0678/4, 0x00000001); | 120 | nv_wo32(ctx, 0x0678, 0x00000001); |
121 | nv_wo32(dev, ctx, 0x0680/4, 0x00040000); | 121 | nv_wo32(ctx, 0x0680, 0x00040000); |
122 | nv_wo32(dev, ctx, 0x0684/4, 0x00010000); | 122 | nv_wo32(ctx, 0x0684, 0x00010000); |
123 | for (i = 0x1b04; i <= 0x2374; i += 16) { | 123 | for (i = 0x1b04; i <= 0x2374; i += 16) { |
124 | nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); | 124 | nv_wo32(ctx, (i + 0), 0x10700ff9); |
125 | nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); | 125 | nv_wo32(ctx, (i + 4), 0x0436086c); |
126 | nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); | 126 | nv_wo32(ctx, (i + 8), 0x000c001b); |
127 | } | 127 | } |
128 | nv_wo32(dev, ctx, 0x2704/4, 0x3f800000); | 128 | nv_wo32(ctx, 0x2704, 0x3f800000); |
129 | nv_wo32(dev, ctx, 0x2718/4, 0x3f800000); | 129 | nv_wo32(ctx, 0x2718, 0x3f800000); |
130 | nv_wo32(dev, ctx, 0x2744/4, 0x40000000); | 130 | nv_wo32(ctx, 0x2744, 0x40000000); |
131 | nv_wo32(dev, ctx, 0x2748/4, 0x3f800000); | 131 | nv_wo32(ctx, 0x2748, 0x3f800000); |
132 | nv_wo32(dev, ctx, 0x274c/4, 0x3f000000); | 132 | nv_wo32(ctx, 0x274c, 0x3f000000); |
133 | nv_wo32(dev, ctx, 0x2754/4, 0x40000000); | 133 | nv_wo32(ctx, 0x2754, 0x40000000); |
134 | nv_wo32(dev, ctx, 0x2758/4, 0x3f800000); | 134 | nv_wo32(ctx, 0x2758, 0x3f800000); |
135 | nv_wo32(dev, ctx, 0x2760/4, 0xbf800000); | 135 | nv_wo32(ctx, 0x2760, 0xbf800000); |
136 | nv_wo32(dev, ctx, 0x2768/4, 0xbf800000); | 136 | nv_wo32(ctx, 0x2768, 0xbf800000); |
137 | nv_wo32(dev, ctx, 0x308c/4, 0x000fe000); | 137 | nv_wo32(ctx, 0x308c, 0x000fe000); |
138 | nv_wo32(dev, ctx, 0x3108/4, 0x000003f8); | 138 | nv_wo32(ctx, 0x3108, 0x000003f8); |
139 | nv_wo32(dev, ctx, 0x3468/4, 0x002fe000); | 139 | nv_wo32(ctx, 0x3468, 0x002fe000); |
140 | for (i = 0x3484; i <= 0x34a0; i += 4) | 140 | for (i = 0x3484; i <= 0x34a0; i += 4) |
141 | nv_wo32(dev, ctx, i/4, 0x001c527c); | 141 | nv_wo32(ctx, i, 0x001c527c); |
142 | } | 142 | } |
143 | 143 | ||
144 | static void | 144 | static void |
@@ -146,49 +146,49 @@ nv2a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) | |||
146 | { | 146 | { |
147 | int i; | 147 | int i; |
148 | 148 | ||
149 | nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); | 149 | nv_wo32(ctx, 0x033c, 0xffff0000); |
150 | nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); | 150 | nv_wo32(ctx, 0x03a0, 0x0fff0000); |
151 | nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); | 151 | nv_wo32(ctx, 0x03a4, 0x0fff0000); |
152 | nv_wo32(dev, ctx, 0x047c/4, 0x00000101); | 152 | nv_wo32(ctx, 0x047c, 0x00000101); |
153 | nv_wo32(dev, ctx, 0x0490/4, 0x00000111); | 153 | nv_wo32(ctx, 0x0490, 0x00000111); |
154 | nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); | 154 | nv_wo32(ctx, 0x04a8, 0x44400000); |
155 | for (i = 0x04d4; i <= 0x04e0; i += 4) | 155 | for (i = 0x04d4; i <= 0x04e0; i += 4) |
156 | nv_wo32(dev, ctx, i/4, 0x00030303); | 156 | nv_wo32(ctx, i, 0x00030303); |
157 | for (i = 0x04f4; i <= 0x0500; i += 4) | 157 | for (i = 0x04f4; i <= 0x0500; i += 4) |
158 | nv_wo32(dev, ctx, i/4, 0x00080000); | 158 | nv_wo32(ctx, i, 0x00080000); |
159 | for (i = 0x050c; i <= 0x0518; i += 4) | 159 | for (i = 0x050c; i <= 0x0518; i += 4) |
160 | nv_wo32(dev, ctx, i/4, 0x01012000); | 160 | nv_wo32(ctx, i, 0x01012000); |
161 | for (i = 0x051c; i <= 0x0528; i += 4) | 161 | for (i = 0x051c; i <= 0x0528; i += 4) |
162 | nv_wo32(dev, ctx, i/4, 0x000105b8); | 162 | nv_wo32(ctx, i, 0x000105b8); |
163 | for (i = 0x052c; i <= 0x0538; i += 4) | 163 | for (i = 0x052c; i <= 0x0538; i += 4) |
164 | nv_wo32(dev, ctx, i/4, 0x00080008); | 164 | nv_wo32(ctx, i, 0x00080008); |
165 | for (i = 0x055c; i <= 0x0598; i += 4) | 165 | for (i = 0x055c; i <= 0x0598; i += 4) |
166 | nv_wo32(dev, ctx, i/4, 0x07ff0000); | 166 | nv_wo32(ctx, i, 0x07ff0000); |
167 | nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); | 167 | nv_wo32(ctx, 0x05a4, 0x4b7fffff); |
168 | nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); | 168 | nv_wo32(ctx, 0x05fc, 0x00000001); |
169 | nv_wo32(dev, ctx, 0x0604/4, 0x00004000); | 169 | nv_wo32(ctx, 0x0604, 0x00004000); |
170 | nv_wo32(dev, ctx, 0x0610/4, 0x00000001); | 170 | nv_wo32(ctx, 0x0610, 0x00000001); |
171 | nv_wo32(dev, ctx, 0x0618/4, 0x00040000); | 171 | nv_wo32(ctx, 0x0618, 0x00040000); |
172 | nv_wo32(dev, ctx, 0x061c/4, 0x00010000); | 172 | nv_wo32(ctx, 0x061c, 0x00010000); |
173 | for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ | 173 | for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ |
174 | nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); | 174 | nv_wo32(ctx, (i + 0), 0x10700ff9); |
175 | nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); | 175 | nv_wo32(ctx, (i + 4), 0x0436086c); |
176 | nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); | 176 | nv_wo32(ctx, (i + 8), 0x000c001b); |
177 | } | 177 | } |
178 | nv_wo32(dev, ctx, 0x269c/4, 0x3f800000); | 178 | nv_wo32(ctx, 0x269c, 0x3f800000); |
179 | nv_wo32(dev, ctx, 0x26b0/4, 0x3f800000); | 179 | nv_wo32(ctx, 0x26b0, 0x3f800000); |
180 | nv_wo32(dev, ctx, 0x26dc/4, 0x40000000); | 180 | nv_wo32(ctx, 0x26dc, 0x40000000); |
181 | nv_wo32(dev, ctx, 0x26e0/4, 0x3f800000); | 181 | nv_wo32(ctx, 0x26e0, 0x3f800000); |
182 | nv_wo32(dev, ctx, 0x26e4/4, 0x3f000000); | 182 | nv_wo32(ctx, 0x26e4, 0x3f000000); |
183 | nv_wo32(dev, ctx, 0x26ec/4, 0x40000000); | 183 | nv_wo32(ctx, 0x26ec, 0x40000000); |
184 | nv_wo32(dev, ctx, 0x26f0/4, 0x3f800000); | 184 | nv_wo32(ctx, 0x26f0, 0x3f800000); |
185 | nv_wo32(dev, ctx, 0x26f8/4, 0xbf800000); | 185 | nv_wo32(ctx, 0x26f8, 0xbf800000); |
186 | nv_wo32(dev, ctx, 0x2700/4, 0xbf800000); | 186 | nv_wo32(ctx, 0x2700, 0xbf800000); |
187 | nv_wo32(dev, ctx, 0x3024/4, 0x000fe000); | 187 | nv_wo32(ctx, 0x3024, 0x000fe000); |
188 | nv_wo32(dev, ctx, 0x30a0/4, 0x000003f8); | 188 | nv_wo32(ctx, 0x30a0, 0x000003f8); |
189 | nv_wo32(dev, ctx, 0x33fc/4, 0x002fe000); | 189 | nv_wo32(ctx, 0x33fc, 0x002fe000); |
190 | for (i = 0x341c; i <= 0x3438; i += 4) | 190 | for (i = 0x341c; i <= 0x3438; i += 4) |
191 | nv_wo32(dev, ctx, i/4, 0x001c527c); | 191 | nv_wo32(ctx, i, 0x001c527c); |
192 | } | 192 | } |
193 | 193 | ||
194 | static void | 194 | static void |
@@ -196,57 +196,57 @@ nv30_31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) | |||
196 | { | 196 | { |
197 | int i; | 197 | int i; |
198 | 198 | ||
199 | nv_wo32(dev, ctx, 0x0410/4, 0x00000101); | 199 | nv_wo32(ctx, 0x0410, 0x00000101); |
200 | nv_wo32(dev, ctx, 0x0424/4, 0x00000111); | 200 | nv_wo32(ctx, 0x0424, 0x00000111); |
201 | nv_wo32(dev, ctx, 0x0428/4, 0x00000060); | 201 | nv_wo32(ctx, 0x0428, 0x00000060); |
202 | nv_wo32(dev, ctx, 0x0444/4, 0x00000080); | 202 | nv_wo32(ctx, 0x0444, 0x00000080); |
203 | nv_wo32(dev, ctx, 0x0448/4, 0xffff0000); | 203 | nv_wo32(ctx, 0x0448, 0xffff0000); |
204 | nv_wo32(dev, ctx, 0x044c/4, 0x00000001); | 204 | nv_wo32(ctx, 0x044c, 0x00000001); |
205 | nv_wo32(dev, ctx, 0x0460/4, 0x44400000); | 205 | nv_wo32(ctx, 0x0460, 0x44400000); |
206 | nv_wo32(dev, ctx, 0x048c/4, 0xffff0000); | 206 | nv_wo32(ctx, 0x048c, 0xffff0000); |
207 | for (i = 0x04e0; i < 0x04e8; i += 4) | 207 | for (i = 0x04e0; i < 0x04e8; i += 4) |
208 | nv_wo32(dev, ctx, i/4, 0x0fff0000); | 208 | nv_wo32(ctx, i, 0x0fff0000); |
209 | nv_wo32(dev, ctx, 0x04ec/4, 0x00011100); | 209 | nv_wo32(ctx, 0x04ec, 0x00011100); |
210 | for (i = 0x0508; i < 0x0548; i += 4) | 210 | for (i = 0x0508; i < 0x0548; i += 4) |
211 | nv_wo32(dev, ctx, i/4, 0x07ff0000); | 211 | nv_wo32(ctx, i, 0x07ff0000); |
212 | nv_wo32(dev, ctx, 0x0550/4, 0x4b7fffff); | 212 | nv_wo32(ctx, 0x0550, 0x4b7fffff); |
213 | nv_wo32(dev, ctx, 0x058c/4, 0x00000080); | 213 | nv_wo32(ctx, 0x058c, 0x00000080); |
214 | nv_wo32(dev, ctx, 0x0590/4, 0x30201000); | 214 | nv_wo32(ctx, 0x0590, 0x30201000); |
215 | nv_wo32(dev, ctx, 0x0594/4, 0x70605040); | 215 | nv_wo32(ctx, 0x0594, 0x70605040); |
216 | nv_wo32(dev, ctx, 0x0598/4, 0xb8a89888); | 216 | nv_wo32(ctx, 0x0598, 0xb8a89888); |
217 | nv_wo32(dev, ctx, 0x059c/4, 0xf8e8d8c8); | 217 | nv_wo32(ctx, 0x059c, 0xf8e8d8c8); |
218 | nv_wo32(dev, ctx, 0x05b0/4, 0xb0000000); | 218 | nv_wo32(ctx, 0x05b0, 0xb0000000); |
219 | for (i = 0x0600; i < 0x0640; i += 4) | 219 | for (i = 0x0600; i < 0x0640; i += 4) |
220 | nv_wo32(dev, ctx, i/4, 0x00010588); | 220 | nv_wo32(ctx, i, 0x00010588); |
221 | for (i = 0x0640; i < 0x0680; i += 4) | 221 | for (i = 0x0640; i < 0x0680; i += 4) |
222 | nv_wo32(dev, ctx, i/4, 0x00030303); | 222 | nv_wo32(ctx, i, 0x00030303); |
223 | for (i = 0x06c0; i < 0x0700; i += 4) | 223 | for (i = 0x06c0; i < 0x0700; i += 4) |
224 | nv_wo32(dev, ctx, i/4, 0x0008aae4); | 224 | nv_wo32(ctx, i, 0x0008aae4); |
225 | for (i = 0x0700; i < 0x0740; i += 4) | 225 | for (i = 0x0700; i < 0x0740; i += 4) |
226 | nv_wo32(dev, ctx, i/4, 0x01012000); | 226 | nv_wo32(ctx, i, 0x01012000); |
227 | for (i = 0x0740; i < 0x0780; i += 4) | 227 | for (i = 0x0740; i < 0x0780; i += 4) |
228 | nv_wo32(dev, ctx, i/4, 0x00080008); | 228 | nv_wo32(ctx, i, 0x00080008); |
229 | nv_wo32(dev, ctx, 0x085c/4, 0x00040000); | 229 | nv_wo32(ctx, 0x085c, 0x00040000); |
230 | nv_wo32(dev, ctx, 0x0860/4, 0x00010000); | 230 | nv_wo32(ctx, 0x0860, 0x00010000); |
231 | for (i = 0x0864; i < 0x0874; i += 4) | 231 | for (i = 0x0864; i < 0x0874; i += 4) |
232 | nv_wo32(dev, ctx, i/4, 0x00040004); | 232 | nv_wo32(ctx, i, 0x00040004); |
233 | for (i = 0x1f18; i <= 0x3088 ; i += 16) { | 233 | for (i = 0x1f18; i <= 0x3088 ; i += 16) { |
234 | nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); | 234 | nv_wo32(ctx, i + 0, 0x10700ff9); |
235 | nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); | 235 | nv_wo32(ctx, i + 1, 0x0436086c); |
236 | nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); | 236 | nv_wo32(ctx, i + 2, 0x000c001b); |
237 | } | 237 | } |
238 | for (i = 0x30b8; i < 0x30c8; i += 4) | 238 | for (i = 0x30b8; i < 0x30c8; i += 4) |
239 | nv_wo32(dev, ctx, i/4, 0x0000ffff); | 239 | nv_wo32(ctx, i, 0x0000ffff); |
240 | nv_wo32(dev, ctx, 0x344c/4, 0x3f800000); | 240 | nv_wo32(ctx, 0x344c, 0x3f800000); |
241 | nv_wo32(dev, ctx, 0x3808/4, 0x3f800000); | 241 | nv_wo32(ctx, 0x3808, 0x3f800000); |
242 | nv_wo32(dev, ctx, 0x381c/4, 0x3f800000); | 242 | nv_wo32(ctx, 0x381c, 0x3f800000); |
243 | nv_wo32(dev, ctx, 0x3848/4, 0x40000000); | 243 | nv_wo32(ctx, 0x3848, 0x40000000); |
244 | nv_wo32(dev, ctx, 0x384c/4, 0x3f800000); | 244 | nv_wo32(ctx, 0x384c, 0x3f800000); |
245 | nv_wo32(dev, ctx, 0x3850/4, 0x3f000000); | 245 | nv_wo32(ctx, 0x3850, 0x3f000000); |
246 | nv_wo32(dev, ctx, 0x3858/4, 0x40000000); | 246 | nv_wo32(ctx, 0x3858, 0x40000000); |
247 | nv_wo32(dev, ctx, 0x385c/4, 0x3f800000); | 247 | nv_wo32(ctx, 0x385c, 0x3f800000); |
248 | nv_wo32(dev, ctx, 0x3864/4, 0xbf800000); | 248 | nv_wo32(ctx, 0x3864, 0xbf800000); |
249 | nv_wo32(dev, ctx, 0x386c/4, 0xbf800000); | 249 | nv_wo32(ctx, 0x386c, 0xbf800000); |
250 | } | 250 | } |
251 | 251 | ||
252 | static void | 252 | static void |
@@ -254,57 +254,57 @@ nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) | |||
254 | { | 254 | { |
255 | int i; | 255 | int i; |
256 | 256 | ||
257 | nv_wo32(dev, ctx, 0x040c/4, 0x01000101); | 257 | nv_wo32(ctx, 0x040c, 0x01000101); |
258 | nv_wo32(dev, ctx, 0x0420/4, 0x00000111); | 258 | nv_wo32(ctx, 0x0420, 0x00000111); |
259 | nv_wo32(dev, ctx, 0x0424/4, 0x00000060); | 259 | nv_wo32(ctx, 0x0424, 0x00000060); |
260 | nv_wo32(dev, ctx, 0x0440/4, 0x00000080); | 260 | nv_wo32(ctx, 0x0440, 0x00000080); |
261 | nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); | 261 | nv_wo32(ctx, 0x0444, 0xffff0000); |
262 | nv_wo32(dev, ctx, 0x0448/4, 0x00000001); | 262 | nv_wo32(ctx, 0x0448, 0x00000001); |
263 | nv_wo32(dev, ctx, 0x045c/4, 0x44400000); | 263 | nv_wo32(ctx, 0x045c, 0x44400000); |
264 | nv_wo32(dev, ctx, 0x0480/4, 0xffff0000); | 264 | nv_wo32(ctx, 0x0480, 0xffff0000); |
265 | for (i = 0x04d4; i < 0x04dc; i += 4) | 265 | for (i = 0x04d4; i < 0x04dc; i += 4) |
266 | nv_wo32(dev, ctx, i/4, 0x0fff0000); | 266 | nv_wo32(ctx, i, 0x0fff0000); |
267 | nv_wo32(dev, ctx, 0x04e0/4, 0x00011100); | 267 | nv_wo32(ctx, 0x04e0, 0x00011100); |
268 | for (i = 0x04fc; i < 0x053c; i += 4) | 268 | for (i = 0x04fc; i < 0x053c; i += 4) |
269 | nv_wo32(dev, ctx, i/4, 0x07ff0000); | 269 | nv_wo32(ctx, i, 0x07ff0000); |
270 | nv_wo32(dev, ctx, 0x0544/4, 0x4b7fffff); | 270 | nv_wo32(ctx, 0x0544, 0x4b7fffff); |
271 | nv_wo32(dev, ctx, 0x057c/4, 0x00000080); | 271 | nv_wo32(ctx, 0x057c, 0x00000080); |
272 | nv_wo32(dev, ctx, 0x0580/4, 0x30201000); | 272 | nv_wo32(ctx, 0x0580, 0x30201000); |
273 | nv_wo32(dev, ctx, 0x0584/4, 0x70605040); | 273 | nv_wo32(ctx, 0x0584, 0x70605040); |
274 | nv_wo32(dev, ctx, 0x0588/4, 0xb8a89888); | 274 | nv_wo32(ctx, 0x0588, 0xb8a89888); |
275 | nv_wo32(dev, ctx, 0x058c/4, 0xf8e8d8c8); | 275 | nv_wo32(ctx, 0x058c, 0xf8e8d8c8); |
276 | nv_wo32(dev, ctx, 0x05a0/4, 0xb0000000); | 276 | nv_wo32(ctx, 0x05a0, 0xb0000000); |
277 | for (i = 0x05f0; i < 0x0630; i += 4) | 277 | for (i = 0x05f0; i < 0x0630; i += 4) |
278 | nv_wo32(dev, ctx, i/4, 0x00010588); | 278 | nv_wo32(ctx, i, 0x00010588); |
279 | for (i = 0x0630; i < 0x0670; i += 4) | 279 | for (i = 0x0630; i < 0x0670; i += 4) |
280 | nv_wo32(dev, ctx, i/4, 0x00030303); | 280 | nv_wo32(ctx, i, 0x00030303); |
281 | for (i = 0x06b0; i < 0x06f0; i += 4) | 281 | for (i = 0x06b0; i < 0x06f0; i += 4) |
282 | nv_wo32(dev, ctx, i/4, 0x0008aae4); | 282 | nv_wo32(ctx, i, 0x0008aae4); |
283 | for (i = 0x06f0; i < 0x0730; i += 4) | 283 | for (i = 0x06f0; i < 0x0730; i += 4) |
284 | nv_wo32(dev, ctx, i/4, 0x01012000); | 284 | nv_wo32(ctx, i, 0x01012000); |
285 | for (i = 0x0730; i < 0x0770; i += 4) | 285 | for (i = 0x0730; i < 0x0770; i += 4) |
286 | nv_wo32(dev, ctx, i/4, 0x00080008); | 286 | nv_wo32(ctx, i, 0x00080008); |
287 | nv_wo32(dev, ctx, 0x0850/4, 0x00040000); | 287 | nv_wo32(ctx, 0x0850, 0x00040000); |
288 | nv_wo32(dev, ctx, 0x0854/4, 0x00010000); | 288 | nv_wo32(ctx, 0x0854, 0x00010000); |
289 | for (i = 0x0858; i < 0x0868; i += 4) | 289 | for (i = 0x0858; i < 0x0868; i += 4) |
290 | nv_wo32(dev, ctx, i/4, 0x00040004); | 290 | nv_wo32(ctx, i, 0x00040004); |
291 | for (i = 0x15ac; i <= 0x271c ; i += 16) { | 291 | for (i = 0x15ac; i <= 0x271c ; i += 16) { |
292 | nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); | 292 | nv_wo32(ctx, i + 0, 0x10700ff9); |
293 | nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); | 293 | nv_wo32(ctx, i + 1, 0x0436086c); |
294 | nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); | 294 | nv_wo32(ctx, i + 2, 0x000c001b); |
295 | } | 295 | } |
296 | for (i = 0x274c; i < 0x275c; i += 4) | 296 | for (i = 0x274c; i < 0x275c; i += 4) |
297 | nv_wo32(dev, ctx, i/4, 0x0000ffff); | 297 | nv_wo32(ctx, i, 0x0000ffff); |
298 | nv_wo32(dev, ctx, 0x2ae0/4, 0x3f800000); | 298 | nv_wo32(ctx, 0x2ae0, 0x3f800000); |
299 | nv_wo32(dev, ctx, 0x2e9c/4, 0x3f800000); | 299 | nv_wo32(ctx, 0x2e9c, 0x3f800000); |
300 | nv_wo32(dev, ctx, 0x2eb0/4, 0x3f800000); | 300 | nv_wo32(ctx, 0x2eb0, 0x3f800000); |
301 | nv_wo32(dev, ctx, 0x2edc/4, 0x40000000); | 301 | nv_wo32(ctx, 0x2edc, 0x40000000); |
302 | nv_wo32(dev, ctx, 0x2ee0/4, 0x3f800000); | 302 | nv_wo32(ctx, 0x2ee0, 0x3f800000); |
303 | nv_wo32(dev, ctx, 0x2ee4/4, 0x3f000000); | 303 | nv_wo32(ctx, 0x2ee4, 0x3f000000); |
304 | nv_wo32(dev, ctx, 0x2eec/4, 0x40000000); | 304 | nv_wo32(ctx, 0x2eec, 0x40000000); |
305 | nv_wo32(dev, ctx, 0x2ef0/4, 0x3f800000); | 305 | nv_wo32(ctx, 0x2ef0, 0x3f800000); |
306 | nv_wo32(dev, ctx, 0x2ef8/4, 0xbf800000); | 306 | nv_wo32(ctx, 0x2ef8, 0xbf800000); |
307 | nv_wo32(dev, ctx, 0x2f00/4, 0xbf800000); | 307 | nv_wo32(ctx, 0x2f00, 0xbf800000); |
308 | } | 308 | } |
309 | 309 | ||
310 | static void | 310 | static void |
@@ -312,57 +312,57 @@ nv35_36_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) | |||
312 | { | 312 | { |
313 | int i; | 313 | int i; |
314 | 314 | ||
315 | nv_wo32(dev, ctx, 0x040c/4, 0x00000101); | 315 | nv_wo32(ctx, 0x040c, 0x00000101); |
316 | nv_wo32(dev, ctx, 0x0420/4, 0x00000111); | 316 | nv_wo32(ctx, 0x0420, 0x00000111); |
317 | nv_wo32(dev, ctx, 0x0424/4, 0x00000060); | 317 | nv_wo32(ctx, 0x0424, 0x00000060); |
318 | nv_wo32(dev, ctx, 0x0440/4, 0x00000080); | 318 | nv_wo32(ctx, 0x0440, 0x00000080); |
319 | nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); | 319 | nv_wo32(ctx, 0x0444, 0xffff0000); |
320 | nv_wo32(dev, ctx, 0x0448/4, 0x00000001); | 320 | nv_wo32(ctx, 0x0448, 0x00000001); |
321 | nv_wo32(dev, ctx, 0x045c/4, 0x44400000); | 321 | nv_wo32(ctx, 0x045c, 0x44400000); |
322 | nv_wo32(dev, ctx, 0x0488/4, 0xffff0000); | 322 | nv_wo32(ctx, 0x0488, 0xffff0000); |
323 | for (i = 0x04dc; i < 0x04e4; i += 4) | 323 | for (i = 0x04dc; i < 0x04e4; i += 4) |
324 | nv_wo32(dev, ctx, i/4, 0x0fff0000); | 324 | nv_wo32(ctx, i, 0x0fff0000); |
325 | nv_wo32(dev, ctx, 0x04e8/4, 0x00011100); | 325 | nv_wo32(ctx, 0x04e8, 0x00011100); |
326 | for (i = 0x0504; i < 0x0544; i += 4) | 326 | for (i = 0x0504; i < 0x0544; i += 4) |
327 | nv_wo32(dev, ctx, i/4, 0x07ff0000); | 327 | nv_wo32(ctx, i, 0x07ff0000); |
328 | nv_wo32(dev, ctx, 0x054c/4, 0x4b7fffff); | 328 | nv_wo32(ctx, 0x054c, 0x4b7fffff); |
329 | nv_wo32(dev, ctx, 0x0588/4, 0x00000080); | 329 | nv_wo32(ctx, 0x0588, 0x00000080); |
330 | nv_wo32(dev, ctx, 0x058c/4, 0x30201000); | 330 | nv_wo32(ctx, 0x058c, 0x30201000); |
331 | nv_wo32(dev, ctx, 0x0590/4, 0x70605040); | 331 | nv_wo32(ctx, 0x0590, 0x70605040); |
332 | nv_wo32(dev, ctx, 0x0594/4, 0xb8a89888); | 332 | nv_wo32(ctx, 0x0594, 0xb8a89888); |
333 | nv_wo32(dev, ctx, 0x0598/4, 0xf8e8d8c8); | 333 | nv_wo32(ctx, 0x0598, 0xf8e8d8c8); |
334 | nv_wo32(dev, ctx, 0x05ac/4, 0xb0000000); | 334 | nv_wo32(ctx, 0x05ac, 0xb0000000); |
335 | for (i = 0x0604; i < 0x0644; i += 4) | 335 | for (i = 0x0604; i < 0x0644; i += 4) |
336 | nv_wo32(dev, ctx, i/4, 0x00010588); | 336 | nv_wo32(ctx, i, 0x00010588); |
337 | for (i = 0x0644; i < 0x0684; i += 4) | 337 | for (i = 0x0644; i < 0x0684; i += 4) |
338 | nv_wo32(dev, ctx, i/4, 0x00030303); | 338 | nv_wo32(ctx, i, 0x00030303); |
339 | for (i = 0x06c4; i < 0x0704; i += 4) | 339 | for (i = 0x06c4; i < 0x0704; i += 4) |
340 | nv_wo32(dev, ctx, i/4, 0x0008aae4); | 340 | nv_wo32(ctx, i, 0x0008aae4); |
341 | for (i = 0x0704; i < 0x0744; i += 4) | 341 | for (i = 0x0704; i < 0x0744; i += 4) |
342 | nv_wo32(dev, ctx, i/4, 0x01012000); | 342 | nv_wo32(ctx, i, 0x01012000); |
343 | for (i = 0x0744; i < 0x0784; i += 4) | 343 | for (i = 0x0744; i < 0x0784; i += 4) |
344 | nv_wo32(dev, ctx, i/4, 0x00080008); | 344 | nv_wo32(ctx, i, 0x00080008); |
345 | nv_wo32(dev, ctx, 0x0860/4, 0x00040000); | 345 | nv_wo32(ctx, 0x0860, 0x00040000); |
346 | nv_wo32(dev, ctx, 0x0864/4, 0x00010000); | 346 | nv_wo32(ctx, 0x0864, 0x00010000); |
347 | for (i = 0x0868; i < 0x0878; i += 4) | 347 | for (i = 0x0868; i < 0x0878; i += 4) |
348 | nv_wo32(dev, ctx, i/4, 0x00040004); | 348 | nv_wo32(ctx, i, 0x00040004); |
349 | for (i = 0x1f1c; i <= 0x308c ; i += 16) { | 349 | for (i = 0x1f1c; i <= 0x308c ; i += 16) { |
350 | nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); | 350 | nv_wo32(ctx, i + 0, 0x10700ff9); |
351 | nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); | 351 | nv_wo32(ctx, i + 4, 0x0436086c); |
352 | nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); | 352 | nv_wo32(ctx, i + 8, 0x000c001b); |
353 | } | 353 | } |
354 | for (i = 0x30bc; i < 0x30cc; i += 4) | 354 | for (i = 0x30bc; i < 0x30cc; i += 4) |
355 | nv_wo32(dev, ctx, i/4, 0x0000ffff); | 355 | nv_wo32(ctx, i, 0x0000ffff); |
356 | nv_wo32(dev, ctx, 0x3450/4, 0x3f800000); | 356 | nv_wo32(ctx, 0x3450, 0x3f800000); |
357 | nv_wo32(dev, ctx, 0x380c/4, 0x3f800000); | 357 | nv_wo32(ctx, 0x380c, 0x3f800000); |
358 | nv_wo32(dev, ctx, 0x3820/4, 0x3f800000); | 358 | nv_wo32(ctx, 0x3820, 0x3f800000); |
359 | nv_wo32(dev, ctx, 0x384c/4, 0x40000000); | 359 | nv_wo32(ctx, 0x384c, 0x40000000); |
360 | nv_wo32(dev, ctx, 0x3850/4, 0x3f800000); | 360 | nv_wo32(ctx, 0x3850, 0x3f800000); |
361 | nv_wo32(dev, ctx, 0x3854/4, 0x3f000000); | 361 | nv_wo32(ctx, 0x3854, 0x3f000000); |
362 | nv_wo32(dev, ctx, 0x385c/4, 0x40000000); | 362 | nv_wo32(ctx, 0x385c, 0x40000000); |
363 | nv_wo32(dev, ctx, 0x3860/4, 0x3f800000); | 363 | nv_wo32(ctx, 0x3860, 0x3f800000); |
364 | nv_wo32(dev, ctx, 0x3868/4, 0xbf800000); | 364 | nv_wo32(ctx, 0x3868, 0xbf800000); |
365 | nv_wo32(dev, ctx, 0x3870/4, 0xbf800000); | 365 | nv_wo32(ctx, 0x3870, 0xbf800000); |
366 | } | 366 | } |
367 | 367 | ||
368 | int | 368 | int |
@@ -372,7 +372,7 @@ nv20_graph_create_context(struct nouveau_channel *chan) | |||
372 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 372 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
373 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 373 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
374 | void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); | 374 | void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); |
375 | unsigned int idoffs = 0x28/4; | 375 | unsigned int idoffs = 0x28; |
376 | int ret; | 376 | int ret; |
377 | 377 | ||
378 | switch (dev_priv->chipset) { | 378 | switch (dev_priv->chipset) { |
@@ -403,21 +403,19 @@ nv20_graph_create_context(struct nouveau_channel *chan) | |||
403 | BUG_ON(1); | 403 | BUG_ON(1); |
404 | } | 404 | } |
405 | 405 | ||
406 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, | 406 | ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, |
407 | 16, NVOBJ_FLAG_ZERO_ALLOC, | 407 | NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx); |
408 | &chan->ramin_grctx); | ||
409 | if (ret) | 408 | if (ret) |
410 | return ret; | 409 | return ret; |
411 | 410 | ||
412 | /* Initialise default context values */ | 411 | /* Initialise default context values */ |
413 | ctx_init(dev, chan->ramin_grctx->gpuobj); | 412 | ctx_init(dev, chan->ramin_grctx); |
414 | 413 | ||
415 | /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ | 414 | /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ |
416 | nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, | 415 | nv_wo32(chan->ramin_grctx, idoffs, |
417 | (chan->id << 24) | 0x1); /* CTX_USER */ | 416 | (chan->id << 24) | 0x1); /* CTX_USER */ |
418 | 417 | ||
419 | nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, | 418 | nv_wo32(pgraph->ctx_table, chan->id * 4, chan->ramin_grctx->pinst >> 4); |
420 | chan->ramin_grctx->instance >> 4); | ||
421 | return 0; | 419 | return 0; |
422 | } | 420 | } |
423 | 421 | ||
@@ -428,10 +426,8 @@ nv20_graph_destroy_context(struct nouveau_channel *chan) | |||
428 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 426 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
429 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 427 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
430 | 428 | ||
431 | if (chan->ramin_grctx) | 429 | nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); |
432 | nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); | 430 | nv_wo32(pgraph->ctx_table, chan->id * 4, 0); |
433 | |||
434 | nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, 0); | ||
435 | } | 431 | } |
436 | 432 | ||
437 | int | 433 | int |
@@ -442,7 +438,7 @@ nv20_graph_load_context(struct nouveau_channel *chan) | |||
442 | 438 | ||
443 | if (!chan->ramin_grctx) | 439 | if (!chan->ramin_grctx) |
444 | return -EINVAL; | 440 | return -EINVAL; |
445 | inst = chan->ramin_grctx->instance >> 4; | 441 | inst = chan->ramin_grctx->pinst >> 4; |
446 | 442 | ||
447 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); | 443 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); |
448 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, | 444 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, |
@@ -465,7 +461,7 @@ nv20_graph_unload_context(struct drm_device *dev) | |||
465 | chan = pgraph->channel(dev); | 461 | chan = pgraph->channel(dev); |
466 | if (!chan) | 462 | if (!chan) |
467 | return 0; | 463 | return 0; |
468 | inst = chan->ramin_grctx->instance >> 4; | 464 | inst = chan->ramin_grctx->pinst >> 4; |
469 | 465 | ||
470 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); | 466 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); |
471 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, | 467 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER, |
@@ -552,15 +548,15 @@ nv20_graph_init(struct drm_device *dev) | |||
552 | 548 | ||
553 | if (!pgraph->ctx_table) { | 549 | if (!pgraph->ctx_table) { |
554 | /* Create Context Pointer Table */ | 550 | /* Create Context Pointer Table */ |
555 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, | 551 | ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, |
556 | NVOBJ_FLAG_ZERO_ALLOC, | 552 | NVOBJ_FLAG_ZERO_ALLOC, |
557 | &pgraph->ctx_table); | 553 | &pgraph->ctx_table); |
558 | if (ret) | 554 | if (ret) |
559 | return ret; | 555 | return ret; |
560 | } | 556 | } |
561 | 557 | ||
562 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, | 558 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, |
563 | pgraph->ctx_table->instance >> 4); | 559 | pgraph->ctx_table->pinst >> 4); |
564 | 560 | ||
565 | nv20_graph_rdi(dev); | 561 | nv20_graph_rdi(dev); |
566 | 562 | ||
@@ -646,7 +642,7 @@ nv20_graph_takedown(struct drm_device *dev) | |||
646 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 642 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
647 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 643 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
648 | 644 | ||
649 | nouveau_gpuobj_ref_del(dev, &pgraph->ctx_table); | 645 | nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); |
650 | } | 646 | } |
651 | 647 | ||
652 | int | 648 | int |
@@ -681,15 +677,15 @@ nv30_graph_init(struct drm_device *dev) | |||
681 | 677 | ||
682 | if (!pgraph->ctx_table) { | 678 | if (!pgraph->ctx_table) { |
683 | /* Create Context Pointer Table */ | 679 | /* Create Context Pointer Table */ |
684 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, | 680 | ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, |
685 | NVOBJ_FLAG_ZERO_ALLOC, | 681 | NVOBJ_FLAG_ZERO_ALLOC, |
686 | &pgraph->ctx_table); | 682 | &pgraph->ctx_table); |
687 | if (ret) | 683 | if (ret) |
688 | return ret; | 684 | return ret; |
689 | } | 685 | } |
690 | 686 | ||
691 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, | 687 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, |
692 | pgraph->ctx_table->instance >> 4); | 688 | pgraph->ctx_table->pinst >> 4); |
693 | 689 | ||
694 | nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); | 690 | nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); |
695 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); | 691 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); |
diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c index 2b67f1835c39..d337b8b28cdd 100644 --- a/drivers/gpu/drm/nouveau/nv40_fifo.c +++ b/drivers/gpu/drm/nouveau/nv40_fifo.c | |||
@@ -27,8 +27,9 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "nouveau_drv.h" | 28 | #include "nouveau_drv.h" |
29 | #include "nouveau_drm.h" | 29 | #include "nouveau_drm.h" |
30 | #include "nouveau_ramht.h" | ||
30 | 31 | ||
31 | #define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV40_RAMFC__SIZE)) | 32 | #define NV40_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV40_RAMFC__SIZE)) |
32 | #define NV40_RAMFC__SIZE 128 | 33 | #define NV40_RAMFC__SIZE 128 |
33 | 34 | ||
34 | int | 35 | int |
@@ -42,7 +43,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan) | |||
42 | 43 | ||
43 | ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0, | 44 | ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0, |
44 | NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | | 45 | NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | |
45 | NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc); | 46 | NVOBJ_FLAG_ZERO_FREE, &chan->ramfc); |
46 | if (ret) | 47 | if (ret) |
47 | return ret; | 48 | return ret; |
48 | 49 | ||
@@ -50,7 +51,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan) | |||
50 | 51 | ||
51 | nv_wi32(dev, fc + 0, chan->pushbuf_base); | 52 | nv_wi32(dev, fc + 0, chan->pushbuf_base); |
52 | nv_wi32(dev, fc + 4, chan->pushbuf_base); | 53 | nv_wi32(dev, fc + 4, chan->pushbuf_base); |
53 | nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); | 54 | nv_wi32(dev, fc + 12, chan->pushbuf->pinst >> 4); |
54 | nv_wi32(dev, fc + 24, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | | 55 | nv_wi32(dev, fc + 24, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | |
55 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | | 56 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | |
56 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | | 57 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | |
@@ -58,7 +59,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan) | |||
58 | NV_PFIFO_CACHE1_BIG_ENDIAN | | 59 | NV_PFIFO_CACHE1_BIG_ENDIAN | |
59 | #endif | 60 | #endif |
60 | 0x30000000 /* no idea.. */); | 61 | 0x30000000 /* no idea.. */); |
61 | nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4); | 62 | nv_wi32(dev, fc + 56, chan->ramin_grctx->pinst >> 4); |
62 | nv_wi32(dev, fc + 60, 0x0001FFFF); | 63 | nv_wi32(dev, fc + 60, 0x0001FFFF); |
63 | 64 | ||
64 | /* enable the fifo dma operation */ | 65 | /* enable the fifo dma operation */ |
@@ -77,8 +78,7 @@ nv40_fifo_destroy_context(struct nouveau_channel *chan) | |||
77 | nv_wr32(dev, NV04_PFIFO_MODE, | 78 | nv_wr32(dev, NV04_PFIFO_MODE, |
78 | nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); | 79 | nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); |
79 | 80 | ||
80 | if (chan->ramfc) | 81 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
81 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | ||
82 | } | 82 | } |
83 | 83 | ||
84 | static void | 84 | static void |
@@ -241,9 +241,9 @@ nv40_fifo_init_ramxx(struct drm_device *dev) | |||
241 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 241 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
242 | 242 | ||
243 | nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | | 243 | nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ | |
244 | ((dev_priv->ramht_bits - 9) << 16) | | 244 | ((dev_priv->ramht->bits - 9) << 16) | |
245 | (dev_priv->ramht_offset >> 8)); | 245 | (dev_priv->ramht->gpuobj->pinst >> 8)); |
246 | nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); | 246 | nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8); |
247 | 247 | ||
248 | switch (dev_priv->chipset) { | 248 | switch (dev_priv->chipset) { |
249 | case 0x47: | 249 | case 0x47: |
@@ -271,7 +271,7 @@ nv40_fifo_init_ramxx(struct drm_device *dev) | |||
271 | nv_wr32(dev, 0x2230, 0); | 271 | nv_wr32(dev, 0x2230, 0); |
272 | nv_wr32(dev, NV40_PFIFO_RAMFC, | 272 | nv_wr32(dev, NV40_PFIFO_RAMFC, |
273 | ((dev_priv->vram_size - 512 * 1024 + | 273 | ((dev_priv->vram_size - 512 * 1024 + |
274 | dev_priv->ramfc_offset) >> 16) | (3 << 16)); | 274 | dev_priv->ramfc->pinst) >> 16) | (3 << 16)); |
275 | break; | 275 | break; |
276 | } | 276 | } |
277 | } | 277 | } |
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index fd7d2b501316..7ee1b91569b8 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c | |||
@@ -45,7 +45,7 @@ nv40_graph_channel(struct drm_device *dev) | |||
45 | struct nouveau_channel *chan = dev_priv->fifos[i]; | 45 | struct nouveau_channel *chan = dev_priv->fifos[i]; |
46 | 46 | ||
47 | if (chan && chan->ramin_grctx && | 47 | if (chan && chan->ramin_grctx && |
48 | chan->ramin_grctx->instance == inst) | 48 | chan->ramin_grctx->pinst == inst) |
49 | return chan; | 49 | return chan; |
50 | } | 50 | } |
51 | 51 | ||
@@ -61,27 +61,25 @@ nv40_graph_create_context(struct nouveau_channel *chan) | |||
61 | struct nouveau_grctx ctx = {}; | 61 | struct nouveau_grctx ctx = {}; |
62 | int ret; | 62 | int ret; |
63 | 63 | ||
64 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, | 64 | ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, |
65 | 16, NVOBJ_FLAG_ZERO_ALLOC, | 65 | NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx); |
66 | &chan->ramin_grctx); | ||
67 | if (ret) | 66 | if (ret) |
68 | return ret; | 67 | return ret; |
69 | 68 | ||
70 | /* Initialise default context values */ | 69 | /* Initialise default context values */ |
71 | ctx.dev = chan->dev; | 70 | ctx.dev = chan->dev; |
72 | ctx.mode = NOUVEAU_GRCTX_VALS; | 71 | ctx.mode = NOUVEAU_GRCTX_VALS; |
73 | ctx.data = chan->ramin_grctx->gpuobj; | 72 | ctx.data = chan->ramin_grctx; |
74 | nv40_grctx_init(&ctx); | 73 | nv40_grctx_init(&ctx); |
75 | 74 | ||
76 | nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, | 75 | nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst); |
77 | chan->ramin_grctx->gpuobj->im_pramin->start); | ||
78 | return 0; | 76 | return 0; |
79 | } | 77 | } |
80 | 78 | ||
81 | void | 79 | void |
82 | nv40_graph_destroy_context(struct nouveau_channel *chan) | 80 | nv40_graph_destroy_context(struct nouveau_channel *chan) |
83 | { | 81 | { |
84 | nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx); | 82 | nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); |
85 | } | 83 | } |
86 | 84 | ||
87 | static int | 85 | static int |
@@ -135,7 +133,7 @@ nv40_graph_load_context(struct nouveau_channel *chan) | |||
135 | 133 | ||
136 | if (!chan->ramin_grctx) | 134 | if (!chan->ramin_grctx) |
137 | return -EINVAL; | 135 | return -EINVAL; |
138 | inst = chan->ramin_grctx->instance >> 4; | 136 | inst = chan->ramin_grctx->pinst >> 4; |
139 | 137 | ||
140 | ret = nv40_graph_transfer_context(dev, inst, 0); | 138 | ret = nv40_graph_transfer_context(dev, inst, 0); |
141 | if (ret) | 139 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/nv40_grctx.c b/drivers/gpu/drm/nouveau/nv40_grctx.c index 9b5c97469588..ce585093264e 100644 --- a/drivers/gpu/drm/nouveau/nv40_grctx.c +++ b/drivers/gpu/drm/nouveau/nv40_grctx.c | |||
@@ -596,13 +596,13 @@ nv40_graph_construct_shader(struct nouveau_grctx *ctx) | |||
596 | 596 | ||
597 | offset += 0x0280/4; | 597 | offset += 0x0280/4; |
598 | for (i = 0; i < 16; i++, offset += 2) | 598 | for (i = 0; i < 16; i++, offset += 2) |
599 | nv_wo32(dev, obj, offset, 0x3f800000); | 599 | nv_wo32(obj, offset * 4, 0x3f800000); |
600 | 600 | ||
601 | for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { | 601 | for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { |
602 | for (i = 0; i < vs_nr_b0 * 6; i += 6) | 602 | for (i = 0; i < vs_nr_b0 * 6; i += 6) |
603 | nv_wo32(dev, obj, offset + b0_offset + i, 0x00000001); | 603 | nv_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001); |
604 | for (i = 0; i < vs_nr_b1 * 4; i += 4) | 604 | for (i = 0; i < vs_nr_b1 * 4; i += 4) |
605 | nv_wo32(dev, obj, offset + b1_offset + i, 0x3f800000); | 605 | nv_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000); |
606 | } | 606 | } |
607 | } | 607 | } |
608 | 608 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index bfd4ca2fe7ef..ba91befd3734 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -104,8 +104,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | |||
104 | OUT_RING(evo, nv_crtc->lut.depth == 8 ? | 104 | OUT_RING(evo, nv_crtc->lut.depth == 8 ? |
105 | NV50_EVO_CRTC_CLUT_MODE_OFF : | 105 | NV50_EVO_CRTC_CLUT_MODE_OFF : |
106 | NV50_EVO_CRTC_CLUT_MODE_ON); | 106 | NV50_EVO_CRTC_CLUT_MODE_ON); |
107 | OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.mm_node->start << | 107 | OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8); |
108 | PAGE_SHIFT) >> 8); | ||
109 | if (dev_priv->chipset != 0x50) { | 108 | if (dev_priv->chipset != 0x50) { |
110 | BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); | 109 | BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); |
111 | OUT_RING(evo, NvEvoVRAM); | 110 | OUT_RING(evo, NvEvoVRAM); |
@@ -266,15 +265,10 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
266 | { | 265 | { |
267 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 266 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
268 | struct pll_lims pll; | 267 | struct pll_lims pll; |
269 | uint32_t reg, reg1, reg2; | 268 | uint32_t reg1, reg2; |
270 | int ret, N1, M1, N2, M2, P; | 269 | int ret, N1, M1, N2, M2, P; |
271 | 270 | ||
272 | if (dev_priv->chipset < NV_C0) | 271 | ret = get_pll_limits(dev, PLL_VPLL0 + head, &pll); |
273 | reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | ||
274 | else | ||
275 | reg = 0x614140 + (head * 0x800); | ||
276 | |||
277 | ret = get_pll_limits(dev, reg, &pll); | ||
278 | if (ret) | 272 | if (ret) |
279 | return ret; | 273 | return ret; |
280 | 274 | ||
@@ -286,11 +280,11 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
286 | NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n", | 280 | NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n", |
287 | pclk, ret, N1, M1, N2, M2, P); | 281 | pclk, ret, N1, M1, N2, M2, P); |
288 | 282 | ||
289 | reg1 = nv_rd32(dev, reg + 4) & 0xff00ff00; | 283 | reg1 = nv_rd32(dev, pll.reg + 4) & 0xff00ff00; |
290 | reg2 = nv_rd32(dev, reg + 8) & 0x8000ff00; | 284 | reg2 = nv_rd32(dev, pll.reg + 8) & 0x8000ff00; |
291 | nv_wr32(dev, reg, 0x10000611); | 285 | nv_wr32(dev, pll.reg + 0, 0x10000611); |
292 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); | 286 | nv_wr32(dev, pll.reg + 4, reg1 | (M1 << 16) | N1); |
293 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); | 287 | nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); |
294 | } else | 288 | } else |
295 | if (dev_priv->chipset < NV_C0) { | 289 | if (dev_priv->chipset < NV_C0) { |
296 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | 290 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); |
@@ -300,10 +294,10 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
300 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | 294 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", |
301 | pclk, ret, N1, N2, M1, P); | 295 | pclk, ret, N1, N2, M1, P); |
302 | 296 | ||
303 | reg1 = nv_rd32(dev, reg + 4) & 0xffc00000; | 297 | reg1 = nv_rd32(dev, pll.reg + 4) & 0xffc00000; |
304 | nv_wr32(dev, reg, 0x50000610); | 298 | nv_wr32(dev, pll.reg + 0, 0x50000610); |
305 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); | 299 | nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); |
306 | nv_wr32(dev, reg + 8, N2); | 300 | nv_wr32(dev, pll.reg + 8, N2); |
307 | } else { | 301 | } else { |
308 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | 302 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); |
309 | if (ret <= 0) | 303 | if (ret <= 0) |
@@ -312,9 +306,9 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
312 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | 306 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", |
313 | pclk, ret, N1, N2, M1, P); | 307 | pclk, ret, N1, N2, M1, P); |
314 | 308 | ||
315 | nv_mask(dev, reg + 0x0c, 0x00000000, 0x00000100); | 309 | nv_mask(dev, pll.reg + 0x0c, 0x00000000, 0x00000100); |
316 | nv_wr32(dev, reg + 0x04, (P << 16) | (N1 << 8) | M1); | 310 | nv_wr32(dev, pll.reg + 0x04, (P << 16) | (N1 << 8) | M1); |
317 | nv_wr32(dev, reg + 0x10, N2 << 16); | 311 | nv_wr32(dev, pll.reg + 0x10, N2 << 16); |
318 | } | 312 | } |
319 | 313 | ||
320 | return 0; | 314 | return 0; |
@@ -338,7 +332,9 @@ nv50_crtc_destroy(struct drm_crtc *crtc) | |||
338 | 332 | ||
339 | nv50_cursor_fini(nv_crtc); | 333 | nv50_cursor_fini(nv_crtc); |
340 | 334 | ||
335 | nouveau_bo_unmap(nv_crtc->lut.nvbo); | ||
341 | nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); | 336 | nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); |
337 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); | ||
342 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); | 338 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); |
343 | kfree(nv_crtc->mode); | 339 | kfree(nv_crtc->mode); |
344 | kfree(nv_crtc); | 340 | kfree(nv_crtc); |
@@ -491,8 +487,9 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
491 | } | 487 | } |
492 | 488 | ||
493 | static int | 489 | static int |
494 | nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, | 490 | nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, |
495 | struct drm_framebuffer *old_fb, bool update) | 491 | struct drm_framebuffer *passed_fb, |
492 | int x, int y, bool update, bool atomic) | ||
496 | { | 493 | { |
497 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 494 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
498 | struct drm_device *dev = nv_crtc->base.dev; | 495 | struct drm_device *dev = nv_crtc->base.dev; |
@@ -504,6 +501,28 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
504 | 501 | ||
505 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 502 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
506 | 503 | ||
504 | /* If atomic, we want to switch to the fb we were passed, so | ||
505 | * now we update pointers to do that. (We don't pin; just | ||
506 | * assume we're already pinned and update the base address.) | ||
507 | */ | ||
508 | if (atomic) { | ||
509 | drm_fb = passed_fb; | ||
510 | fb = nouveau_framebuffer(passed_fb); | ||
511 | } | ||
512 | else { | ||
513 | /* If not atomic, we can go ahead and pin, and unpin the | ||
514 | * old fb we were passed. | ||
515 | */ | ||
516 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | ||
517 | if (ret) | ||
518 | return ret; | ||
519 | |||
520 | if (passed_fb) { | ||
521 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); | ||
522 | nouveau_bo_unpin(ofb->nvbo); | ||
523 | } | ||
524 | } | ||
525 | |||
507 | switch (drm_fb->depth) { | 526 | switch (drm_fb->depth) { |
508 | case 8: | 527 | case 8: |
509 | format = NV50_EVO_CRTC_FB_DEPTH_8; | 528 | format = NV50_EVO_CRTC_FB_DEPTH_8; |
@@ -526,15 +545,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
526 | return -EINVAL; | 545 | return -EINVAL; |
527 | } | 546 | } |
528 | 547 | ||
529 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | ||
530 | if (ret) | ||
531 | return ret; | ||
532 | |||
533 | if (old_fb) { | ||
534 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb); | ||
535 | nouveau_bo_unpin(ofb->nvbo); | ||
536 | } | ||
537 | |||
538 | nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; | 548 | nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; |
539 | nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; | 549 | nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; |
540 | nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; | 550 | nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; |
@@ -685,14 +695,22 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
685 | nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); | 695 | nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); |
686 | nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); | 696 | nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); |
687 | 697 | ||
688 | return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, false); | 698 | return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); |
689 | } | 699 | } |
690 | 700 | ||
691 | static int | 701 | static int |
692 | nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 702 | nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
693 | struct drm_framebuffer *old_fb) | 703 | struct drm_framebuffer *old_fb) |
694 | { | 704 | { |
695 | return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, true); | 705 | return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); |
706 | } | ||
707 | |||
708 | static int | ||
709 | nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, | ||
710 | struct drm_framebuffer *fb, | ||
711 | int x, int y, int enter) | ||
712 | { | ||
713 | return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); | ||
696 | } | 714 | } |
697 | 715 | ||
698 | static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { | 716 | static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { |
@@ -702,6 +720,7 @@ static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { | |||
702 | .mode_fixup = nv50_crtc_mode_fixup, | 720 | .mode_fixup = nv50_crtc_mode_fixup, |
703 | .mode_set = nv50_crtc_mode_set, | 721 | .mode_set = nv50_crtc_mode_set, |
704 | .mode_set_base = nv50_crtc_mode_set_base, | 722 | .mode_set_base = nv50_crtc_mode_set_base, |
723 | .mode_set_base_atomic = nv50_crtc_mode_set_base_atomic, | ||
705 | .load_lut = nv50_crtc_lut_load, | 724 | .load_lut = nv50_crtc_lut_load, |
706 | }; | 725 | }; |
707 | 726 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c index 03ad7ab14f09..1b9ce3021aa3 100644 --- a/drivers/gpu/drm/nouveau/nv50_cursor.c +++ b/drivers/gpu/drm/nouveau/nv50_cursor.c | |||
@@ -147,7 +147,7 @@ nv50_cursor_fini(struct nouveau_crtc *nv_crtc) | |||
147 | NV_DEBUG_KMS(dev, "\n"); | 147 | NV_DEBUG_KMS(dev, "\n"); |
148 | 148 | ||
149 | nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); | 149 | nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); |
150 | if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), | 150 | if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), |
151 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { | 151 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { |
152 | NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); | 152 | NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); |
153 | NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", | 153 | NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", |
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index 1bc085962945..875414b09ade 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c | |||
@@ -79,7 +79,7 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
79 | 79 | ||
80 | nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | 80 | nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), |
81 | 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | 81 | 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); |
82 | if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), | 82 | if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), |
83 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { | 83 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { |
84 | NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); | 84 | NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); |
85 | NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, | 85 | NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, |
@@ -130,7 +130,7 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode) | |||
130 | NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); | 130 | NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); |
131 | 131 | ||
132 | /* wait for it to be done */ | 132 | /* wait for it to be done */ |
133 | if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), | 133 | if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), |
134 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { | 134 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { |
135 | NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); | 135 | NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); |
136 | NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, | 136 | NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 612fa6d6a0cb..55c9663ef2bf 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -30,8 +30,22 @@ | |||
30 | #include "nouveau_connector.h" | 30 | #include "nouveau_connector.h" |
31 | #include "nouveau_fb.h" | 31 | #include "nouveau_fb.h" |
32 | #include "nouveau_fbcon.h" | 32 | #include "nouveau_fbcon.h" |
33 | #include "nouveau_ramht.h" | ||
33 | #include "drm_crtc_helper.h" | 34 | #include "drm_crtc_helper.h" |
34 | 35 | ||
36 | static inline int | ||
37 | nv50_sor_nr(struct drm_device *dev) | ||
38 | { | ||
39 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
40 | |||
41 | if (dev_priv->chipset < 0x90 || | ||
42 | dev_priv->chipset == 0x92 || | ||
43 | dev_priv->chipset == 0xa0) | ||
44 | return 2; | ||
45 | |||
46 | return 4; | ||
47 | } | ||
48 | |||
35 | static void | 49 | static void |
36 | nv50_evo_channel_del(struct nouveau_channel **pchan) | 50 | nv50_evo_channel_del(struct nouveau_channel **pchan) |
37 | { | 51 | { |
@@ -42,6 +56,7 @@ nv50_evo_channel_del(struct nouveau_channel **pchan) | |||
42 | *pchan = NULL; | 56 | *pchan = NULL; |
43 | 57 | ||
44 | nouveau_gpuobj_channel_takedown(chan); | 58 | nouveau_gpuobj_channel_takedown(chan); |
59 | nouveau_bo_unmap(chan->pushbuf_bo); | ||
45 | nouveau_bo_ref(NULL, &chan->pushbuf_bo); | 60 | nouveau_bo_ref(NULL, &chan->pushbuf_bo); |
46 | 61 | ||
47 | if (chan->user) | 62 | if (chan->user) |
@@ -65,23 +80,23 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, | |||
65 | return ret; | 80 | return ret; |
66 | obj->engine = NVOBJ_ENGINE_DISPLAY; | 81 | obj->engine = NVOBJ_ENGINE_DISPLAY; |
67 | 82 | ||
68 | ret = nouveau_gpuobj_ref_add(dev, evo, name, obj, NULL); | 83 | nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); |
69 | if (ret) { | 84 | nv_wo32(obj, 4, limit); |
70 | nouveau_gpuobj_del(dev, &obj); | 85 | nv_wo32(obj, 8, offset); |
71 | return ret; | 86 | nv_wo32(obj, 12, 0x00000000); |
72 | } | 87 | nv_wo32(obj, 16, 0x00000000); |
73 | |||
74 | nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); | ||
75 | nv_wo32(dev, obj, 1, limit); | ||
76 | nv_wo32(dev, obj, 2, offset); | ||
77 | nv_wo32(dev, obj, 3, 0x00000000); | ||
78 | nv_wo32(dev, obj, 4, 0x00000000); | ||
79 | if (dev_priv->card_type < NV_C0) | 88 | if (dev_priv->card_type < NV_C0) |
80 | nv_wo32(dev, obj, 5, 0x00010000); | 89 | nv_wo32(obj, 20, 0x00010000); |
81 | else | 90 | else |
82 | nv_wo32(dev, obj, 5, 0x00020000); | 91 | nv_wo32(obj, 20, 0x00020000); |
83 | dev_priv->engine.instmem.flush(dev); | 92 | dev_priv->engine.instmem.flush(dev); |
84 | 93 | ||
94 | ret = nouveau_ramht_insert(evo, name, obj); | ||
95 | nouveau_gpuobj_ref(NULL, &obj); | ||
96 | if (ret) { | ||
97 | return ret; | ||
98 | } | ||
99 | |||
85 | return 0; | 100 | return 0; |
86 | } | 101 | } |
87 | 102 | ||
@@ -89,6 +104,7 @@ static int | |||
89 | nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) | 104 | nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) |
90 | { | 105 | { |
91 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 106 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
107 | struct nouveau_gpuobj *ramht = NULL; | ||
92 | struct nouveau_channel *chan; | 108 | struct nouveau_channel *chan; |
93 | int ret; | 109 | int ret; |
94 | 110 | ||
@@ -102,32 +118,35 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) | |||
102 | chan->user_get = 4; | 118 | chan->user_get = 4; |
103 | chan->user_put = 0; | 119 | chan->user_put = 0; |
104 | 120 | ||
105 | INIT_LIST_HEAD(&chan->ramht_refs); | 121 | ret = nouveau_gpuobj_new(dev, NULL, 32768, 0x1000, |
106 | 122 | NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); | |
107 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32768, 0x1000, | ||
108 | NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); | ||
109 | if (ret) { | 123 | if (ret) { |
110 | NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); | 124 | NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); |
111 | nv50_evo_channel_del(pchan); | 125 | nv50_evo_channel_del(pchan); |
112 | return ret; | 126 | return ret; |
113 | } | 127 | } |
114 | 128 | ||
115 | ret = drm_mm_init(&chan->ramin_heap, | 129 | ret = drm_mm_init(&chan->ramin_heap, 0, 32768); |
116 | chan->ramin->gpuobj->im_pramin->start, 32768); | ||
117 | if (ret) { | 130 | if (ret) { |
118 | NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); | 131 | NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); |
119 | nv50_evo_channel_del(pchan); | 132 | nv50_evo_channel_del(pchan); |
120 | return ret; | 133 | return ret; |
121 | } | 134 | } |
122 | 135 | ||
123 | ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 4096, 16, | 136 | ret = nouveau_gpuobj_new(dev, chan, 4096, 16, 0, &ramht); |
124 | 0, &chan->ramht); | ||
125 | if (ret) { | 137 | if (ret) { |
126 | NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); | 138 | NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); |
127 | nv50_evo_channel_del(pchan); | 139 | nv50_evo_channel_del(pchan); |
128 | return ret; | 140 | return ret; |
129 | } | 141 | } |
130 | 142 | ||
143 | ret = nouveau_ramht_new(dev, ramht, &chan->ramht); | ||
144 | nouveau_gpuobj_ref(NULL, &ramht); | ||
145 | if (ret) { | ||
146 | nv50_evo_channel_del(pchan); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
131 | if (dev_priv->chipset != 0x50) { | 150 | if (dev_priv->chipset != 0x50) { |
132 | ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, | 151 | ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, |
133 | 0, 0xffffffff); | 152 | 0, 0xffffffff); |
@@ -227,11 +246,11 @@ nv50_display_init(struct drm_device *dev) | |||
227 | nv_wr32(dev, 0x006101d0 + (i * 0x04), val); | 246 | nv_wr32(dev, 0x006101d0 + (i * 0x04), val); |
228 | } | 247 | } |
229 | /* SOR */ | 248 | /* SOR */ |
230 | for (i = 0; i < 4; i++) { | 249 | for (i = 0; i < nv50_sor_nr(dev); i++) { |
231 | val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); | 250 | val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); |
232 | nv_wr32(dev, 0x006101e0 + (i * 0x04), val); | 251 | nv_wr32(dev, 0x006101e0 + (i * 0x04), val); |
233 | } | 252 | } |
234 | /* Something not yet in use, tv-out maybe. */ | 253 | /* EXT */ |
235 | for (i = 0; i < 3; i++) { | 254 | for (i = 0; i < 3; i++) { |
236 | val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); | 255 | val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); |
237 | nv_wr32(dev, 0x006101f0 + (i * 0x04), val); | 256 | nv_wr32(dev, 0x006101f0 + (i * 0x04), val); |
@@ -260,7 +279,7 @@ nv50_display_init(struct drm_device *dev) | |||
260 | if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { | 279 | if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { |
261 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); | 280 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); |
262 | nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); | 281 | nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); |
263 | if (!nv_wait(0x006194e8, 2, 0)) { | 282 | if (!nv_wait(dev, 0x006194e8, 2, 0)) { |
264 | NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); | 283 | NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); |
265 | NV_ERROR(dev, "0x6194e8 = 0x%08x\n", | 284 | NV_ERROR(dev, "0x6194e8 = 0x%08x\n", |
266 | nv_rd32(dev, 0x6194e8)); | 285 | nv_rd32(dev, 0x6194e8)); |
@@ -291,7 +310,8 @@ nv50_display_init(struct drm_device *dev) | |||
291 | 310 | ||
292 | nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); | 311 | nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); |
293 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); | 312 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); |
294 | if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x40000000, 0x40000000)) { | 313 | if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), |
314 | 0x40000000, 0x40000000)) { | ||
295 | NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); | 315 | NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); |
296 | NV_ERROR(dev, "0x610200 = 0x%08x\n", | 316 | NV_ERROR(dev, "0x610200 = 0x%08x\n", |
297 | nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); | 317 | nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); |
@@ -300,7 +320,7 @@ nv50_display_init(struct drm_device *dev) | |||
300 | 320 | ||
301 | for (i = 0; i < 2; i++) { | 321 | for (i = 0; i < 2; i++) { |
302 | nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); | 322 | nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); |
303 | if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 323 | if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), |
304 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { | 324 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { |
305 | NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); | 325 | NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); |
306 | NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", | 326 | NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", |
@@ -310,7 +330,7 @@ nv50_display_init(struct drm_device *dev) | |||
310 | 330 | ||
311 | nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 331 | nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), |
312 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); | 332 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); |
313 | if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 333 | if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), |
314 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, | 334 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, |
315 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { | 335 | NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { |
316 | NV_ERROR(dev, "timeout: " | 336 | NV_ERROR(dev, "timeout: " |
@@ -321,16 +341,16 @@ nv50_display_init(struct drm_device *dev) | |||
321 | } | 341 | } |
322 | } | 342 | } |
323 | 343 | ||
324 | nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->instance >> 8) | 9); | 344 | nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); |
325 | 345 | ||
326 | /* initialise fifo */ | 346 | /* initialise fifo */ |
327 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), | 347 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), |
328 | ((evo->pushbuf_bo->bo.mem.mm_node->start << PAGE_SHIFT) >> 8) | | 348 | ((evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT) >> 8) | |
329 | NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | | 349 | NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | |
330 | NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); | 350 | NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); |
331 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); | 351 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); |
332 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); | 352 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); |
333 | if (!nv_wait(0x610200, 0x80000000, 0x00000000)) { | 353 | if (!nv_wait(dev, 0x610200, 0x80000000, 0x00000000)) { |
334 | NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); | 354 | NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); |
335 | NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); | 355 | NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); |
336 | return -EBUSY; | 356 | return -EBUSY; |
@@ -370,7 +390,7 @@ nv50_display_init(struct drm_device *dev) | |||
370 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); | 390 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); |
371 | OUT_RING(evo, 0); | 391 | OUT_RING(evo, 0); |
372 | FIRE_RING(evo); | 392 | FIRE_RING(evo); |
373 | if (!nv_wait(0x640004, 0xffffffff, evo->dma.put << 2)) | 393 | if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) |
374 | NV_ERROR(dev, "evo pushbuf stalled\n"); | 394 | NV_ERROR(dev, "evo pushbuf stalled\n"); |
375 | 395 | ||
376 | /* enable clock change interrupts. */ | 396 | /* enable clock change interrupts. */ |
@@ -424,7 +444,7 @@ static int nv50_display_disable(struct drm_device *dev) | |||
424 | continue; | 444 | continue; |
425 | 445 | ||
426 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); | 446 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); |
427 | if (!nv_wait(NV50_PDISPLAY_INTR_1, mask, mask)) { | 447 | if (!nv_wait(dev, NV50_PDISPLAY_INTR_1, mask, mask)) { |
428 | NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " | 448 | NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " |
429 | "0x%08x\n", mask, mask); | 449 | "0x%08x\n", mask, mask); |
430 | NV_ERROR(dev, "0x610024 = 0x%08x\n", | 450 | NV_ERROR(dev, "0x610024 = 0x%08x\n", |
@@ -434,14 +454,14 @@ static int nv50_display_disable(struct drm_device *dev) | |||
434 | 454 | ||
435 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); | 455 | nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); |
436 | nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); | 456 | nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); |
437 | if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { | 457 | if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { |
438 | NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); | 458 | NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); |
439 | NV_ERROR(dev, "0x610200 = 0x%08x\n", | 459 | NV_ERROR(dev, "0x610200 = 0x%08x\n", |
440 | nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); | 460 | nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); |
441 | } | 461 | } |
442 | 462 | ||
443 | for (i = 0; i < 3; i++) { | 463 | for (i = 0; i < 3; i++) { |
444 | if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(i), | 464 | if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), |
445 | NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { | 465 | NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { |
446 | NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); | 466 | NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); |
447 | NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, | 467 | NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, |
@@ -710,7 +730,7 @@ nv50_display_unk10_handler(struct drm_device *dev) | |||
710 | or = i; | 730 | or = i; |
711 | } | 731 | } |
712 | 732 | ||
713 | for (i = 0; type == OUTPUT_ANY && i < 4; i++) { | 733 | for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { |
714 | if (dev_priv->chipset < 0x90 || | 734 | if (dev_priv->chipset < 0x90 || |
715 | dev_priv->chipset == 0x92 || | 735 | dev_priv->chipset == 0x92 || |
716 | dev_priv->chipset == 0xa0) | 736 | dev_priv->chipset == 0xa0) |
@@ -841,7 +861,7 @@ nv50_display_unk20_handler(struct drm_device *dev) | |||
841 | or = i; | 861 | or = i; |
842 | } | 862 | } |
843 | 863 | ||
844 | for (i = 0; type == OUTPUT_ANY && i < 4; i++) { | 864 | for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { |
845 | if (dev_priv->chipset < 0x90 || | 865 | if (dev_priv->chipset < 0x90 || |
846 | dev_priv->chipset == 0x92 || | 866 | dev_priv->chipset == 0x92 || |
847 | dev_priv->chipset == 0xa0) | 867 | dev_priv->chipset == 0xa0) |
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c index 32611bd30e6d..cd1988b15d2c 100644 --- a/drivers/gpu/drm/nouveau/nv50_fb.c +++ b/drivers/gpu/drm/nouveau/nv50_fb.c | |||
@@ -20,6 +20,7 @@ nv50_fb_init(struct drm_device *dev) | |||
20 | case 0x50: | 20 | case 0x50: |
21 | nv_wr32(dev, 0x100c90, 0x0707ff); | 21 | nv_wr32(dev, 0x100c90, 0x0707ff); |
22 | break; | 22 | break; |
23 | case 0xa3: | ||
23 | case 0xa5: | 24 | case 0xa5: |
24 | case 0xa8: | 25 | case 0xa8: |
25 | nv_wr32(dev, 0x100c90, 0x0d0fff); | 26 | nv_wr32(dev, 0x100c90, 0x0d0fff); |
@@ -36,3 +37,42 @@ void | |||
36 | nv50_fb_takedown(struct drm_device *dev) | 37 | nv50_fb_takedown(struct drm_device *dev) |
37 | { | 38 | { |
38 | } | 39 | } |
40 | |||
41 | void | ||
42 | nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | ||
43 | { | ||
44 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
45 | u32 trap[6], idx, chinst; | ||
46 | int i, ch; | ||
47 | |||
48 | idx = nv_rd32(dev, 0x100c90); | ||
49 | if (!(idx & 0x80000000)) | ||
50 | return; | ||
51 | idx &= 0x00ffffff; | ||
52 | |||
53 | for (i = 0; i < 6; i++) { | ||
54 | nv_wr32(dev, 0x100c90, idx | i << 24); | ||
55 | trap[i] = nv_rd32(dev, 0x100c94); | ||
56 | } | ||
57 | nv_wr32(dev, 0x100c90, idx | 0x80000000); | ||
58 | |||
59 | if (!display) | ||
60 | return; | ||
61 | |||
62 | chinst = (trap[2] << 16) | trap[1]; | ||
63 | for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { | ||
64 | struct nouveau_channel *chan = dev_priv->fifos[ch]; | ||
65 | |||
66 | if (!chan || !chan->ramin) | ||
67 | continue; | ||
68 | |||
69 | if (chinst == chan->ramin->vinst >> 12) | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " | ||
74 | "channel %d (0x%08x)\n", | ||
75 | name, (trap[5] & 0x100 ? "read" : "write"), | ||
76 | trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, | ||
77 | trap[0], ch, chinst); | ||
78 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 6bf025c6fc6f..6dcf048eddbc 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "drmP.h" | 1 | #include "drmP.h" |
2 | #include "nouveau_drv.h" | 2 | #include "nouveau_drv.h" |
3 | #include "nouveau_dma.h" | 3 | #include "nouveau_dma.h" |
4 | #include "nouveau_ramht.h" | ||
4 | #include "nouveau_fbcon.h" | 5 | #include "nouveau_fbcon.h" |
5 | 6 | ||
6 | void | 7 | void |
@@ -193,7 +194,8 @@ nv50_fbcon_accel_init(struct fb_info *info) | |||
193 | if (ret) | 194 | if (ret) |
194 | return ret; | 195 | return ret; |
195 | 196 | ||
196 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, Nv2D, eng2d, NULL); | 197 | ret = nouveau_ramht_insert(dev_priv->channel, Nv2D, eng2d); |
198 | nouveau_gpuobj_ref(NULL, &eng2d); | ||
197 | if (ret) | 199 | if (ret) |
198 | return ret; | 200 | return ret; |
199 | 201 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index fb0281ae8f90..a46a961102f3 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
@@ -27,13 +27,14 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
30 | #include "nouveau_ramht.h" | ||
30 | 31 | ||
31 | static void | 32 | static void |
32 | nv50_fifo_playlist_update(struct drm_device *dev) | 33 | nv50_fifo_playlist_update(struct drm_device *dev) |
33 | { | 34 | { |
34 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 35 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
35 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; | 36 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; |
36 | struct nouveau_gpuobj_ref *cur; | 37 | struct nouveau_gpuobj *cur; |
37 | int i, nr; | 38 | int i, nr; |
38 | 39 | ||
39 | NV_DEBUG(dev, "\n"); | 40 | NV_DEBUG(dev, "\n"); |
@@ -43,12 +44,14 @@ nv50_fifo_playlist_update(struct drm_device *dev) | |||
43 | 44 | ||
44 | /* We never schedule channel 0 or 127 */ | 45 | /* We never schedule channel 0 or 127 */ |
45 | for (i = 1, nr = 0; i < 127; i++) { | 46 | for (i = 1, nr = 0; i < 127; i++) { |
46 | if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) | 47 | if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) { |
47 | nv_wo32(dev, cur->gpuobj, nr++, i); | 48 | nv_wo32(cur, (nr * 4), i); |
49 | nr++; | ||
50 | } | ||
48 | } | 51 | } |
49 | dev_priv->engine.instmem.flush(dev); | 52 | dev_priv->engine.instmem.flush(dev); |
50 | 53 | ||
51 | nv_wr32(dev, 0x32f4, cur->instance >> 12); | 54 | nv_wr32(dev, 0x32f4, cur->vinst >> 12); |
52 | nv_wr32(dev, 0x32ec, nr); | 55 | nv_wr32(dev, 0x32ec, nr); |
53 | nv_wr32(dev, 0x2500, 0x101); | 56 | nv_wr32(dev, 0x2500, 0x101); |
54 | } | 57 | } |
@@ -63,9 +66,9 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel) | |||
63 | NV_DEBUG(dev, "ch%d\n", channel); | 66 | NV_DEBUG(dev, "ch%d\n", channel); |
64 | 67 | ||
65 | if (dev_priv->chipset == 0x50) | 68 | if (dev_priv->chipset == 0x50) |
66 | inst = chan->ramfc->instance >> 12; | 69 | inst = chan->ramfc->vinst >> 12; |
67 | else | 70 | else |
68 | inst = chan->ramfc->instance >> 8; | 71 | inst = chan->ramfc->vinst >> 8; |
69 | 72 | ||
70 | nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst | | 73 | nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst | |
71 | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); | 74 | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); |
@@ -163,19 +166,19 @@ nv50_fifo_init(struct drm_device *dev) | |||
163 | goto just_reset; | 166 | goto just_reset; |
164 | } | 167 | } |
165 | 168 | ||
166 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, | 169 | ret = nouveau_gpuobj_new(dev, NULL, 128*4, 0x1000, |
167 | NVOBJ_FLAG_ZERO_ALLOC, | 170 | NVOBJ_FLAG_ZERO_ALLOC, |
168 | &pfifo->playlist[0]); | 171 | &pfifo->playlist[0]); |
169 | if (ret) { | 172 | if (ret) { |
170 | NV_ERROR(dev, "error creating playlist 0: %d\n", ret); | 173 | NV_ERROR(dev, "error creating playlist 0: %d\n", ret); |
171 | return ret; | 174 | return ret; |
172 | } | 175 | } |
173 | 176 | ||
174 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, | 177 | ret = nouveau_gpuobj_new(dev, NULL, 128*4, 0x1000, |
175 | NVOBJ_FLAG_ZERO_ALLOC, | 178 | NVOBJ_FLAG_ZERO_ALLOC, |
176 | &pfifo->playlist[1]); | 179 | &pfifo->playlist[1]); |
177 | if (ret) { | 180 | if (ret) { |
178 | nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); | 181 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); |
179 | NV_ERROR(dev, "error creating playlist 1: %d\n", ret); | 182 | NV_ERROR(dev, "error creating playlist 1: %d\n", ret); |
180 | return ret; | 183 | return ret; |
181 | } | 184 | } |
@@ -203,8 +206,8 @@ nv50_fifo_takedown(struct drm_device *dev) | |||
203 | if (!pfifo->playlist[0]) | 206 | if (!pfifo->playlist[0]) |
204 | return; | 207 | return; |
205 | 208 | ||
206 | nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); | 209 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); |
207 | nouveau_gpuobj_ref_del(dev, &pfifo->playlist[1]); | 210 | nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]); |
208 | } | 211 | } |
209 | 212 | ||
210 | int | 213 | int |
@@ -226,59 +229,54 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
226 | NV_DEBUG(dev, "ch%d\n", chan->id); | 229 | NV_DEBUG(dev, "ch%d\n", chan->id); |
227 | 230 | ||
228 | if (dev_priv->chipset == 0x50) { | 231 | if (dev_priv->chipset == 0x50) { |
229 | uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; | 232 | ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst, |
230 | uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; | 233 | chan->ramin->vinst, 0x100, |
231 | 234 | NVOBJ_FLAG_ZERO_ALLOC | | |
232 | ret = nouveau_gpuobj_new_fake(dev, ramin_poffset, ramin_voffset, | 235 | NVOBJ_FLAG_ZERO_FREE, |
233 | 0x100, NVOBJ_FLAG_ZERO_ALLOC | | ||
234 | NVOBJ_FLAG_ZERO_FREE, &ramfc, | ||
235 | &chan->ramfc); | 236 | &chan->ramfc); |
236 | if (ret) | 237 | if (ret) |
237 | return ret; | 238 | return ret; |
238 | 239 | ||
239 | ret = nouveau_gpuobj_new_fake(dev, ramin_poffset + 0x0400, | 240 | ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst + 0x0400, |
240 | ramin_voffset + 0x0400, 4096, | 241 | chan->ramin->vinst + 0x0400, |
241 | 0, NULL, &chan->cache); | 242 | 4096, 0, &chan->cache); |
242 | if (ret) | 243 | if (ret) |
243 | return ret; | 244 | return ret; |
244 | } else { | 245 | } else { |
245 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256, | 246 | ret = nouveau_gpuobj_new(dev, chan, 0x100, 256, |
246 | NVOBJ_FLAG_ZERO_ALLOC | | 247 | NVOBJ_FLAG_ZERO_ALLOC | |
247 | NVOBJ_FLAG_ZERO_FREE, | 248 | NVOBJ_FLAG_ZERO_FREE, &chan->ramfc); |
248 | &chan->ramfc); | ||
249 | if (ret) | 249 | if (ret) |
250 | return ret; | 250 | return ret; |
251 | ramfc = chan->ramfc->gpuobj; | ||
252 | 251 | ||
253 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024, | 252 | ret = nouveau_gpuobj_new(dev, chan, 4096, 1024, |
254 | 0, &chan->cache); | 253 | 0, &chan->cache); |
255 | if (ret) | 254 | if (ret) |
256 | return ret; | 255 | return ret; |
257 | } | 256 | } |
257 | ramfc = chan->ramfc; | ||
258 | 258 | ||
259 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 259 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
260 | 260 | ||
261 | nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); | 261 | nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4); |
262 | nv_wo32(dev, ramfc, 0x80/4, (0 << 27) /* 4KiB */ | | 262 | nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | |
263 | (4 << 24) /* SEARCH_FULL */ | | 263 | (4 << 24) /* SEARCH_FULL */ | |
264 | (chan->ramht->instance >> 4)); | 264 | (chan->ramht->gpuobj->cinst >> 4)); |
265 | nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); | 265 | nv_wo32(ramfc, 0x44, 0x2101ffff); |
266 | nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); | 266 | nv_wo32(ramfc, 0x60, 0x7fffffff); |
267 | nv_wo32(dev, ramfc, 0x40/4, 0x00000000); | 267 | nv_wo32(ramfc, 0x40, 0x00000000); |
268 | nv_wo32(dev, ramfc, 0x7c/4, 0x30000001); | 268 | nv_wo32(ramfc, 0x7c, 0x30000001); |
269 | nv_wo32(dev, ramfc, 0x78/4, 0x00000000); | 269 | nv_wo32(ramfc, 0x78, 0x00000000); |
270 | nv_wo32(dev, ramfc, 0x3c/4, 0x403f6078); | 270 | nv_wo32(ramfc, 0x3c, 0x403f6078); |
271 | nv_wo32(dev, ramfc, 0x50/4, chan->pushbuf_base + | 271 | nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4); |
272 | chan->dma.ib_base * 4); | 272 | nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16); |
273 | nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); | ||
274 | 273 | ||
275 | if (dev_priv->chipset != 0x50) { | 274 | if (dev_priv->chipset != 0x50) { |
276 | nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); | 275 | nv_wo32(chan->ramin, 0, chan->id); |
277 | nv_wo32(dev, chan->ramin->gpuobj, 1, | 276 | nv_wo32(chan->ramin, 4, chan->ramfc->vinst >> 8); |
278 | chan->ramfc->instance >> 8); | ||
279 | 277 | ||
280 | nv_wo32(dev, ramfc, 0x88/4, chan->cache->instance >> 10); | 278 | nv_wo32(ramfc, 0x88, chan->cache->vinst >> 10); |
281 | nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); | 279 | nv_wo32(ramfc, 0x98, chan->ramin->vinst >> 12); |
282 | } | 280 | } |
283 | 281 | ||
284 | dev_priv->engine.instmem.flush(dev); | 282 | dev_priv->engine.instmem.flush(dev); |
@@ -293,12 +291,13 @@ void | |||
293 | nv50_fifo_destroy_context(struct nouveau_channel *chan) | 291 | nv50_fifo_destroy_context(struct nouveau_channel *chan) |
294 | { | 292 | { |
295 | struct drm_device *dev = chan->dev; | 293 | struct drm_device *dev = chan->dev; |
296 | struct nouveau_gpuobj_ref *ramfc = chan->ramfc; | 294 | struct nouveau_gpuobj *ramfc = NULL; |
297 | 295 | ||
298 | NV_DEBUG(dev, "ch%d\n", chan->id); | 296 | NV_DEBUG(dev, "ch%d\n", chan->id); |
299 | 297 | ||
300 | /* This will ensure the channel is seen as disabled. */ | 298 | /* This will ensure the channel is seen as disabled. */ |
301 | chan->ramfc = NULL; | 299 | nouveau_gpuobj_ref(chan->ramfc, &ramfc); |
300 | nouveau_gpuobj_ref(NULL, &chan->ramfc); | ||
302 | nv50_fifo_channel_disable(dev, chan->id); | 301 | nv50_fifo_channel_disable(dev, chan->id); |
303 | 302 | ||
304 | /* Dummy channel, also used on ch 127 */ | 303 | /* Dummy channel, also used on ch 127 */ |
@@ -306,8 +305,8 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) | |||
306 | nv50_fifo_channel_disable(dev, 127); | 305 | nv50_fifo_channel_disable(dev, 127); |
307 | nv50_fifo_playlist_update(dev); | 306 | nv50_fifo_playlist_update(dev); |
308 | 307 | ||
309 | nouveau_gpuobj_ref_del(dev, &ramfc); | 308 | nouveau_gpuobj_ref(NULL, &ramfc); |
310 | nouveau_gpuobj_ref_del(dev, &chan->cache); | 309 | nouveau_gpuobj_ref(NULL, &chan->cache); |
311 | } | 310 | } |
312 | 311 | ||
313 | int | 312 | int |
@@ -315,63 +314,63 @@ nv50_fifo_load_context(struct nouveau_channel *chan) | |||
315 | { | 314 | { |
316 | struct drm_device *dev = chan->dev; | 315 | struct drm_device *dev = chan->dev; |
317 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 316 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
318 | struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj; | 317 | struct nouveau_gpuobj *ramfc = chan->ramfc; |
319 | struct nouveau_gpuobj *cache = chan->cache->gpuobj; | 318 | struct nouveau_gpuobj *cache = chan->cache; |
320 | int ptr, cnt; | 319 | int ptr, cnt; |
321 | 320 | ||
322 | NV_DEBUG(dev, "ch%d\n", chan->id); | 321 | NV_DEBUG(dev, "ch%d\n", chan->id); |
323 | 322 | ||
324 | nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); | 323 | nv_wr32(dev, 0x3330, nv_ro32(ramfc, 0x00)); |
325 | nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); | 324 | nv_wr32(dev, 0x3334, nv_ro32(ramfc, 0x04)); |
326 | nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); | 325 | nv_wr32(dev, 0x3240, nv_ro32(ramfc, 0x08)); |
327 | nv_wr32(dev, 0x3320, nv_ro32(dev, ramfc, 0x0c/4)); | 326 | nv_wr32(dev, 0x3320, nv_ro32(ramfc, 0x0c)); |
328 | nv_wr32(dev, 0x3244, nv_ro32(dev, ramfc, 0x10/4)); | 327 | nv_wr32(dev, 0x3244, nv_ro32(ramfc, 0x10)); |
329 | nv_wr32(dev, 0x3328, nv_ro32(dev, ramfc, 0x14/4)); | 328 | nv_wr32(dev, 0x3328, nv_ro32(ramfc, 0x14)); |
330 | nv_wr32(dev, 0x3368, nv_ro32(dev, ramfc, 0x18/4)); | 329 | nv_wr32(dev, 0x3368, nv_ro32(ramfc, 0x18)); |
331 | nv_wr32(dev, 0x336c, nv_ro32(dev, ramfc, 0x1c/4)); | 330 | nv_wr32(dev, 0x336c, nv_ro32(ramfc, 0x1c)); |
332 | nv_wr32(dev, 0x3370, nv_ro32(dev, ramfc, 0x20/4)); | 331 | nv_wr32(dev, 0x3370, nv_ro32(ramfc, 0x20)); |
333 | nv_wr32(dev, 0x3374, nv_ro32(dev, ramfc, 0x24/4)); | 332 | nv_wr32(dev, 0x3374, nv_ro32(ramfc, 0x24)); |
334 | nv_wr32(dev, 0x3378, nv_ro32(dev, ramfc, 0x28/4)); | 333 | nv_wr32(dev, 0x3378, nv_ro32(ramfc, 0x28)); |
335 | nv_wr32(dev, 0x337c, nv_ro32(dev, ramfc, 0x2c/4)); | 334 | nv_wr32(dev, 0x337c, nv_ro32(ramfc, 0x2c)); |
336 | nv_wr32(dev, 0x3228, nv_ro32(dev, ramfc, 0x30/4)); | 335 | nv_wr32(dev, 0x3228, nv_ro32(ramfc, 0x30)); |
337 | nv_wr32(dev, 0x3364, nv_ro32(dev, ramfc, 0x34/4)); | 336 | nv_wr32(dev, 0x3364, nv_ro32(ramfc, 0x34)); |
338 | nv_wr32(dev, 0x32a0, nv_ro32(dev, ramfc, 0x38/4)); | 337 | nv_wr32(dev, 0x32a0, nv_ro32(ramfc, 0x38)); |
339 | nv_wr32(dev, 0x3224, nv_ro32(dev, ramfc, 0x3c/4)); | 338 | nv_wr32(dev, 0x3224, nv_ro32(ramfc, 0x3c)); |
340 | nv_wr32(dev, 0x324c, nv_ro32(dev, ramfc, 0x40/4)); | 339 | nv_wr32(dev, 0x324c, nv_ro32(ramfc, 0x40)); |
341 | nv_wr32(dev, 0x2044, nv_ro32(dev, ramfc, 0x44/4)); | 340 | nv_wr32(dev, 0x2044, nv_ro32(ramfc, 0x44)); |
342 | nv_wr32(dev, 0x322c, nv_ro32(dev, ramfc, 0x48/4)); | 341 | nv_wr32(dev, 0x322c, nv_ro32(ramfc, 0x48)); |
343 | nv_wr32(dev, 0x3234, nv_ro32(dev, ramfc, 0x4c/4)); | 342 | nv_wr32(dev, 0x3234, nv_ro32(ramfc, 0x4c)); |
344 | nv_wr32(dev, 0x3340, nv_ro32(dev, ramfc, 0x50/4)); | 343 | nv_wr32(dev, 0x3340, nv_ro32(ramfc, 0x50)); |
345 | nv_wr32(dev, 0x3344, nv_ro32(dev, ramfc, 0x54/4)); | 344 | nv_wr32(dev, 0x3344, nv_ro32(ramfc, 0x54)); |
346 | nv_wr32(dev, 0x3280, nv_ro32(dev, ramfc, 0x58/4)); | 345 | nv_wr32(dev, 0x3280, nv_ro32(ramfc, 0x58)); |
347 | nv_wr32(dev, 0x3254, nv_ro32(dev, ramfc, 0x5c/4)); | 346 | nv_wr32(dev, 0x3254, nv_ro32(ramfc, 0x5c)); |
348 | nv_wr32(dev, 0x3260, nv_ro32(dev, ramfc, 0x60/4)); | 347 | nv_wr32(dev, 0x3260, nv_ro32(ramfc, 0x60)); |
349 | nv_wr32(dev, 0x3264, nv_ro32(dev, ramfc, 0x64/4)); | 348 | nv_wr32(dev, 0x3264, nv_ro32(ramfc, 0x64)); |
350 | nv_wr32(dev, 0x3268, nv_ro32(dev, ramfc, 0x68/4)); | 349 | nv_wr32(dev, 0x3268, nv_ro32(ramfc, 0x68)); |
351 | nv_wr32(dev, 0x326c, nv_ro32(dev, ramfc, 0x6c/4)); | 350 | nv_wr32(dev, 0x326c, nv_ro32(ramfc, 0x6c)); |
352 | nv_wr32(dev, 0x32e4, nv_ro32(dev, ramfc, 0x70/4)); | 351 | nv_wr32(dev, 0x32e4, nv_ro32(ramfc, 0x70)); |
353 | nv_wr32(dev, 0x3248, nv_ro32(dev, ramfc, 0x74/4)); | 352 | nv_wr32(dev, 0x3248, nv_ro32(ramfc, 0x74)); |
354 | nv_wr32(dev, 0x2088, nv_ro32(dev, ramfc, 0x78/4)); | 353 | nv_wr32(dev, 0x2088, nv_ro32(ramfc, 0x78)); |
355 | nv_wr32(dev, 0x2058, nv_ro32(dev, ramfc, 0x7c/4)); | 354 | nv_wr32(dev, 0x2058, nv_ro32(ramfc, 0x7c)); |
356 | nv_wr32(dev, 0x2210, nv_ro32(dev, ramfc, 0x80/4)); | 355 | nv_wr32(dev, 0x2210, nv_ro32(ramfc, 0x80)); |
357 | 356 | ||
358 | cnt = nv_ro32(dev, ramfc, 0x84/4); | 357 | cnt = nv_ro32(ramfc, 0x84); |
359 | for (ptr = 0; ptr < cnt; ptr++) { | 358 | for (ptr = 0; ptr < cnt; ptr++) { |
360 | nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr), | 359 | nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr), |
361 | nv_ro32(dev, cache, (ptr * 2) + 0)); | 360 | nv_ro32(cache, (ptr * 8) + 0)); |
362 | nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), | 361 | nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), |
363 | nv_ro32(dev, cache, (ptr * 2) + 1)); | 362 | nv_ro32(cache, (ptr * 8) + 4)); |
364 | } | 363 | } |
365 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2); | 364 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2); |
366 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); | 365 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); |
367 | 366 | ||
368 | /* guessing that all the 0x34xx regs aren't on NV50 */ | 367 | /* guessing that all the 0x34xx regs aren't on NV50 */ |
369 | if (dev_priv->chipset != 0x50) { | 368 | if (dev_priv->chipset != 0x50) { |
370 | nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); | 369 | nv_wr32(dev, 0x340c, nv_ro32(ramfc, 0x88)); |
371 | nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); | 370 | nv_wr32(dev, 0x3400, nv_ro32(ramfc, 0x8c)); |
372 | nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); | 371 | nv_wr32(dev, 0x3404, nv_ro32(ramfc, 0x90)); |
373 | nv_wr32(dev, 0x3408, nv_ro32(dev, ramfc, 0x94/4)); | 372 | nv_wr32(dev, 0x3408, nv_ro32(ramfc, 0x94)); |
374 | nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); | 373 | nv_wr32(dev, 0x3410, nv_ro32(ramfc, 0x98)); |
375 | } | 374 | } |
376 | 375 | ||
377 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); | 376 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); |
@@ -399,62 +398,63 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
399 | return -EINVAL; | 398 | return -EINVAL; |
400 | } | 399 | } |
401 | NV_DEBUG(dev, "ch%d\n", chan->id); | 400 | NV_DEBUG(dev, "ch%d\n", chan->id); |
402 | ramfc = chan->ramfc->gpuobj; | 401 | ramfc = chan->ramfc; |
403 | cache = chan->cache->gpuobj; | 402 | cache = chan->cache; |
404 | 403 | ||
405 | nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); | 404 | nv_wo32(ramfc, 0x00, nv_rd32(dev, 0x3330)); |
406 | nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); | 405 | nv_wo32(ramfc, 0x04, nv_rd32(dev, 0x3334)); |
407 | nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); | 406 | nv_wo32(ramfc, 0x08, nv_rd32(dev, 0x3240)); |
408 | nv_wo32(dev, ramfc, 0x0c/4, nv_rd32(dev, 0x3320)); | 407 | nv_wo32(ramfc, 0x0c, nv_rd32(dev, 0x3320)); |
409 | nv_wo32(dev, ramfc, 0x10/4, nv_rd32(dev, 0x3244)); | 408 | nv_wo32(ramfc, 0x10, nv_rd32(dev, 0x3244)); |
410 | nv_wo32(dev, ramfc, 0x14/4, nv_rd32(dev, 0x3328)); | 409 | nv_wo32(ramfc, 0x14, nv_rd32(dev, 0x3328)); |
411 | nv_wo32(dev, ramfc, 0x18/4, nv_rd32(dev, 0x3368)); | 410 | nv_wo32(ramfc, 0x18, nv_rd32(dev, 0x3368)); |
412 | nv_wo32(dev, ramfc, 0x1c/4, nv_rd32(dev, 0x336c)); | 411 | nv_wo32(ramfc, 0x1c, nv_rd32(dev, 0x336c)); |
413 | nv_wo32(dev, ramfc, 0x20/4, nv_rd32(dev, 0x3370)); | 412 | nv_wo32(ramfc, 0x20, nv_rd32(dev, 0x3370)); |
414 | nv_wo32(dev, ramfc, 0x24/4, nv_rd32(dev, 0x3374)); | 413 | nv_wo32(ramfc, 0x24, nv_rd32(dev, 0x3374)); |
415 | nv_wo32(dev, ramfc, 0x28/4, nv_rd32(dev, 0x3378)); | 414 | nv_wo32(ramfc, 0x28, nv_rd32(dev, 0x3378)); |
416 | nv_wo32(dev, ramfc, 0x2c/4, nv_rd32(dev, 0x337c)); | 415 | nv_wo32(ramfc, 0x2c, nv_rd32(dev, 0x337c)); |
417 | nv_wo32(dev, ramfc, 0x30/4, nv_rd32(dev, 0x3228)); | 416 | nv_wo32(ramfc, 0x30, nv_rd32(dev, 0x3228)); |
418 | nv_wo32(dev, ramfc, 0x34/4, nv_rd32(dev, 0x3364)); | 417 | nv_wo32(ramfc, 0x34, nv_rd32(dev, 0x3364)); |
419 | nv_wo32(dev, ramfc, 0x38/4, nv_rd32(dev, 0x32a0)); | 418 | nv_wo32(ramfc, 0x38, nv_rd32(dev, 0x32a0)); |
420 | nv_wo32(dev, ramfc, 0x3c/4, nv_rd32(dev, 0x3224)); | 419 | nv_wo32(ramfc, 0x3c, nv_rd32(dev, 0x3224)); |
421 | nv_wo32(dev, ramfc, 0x40/4, nv_rd32(dev, 0x324c)); | 420 | nv_wo32(ramfc, 0x40, nv_rd32(dev, 0x324c)); |
422 | nv_wo32(dev, ramfc, 0x44/4, nv_rd32(dev, 0x2044)); | 421 | nv_wo32(ramfc, 0x44, nv_rd32(dev, 0x2044)); |
423 | nv_wo32(dev, ramfc, 0x48/4, nv_rd32(dev, 0x322c)); | 422 | nv_wo32(ramfc, 0x48, nv_rd32(dev, 0x322c)); |
424 | nv_wo32(dev, ramfc, 0x4c/4, nv_rd32(dev, 0x3234)); | 423 | nv_wo32(ramfc, 0x4c, nv_rd32(dev, 0x3234)); |
425 | nv_wo32(dev, ramfc, 0x50/4, nv_rd32(dev, 0x3340)); | 424 | nv_wo32(ramfc, 0x50, nv_rd32(dev, 0x3340)); |
426 | nv_wo32(dev, ramfc, 0x54/4, nv_rd32(dev, 0x3344)); | 425 | nv_wo32(ramfc, 0x54, nv_rd32(dev, 0x3344)); |
427 | nv_wo32(dev, ramfc, 0x58/4, nv_rd32(dev, 0x3280)); | 426 | nv_wo32(ramfc, 0x58, nv_rd32(dev, 0x3280)); |
428 | nv_wo32(dev, ramfc, 0x5c/4, nv_rd32(dev, 0x3254)); | 427 | nv_wo32(ramfc, 0x5c, nv_rd32(dev, 0x3254)); |
429 | nv_wo32(dev, ramfc, 0x60/4, nv_rd32(dev, 0x3260)); | 428 | nv_wo32(ramfc, 0x60, nv_rd32(dev, 0x3260)); |
430 | nv_wo32(dev, ramfc, 0x64/4, nv_rd32(dev, 0x3264)); | 429 | nv_wo32(ramfc, 0x64, nv_rd32(dev, 0x3264)); |
431 | nv_wo32(dev, ramfc, 0x68/4, nv_rd32(dev, 0x3268)); | 430 | nv_wo32(ramfc, 0x68, nv_rd32(dev, 0x3268)); |
432 | nv_wo32(dev, ramfc, 0x6c/4, nv_rd32(dev, 0x326c)); | 431 | nv_wo32(ramfc, 0x6c, nv_rd32(dev, 0x326c)); |
433 | nv_wo32(dev, ramfc, 0x70/4, nv_rd32(dev, 0x32e4)); | 432 | nv_wo32(ramfc, 0x70, nv_rd32(dev, 0x32e4)); |
434 | nv_wo32(dev, ramfc, 0x74/4, nv_rd32(dev, 0x3248)); | 433 | nv_wo32(ramfc, 0x74, nv_rd32(dev, 0x3248)); |
435 | nv_wo32(dev, ramfc, 0x78/4, nv_rd32(dev, 0x2088)); | 434 | nv_wo32(ramfc, 0x78, nv_rd32(dev, 0x2088)); |
436 | nv_wo32(dev, ramfc, 0x7c/4, nv_rd32(dev, 0x2058)); | 435 | nv_wo32(ramfc, 0x7c, nv_rd32(dev, 0x2058)); |
437 | nv_wo32(dev, ramfc, 0x80/4, nv_rd32(dev, 0x2210)); | 436 | nv_wo32(ramfc, 0x80, nv_rd32(dev, 0x2210)); |
438 | 437 | ||
439 | put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2; | 438 | put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2; |
440 | get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2; | 439 | get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2; |
441 | ptr = 0; | 440 | ptr = 0; |
442 | while (put != get) { | 441 | while (put != get) { |
443 | nv_wo32(dev, cache, ptr++, | 442 | nv_wo32(cache, ptr + 0, |
444 | nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); | 443 | nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); |
445 | nv_wo32(dev, cache, ptr++, | 444 | nv_wo32(cache, ptr + 4, |
446 | nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); | 445 | nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); |
447 | get = (get + 1) & 0x1ff; | 446 | get = (get + 1) & 0x1ff; |
447 | ptr += 8; | ||
448 | } | 448 | } |
449 | 449 | ||
450 | /* guessing that all the 0x34xx regs aren't on NV50 */ | 450 | /* guessing that all the 0x34xx regs aren't on NV50 */ |
451 | if (dev_priv->chipset != 0x50) { | 451 | if (dev_priv->chipset != 0x50) { |
452 | nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); | 452 | nv_wo32(ramfc, 0x84, ptr >> 3); |
453 | nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); | 453 | nv_wo32(ramfc, 0x88, nv_rd32(dev, 0x340c)); |
454 | nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); | 454 | nv_wo32(ramfc, 0x8c, nv_rd32(dev, 0x3400)); |
455 | nv_wo32(dev, ramfc, 0x90/4, nv_rd32(dev, 0x3404)); | 455 | nv_wo32(ramfc, 0x90, nv_rd32(dev, 0x3404)); |
456 | nv_wo32(dev, ramfc, 0x94/4, nv_rd32(dev, 0x3408)); | 456 | nv_wo32(ramfc, 0x94, nv_rd32(dev, 0x3408)); |
457 | nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); | 457 | nv_wo32(ramfc, 0x98, nv_rd32(dev, 0x3410)); |
458 | } | 458 | } |
459 | 459 | ||
460 | dev_priv->engine.instmem.flush(dev); | 460 | dev_priv->engine.instmem.flush(dev); |
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 1413028e1580..cbf5ae2f67d4 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
30 | 30 | #include "nouveau_ramht.h" | |
31 | #include "nouveau_grctx.h" | 31 | #include "nouveau_grctx.h" |
32 | 32 | ||
33 | static void | 33 | static void |
@@ -181,7 +181,7 @@ nv50_graph_channel(struct drm_device *dev) | |||
181 | /* Be sure we're not in the middle of a context switch or bad things | 181 | /* Be sure we're not in the middle of a context switch or bad things |
182 | * will happen, such as unloading the wrong pgraph context. | 182 | * will happen, such as unloading the wrong pgraph context. |
183 | */ | 183 | */ |
184 | if (!nv_wait(0x400300, 0x00000001, 0x00000000)) | 184 | if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) |
185 | NV_ERROR(dev, "Ctxprog is still running\n"); | 185 | NV_ERROR(dev, "Ctxprog is still running\n"); |
186 | 186 | ||
187 | inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); | 187 | inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); |
@@ -192,7 +192,7 @@ nv50_graph_channel(struct drm_device *dev) | |||
192 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { | 192 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { |
193 | struct nouveau_channel *chan = dev_priv->fifos[i]; | 193 | struct nouveau_channel *chan = dev_priv->fifos[i]; |
194 | 194 | ||
195 | if (chan && chan->ramin && chan->ramin->instance == inst) | 195 | if (chan && chan->ramin && chan->ramin->vinst == inst) |
196 | return chan; | 196 | return chan; |
197 | } | 197 | } |
198 | 198 | ||
@@ -204,36 +204,34 @@ nv50_graph_create_context(struct nouveau_channel *chan) | |||
204 | { | 204 | { |
205 | struct drm_device *dev = chan->dev; | 205 | struct drm_device *dev = chan->dev; |
206 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 206 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
207 | struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; | 207 | struct nouveau_gpuobj *ramin = chan->ramin; |
208 | struct nouveau_gpuobj *obj; | ||
209 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 208 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
210 | struct nouveau_grctx ctx = {}; | 209 | struct nouveau_grctx ctx = {}; |
211 | int hdr, ret; | 210 | int hdr, ret; |
212 | 211 | ||
213 | NV_DEBUG(dev, "ch%d\n", chan->id); | 212 | NV_DEBUG(dev, "ch%d\n", chan->id); |
214 | 213 | ||
215 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, | 214 | ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0x1000, |
216 | 0x1000, NVOBJ_FLAG_ZERO_ALLOC | | 215 | NVOBJ_FLAG_ZERO_ALLOC | |
217 | NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); | 216 | NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); |
218 | if (ret) | 217 | if (ret) |
219 | return ret; | 218 | return ret; |
220 | obj = chan->ramin_grctx->gpuobj; | ||
221 | 219 | ||
222 | hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; | 220 | hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; |
223 | nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); | 221 | nv_wo32(ramin, hdr + 0x00, 0x00190002); |
224 | nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + | 222 | nv_wo32(ramin, hdr + 0x04, chan->ramin_grctx->vinst + |
225 | pgraph->grctx_size - 1); | 223 | pgraph->grctx_size - 1); |
226 | nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance); | 224 | nv_wo32(ramin, hdr + 0x08, chan->ramin_grctx->vinst); |
227 | nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); | 225 | nv_wo32(ramin, hdr + 0x0c, 0); |
228 | nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); | 226 | nv_wo32(ramin, hdr + 0x10, 0); |
229 | nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); | 227 | nv_wo32(ramin, hdr + 0x14, 0x00010000); |
230 | 228 | ||
231 | ctx.dev = chan->dev; | 229 | ctx.dev = chan->dev; |
232 | ctx.mode = NOUVEAU_GRCTX_VALS; | 230 | ctx.mode = NOUVEAU_GRCTX_VALS; |
233 | ctx.data = obj; | 231 | ctx.data = chan->ramin_grctx; |
234 | nv50_grctx_init(&ctx); | 232 | nv50_grctx_init(&ctx); |
235 | 233 | ||
236 | nv_wo32(dev, obj, 0x00000/4, chan->ramin->instance >> 12); | 234 | nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12); |
237 | 235 | ||
238 | dev_priv->engine.instmem.flush(dev); | 236 | dev_priv->engine.instmem.flush(dev); |
239 | return 0; | 237 | return 0; |
@@ -248,14 +246,14 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) | |||
248 | 246 | ||
249 | NV_DEBUG(dev, "ch%d\n", chan->id); | 247 | NV_DEBUG(dev, "ch%d\n", chan->id); |
250 | 248 | ||
251 | if (!chan->ramin || !chan->ramin->gpuobj) | 249 | if (!chan->ramin) |
252 | return; | 250 | return; |
253 | 251 | ||
254 | for (i = hdr; i < hdr + 24; i += 4) | 252 | for (i = hdr; i < hdr + 24; i += 4) |
255 | nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); | 253 | nv_wo32(chan->ramin, i, 0); |
256 | dev_priv->engine.instmem.flush(dev); | 254 | dev_priv->engine.instmem.flush(dev); |
257 | 255 | ||
258 | nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); | 256 | nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); |
259 | } | 257 | } |
260 | 258 | ||
261 | static int | 259 | static int |
@@ -282,7 +280,7 @@ nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst) | |||
282 | int | 280 | int |
283 | nv50_graph_load_context(struct nouveau_channel *chan) | 281 | nv50_graph_load_context(struct nouveau_channel *chan) |
284 | { | 282 | { |
285 | uint32_t inst = chan->ramin->instance >> 12; | 283 | uint32_t inst = chan->ramin->vinst >> 12; |
286 | 284 | ||
287 | NV_DEBUG(chan->dev, "ch%d\n", chan->id); | 285 | NV_DEBUG(chan->dev, "ch%d\n", chan->id); |
288 | return nv50_graph_do_load_context(chan->dev, inst); | 286 | return nv50_graph_do_load_context(chan->dev, inst); |
@@ -327,15 +325,16 @@ static int | |||
327 | nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, | 325 | nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, |
328 | int mthd, uint32_t data) | 326 | int mthd, uint32_t data) |
329 | { | 327 | { |
330 | struct nouveau_gpuobj_ref *ref = NULL; | 328 | struct nouveau_gpuobj *gpuobj; |
331 | 329 | ||
332 | if (nouveau_gpuobj_ref_find(chan, data, &ref)) | 330 | gpuobj = nouveau_ramht_find(chan, data); |
331 | if (!gpuobj) | ||
333 | return -ENOENT; | 332 | return -ENOENT; |
334 | 333 | ||
335 | if (nouveau_notifier_offset(ref->gpuobj, NULL)) | 334 | if (nouveau_notifier_offset(gpuobj, NULL)) |
336 | return -EINVAL; | 335 | return -EINVAL; |
337 | 336 | ||
338 | chan->nvsw.vblsem = ref->gpuobj; | 337 | chan->nvsw.vblsem = gpuobj; |
339 | chan->nvsw.vblsem_offset = ~0; | 338 | chan->nvsw.vblsem_offset = ~0; |
340 | return 0; | 339 | return 0; |
341 | } | 340 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c index 42a8fb20c1e6..336aab2a24a6 100644 --- a/drivers/gpu/drm/nouveau/nv50_grctx.c +++ b/drivers/gpu/drm/nouveau/nv50_grctx.c | |||
@@ -103,6 +103,9 @@ | |||
103 | #include "nouveau_drv.h" | 103 | #include "nouveau_drv.h" |
104 | #include "nouveau_grctx.h" | 104 | #include "nouveau_grctx.h" |
105 | 105 | ||
106 | #define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) | ||
107 | #define IS_NVAAF(x) ((x) >= 0xaa && (x) <= 0xac) | ||
108 | |||
106 | /* | 109 | /* |
107 | * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's | 110 | * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's |
108 | * the GPU itself that does context-switching, but it needs a special | 111 | * the GPU itself that does context-switching, but it needs a special |
@@ -182,6 +185,7 @@ nv50_grctx_init(struct nouveau_grctx *ctx) | |||
182 | case 0xa8: | 185 | case 0xa8: |
183 | case 0xaa: | 186 | case 0xaa: |
184 | case 0xac: | 187 | case 0xac: |
188 | case 0xaf: | ||
185 | break; | 189 | break; |
186 | default: | 190 | default: |
187 | NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for " | 191 | NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for " |
@@ -268,6 +272,9 @@ nv50_grctx_init(struct nouveau_grctx *ctx) | |||
268 | */ | 272 | */ |
269 | 273 | ||
270 | static void | 274 | static void |
275 | nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx); | ||
276 | |||
277 | static void | ||
271 | nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | 278 | nv50_graph_construct_mmio(struct nouveau_grctx *ctx) |
272 | { | 279 | { |
273 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 280 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
@@ -286,7 +293,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
286 | gr_def(ctx, 0x400840, 0xffe806a8); | 293 | gr_def(ctx, 0x400840, 0xffe806a8); |
287 | } | 294 | } |
288 | gr_def(ctx, 0x400844, 0x00000002); | 295 | gr_def(ctx, 0x400844, 0x00000002); |
289 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 296 | if (IS_NVA3F(dev_priv->chipset)) |
290 | gr_def(ctx, 0x400894, 0x00001000); | 297 | gr_def(ctx, 0x400894, 0x00001000); |
291 | gr_def(ctx, 0x4008e8, 0x00000003); | 298 | gr_def(ctx, 0x4008e8, 0x00000003); |
292 | gr_def(ctx, 0x4008ec, 0x00001000); | 299 | gr_def(ctx, 0x4008ec, 0x00001000); |
@@ -299,13 +306,15 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
299 | 306 | ||
300 | if (dev_priv->chipset >= 0xa0) | 307 | if (dev_priv->chipset >= 0xa0) |
301 | cp_ctx(ctx, 0x400b00, 0x1); | 308 | cp_ctx(ctx, 0x400b00, 0x1); |
302 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 309 | if (IS_NVA3F(dev_priv->chipset)) { |
303 | cp_ctx(ctx, 0x400b10, 0x1); | 310 | cp_ctx(ctx, 0x400b10, 0x1); |
304 | gr_def(ctx, 0x400b10, 0x0001629d); | 311 | gr_def(ctx, 0x400b10, 0x0001629d); |
305 | cp_ctx(ctx, 0x400b20, 0x1); | 312 | cp_ctx(ctx, 0x400b20, 0x1); |
306 | gr_def(ctx, 0x400b20, 0x0001629d); | 313 | gr_def(ctx, 0x400b20, 0x0001629d); |
307 | } | 314 | } |
308 | 315 | ||
316 | nv50_graph_construct_mmio_ddata(ctx); | ||
317 | |||
309 | /* 0C00: VFETCH */ | 318 | /* 0C00: VFETCH */ |
310 | cp_ctx(ctx, 0x400c08, 0x2); | 319 | cp_ctx(ctx, 0x400c08, 0x2); |
311 | gr_def(ctx, 0x400c08, 0x0000fe0c); | 320 | gr_def(ctx, 0x400c08, 0x0000fe0c); |
@@ -314,7 +323,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
314 | if (dev_priv->chipset < 0xa0) { | 323 | if (dev_priv->chipset < 0xa0) { |
315 | cp_ctx(ctx, 0x401008, 0x4); | 324 | cp_ctx(ctx, 0x401008, 0x4); |
316 | gr_def(ctx, 0x401014, 0x00001000); | 325 | gr_def(ctx, 0x401014, 0x00001000); |
317 | } else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) { | 326 | } else if (!IS_NVA3F(dev_priv->chipset)) { |
318 | cp_ctx(ctx, 0x401008, 0x5); | 327 | cp_ctx(ctx, 0x401008, 0x5); |
319 | gr_def(ctx, 0x401018, 0x00001000); | 328 | gr_def(ctx, 0x401018, 0x00001000); |
320 | } else { | 329 | } else { |
@@ -368,10 +377,13 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
368 | case 0xa3: | 377 | case 0xa3: |
369 | case 0xa5: | 378 | case 0xa5: |
370 | case 0xa8: | 379 | case 0xa8: |
380 | case 0xaf: | ||
371 | gr_def(ctx, 0x401c00, 0x142500df); | 381 | gr_def(ctx, 0x401c00, 0x142500df); |
372 | break; | 382 | break; |
373 | } | 383 | } |
374 | 384 | ||
385 | /* 2000 */ | ||
386 | |||
375 | /* 2400 */ | 387 | /* 2400 */ |
376 | cp_ctx(ctx, 0x402400, 0x1); | 388 | cp_ctx(ctx, 0x402400, 0x1); |
377 | if (dev_priv->chipset == 0x50) | 389 | if (dev_priv->chipset == 0x50) |
@@ -380,12 +392,12 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
380 | cp_ctx(ctx, 0x402408, 0x2); | 392 | cp_ctx(ctx, 0x402408, 0x2); |
381 | gr_def(ctx, 0x402408, 0x00000600); | 393 | gr_def(ctx, 0x402408, 0x00000600); |
382 | 394 | ||
383 | /* 2800 */ | 395 | /* 2800: CSCHED */ |
384 | cp_ctx(ctx, 0x402800, 0x1); | 396 | cp_ctx(ctx, 0x402800, 0x1); |
385 | if (dev_priv->chipset == 0x50) | 397 | if (dev_priv->chipset == 0x50) |
386 | gr_def(ctx, 0x402800, 0x00000006); | 398 | gr_def(ctx, 0x402800, 0x00000006); |
387 | 399 | ||
388 | /* 2C00 */ | 400 | /* 2C00: ZCULL */ |
389 | cp_ctx(ctx, 0x402c08, 0x6); | 401 | cp_ctx(ctx, 0x402c08, 0x6); |
390 | if (dev_priv->chipset != 0x50) | 402 | if (dev_priv->chipset != 0x50) |
391 | gr_def(ctx, 0x402c14, 0x01000000); | 403 | gr_def(ctx, 0x402c14, 0x01000000); |
@@ -396,23 +408,23 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
396 | cp_ctx(ctx, 0x402ca0, 0x2); | 408 | cp_ctx(ctx, 0x402ca0, 0x2); |
397 | if (dev_priv->chipset < 0xa0) | 409 | if (dev_priv->chipset < 0xa0) |
398 | gr_def(ctx, 0x402ca0, 0x00000400); | 410 | gr_def(ctx, 0x402ca0, 0x00000400); |
399 | else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) | 411 | else if (!IS_NVA3F(dev_priv->chipset)) |
400 | gr_def(ctx, 0x402ca0, 0x00000800); | 412 | gr_def(ctx, 0x402ca0, 0x00000800); |
401 | else | 413 | else |
402 | gr_def(ctx, 0x402ca0, 0x00000400); | 414 | gr_def(ctx, 0x402ca0, 0x00000400); |
403 | cp_ctx(ctx, 0x402cac, 0x4); | 415 | cp_ctx(ctx, 0x402cac, 0x4); |
404 | 416 | ||
405 | /* 3000 */ | 417 | /* 3000: ENG2D */ |
406 | cp_ctx(ctx, 0x403004, 0x1); | 418 | cp_ctx(ctx, 0x403004, 0x1); |
407 | gr_def(ctx, 0x403004, 0x00000001); | 419 | gr_def(ctx, 0x403004, 0x00000001); |
408 | 420 | ||
409 | /* 3404 */ | 421 | /* 3400 */ |
410 | if (dev_priv->chipset >= 0xa0) { | 422 | if (dev_priv->chipset >= 0xa0) { |
411 | cp_ctx(ctx, 0x403404, 0x1); | 423 | cp_ctx(ctx, 0x403404, 0x1); |
412 | gr_def(ctx, 0x403404, 0x00000001); | 424 | gr_def(ctx, 0x403404, 0x00000001); |
413 | } | 425 | } |
414 | 426 | ||
415 | /* 5000 */ | 427 | /* 5000: CCACHE */ |
416 | cp_ctx(ctx, 0x405000, 0x1); | 428 | cp_ctx(ctx, 0x405000, 0x1); |
417 | switch (dev_priv->chipset) { | 429 | switch (dev_priv->chipset) { |
418 | case 0x50: | 430 | case 0x50: |
@@ -425,6 +437,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
425 | case 0xa8: | 437 | case 0xa8: |
426 | case 0xaa: | 438 | case 0xaa: |
427 | case 0xac: | 439 | case 0xac: |
440 | case 0xaf: | ||
428 | gr_def(ctx, 0x405000, 0x000e0080); | 441 | gr_def(ctx, 0x405000, 0x000e0080); |
429 | break; | 442 | break; |
430 | case 0x86: | 443 | case 0x86: |
@@ -441,210 +454,6 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
441 | cp_ctx(ctx, 0x405024, 0x1); | 454 | cp_ctx(ctx, 0x405024, 0x1); |
442 | cp_ctx(ctx, 0x40502c, 0x1); | 455 | cp_ctx(ctx, 0x40502c, 0x1); |
443 | 456 | ||
444 | /* 5400 or maybe 4800 */ | ||
445 | if (dev_priv->chipset == 0x50) { | ||
446 | offset = 0x405400; | ||
447 | cp_ctx(ctx, 0x405400, 0xea); | ||
448 | } else if (dev_priv->chipset < 0x94) { | ||
449 | offset = 0x405400; | ||
450 | cp_ctx(ctx, 0x405400, 0xcb); | ||
451 | } else if (dev_priv->chipset < 0xa0) { | ||
452 | offset = 0x405400; | ||
453 | cp_ctx(ctx, 0x405400, 0xcc); | ||
454 | } else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | ||
455 | offset = 0x404800; | ||
456 | cp_ctx(ctx, 0x404800, 0xda); | ||
457 | } else { | ||
458 | offset = 0x405400; | ||
459 | cp_ctx(ctx, 0x405400, 0xd4); | ||
460 | } | ||
461 | gr_def(ctx, offset + 0x0c, 0x00000002); | ||
462 | gr_def(ctx, offset + 0x10, 0x00000001); | ||
463 | if (dev_priv->chipset >= 0x94) | ||
464 | offset += 4; | ||
465 | gr_def(ctx, offset + 0x1c, 0x00000001); | ||
466 | gr_def(ctx, offset + 0x20, 0x00000100); | ||
467 | gr_def(ctx, offset + 0x38, 0x00000002); | ||
468 | gr_def(ctx, offset + 0x3c, 0x00000001); | ||
469 | gr_def(ctx, offset + 0x40, 0x00000001); | ||
470 | gr_def(ctx, offset + 0x50, 0x00000001); | ||
471 | gr_def(ctx, offset + 0x54, 0x003fffff); | ||
472 | gr_def(ctx, offset + 0x58, 0x00001fff); | ||
473 | gr_def(ctx, offset + 0x60, 0x00000001); | ||
474 | gr_def(ctx, offset + 0x64, 0x00000001); | ||
475 | gr_def(ctx, offset + 0x6c, 0x00000001); | ||
476 | gr_def(ctx, offset + 0x70, 0x00000001); | ||
477 | gr_def(ctx, offset + 0x74, 0x00000001); | ||
478 | gr_def(ctx, offset + 0x78, 0x00000004); | ||
479 | gr_def(ctx, offset + 0x7c, 0x00000001); | ||
480 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
481 | offset += 4; | ||
482 | gr_def(ctx, offset + 0x80, 0x00000001); | ||
483 | gr_def(ctx, offset + 0x84, 0x00000001); | ||
484 | gr_def(ctx, offset + 0x88, 0x00000007); | ||
485 | gr_def(ctx, offset + 0x8c, 0x00000001); | ||
486 | gr_def(ctx, offset + 0x90, 0x00000007); | ||
487 | gr_def(ctx, offset + 0x94, 0x00000001); | ||
488 | gr_def(ctx, offset + 0x98, 0x00000001); | ||
489 | gr_def(ctx, offset + 0x9c, 0x00000001); | ||
490 | if (dev_priv->chipset == 0x50) { | ||
491 | gr_def(ctx, offset + 0xb0, 0x00000001); | ||
492 | gr_def(ctx, offset + 0xb4, 0x00000001); | ||
493 | gr_def(ctx, offset + 0xbc, 0x00000001); | ||
494 | gr_def(ctx, offset + 0xc0, 0x0000000a); | ||
495 | gr_def(ctx, offset + 0xd0, 0x00000040); | ||
496 | gr_def(ctx, offset + 0xd8, 0x00000002); | ||
497 | gr_def(ctx, offset + 0xdc, 0x00000100); | ||
498 | gr_def(ctx, offset + 0xe0, 0x00000001); | ||
499 | gr_def(ctx, offset + 0xe4, 0x00000100); | ||
500 | gr_def(ctx, offset + 0x100, 0x00000001); | ||
501 | gr_def(ctx, offset + 0x124, 0x00000004); | ||
502 | gr_def(ctx, offset + 0x13c, 0x00000001); | ||
503 | gr_def(ctx, offset + 0x140, 0x00000100); | ||
504 | gr_def(ctx, offset + 0x148, 0x00000001); | ||
505 | gr_def(ctx, offset + 0x154, 0x00000100); | ||
506 | gr_def(ctx, offset + 0x158, 0x00000001); | ||
507 | gr_def(ctx, offset + 0x15c, 0x00000100); | ||
508 | gr_def(ctx, offset + 0x164, 0x00000001); | ||
509 | gr_def(ctx, offset + 0x170, 0x00000100); | ||
510 | gr_def(ctx, offset + 0x174, 0x00000001); | ||
511 | gr_def(ctx, offset + 0x17c, 0x00000001); | ||
512 | gr_def(ctx, offset + 0x188, 0x00000002); | ||
513 | gr_def(ctx, offset + 0x190, 0x00000001); | ||
514 | gr_def(ctx, offset + 0x198, 0x00000001); | ||
515 | gr_def(ctx, offset + 0x1ac, 0x00000003); | ||
516 | offset += 0xd0; | ||
517 | } else { | ||
518 | gr_def(ctx, offset + 0xb0, 0x00000001); | ||
519 | gr_def(ctx, offset + 0xb4, 0x00000100); | ||
520 | gr_def(ctx, offset + 0xbc, 0x00000001); | ||
521 | gr_def(ctx, offset + 0xc8, 0x00000100); | ||
522 | gr_def(ctx, offset + 0xcc, 0x00000001); | ||
523 | gr_def(ctx, offset + 0xd0, 0x00000100); | ||
524 | gr_def(ctx, offset + 0xd8, 0x00000001); | ||
525 | gr_def(ctx, offset + 0xe4, 0x00000100); | ||
526 | } | ||
527 | gr_def(ctx, offset + 0xf8, 0x00000004); | ||
528 | gr_def(ctx, offset + 0xfc, 0x00000070); | ||
529 | gr_def(ctx, offset + 0x100, 0x00000080); | ||
530 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
531 | offset += 4; | ||
532 | gr_def(ctx, offset + 0x114, 0x0000000c); | ||
533 | if (dev_priv->chipset == 0x50) | ||
534 | offset -= 4; | ||
535 | gr_def(ctx, offset + 0x11c, 0x00000008); | ||
536 | gr_def(ctx, offset + 0x120, 0x00000014); | ||
537 | if (dev_priv->chipset == 0x50) { | ||
538 | gr_def(ctx, offset + 0x124, 0x00000026); | ||
539 | offset -= 0x18; | ||
540 | } else { | ||
541 | gr_def(ctx, offset + 0x128, 0x00000029); | ||
542 | gr_def(ctx, offset + 0x12c, 0x00000027); | ||
543 | gr_def(ctx, offset + 0x130, 0x00000026); | ||
544 | gr_def(ctx, offset + 0x134, 0x00000008); | ||
545 | gr_def(ctx, offset + 0x138, 0x00000004); | ||
546 | gr_def(ctx, offset + 0x13c, 0x00000027); | ||
547 | } | ||
548 | gr_def(ctx, offset + 0x148, 0x00000001); | ||
549 | gr_def(ctx, offset + 0x14c, 0x00000002); | ||
550 | gr_def(ctx, offset + 0x150, 0x00000003); | ||
551 | gr_def(ctx, offset + 0x154, 0x00000004); | ||
552 | gr_def(ctx, offset + 0x158, 0x00000005); | ||
553 | gr_def(ctx, offset + 0x15c, 0x00000006); | ||
554 | gr_def(ctx, offset + 0x160, 0x00000007); | ||
555 | gr_def(ctx, offset + 0x164, 0x00000001); | ||
556 | gr_def(ctx, offset + 0x1a8, 0x000000cf); | ||
557 | if (dev_priv->chipset == 0x50) | ||
558 | offset -= 4; | ||
559 | gr_def(ctx, offset + 0x1d8, 0x00000080); | ||
560 | gr_def(ctx, offset + 0x1dc, 0x00000004); | ||
561 | gr_def(ctx, offset + 0x1e0, 0x00000004); | ||
562 | if (dev_priv->chipset == 0x50) | ||
563 | offset -= 4; | ||
564 | else | ||
565 | gr_def(ctx, offset + 0x1e4, 0x00000003); | ||
566 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | ||
567 | gr_def(ctx, offset + 0x1ec, 0x00000003); | ||
568 | offset += 8; | ||
569 | } | ||
570 | gr_def(ctx, offset + 0x1e8, 0x00000001); | ||
571 | if (dev_priv->chipset == 0x50) | ||
572 | offset -= 4; | ||
573 | gr_def(ctx, offset + 0x1f4, 0x00000012); | ||
574 | gr_def(ctx, offset + 0x1f8, 0x00000010); | ||
575 | gr_def(ctx, offset + 0x1fc, 0x0000000c); | ||
576 | gr_def(ctx, offset + 0x200, 0x00000001); | ||
577 | gr_def(ctx, offset + 0x210, 0x00000004); | ||
578 | gr_def(ctx, offset + 0x214, 0x00000002); | ||
579 | gr_def(ctx, offset + 0x218, 0x00000004); | ||
580 | if (dev_priv->chipset >= 0xa0) | ||
581 | offset += 4; | ||
582 | gr_def(ctx, offset + 0x224, 0x003fffff); | ||
583 | gr_def(ctx, offset + 0x228, 0x00001fff); | ||
584 | if (dev_priv->chipset == 0x50) | ||
585 | offset -= 0x20; | ||
586 | else if (dev_priv->chipset >= 0xa0) { | ||
587 | gr_def(ctx, offset + 0x250, 0x00000001); | ||
588 | gr_def(ctx, offset + 0x254, 0x00000001); | ||
589 | gr_def(ctx, offset + 0x258, 0x00000002); | ||
590 | offset += 0x10; | ||
591 | } | ||
592 | gr_def(ctx, offset + 0x250, 0x00000004); | ||
593 | gr_def(ctx, offset + 0x254, 0x00000014); | ||
594 | gr_def(ctx, offset + 0x258, 0x00000001); | ||
595 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
596 | offset += 4; | ||
597 | gr_def(ctx, offset + 0x264, 0x00000002); | ||
598 | if (dev_priv->chipset >= 0xa0) | ||
599 | offset += 8; | ||
600 | gr_def(ctx, offset + 0x270, 0x00000001); | ||
601 | gr_def(ctx, offset + 0x278, 0x00000002); | ||
602 | gr_def(ctx, offset + 0x27c, 0x00001000); | ||
603 | if (dev_priv->chipset == 0x50) | ||
604 | offset -= 0xc; | ||
605 | else { | ||
606 | gr_def(ctx, offset + 0x280, 0x00000e00); | ||
607 | gr_def(ctx, offset + 0x284, 0x00001000); | ||
608 | gr_def(ctx, offset + 0x288, 0x00001e00); | ||
609 | } | ||
610 | gr_def(ctx, offset + 0x290, 0x00000001); | ||
611 | gr_def(ctx, offset + 0x294, 0x00000001); | ||
612 | gr_def(ctx, offset + 0x298, 0x00000001); | ||
613 | gr_def(ctx, offset + 0x29c, 0x00000001); | ||
614 | gr_def(ctx, offset + 0x2a0, 0x00000001); | ||
615 | gr_def(ctx, offset + 0x2b0, 0x00000200); | ||
616 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | ||
617 | gr_def(ctx, offset + 0x2b4, 0x00000200); | ||
618 | offset += 4; | ||
619 | } | ||
620 | if (dev_priv->chipset < 0xa0) { | ||
621 | gr_def(ctx, offset + 0x2b8, 0x00000001); | ||
622 | gr_def(ctx, offset + 0x2bc, 0x00000070); | ||
623 | gr_def(ctx, offset + 0x2c0, 0x00000080); | ||
624 | gr_def(ctx, offset + 0x2cc, 0x00000001); | ||
625 | gr_def(ctx, offset + 0x2d0, 0x00000070); | ||
626 | gr_def(ctx, offset + 0x2d4, 0x00000080); | ||
627 | } else { | ||
628 | gr_def(ctx, offset + 0x2b8, 0x00000001); | ||
629 | gr_def(ctx, offset + 0x2bc, 0x000000f0); | ||
630 | gr_def(ctx, offset + 0x2c0, 0x000000ff); | ||
631 | gr_def(ctx, offset + 0x2cc, 0x00000001); | ||
632 | gr_def(ctx, offset + 0x2d0, 0x000000f0); | ||
633 | gr_def(ctx, offset + 0x2d4, 0x000000ff); | ||
634 | gr_def(ctx, offset + 0x2dc, 0x00000009); | ||
635 | offset += 4; | ||
636 | } | ||
637 | gr_def(ctx, offset + 0x2e4, 0x00000001); | ||
638 | gr_def(ctx, offset + 0x2e8, 0x000000cf); | ||
639 | gr_def(ctx, offset + 0x2f0, 0x00000001); | ||
640 | gr_def(ctx, offset + 0x300, 0x000000cf); | ||
641 | gr_def(ctx, offset + 0x308, 0x00000002); | ||
642 | gr_def(ctx, offset + 0x310, 0x00000001); | ||
643 | gr_def(ctx, offset + 0x318, 0x00000001); | ||
644 | gr_def(ctx, offset + 0x320, 0x000000cf); | ||
645 | gr_def(ctx, offset + 0x324, 0x000000cf); | ||
646 | gr_def(ctx, offset + 0x328, 0x00000001); | ||
647 | |||
648 | /* 6000? */ | 457 | /* 6000? */ |
649 | if (dev_priv->chipset == 0x50) | 458 | if (dev_priv->chipset == 0x50) |
650 | cp_ctx(ctx, 0x4063e0, 0x1); | 459 | cp_ctx(ctx, 0x4063e0, 0x1); |
@@ -661,7 +470,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
661 | gr_def(ctx, 0x406818, 0x00000f80); | 470 | gr_def(ctx, 0x406818, 0x00000f80); |
662 | else | 471 | else |
663 | gr_def(ctx, 0x406818, 0x00001f80); | 472 | gr_def(ctx, 0x406818, 0x00001f80); |
664 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 473 | if (IS_NVA3F(dev_priv->chipset)) |
665 | gr_def(ctx, 0x40681c, 0x00000030); | 474 | gr_def(ctx, 0x40681c, 0x00000030); |
666 | cp_ctx(ctx, 0x406830, 0x3); | 475 | cp_ctx(ctx, 0x406830, 0x3); |
667 | } | 476 | } |
@@ -706,7 +515,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
706 | 515 | ||
707 | if (dev_priv->chipset < 0xa0) | 516 | if (dev_priv->chipset < 0xa0) |
708 | cp_ctx(ctx, 0x407094 + (i<<8), 1); | 517 | cp_ctx(ctx, 0x407094 + (i<<8), 1); |
709 | else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) | 518 | else if (!IS_NVA3F(dev_priv->chipset)) |
710 | cp_ctx(ctx, 0x407094 + (i<<8), 3); | 519 | cp_ctx(ctx, 0x407094 + (i<<8), 3); |
711 | else { | 520 | else { |
712 | cp_ctx(ctx, 0x407094 + (i<<8), 4); | 521 | cp_ctx(ctx, 0x407094 + (i<<8), 4); |
@@ -799,6 +608,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
799 | case 0xa8: | 608 | case 0xa8: |
800 | case 0xaa: | 609 | case 0xaa: |
801 | case 0xac: | 610 | case 0xac: |
611 | case 0xaf: | ||
802 | gr_def(ctx, offset + 0x1c, 0x300c0000); | 612 | gr_def(ctx, offset + 0x1c, 0x300c0000); |
803 | break; | 613 | break; |
804 | } | 614 | } |
@@ -825,7 +635,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
825 | gr_def(ctx, base + 0x304, 0x00007070); | 635 | gr_def(ctx, base + 0x304, 0x00007070); |
826 | else if (dev_priv->chipset < 0xa0) | 636 | else if (dev_priv->chipset < 0xa0) |
827 | gr_def(ctx, base + 0x304, 0x00027070); | 637 | gr_def(ctx, base + 0x304, 0x00027070); |
828 | else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) | 638 | else if (!IS_NVA3F(dev_priv->chipset)) |
829 | gr_def(ctx, base + 0x304, 0x01127070); | 639 | gr_def(ctx, base + 0x304, 0x01127070); |
830 | else | 640 | else |
831 | gr_def(ctx, base + 0x304, 0x05127070); | 641 | gr_def(ctx, base + 0x304, 0x05127070); |
@@ -849,7 +659,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
849 | if (dev_priv->chipset < 0xa0) { | 659 | if (dev_priv->chipset < 0xa0) { |
850 | cp_ctx(ctx, base + 0x340, 9); | 660 | cp_ctx(ctx, base + 0x340, 9); |
851 | offset = base + 0x340; | 661 | offset = base + 0x340; |
852 | } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { | 662 | } else if (!IS_NVA3F(dev_priv->chipset)) { |
853 | cp_ctx(ctx, base + 0x33c, 0xb); | 663 | cp_ctx(ctx, base + 0x33c, 0xb); |
854 | offset = base + 0x344; | 664 | offset = base + 0x344; |
855 | } else { | 665 | } else { |
@@ -880,7 +690,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
880 | gr_def(ctx, offset + 0x0, 0x000001f0); | 690 | gr_def(ctx, offset + 0x0, 0x000001f0); |
881 | gr_def(ctx, offset + 0x4, 0x00000001); | 691 | gr_def(ctx, offset + 0x4, 0x00000001); |
882 | gr_def(ctx, offset + 0x8, 0x00000003); | 692 | gr_def(ctx, offset + 0x8, 0x00000003); |
883 | if (dev_priv->chipset == 0x50 || dev_priv->chipset >= 0xaa) | 693 | if (dev_priv->chipset == 0x50 || IS_NVAAF(dev_priv->chipset)) |
884 | gr_def(ctx, offset + 0xc, 0x00008000); | 694 | gr_def(ctx, offset + 0xc, 0x00008000); |
885 | gr_def(ctx, offset + 0x14, 0x00039e00); | 695 | gr_def(ctx, offset + 0x14, 0x00039e00); |
886 | cp_ctx(ctx, offset + 0x1c, 2); | 696 | cp_ctx(ctx, offset + 0x1c, 2); |
@@ -892,7 +702,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
892 | 702 | ||
893 | if (dev_priv->chipset >= 0xa0) { | 703 | if (dev_priv->chipset >= 0xa0) { |
894 | cp_ctx(ctx, base + 0x54c, 2); | 704 | cp_ctx(ctx, base + 0x54c, 2); |
895 | if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) | 705 | if (!IS_NVA3F(dev_priv->chipset)) |
896 | gr_def(ctx, base + 0x54c, 0x003fe006); | 706 | gr_def(ctx, base + 0x54c, 0x003fe006); |
897 | else | 707 | else |
898 | gr_def(ctx, base + 0x54c, 0x003fe007); | 708 | gr_def(ctx, base + 0x54c, 0x003fe007); |
@@ -948,6 +758,336 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
948 | } | 758 | } |
949 | } | 759 | } |
950 | 760 | ||
761 | static void | ||
762 | dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { | ||
763 | int i; | ||
764 | if (val && ctx->mode == NOUVEAU_GRCTX_VALS) | ||
765 | for (i = 0; i < num; i++) | ||
766 | nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + i), val); | ||
767 | ctx->ctxvals_pos += num; | ||
768 | } | ||
769 | |||
770 | static void | ||
771 | nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) | ||
772 | { | ||
773 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
774 | int base, num; | ||
775 | base = ctx->ctxvals_pos; | ||
776 | |||
777 | /* tesla state */ | ||
778 | dd_emit(ctx, 1, 0); /* 00000001 UNK0F90 */ | ||
779 | dd_emit(ctx, 1, 0); /* 00000001 UNK135C */ | ||
780 | |||
781 | /* SRC_TIC state */ | ||
782 | dd_emit(ctx, 1, 0); /* 00000007 SRC_TILE_MODE_Z */ | ||
783 | dd_emit(ctx, 1, 2); /* 00000007 SRC_TILE_MODE_Y */ | ||
784 | dd_emit(ctx, 1, 1); /* 00000001 SRC_LINEAR #1 */ | ||
785 | dd_emit(ctx, 1, 0); /* 000000ff SRC_ADDRESS_HIGH */ | ||
786 | dd_emit(ctx, 1, 0); /* 00000001 SRC_SRGB */ | ||
787 | if (dev_priv->chipset >= 0x94) | ||
788 | dd_emit(ctx, 1, 0); /* 00000003 eng2d UNK0258 */ | ||
789 | dd_emit(ctx, 1, 1); /* 00000fff SRC_DEPTH */ | ||
790 | dd_emit(ctx, 1, 0x100); /* 0000ffff SRC_HEIGHT */ | ||
791 | |||
792 | /* turing state */ | ||
793 | dd_emit(ctx, 1, 0); /* 0000000f TEXTURES_LOG2 */ | ||
794 | dd_emit(ctx, 1, 0); /* 0000000f SAMPLERS_LOG2 */ | ||
795 | dd_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ | ||
796 | dd_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ | ||
797 | dd_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ | ||
798 | dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ | ||
799 | dd_emit(ctx, 1, 1); /* 0000ffff BLOCK_ALLOC_THREADS */ | ||
800 | dd_emit(ctx, 1, 1); /* 00000001 LANES32 */ | ||
801 | dd_emit(ctx, 1, 0); /* 000000ff UNK370 */ | ||
802 | dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_UNK */ | ||
803 | dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_COUNT */ | ||
804 | dd_emit(ctx, 1, 1); /* 000000ff UNK384 bits 8-15 */ | ||
805 | dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ | ||
806 | dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ | ||
807 | dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ | ||
808 | dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_X */ | ||
809 | dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_XMY */ | ||
810 | dd_emit(ctx, 1, 0); /* 00000001 BLOCKDIM_XMY_OVERFLOW */ | ||
811 | dd_emit(ctx, 1, 1); /* 0003ffff BLOCKDIM_XMYMZ */ | ||
812 | dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_Y */ | ||
813 | dd_emit(ctx, 1, 1); /* 0000007f BLOCKDIM_Z */ | ||
814 | dd_emit(ctx, 1, 4); /* 000000ff CP_REG_ALLOC_TEMP */ | ||
815 | dd_emit(ctx, 1, 1); /* 00000001 BLOCKDIM_DIRTY */ | ||
816 | if (IS_NVA3F(dev_priv->chipset)) | ||
817 | dd_emit(ctx, 1, 0); /* 00000003 UNK03E8 */ | ||
818 | dd_emit(ctx, 1, 1); /* 0000007f BLOCK_ALLOC_HALFWARPS */ | ||
819 | dd_emit(ctx, 1, 1); /* 00000007 LOCAL_WARPS_NO_CLAMP */ | ||
820 | dd_emit(ctx, 1, 7); /* 00000007 LOCAL_WARPS_LOG_ALLOC */ | ||
821 | dd_emit(ctx, 1, 1); /* 00000007 STACK_WARPS_NO_CLAMP */ | ||
822 | dd_emit(ctx, 1, 7); /* 00000007 STACK_WARPS_LOG_ALLOC */ | ||
823 | dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_PACKED */ | ||
824 | dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_STRIDED */ | ||
825 | dd_emit(ctx, 1, 1); /* 000007ff BLOCK_ALLOC_THREADS */ | ||
826 | |||
827 | /* compat 2d state */ | ||
828 | if (dev_priv->chipset == 0x50) { | ||
829 | dd_emit(ctx, 4, 0); /* 0000ffff clip X, Y, W, H */ | ||
830 | |||
831 | dd_emit(ctx, 1, 1); /* ffffffff chroma COLOR_FORMAT */ | ||
832 | |||
833 | dd_emit(ctx, 1, 1); /* ffffffff pattern COLOR_FORMAT */ | ||
834 | dd_emit(ctx, 1, 0); /* ffffffff pattern SHAPE */ | ||
835 | dd_emit(ctx, 1, 1); /* ffffffff pattern PATTERN_SELECT */ | ||
836 | |||
837 | dd_emit(ctx, 1, 0xa); /* ffffffff surf2d SRC_FORMAT */ | ||
838 | dd_emit(ctx, 1, 0); /* ffffffff surf2d DMA_SRC */ | ||
839 | dd_emit(ctx, 1, 0); /* 000000ff surf2d SRC_ADDRESS_HIGH */ | ||
840 | dd_emit(ctx, 1, 0); /* ffffffff surf2d SRC_ADDRESS_LOW */ | ||
841 | dd_emit(ctx, 1, 0x40); /* 0000ffff surf2d SRC_PITCH */ | ||
842 | dd_emit(ctx, 1, 0); /* 0000000f surf2d SRC_TILE_MODE_Z */ | ||
843 | dd_emit(ctx, 1, 2); /* 0000000f surf2d SRC_TILE_MODE_Y */ | ||
844 | dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_HEIGHT */ | ||
845 | dd_emit(ctx, 1, 1); /* 00000001 surf2d SRC_LINEAR */ | ||
846 | dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_WIDTH */ | ||
847 | |||
848 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_X */ | ||
849 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_Y */ | ||
850 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_X */ | ||
851 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_Y */ | ||
852 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_X */ | ||
853 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_Y */ | ||
854 | dd_emit(ctx, 1, 1); /* ffffffff gdirect COLOR_FORMAT */ | ||
855 | dd_emit(ctx, 1, 0); /* ffffffff gdirect OPERATION */ | ||
856 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_X */ | ||
857 | dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_Y */ | ||
858 | |||
859 | dd_emit(ctx, 1, 0); /* 0000ffff blit SRC_Y */ | ||
860 | dd_emit(ctx, 1, 0); /* ffffffff blit OPERATION */ | ||
861 | |||
862 | dd_emit(ctx, 1, 0); /* ffffffff ifc OPERATION */ | ||
863 | |||
864 | dd_emit(ctx, 1, 0); /* ffffffff iifc INDEX_FORMAT */ | ||
865 | dd_emit(ctx, 1, 0); /* ffffffff iifc LUT_OFFSET */ | ||
866 | dd_emit(ctx, 1, 4); /* ffffffff iifc COLOR_FORMAT */ | ||
867 | dd_emit(ctx, 1, 0); /* ffffffff iifc OPERATION */ | ||
868 | } | ||
869 | |||
870 | /* m2mf state */ | ||
871 | dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_COUNT */ | ||
872 | dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_LENGTH_IN */ | ||
873 | dd_emit(ctx, 2, 0); /* ffffffff m2mf OFFSET_IN, OFFSET_OUT */ | ||
874 | dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_OUT */ | ||
875 | dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_OUT */ | ||
876 | dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_OUT_Z */ | ||
877 | dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_OUT */ | ||
878 | dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_OUT_X, Y */ | ||
879 | dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_OUT */ | ||
880 | dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_IN */ | ||
881 | dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_IN */ | ||
882 | dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_IN_Z */ | ||
883 | dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_IN */ | ||
884 | dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_IN_X, Y */ | ||
885 | dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_IN */ | ||
886 | |||
887 | /* more compat 2d state */ | ||
888 | if (dev_priv->chipset == 0x50) { | ||
889 | dd_emit(ctx, 1, 1); /* ffffffff line COLOR_FORMAT */ | ||
890 | dd_emit(ctx, 1, 0); /* ffffffff line OPERATION */ | ||
891 | |||
892 | dd_emit(ctx, 1, 1); /* ffffffff triangle COLOR_FORMAT */ | ||
893 | dd_emit(ctx, 1, 0); /* ffffffff triangle OPERATION */ | ||
894 | |||
895 | dd_emit(ctx, 1, 0); /* 0000000f sifm TILE_MODE_Z */ | ||
896 | dd_emit(ctx, 1, 2); /* 0000000f sifm TILE_MODE_Y */ | ||
897 | dd_emit(ctx, 1, 0); /* 000000ff sifm FORMAT_FILTER */ | ||
898 | dd_emit(ctx, 1, 1); /* 000000ff sifm FORMAT_ORIGIN */ | ||
899 | dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_PITCH */ | ||
900 | dd_emit(ctx, 1, 1); /* 00000001 sifm SRC_LINEAR */ | ||
901 | dd_emit(ctx, 1, 0); /* 000000ff sifm SRC_OFFSET_HIGH */ | ||
902 | dd_emit(ctx, 1, 0); /* ffffffff sifm SRC_OFFSET */ | ||
903 | dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_HEIGHT */ | ||
904 | dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_WIDTH */ | ||
905 | dd_emit(ctx, 1, 3); /* ffffffff sifm COLOR_FORMAT */ | ||
906 | dd_emit(ctx, 1, 0); /* ffffffff sifm OPERATION */ | ||
907 | |||
908 | dd_emit(ctx, 1, 0); /* ffffffff sifc OPERATION */ | ||
909 | } | ||
910 | |||
911 | /* tesla state */ | ||
912 | dd_emit(ctx, 1, 0); /* 0000000f GP_TEXTURES_LOG2 */ | ||
913 | dd_emit(ctx, 1, 0); /* 0000000f GP_SAMPLERS_LOG2 */ | ||
914 | dd_emit(ctx, 1, 0); /* 000000ff */ | ||
915 | dd_emit(ctx, 1, 0); /* ffffffff */ | ||
916 | dd_emit(ctx, 1, 4); /* 000000ff UNK12B0_0 */ | ||
917 | dd_emit(ctx, 1, 0x70); /* 000000ff UNK12B0_1 */ | ||
918 | dd_emit(ctx, 1, 0x80); /* 000000ff UNK12B0_3 */ | ||
919 | dd_emit(ctx, 1, 0); /* 000000ff UNK12B0_2 */ | ||
920 | dd_emit(ctx, 1, 0); /* 0000000f FP_TEXTURES_LOG2 */ | ||
921 | dd_emit(ctx, 1, 0); /* 0000000f FP_SAMPLERS_LOG2 */ | ||
922 | if (IS_NVA3F(dev_priv->chipset)) { | ||
923 | dd_emit(ctx, 1, 0); /* ffffffff */ | ||
924 | dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ | ||
925 | } else { | ||
926 | dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ | ||
927 | } | ||
928 | dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ | ||
929 | if (dev_priv->chipset != 0x50) | ||
930 | dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ | ||
931 | dd_emit(ctx, 1, 8); /* 000000ff SEMANTIC_COLOR.COLR_NR */ | ||
932 | dd_emit(ctx, 1, 0x14); /* 000000ff SEMANTIC_COLOR.FFC0_ID */ | ||
933 | if (dev_priv->chipset == 0x50) { | ||
934 | dd_emit(ctx, 1, 0); /* 000000ff SEMANTIC_LAYER */ | ||
935 | dd_emit(ctx, 1, 0); /* 00000001 */ | ||
936 | } else { | ||
937 | dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_PTSZ.ENABLE */ | ||
938 | dd_emit(ctx, 1, 0x29); /* 000000ff SEMANTIC_PTSZ.PTSZ_ID */ | ||
939 | dd_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM */ | ||
940 | dd_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ | ||
941 | dd_emit(ctx, 1, 8); /* 0000000f SMENATIC_CLIP.CLIP_HIGH */ | ||
942 | dd_emit(ctx, 1, 4); /* 000000ff SEMANTIC_CLIP.CLIP_LO */ | ||
943 | dd_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ | ||
944 | dd_emit(ctx, 1, 0); /* 00000001 UNK1900 */ | ||
945 | } | ||
946 | dd_emit(ctx, 1, 0); /* 00000007 RT_CONTROL_MAP0 */ | ||
947 | dd_emit(ctx, 1, 1); /* 00000007 RT_CONTROL_MAP1 */ | ||
948 | dd_emit(ctx, 1, 2); /* 00000007 RT_CONTROL_MAP2 */ | ||
949 | dd_emit(ctx, 1, 3); /* 00000007 RT_CONTROL_MAP3 */ | ||
950 | dd_emit(ctx, 1, 4); /* 00000007 RT_CONTROL_MAP4 */ | ||
951 | dd_emit(ctx, 1, 5); /* 00000007 RT_CONTROL_MAP5 */ | ||
952 | dd_emit(ctx, 1, 6); /* 00000007 RT_CONTROL_MAP6 */ | ||
953 | dd_emit(ctx, 1, 7); /* 00000007 RT_CONTROL_MAP7 */ | ||
954 | dd_emit(ctx, 1, 1); /* 0000000f RT_CONTROL_COUNT */ | ||
955 | dd_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_UNK */ | ||
956 | dd_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ | ||
957 | dd_emit(ctx, 1, 0xcf); /* 000000ff RT_FORMAT */ | ||
958 | dd_emit(ctx, 7, 0); /* 000000ff RT_FORMAT */ | ||
959 | if (dev_priv->chipset != 0x50) | ||
960 | dd_emit(ctx, 3, 0); /* 1, 1, 1 */ | ||
961 | else | ||
962 | dd_emit(ctx, 2, 0); /* 1, 1 */ | ||
963 | dd_emit(ctx, 1, 0); /* ffffffff GP_ENABLE */ | ||
964 | dd_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT*/ | ||
965 | dd_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ | ||
966 | dd_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
967 | if (IS_NVA3F(dev_priv->chipset)) { | ||
968 | dd_emit(ctx, 1, 3); /* 00000003 */ | ||
969 | dd_emit(ctx, 1, 0); /* 00000001 UNK1418. Alone. */ | ||
970 | } | ||
971 | if (dev_priv->chipset != 0x50) | ||
972 | dd_emit(ctx, 1, 3); /* 00000003 UNK15AC */ | ||
973 | dd_emit(ctx, 1, 1); /* ffffffff RASTERIZE_ENABLE */ | ||
974 | dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.EXPORTS_Z */ | ||
975 | if (dev_priv->chipset != 0x50) | ||
976 | dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.MULTIPLE_RESULTS */ | ||
977 | dd_emit(ctx, 1, 0x12); /* 000000ff FP_INTERPOLANT_CTRL.COUNT */ | ||
978 | dd_emit(ctx, 1, 0x10); /* 000000ff FP_INTERPOLANT_CTRL.COUNT_NONFLAT */ | ||
979 | dd_emit(ctx, 1, 0xc); /* 000000ff FP_INTERPOLANT_CTRL.OFFSET */ | ||
980 | dd_emit(ctx, 1, 1); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.W */ | ||
981 | dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.X */ | ||
982 | dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Y */ | ||
983 | dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Z */ | ||
984 | dd_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ | ||
985 | dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ | ||
986 | dd_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ | ||
987 | if (dev_priv->chipset >= 0xa0) | ||
988 | dd_emit(ctx, 1, 0); /* ffffffff */ | ||
989 | dd_emit(ctx, 1, 0); /* 00000001 GP_BUILTIN_RESULT_EN.LAYER_IDX */ | ||
990 | dd_emit(ctx, 1, 0); /* ffffffff STRMOUT_ENABLE */ | ||
991 | dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ | ||
992 | dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ | ||
993 | dd_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE*/ | ||
994 | if (dev_priv->chipset != 0x50) | ||
995 | dd_emit(ctx, 8, 0); /* 00000001 */ | ||
996 | if (dev_priv->chipset >= 0xa0) { | ||
997 | dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.COMP */ | ||
998 | dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.SIZE */ | ||
999 | dd_emit(ctx, 1, 2); /* 00000007 VTX_ATTR_DEFINE.TYPE */ | ||
1000 | dd_emit(ctx, 1, 0); /* 000000ff VTX_ATTR_DEFINE.ATTR */ | ||
1001 | } | ||
1002 | dd_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
1003 | dd_emit(ctx, 1, 0x14); /* 0000001f ZETA_FORMAT */ | ||
1004 | dd_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ | ||
1005 | dd_emit(ctx, 1, 0); /* 0000000f VP_TEXTURES_LOG2 */ | ||
1006 | dd_emit(ctx, 1, 0); /* 0000000f VP_SAMPLERS_LOG2 */ | ||
1007 | if (IS_NVA3F(dev_priv->chipset)) | ||
1008 | dd_emit(ctx, 1, 0); /* 00000001 */ | ||
1009 | dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_BACK */ | ||
1010 | if (dev_priv->chipset >= 0xa0) | ||
1011 | dd_emit(ctx, 1, 0); /* 00000003 VTX_ATTR_DEFINE.SIZE - 1 */ | ||
1012 | dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ | ||
1013 | if (dev_priv->chipset >= 0xa0) | ||
1014 | dd_emit(ctx, 1, 0); /* 00000003 */ | ||
1015 | dd_emit(ctx, 1, 0); /* 00000001 CULL_FACE_ENABLE */ | ||
1016 | dd_emit(ctx, 1, 1); /* 00000003 CULL_FACE */ | ||
1017 | dd_emit(ctx, 1, 0); /* 00000001 FRONT_FACE */ | ||
1018 | dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_FRONT */ | ||
1019 | dd_emit(ctx, 1, 0x1000); /* 00007fff UNK141C */ | ||
1020 | if (dev_priv->chipset != 0x50) { | ||
1021 | dd_emit(ctx, 1, 0xe00); /* 7fff */ | ||
1022 | dd_emit(ctx, 1, 0x1000); /* 7fff */ | ||
1023 | dd_emit(ctx, 1, 0x1e00); /* 7fff */ | ||
1024 | } | ||
1025 | dd_emit(ctx, 1, 0); /* 00000001 BEGIN_END_ACTIVE */ | ||
1026 | dd_emit(ctx, 1, 1); /* 00000001 POLYGON_MODE_??? */ | ||
1027 | dd_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP / 4 rounded up */ | ||
1028 | dd_emit(ctx, 1, 1); /* 000000ff FP_REG_ALLOC_TEMP... without /4? */ | ||
1029 | dd_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP / 4 rounded up */ | ||
1030 | dd_emit(ctx, 1, 1); /* 00000001 */ | ||
1031 | dd_emit(ctx, 1, 0); /* 00000001 */ | ||
1032 | dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK0 nonempty */ | ||
1033 | dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK1 nonempty */ | ||
1034 | dd_emit(ctx, 1, 0x200); /* 0003ffff GP_VERTEX_OUTPUT_COUNT*GP_REG_ALLOC_RESULT */ | ||
1035 | if (IS_NVA3F(dev_priv->chipset)) | ||
1036 | dd_emit(ctx, 1, 0x200); | ||
1037 | dd_emit(ctx, 1, 0); /* 00000001 */ | ||
1038 | if (dev_priv->chipset < 0xa0) { | ||
1039 | dd_emit(ctx, 1, 1); /* 00000001 */ | ||
1040 | dd_emit(ctx, 1, 0x70); /* 000000ff */ | ||
1041 | dd_emit(ctx, 1, 0x80); /* 000000ff */ | ||
1042 | dd_emit(ctx, 1, 0); /* 000000ff */ | ||
1043 | dd_emit(ctx, 1, 0); /* 00000001 */ | ||
1044 | dd_emit(ctx, 1, 1); /* 00000001 */ | ||
1045 | dd_emit(ctx, 1, 0x70); /* 000000ff */ | ||
1046 | dd_emit(ctx, 1, 0x80); /* 000000ff */ | ||
1047 | dd_emit(ctx, 1, 0); /* 000000ff */ | ||
1048 | } else { | ||
1049 | dd_emit(ctx, 1, 1); /* 00000001 */ | ||
1050 | dd_emit(ctx, 1, 0xf0); /* 000000ff */ | ||
1051 | dd_emit(ctx, 1, 0xff); /* 000000ff */ | ||
1052 | dd_emit(ctx, 1, 0); /* 000000ff */ | ||
1053 | dd_emit(ctx, 1, 0); /* 00000001 */ | ||
1054 | dd_emit(ctx, 1, 1); /* 00000001 */ | ||
1055 | dd_emit(ctx, 1, 0xf0); /* 000000ff */ | ||
1056 | dd_emit(ctx, 1, 0xff); /* 000000ff */ | ||
1057 | dd_emit(ctx, 1, 0); /* 000000ff */ | ||
1058 | dd_emit(ctx, 1, 9); /* 0000003f UNK114C.COMP,SIZE */ | ||
1059 | } | ||
1060 | |||
1061 | /* eng2d state */ | ||
1062 | dd_emit(ctx, 1, 0); /* 00000001 eng2d COLOR_KEY_ENABLE */ | ||
1063 | dd_emit(ctx, 1, 0); /* 00000007 eng2d COLOR_KEY_FORMAT */ | ||
1064 | dd_emit(ctx, 1, 1); /* ffffffff eng2d DST_DEPTH */ | ||
1065 | dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DST_FORMAT */ | ||
1066 | dd_emit(ctx, 1, 0); /* ffffffff eng2d DST_LAYER */ | ||
1067 | dd_emit(ctx, 1, 1); /* 00000001 eng2d DST_LINEAR */ | ||
1068 | dd_emit(ctx, 1, 0); /* 00000007 eng2d PATTERN_COLOR_FORMAT */ | ||
1069 | dd_emit(ctx, 1, 0); /* 00000007 eng2d OPERATION */ | ||
1070 | dd_emit(ctx, 1, 0); /* 00000003 eng2d PATTERN_SELECT */ | ||
1071 | dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SIFC_FORMAT */ | ||
1072 | dd_emit(ctx, 1, 0); /* 00000001 eng2d SIFC_BITMAP_ENABLE */ | ||
1073 | dd_emit(ctx, 1, 2); /* 00000003 eng2d SIFC_BITMAP_UNK808 */ | ||
1074 | dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DU_DX_FRACT */ | ||
1075 | dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DU_DX_INT */ | ||
1076 | dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DV_DY_FRACT */ | ||
1077 | dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DV_DY_INT */ | ||
1078 | dd_emit(ctx, 1, 0); /* 00000001 eng2d BLIT_CONTROL_FILTER */ | ||
1079 | dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DRAW_COLOR_FORMAT */ | ||
1080 | dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SRC_FORMAT */ | ||
1081 | dd_emit(ctx, 1, 1); /* 00000001 eng2d SRC_LINEAR #2 */ | ||
1082 | |||
1083 | num = ctx->ctxvals_pos - base; | ||
1084 | ctx->ctxvals_pos = base; | ||
1085 | if (IS_NVA3F(dev_priv->chipset)) | ||
1086 | cp_ctx(ctx, 0x404800, num); | ||
1087 | else | ||
1088 | cp_ctx(ctx, 0x405400, num); | ||
1089 | } | ||
1090 | |||
951 | /* | 1091 | /* |
952 | * xfer areas. These are a pain. | 1092 | * xfer areas. These are a pain. |
953 | * | 1093 | * |
@@ -990,28 +1130,33 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) | |||
990 | * without the help of ctxprog. | 1130 | * without the help of ctxprog. |
991 | */ | 1131 | */ |
992 | 1132 | ||
993 | static inline void | 1133 | static void |
994 | xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { | 1134 | xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { |
995 | int i; | 1135 | int i; |
996 | if (val && ctx->mode == NOUVEAU_GRCTX_VALS) | 1136 | if (val && ctx->mode == NOUVEAU_GRCTX_VALS) |
997 | for (i = 0; i < num; i++) | 1137 | for (i = 0; i < num; i++) |
998 | nv_wo32(ctx->dev, ctx->data, ctx->ctxvals_pos + (i << 3), val); | 1138 | nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val); |
999 | ctx->ctxvals_pos += num << 3; | 1139 | ctx->ctxvals_pos += num << 3; |
1000 | } | 1140 | } |
1001 | 1141 | ||
1002 | /* Gene declarations... */ | 1142 | /* Gene declarations... */ |
1003 | 1143 | ||
1144 | static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx); | ||
1004 | static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx); | 1145 | static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx); |
1005 | static void nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx); | 1146 | static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx); |
1006 | static void nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx); | 1147 | static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx); |
1007 | static void nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx); | 1148 | static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx); |
1008 | static void nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx); | 1149 | static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx); |
1009 | static void nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx); | 1150 | static void nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx); |
1010 | static void nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx); | 1151 | static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx); |
1011 | static void nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx); | 1152 | static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx); |
1012 | static void nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx); | 1153 | static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx); |
1013 | static void nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx); | 1154 | static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx); |
1014 | static void nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx); | 1155 | static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx); |
1156 | static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx); | ||
1157 | static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx); | ||
1158 | static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx); | ||
1159 | static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx); | ||
1015 | static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx); | 1160 | static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx); |
1016 | static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx); | 1161 | static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx); |
1017 | 1162 | ||
@@ -1030,102 +1175,32 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) | |||
1030 | if (dev_priv->chipset < 0xa0) { | 1175 | if (dev_priv->chipset < 0xa0) { |
1031 | /* Strand 0 */ | 1176 | /* Strand 0 */ |
1032 | ctx->ctxvals_pos = offset; | 1177 | ctx->ctxvals_pos = offset; |
1033 | switch (dev_priv->chipset) { | 1178 | nv50_graph_construct_gene_dispatch(ctx); |
1034 | case 0x50: | 1179 | nv50_graph_construct_gene_m2mf(ctx); |
1035 | xf_emit(ctx, 0x99, 0); | 1180 | nv50_graph_construct_gene_unk24xx(ctx); |
1036 | break; | 1181 | nv50_graph_construct_gene_clipid(ctx); |
1037 | case 0x84: | 1182 | nv50_graph_construct_gene_zcull(ctx); |
1038 | case 0x86: | ||
1039 | xf_emit(ctx, 0x384, 0); | ||
1040 | break; | ||
1041 | case 0x92: | ||
1042 | case 0x94: | ||
1043 | case 0x96: | ||
1044 | case 0x98: | ||
1045 | xf_emit(ctx, 0x380, 0); | ||
1046 | break; | ||
1047 | } | ||
1048 | nv50_graph_construct_gene_m2mf (ctx); | ||
1049 | switch (dev_priv->chipset) { | ||
1050 | case 0x50: | ||
1051 | case 0x84: | ||
1052 | case 0x86: | ||
1053 | case 0x98: | ||
1054 | xf_emit(ctx, 0x4c4, 0); | ||
1055 | break; | ||
1056 | case 0x92: | ||
1057 | case 0x94: | ||
1058 | case 0x96: | ||
1059 | xf_emit(ctx, 0x984, 0); | ||
1060 | break; | ||
1061 | } | ||
1062 | nv50_graph_construct_gene_unk5(ctx); | ||
1063 | if (dev_priv->chipset == 0x50) | ||
1064 | xf_emit(ctx, 0xa, 0); | ||
1065 | else | ||
1066 | xf_emit(ctx, 0xb, 0); | ||
1067 | nv50_graph_construct_gene_unk4(ctx); | ||
1068 | nv50_graph_construct_gene_unk3(ctx); | ||
1069 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1183 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1070 | size = (ctx->ctxvals_pos-offset)/8; | 1184 | size = (ctx->ctxvals_pos-offset)/8; |
1071 | 1185 | ||
1072 | /* Strand 1 */ | 1186 | /* Strand 1 */ |
1073 | ctx->ctxvals_pos = offset + 0x1; | 1187 | ctx->ctxvals_pos = offset + 0x1; |
1074 | nv50_graph_construct_gene_unk6(ctx); | 1188 | nv50_graph_construct_gene_vfetch(ctx); |
1075 | nv50_graph_construct_gene_unk7(ctx); | 1189 | nv50_graph_construct_gene_eng2d(ctx); |
1076 | nv50_graph_construct_gene_unk8(ctx); | 1190 | nv50_graph_construct_gene_csched(ctx); |
1077 | switch (dev_priv->chipset) { | 1191 | nv50_graph_construct_gene_ropm1(ctx); |
1078 | case 0x50: | 1192 | nv50_graph_construct_gene_ropm2(ctx); |
1079 | case 0x92: | ||
1080 | xf_emit(ctx, 0xfb, 0); | ||
1081 | break; | ||
1082 | case 0x84: | ||
1083 | xf_emit(ctx, 0xd3, 0); | ||
1084 | break; | ||
1085 | case 0x94: | ||
1086 | case 0x96: | ||
1087 | xf_emit(ctx, 0xab, 0); | ||
1088 | break; | ||
1089 | case 0x86: | ||
1090 | case 0x98: | ||
1091 | xf_emit(ctx, 0x6b, 0); | ||
1092 | break; | ||
1093 | } | ||
1094 | xf_emit(ctx, 2, 0x4e3bfdf); | ||
1095 | xf_emit(ctx, 4, 0); | ||
1096 | xf_emit(ctx, 1, 0x0fac6881); | ||
1097 | xf_emit(ctx, 0xb, 0); | ||
1098 | xf_emit(ctx, 2, 0x4e3bfdf); | ||
1099 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1193 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1100 | size = (ctx->ctxvals_pos-offset)/8; | 1194 | size = (ctx->ctxvals_pos-offset)/8; |
1101 | 1195 | ||
1102 | /* Strand 2 */ | 1196 | /* Strand 2 */ |
1103 | ctx->ctxvals_pos = offset + 0x2; | 1197 | ctx->ctxvals_pos = offset + 0x2; |
1104 | switch (dev_priv->chipset) { | 1198 | nv50_graph_construct_gene_ccache(ctx); |
1105 | case 0x50: | 1199 | nv50_graph_construct_gene_unk1cxx(ctx); |
1106 | case 0x92: | 1200 | nv50_graph_construct_gene_strmout(ctx); |
1107 | xf_emit(ctx, 0xa80, 0); | 1201 | nv50_graph_construct_gene_unk14xx(ctx); |
1108 | break; | 1202 | nv50_graph_construct_gene_unk10xx(ctx); |
1109 | case 0x84: | 1203 | nv50_graph_construct_gene_unk34xx(ctx); |
1110 | xf_emit(ctx, 0xa7e, 0); | ||
1111 | break; | ||
1112 | case 0x94: | ||
1113 | case 0x96: | ||
1114 | xf_emit(ctx, 0xa7c, 0); | ||
1115 | break; | ||
1116 | case 0x86: | ||
1117 | case 0x98: | ||
1118 | xf_emit(ctx, 0xa7a, 0); | ||
1119 | break; | ||
1120 | } | ||
1121 | xf_emit(ctx, 1, 0x3fffff); | ||
1122 | xf_emit(ctx, 2, 0); | ||
1123 | xf_emit(ctx, 1, 0x1fff); | ||
1124 | xf_emit(ctx, 0xe, 0); | ||
1125 | nv50_graph_construct_gene_unk9(ctx); | ||
1126 | nv50_graph_construct_gene_unk2(ctx); | ||
1127 | nv50_graph_construct_gene_unk1(ctx); | ||
1128 | nv50_graph_construct_gene_unk10(ctx); | ||
1129 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1204 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1130 | size = (ctx->ctxvals_pos-offset)/8; | 1205 | size = (ctx->ctxvals_pos-offset)/8; |
1131 | 1206 | ||
@@ -1150,86 +1225,46 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) | |||
1150 | } else { | 1225 | } else { |
1151 | /* Strand 0 */ | 1226 | /* Strand 0 */ |
1152 | ctx->ctxvals_pos = offset; | 1227 | ctx->ctxvals_pos = offset; |
1153 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 1228 | nv50_graph_construct_gene_dispatch(ctx); |
1154 | xf_emit(ctx, 0x385, 0); | ||
1155 | else | ||
1156 | xf_emit(ctx, 0x384, 0); | ||
1157 | nv50_graph_construct_gene_m2mf(ctx); | 1229 | nv50_graph_construct_gene_m2mf(ctx); |
1158 | xf_emit(ctx, 0x950, 0); | 1230 | nv50_graph_construct_gene_unk34xx(ctx); |
1159 | nv50_graph_construct_gene_unk10(ctx); | 1231 | nv50_graph_construct_gene_csched(ctx); |
1160 | xf_emit(ctx, 1, 0x0fac6881); | 1232 | nv50_graph_construct_gene_unk1cxx(ctx); |
1161 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 1233 | nv50_graph_construct_gene_strmout(ctx); |
1162 | xf_emit(ctx, 1, 1); | ||
1163 | xf_emit(ctx, 3, 0); | ||
1164 | } | ||
1165 | nv50_graph_construct_gene_unk8(ctx); | ||
1166 | if (dev_priv->chipset == 0xa0) | ||
1167 | xf_emit(ctx, 0x189, 0); | ||
1168 | else if (dev_priv->chipset == 0xa3) | ||
1169 | xf_emit(ctx, 0xd5, 0); | ||
1170 | else if (dev_priv->chipset == 0xa5) | ||
1171 | xf_emit(ctx, 0x99, 0); | ||
1172 | else if (dev_priv->chipset == 0xaa) | ||
1173 | xf_emit(ctx, 0x65, 0); | ||
1174 | else | ||
1175 | xf_emit(ctx, 0x6d, 0); | ||
1176 | nv50_graph_construct_gene_unk9(ctx); | ||
1177 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1234 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1178 | size = (ctx->ctxvals_pos-offset)/8; | 1235 | size = (ctx->ctxvals_pos-offset)/8; |
1179 | 1236 | ||
1180 | /* Strand 1 */ | 1237 | /* Strand 1 */ |
1181 | ctx->ctxvals_pos = offset + 1; | 1238 | ctx->ctxvals_pos = offset + 1; |
1182 | nv50_graph_construct_gene_unk1(ctx); | 1239 | nv50_graph_construct_gene_unk10xx(ctx); |
1183 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1240 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1184 | size = (ctx->ctxvals_pos-offset)/8; | 1241 | size = (ctx->ctxvals_pos-offset)/8; |
1185 | 1242 | ||
1186 | /* Strand 2 */ | 1243 | /* Strand 2 */ |
1187 | ctx->ctxvals_pos = offset + 2; | 1244 | ctx->ctxvals_pos = offset + 2; |
1188 | if (dev_priv->chipset == 0xa0) { | 1245 | if (dev_priv->chipset == 0xa0) |
1189 | nv50_graph_construct_gene_unk2(ctx); | 1246 | nv50_graph_construct_gene_unk14xx(ctx); |
1190 | } | 1247 | nv50_graph_construct_gene_unk24xx(ctx); |
1191 | xf_emit(ctx, 0x36, 0); | ||
1192 | nv50_graph_construct_gene_unk5(ctx); | ||
1193 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1248 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1194 | size = (ctx->ctxvals_pos-offset)/8; | 1249 | size = (ctx->ctxvals_pos-offset)/8; |
1195 | 1250 | ||
1196 | /* Strand 3 */ | 1251 | /* Strand 3 */ |
1197 | ctx->ctxvals_pos = offset + 3; | 1252 | ctx->ctxvals_pos = offset + 3; |
1198 | xf_emit(ctx, 1, 0); | 1253 | nv50_graph_construct_gene_vfetch(ctx); |
1199 | xf_emit(ctx, 1, 1); | ||
1200 | nv50_graph_construct_gene_unk6(ctx); | ||
1201 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1254 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1202 | size = (ctx->ctxvals_pos-offset)/8; | 1255 | size = (ctx->ctxvals_pos-offset)/8; |
1203 | 1256 | ||
1204 | /* Strand 4 */ | 1257 | /* Strand 4 */ |
1205 | ctx->ctxvals_pos = offset + 4; | 1258 | ctx->ctxvals_pos = offset + 4; |
1206 | if (dev_priv->chipset == 0xa0) | 1259 | nv50_graph_construct_gene_ccache(ctx); |
1207 | xf_emit(ctx, 0xa80, 0); | ||
1208 | else if (dev_priv->chipset == 0xa3) | ||
1209 | xf_emit(ctx, 0xa7c, 0); | ||
1210 | else | ||
1211 | xf_emit(ctx, 0xa7a, 0); | ||
1212 | xf_emit(ctx, 1, 0x3fffff); | ||
1213 | xf_emit(ctx, 2, 0); | ||
1214 | xf_emit(ctx, 1, 0x1fff); | ||
1215 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1260 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1216 | size = (ctx->ctxvals_pos-offset)/8; | 1261 | size = (ctx->ctxvals_pos-offset)/8; |
1217 | 1262 | ||
1218 | /* Strand 5 */ | 1263 | /* Strand 5 */ |
1219 | ctx->ctxvals_pos = offset + 5; | 1264 | ctx->ctxvals_pos = offset + 5; |
1220 | xf_emit(ctx, 1, 0); | 1265 | nv50_graph_construct_gene_ropm2(ctx); |
1221 | xf_emit(ctx, 1, 0x0fac6881); | 1266 | nv50_graph_construct_gene_ropm1(ctx); |
1222 | xf_emit(ctx, 0xb, 0); | 1267 | /* per-ROP context */ |
1223 | xf_emit(ctx, 2, 0x4e3bfdf); | ||
1224 | xf_emit(ctx, 3, 0); | ||
1225 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
1226 | xf_emit(ctx, 1, 0x11); | ||
1227 | xf_emit(ctx, 1, 0); | ||
1228 | xf_emit(ctx, 2, 0x4e3bfdf); | ||
1229 | xf_emit(ctx, 2, 0); | ||
1230 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
1231 | xf_emit(ctx, 1, 0x11); | ||
1232 | xf_emit(ctx, 1, 0); | ||
1233 | for (i = 0; i < 8; i++) | 1268 | for (i = 0; i < 8; i++) |
1234 | if (units & (1<<(i+16))) | 1269 | if (units & (1<<(i+16))) |
1235 | nv50_graph_construct_gene_ropc(ctx); | 1270 | nv50_graph_construct_gene_ropc(ctx); |
@@ -1238,10 +1273,9 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) | |||
1238 | 1273 | ||
1239 | /* Strand 6 */ | 1274 | /* Strand 6 */ |
1240 | ctx->ctxvals_pos = offset + 6; | 1275 | ctx->ctxvals_pos = offset + 6; |
1241 | nv50_graph_construct_gene_unk3(ctx); | 1276 | nv50_graph_construct_gene_zcull(ctx); |
1242 | xf_emit(ctx, 0xb, 0); | 1277 | nv50_graph_construct_gene_clipid(ctx); |
1243 | nv50_graph_construct_gene_unk4(ctx); | 1278 | nv50_graph_construct_gene_eng2d(ctx); |
1244 | nv50_graph_construct_gene_unk7(ctx); | ||
1245 | if (units & (1 << 0)) | 1279 | if (units & (1 << 0)) |
1246 | nv50_graph_construct_xfer_tp(ctx); | 1280 | nv50_graph_construct_xfer_tp(ctx); |
1247 | if (units & (1 << 1)) | 1281 | if (units & (1 << 1)) |
@@ -1269,7 +1303,7 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) | |||
1269 | if (units & (1 << 9)) | 1303 | if (units & (1 << 9)) |
1270 | nv50_graph_construct_xfer_tp(ctx); | 1304 | nv50_graph_construct_xfer_tp(ctx); |
1271 | } else { | 1305 | } else { |
1272 | nv50_graph_construct_gene_unk2(ctx); | 1306 | nv50_graph_construct_gene_unk14xx(ctx); |
1273 | } | 1307 | } |
1274 | if ((ctx->ctxvals_pos-offset)/8 > size) | 1308 | if ((ctx->ctxvals_pos-offset)/8 > size) |
1275 | size = (ctx->ctxvals_pos-offset)/8; | 1309 | size = (ctx->ctxvals_pos-offset)/8; |
@@ -1290,9 +1324,70 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) | |||
1290 | */ | 1324 | */ |
1291 | 1325 | ||
1292 | static void | 1326 | static void |
1327 | nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) | ||
1328 | { | ||
1329 | /* start of strand 0 */ | ||
1330 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
1331 | /* SEEK */ | ||
1332 | if (dev_priv->chipset == 0x50) | ||
1333 | xf_emit(ctx, 5, 0); | ||
1334 | else if (!IS_NVA3F(dev_priv->chipset)) | ||
1335 | xf_emit(ctx, 6, 0); | ||
1336 | else | ||
1337 | xf_emit(ctx, 4, 0); | ||
1338 | /* SEEK */ | ||
1339 | /* the PGRAPH's internal FIFO */ | ||
1340 | if (dev_priv->chipset == 0x50) | ||
1341 | xf_emit(ctx, 8*3, 0); | ||
1342 | else | ||
1343 | xf_emit(ctx, 0x100*3, 0); | ||
1344 | /* and another bonus slot?!? */ | ||
1345 | xf_emit(ctx, 3, 0); | ||
1346 | /* and YET ANOTHER bonus slot? */ | ||
1347 | if (IS_NVA3F(dev_priv->chipset)) | ||
1348 | xf_emit(ctx, 3, 0); | ||
1349 | /* SEEK */ | ||
1350 | /* CTX_SWITCH: caches of gr objects bound to subchannels. 8 values, last used index */ | ||
1351 | xf_emit(ctx, 9, 0); | ||
1352 | /* SEEK */ | ||
1353 | xf_emit(ctx, 9, 0); | ||
1354 | /* SEEK */ | ||
1355 | xf_emit(ctx, 9, 0); | ||
1356 | /* SEEK */ | ||
1357 | xf_emit(ctx, 9, 0); | ||
1358 | /* SEEK */ | ||
1359 | if (dev_priv->chipset < 0x90) | ||
1360 | xf_emit(ctx, 4, 0); | ||
1361 | /* SEEK */ | ||
1362 | xf_emit(ctx, 2, 0); | ||
1363 | /* SEEK */ | ||
1364 | xf_emit(ctx, 6*2, 0); | ||
1365 | xf_emit(ctx, 2, 0); | ||
1366 | /* SEEK */ | ||
1367 | xf_emit(ctx, 2, 0); | ||
1368 | /* SEEK */ | ||
1369 | xf_emit(ctx, 6*2, 0); | ||
1370 | xf_emit(ctx, 2, 0); | ||
1371 | /* SEEK */ | ||
1372 | if (dev_priv->chipset == 0x50) | ||
1373 | xf_emit(ctx, 0x1c, 0); | ||
1374 | else if (dev_priv->chipset < 0xa0) | ||
1375 | xf_emit(ctx, 0x1e, 0); | ||
1376 | else | ||
1377 | xf_emit(ctx, 0x22, 0); | ||
1378 | /* SEEK */ | ||
1379 | xf_emit(ctx, 0x15, 0); | ||
1380 | } | ||
1381 | |||
1382 | static void | ||
1293 | nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) | 1383 | nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) |
1294 | { | 1384 | { |
1295 | /* m2mf state */ | 1385 | /* Strand 0, right after dispatch */ |
1386 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
1387 | int smallm2mf = 0; | ||
1388 | if (dev_priv->chipset < 0x92 || dev_priv->chipset == 0x98) | ||
1389 | smallm2mf = 1; | ||
1390 | /* SEEK */ | ||
1296 | xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ | 1391 | xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ |
1297 | xf_emit (ctx, 1, 0); /* DMA_BUFFER_IN instance >> 4 */ | 1392 | xf_emit (ctx, 1, 0); /* DMA_BUFFER_IN instance >> 4 */ |
1298 | xf_emit (ctx, 1, 0); /* DMA_BUFFER_OUT instance >> 4 */ | 1393 | xf_emit (ctx, 1, 0); /* DMA_BUFFER_OUT instance >> 4 */ |
@@ -1319,427 +1414,975 @@ nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) | |||
1319 | xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT */ | 1414 | xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT */ |
1320 | xf_emit (ctx, 1, 0); /* OFFSET_IN_HIGH */ | 1415 | xf_emit (ctx, 1, 0); /* OFFSET_IN_HIGH */ |
1321 | xf_emit (ctx, 1, 0); /* OFFSET_OUT_HIGH */ | 1416 | xf_emit (ctx, 1, 0); /* OFFSET_OUT_HIGH */ |
1417 | /* SEEK */ | ||
1418 | if (smallm2mf) | ||
1419 | xf_emit(ctx, 0x40, 0); /* 20 * ffffffff, 3ffff */ | ||
1420 | else | ||
1421 | xf_emit(ctx, 0x100, 0); /* 80 * ffffffff, 3ffff */ | ||
1422 | xf_emit(ctx, 4, 0); /* 1f/7f, 0, 1f/7f, 0 [1f for smallm2mf, 7f otherwise] */ | ||
1423 | /* SEEK */ | ||
1424 | if (smallm2mf) | ||
1425 | xf_emit(ctx, 0x400, 0); /* ffffffff */ | ||
1426 | else | ||
1427 | xf_emit(ctx, 0x800, 0); /* ffffffff */ | ||
1428 | xf_emit(ctx, 4, 0); /* ff/1ff, 0, 0, 0 [ff for smallm2mf, 1ff otherwise] */ | ||
1429 | /* SEEK */ | ||
1430 | xf_emit(ctx, 0x40, 0); /* 20 * bits ffffffff, 3ffff */ | ||
1431 | xf_emit(ctx, 0x6, 0); /* 1f, 0, 1f, 0, 1f, 0 */ | ||
1322 | } | 1432 | } |
1323 | 1433 | ||
1324 | static void | 1434 | static void |
1325 | nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx) | 1435 | nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) |
1326 | { | 1436 | { |
1327 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 1437 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1328 | /* end of area 2 on pre-NVA0, area 1 on NVAx */ | 1438 | xf_emit(ctx, 2, 0); /* RO */ |
1329 | xf_emit(ctx, 2, 4); | 1439 | xf_emit(ctx, 0x800, 0); /* ffffffff */ |
1330 | xf_emit(ctx, 1, 0); | ||
1331 | xf_emit(ctx, 1, 0x80); | ||
1332 | xf_emit(ctx, 1, 4); | ||
1333 | xf_emit(ctx, 1, 0x80c14); | ||
1334 | xf_emit(ctx, 1, 0); | ||
1335 | if (dev_priv->chipset == 0x50) | ||
1336 | xf_emit(ctx, 1, 0x3ff); | ||
1337 | else | ||
1338 | xf_emit(ctx, 1, 0x7ff); | ||
1339 | switch (dev_priv->chipset) { | 1440 | switch (dev_priv->chipset) { |
1340 | case 0x50: | 1441 | case 0x50: |
1341 | case 0x86: | 1442 | case 0x92: |
1342 | case 0x98: | 1443 | case 0xa0: |
1343 | case 0xaa: | 1444 | xf_emit(ctx, 0x2b, 0); |
1344 | case 0xac: | ||
1345 | xf_emit(ctx, 0x542, 0); | ||
1346 | break; | 1445 | break; |
1347 | case 0x84: | 1446 | case 0x84: |
1348 | case 0x92: | 1447 | xf_emit(ctx, 0x29, 0); |
1448 | break; | ||
1349 | case 0x94: | 1449 | case 0x94: |
1350 | case 0x96: | 1450 | case 0x96: |
1351 | xf_emit(ctx, 0x942, 0); | ||
1352 | break; | ||
1353 | case 0xa0: | ||
1354 | case 0xa3: | 1451 | case 0xa3: |
1355 | xf_emit(ctx, 0x2042, 0); | 1452 | xf_emit(ctx, 0x27, 0); |
1356 | break; | 1453 | break; |
1454 | case 0x86: | ||
1455 | case 0x98: | ||
1357 | case 0xa5: | 1456 | case 0xa5: |
1358 | case 0xa8: | 1457 | case 0xa8: |
1359 | xf_emit(ctx, 0x842, 0); | 1458 | case 0xaa: |
1459 | case 0xac: | ||
1460 | case 0xaf: | ||
1461 | xf_emit(ctx, 0x25, 0); | ||
1360 | break; | 1462 | break; |
1361 | } | 1463 | } |
1362 | xf_emit(ctx, 2, 4); | 1464 | /* CB bindings, 0x80 of them. first word is address >> 8, second is |
1363 | xf_emit(ctx, 1, 0); | 1465 | * size >> 4 | valid << 24 */ |
1364 | xf_emit(ctx, 1, 0x80); | 1466 | xf_emit(ctx, 0x100, 0); /* ffffffff CB_DEF */ |
1365 | xf_emit(ctx, 1, 4); | 1467 | xf_emit(ctx, 1, 0); /* 0000007f CB_ADDR_BUFFER */ |
1366 | xf_emit(ctx, 1, 1); | 1468 | xf_emit(ctx, 1, 0); /* 0 */ |
1367 | xf_emit(ctx, 1, 0); | 1469 | xf_emit(ctx, 0x30, 0); /* ff SET_PROGRAM_CB */ |
1368 | xf_emit(ctx, 1, 0x27); | 1470 | xf_emit(ctx, 1, 0); /* 3f last SET_PROGRAM_CB */ |
1369 | xf_emit(ctx, 1, 0); | 1471 | xf_emit(ctx, 4, 0); /* RO */ |
1370 | xf_emit(ctx, 1, 0x26); | 1472 | xf_emit(ctx, 0x100, 0); /* ffffffff */ |
1371 | xf_emit(ctx, 3, 0); | 1473 | xf_emit(ctx, 8, 0); /* 1f, 0, 0, ... */ |
1474 | xf_emit(ctx, 8, 0); /* ffffffff */ | ||
1475 | xf_emit(ctx, 4, 0); /* ffffffff */ | ||
1476 | xf_emit(ctx, 1, 0); /* 3 */ | ||
1477 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
1478 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_CODE_CB */ | ||
1479 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_TIC */ | ||
1480 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_TSC */ | ||
1481 | xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ | ||
1482 | xf_emit(ctx, 1, 0); /* 000000ff TIC_ADDRESS_HIGH */ | ||
1483 | xf_emit(ctx, 1, 0); /* ffffffff TIC_ADDRESS_LOW */ | ||
1484 | xf_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ | ||
1485 | xf_emit(ctx, 1, 0); /* 000000ff TSC_ADDRESS_HIGH */ | ||
1486 | xf_emit(ctx, 1, 0); /* ffffffff TSC_ADDRESS_LOW */ | ||
1487 | xf_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ | ||
1488 | xf_emit(ctx, 1, 0); /* 000000ff VP_ADDRESS_HIGH */ | ||
1489 | xf_emit(ctx, 1, 0); /* ffffffff VP_ADDRESS_LOW */ | ||
1490 | xf_emit(ctx, 1, 0); /* 00ffffff VP_START_ID */ | ||
1491 | xf_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ | ||
1492 | xf_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ | ||
1493 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1494 | xf_emit(ctx, 1, 0); /* 000000ff GP_ADDRESS_HIGH */ | ||
1495 | xf_emit(ctx, 1, 0); /* ffffffff GP_ADDRESS_LOW */ | ||
1496 | xf_emit(ctx, 1, 0); /* 00ffffff GP_START_ID */ | ||
1497 | xf_emit(ctx, 1, 0); /* 000000ff FP_ADDRESS_HIGH */ | ||
1498 | xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ | ||
1499 | xf_emit(ctx, 1, 0); /* 00ffffff FP_START_ID */ | ||
1372 | } | 1500 | } |
1373 | 1501 | ||
1374 | static void | 1502 | static void |
1375 | nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx) | 1503 | nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) |
1376 | { | 1504 | { |
1505 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
1506 | int i; | ||
1377 | /* end of area 2 on pre-NVA0, area 1 on NVAx */ | 1507 | /* end of area 2 on pre-NVA0, area 1 on NVAx */ |
1378 | xf_emit(ctx, 0x10, 0x04000000); | 1508 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ |
1379 | xf_emit(ctx, 0x24, 0); | 1509 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ |
1380 | xf_emit(ctx, 2, 0x04e3bfdf); | 1510 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1381 | xf_emit(ctx, 2, 0); | 1511 | xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ |
1382 | xf_emit(ctx, 1, 0x1fe21); | 1512 | xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ |
1513 | xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ | ||
1514 | xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ | ||
1515 | if (dev_priv->chipset == 0x50) | ||
1516 | xf_emit(ctx, 1, 0x3ff); | ||
1517 | else | ||
1518 | xf_emit(ctx, 1, 0x7ff); /* 000007ff */ | ||
1519 | xf_emit(ctx, 1, 0); /* 111/113 */ | ||
1520 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1521 | for (i = 0; i < 8; i++) { | ||
1522 | switch (dev_priv->chipset) { | ||
1523 | case 0x50: | ||
1524 | case 0x86: | ||
1525 | case 0x98: | ||
1526 | case 0xaa: | ||
1527 | case 0xac: | ||
1528 | xf_emit(ctx, 0xa0, 0); /* ffffffff */ | ||
1529 | break; | ||
1530 | case 0x84: | ||
1531 | case 0x92: | ||
1532 | case 0x94: | ||
1533 | case 0x96: | ||
1534 | xf_emit(ctx, 0x120, 0); | ||
1535 | break; | ||
1536 | case 0xa5: | ||
1537 | case 0xa8: | ||
1538 | xf_emit(ctx, 0x100, 0); /* ffffffff */ | ||
1539 | break; | ||
1540 | case 0xa0: | ||
1541 | case 0xa3: | ||
1542 | case 0xaf: | ||
1543 | xf_emit(ctx, 0x400, 0); /* ffffffff */ | ||
1544 | break; | ||
1545 | } | ||
1546 | xf_emit(ctx, 4, 0); /* 3f, 0, 0, 0 */ | ||
1547 | xf_emit(ctx, 4, 0); /* ffffffff */ | ||
1548 | } | ||
1549 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
1550 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
1551 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1552 | xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ | ||
1553 | xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_TEMP */ | ||
1554 | xf_emit(ctx, 1, 1); /* 00000001 RASTERIZE_ENABLE */ | ||
1555 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ | ||
1556 | xf_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ | ||
1557 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ | ||
1558 | xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ | ||
1559 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1560 | } | ||
1561 | |||
1562 | static void | ||
1563 | nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) | ||
1564 | { | ||
1565 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
1566 | /* end of area 2 on pre-NVA0, area 1 on NVAx */ | ||
1567 | xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ | ||
1568 | xf_emit(ctx, 1, 0); /* 00000003 VIEWPORT_CLIP_MODE */ | ||
1569 | xf_emit(ctx, 0x10, 0x04000000); /* 07ffffff VIEWPORT_CLIP_HORIZ*8, VIEWPORT_CLIP_VERT*8 */ | ||
1570 | xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ | ||
1571 | xf_emit(ctx, 0x20, 0); /* ffffffff POLYGON_STIPPLE */ | ||
1572 | xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ | ||
1573 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
1574 | xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ | ||
1575 | xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ | ||
1576 | xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ | ||
1577 | xf_emit(ctx, 1, 0); /* 00000007 */ | ||
1578 | xf_emit(ctx, 1, 0x1fe21); /* 0001ffff tesla UNK0FAC */ | ||
1579 | if (dev_priv->chipset >= 0xa0) | ||
1580 | xf_emit(ctx, 1, 0x0fac6881); | ||
1581 | if (IS_NVA3F(dev_priv->chipset)) { | ||
1582 | xf_emit(ctx, 1, 1); | ||
1583 | xf_emit(ctx, 3, 0); | ||
1584 | } | ||
1383 | } | 1585 | } |
1384 | 1586 | ||
1385 | static void | 1587 | static void |
1386 | nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx) | 1588 | nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) |
1387 | { | 1589 | { |
1388 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 1590 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1389 | /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ | 1591 | /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ |
1390 | if (dev_priv->chipset != 0x50) { | 1592 | if (dev_priv->chipset != 0x50) { |
1391 | xf_emit(ctx, 5, 0); | 1593 | xf_emit(ctx, 5, 0); /* ffffffff */ |
1392 | xf_emit(ctx, 1, 0x80c14); | 1594 | xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ |
1393 | xf_emit(ctx, 2, 0); | 1595 | xf_emit(ctx, 1, 0); /* 00000001 */ |
1394 | xf_emit(ctx, 1, 0x804); | 1596 | xf_emit(ctx, 1, 0); /* 000003ff */ |
1395 | xf_emit(ctx, 1, 0); | 1597 | xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ |
1396 | xf_emit(ctx, 2, 4); | 1598 | xf_emit(ctx, 1, 0); /* 00000001 */ |
1397 | xf_emit(ctx, 1, 0x8100c12); | 1599 | xf_emit(ctx, 2, 4); /* 7f, ff */ |
1600 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ | ||
1398 | } | 1601 | } |
1399 | xf_emit(ctx, 1, 0); | 1602 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
1400 | xf_emit(ctx, 2, 4); | 1603 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ |
1401 | xf_emit(ctx, 1, 0); | 1604 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ |
1402 | xf_emit(ctx, 1, 0x10); | 1605 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1403 | if (dev_priv->chipset == 0x50) | 1606 | xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ |
1404 | xf_emit(ctx, 3, 0); | 1607 | xf_emit(ctx, 1, 0); /* 000000ff VP_CLIP_DISTANCE_ENABLE */ |
1405 | else | ||
1406 | xf_emit(ctx, 4, 0); | ||
1407 | xf_emit(ctx, 1, 0x804); | ||
1408 | xf_emit(ctx, 1, 1); | ||
1409 | xf_emit(ctx, 1, 0x1a); | ||
1410 | if (dev_priv->chipset != 0x50) | 1608 | if (dev_priv->chipset != 0x50) |
1411 | xf_emit(ctx, 1, 0x7f); | 1609 | xf_emit(ctx, 1, 0); /* 3ff */ |
1412 | xf_emit(ctx, 1, 0); | 1610 | xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1940 */ |
1413 | xf_emit(ctx, 1, 1); | 1611 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ |
1414 | xf_emit(ctx, 1, 0x80c14); | 1612 | xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ |
1415 | xf_emit(ctx, 1, 0); | 1613 | xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ |
1416 | xf_emit(ctx, 1, 0x8100c12); | 1614 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ |
1417 | xf_emit(ctx, 2, 4); | ||
1418 | xf_emit(ctx, 1, 0); | ||
1419 | xf_emit(ctx, 1, 0x10); | ||
1420 | xf_emit(ctx, 3, 0); | ||
1421 | xf_emit(ctx, 1, 1); | ||
1422 | xf_emit(ctx, 1, 0x8100c12); | ||
1423 | xf_emit(ctx, 6, 0); | ||
1424 | if (dev_priv->chipset == 0x50) | ||
1425 | xf_emit(ctx, 1, 0x3ff); | ||
1426 | else | ||
1427 | xf_emit(ctx, 1, 0x7ff); | ||
1428 | xf_emit(ctx, 1, 0x80c14); | ||
1429 | xf_emit(ctx, 0x38, 0); | ||
1430 | xf_emit(ctx, 1, 1); | ||
1431 | xf_emit(ctx, 2, 0); | ||
1432 | xf_emit(ctx, 1, 0x10); | ||
1433 | xf_emit(ctx, 0x38, 0); | ||
1434 | xf_emit(ctx, 2, 0x88); | ||
1435 | xf_emit(ctx, 2, 0); | ||
1436 | xf_emit(ctx, 1, 4); | ||
1437 | xf_emit(ctx, 0x16, 0); | ||
1438 | xf_emit(ctx, 1, 0x26); | ||
1439 | xf_emit(ctx, 2, 0); | ||
1440 | xf_emit(ctx, 1, 0x3f800000); | ||
1441 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
1442 | xf_emit(ctx, 4, 0); | ||
1443 | else | ||
1444 | xf_emit(ctx, 3, 0); | ||
1445 | xf_emit(ctx, 1, 0x1a); | ||
1446 | xf_emit(ctx, 1, 0x10); | ||
1447 | if (dev_priv->chipset != 0x50) | 1615 | if (dev_priv->chipset != 0x50) |
1448 | xf_emit(ctx, 0x28, 0); | 1616 | xf_emit(ctx, 1, 0x7f); /* 000000ff tesla UNK0FFC */ |
1617 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1618 | xf_emit(ctx, 1, 1); /* 00000001 SHADE_MODEL */ | ||
1619 | xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ | ||
1620 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ | ||
1621 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ | ||
1622 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
1623 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
1624 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1625 | xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ | ||
1626 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ | ||
1627 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0F8C */ | ||
1628 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1629 | xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ | ||
1630 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ | ||
1631 | xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ | ||
1632 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ | ||
1633 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
1634 | if (dev_priv->chipset == 0x50) | ||
1635 | xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ | ||
1449 | else | 1636 | else |
1450 | xf_emit(ctx, 0x25, 0); | 1637 | xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ |
1451 | xf_emit(ctx, 1, 0x52); | 1638 | xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ |
1452 | xf_emit(ctx, 1, 0); | 1639 | xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ |
1453 | xf_emit(ctx, 1, 0x26); | 1640 | xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_SCALE: X0, Y0, Z0, X1, Y1, ... */ |
1454 | xf_emit(ctx, 1, 0); | 1641 | xf_emit(ctx, 3, 0); /* f, 0, 0 */ |
1455 | xf_emit(ctx, 2, 4); | 1642 | xf_emit(ctx, 3, 0); /* ffffffff last VIEWPORT_SCALE? */ |
1456 | xf_emit(ctx, 1, 0); | 1643 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
1457 | xf_emit(ctx, 1, 0x1a); | 1644 | xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ |
1458 | xf_emit(ctx, 2, 0); | 1645 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ |
1459 | xf_emit(ctx, 1, 0x00ffff00); | 1646 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ |
1460 | xf_emit(ctx, 1, 0); | 1647 | xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ |
1648 | xf_emit(ctx, 1, 0); /* 00000001 */ | ||
1649 | xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_TRANSLATE */ | ||
1650 | xf_emit(ctx, 3, 0); /* f, 0, 0 */ | ||
1651 | xf_emit(ctx, 3, 0); /* ffffffff */ | ||
1652 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1653 | xf_emit(ctx, 2, 0x88); /* 000001ff tesla UNK19D8 */ | ||
1654 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ | ||
1655 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1656 | xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ | ||
1657 | xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ | ||
1658 | xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ | ||
1659 | xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ | ||
1660 | xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ | ||
1661 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ | ||
1662 | xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ | ||
1663 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ | ||
1664 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
1665 | xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ | ||
1666 | xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ | ||
1667 | xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ | ||
1668 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ | ||
1669 | if (IS_NVA3F(dev_priv->chipset)) | ||
1670 | xf_emit(ctx, 1, 0); /* 00000001 */ | ||
1671 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ | ||
1672 | xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ | ||
1673 | if (dev_priv->chipset != 0x50) { | ||
1674 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
1675 | xf_emit(ctx, 1, 0); /* 00000001 */ | ||
1676 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
1677 | } | ||
1678 | xf_emit(ctx, 0x20, 0); /* 10xbits ffffffff, 3fffff. SCISSOR_* */ | ||
1679 | xf_emit(ctx, 1, 0); /* f */ | ||
1680 | xf_emit(ctx, 1, 0); /* 0? */ | ||
1681 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
1682 | xf_emit(ctx, 1, 0); /* 003fffff */ | ||
1683 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1684 | xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ | ||
1685 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ | ||
1686 | xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ | ||
1687 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ | ||
1688 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
1689 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
1690 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1691 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ | ||
1692 | xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ | ||
1693 | xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ | ||
1694 | xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ | ||
1695 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
1461 | } | 1696 | } |
1462 | 1697 | ||
1463 | static void | 1698 | static void |
1464 | nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx) | 1699 | nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) |
1465 | { | 1700 | { |
1466 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 1701 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1467 | /* end of area 0 on pre-NVA0, beginning of area 6 on NVAx */ | 1702 | /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */ |
1468 | xf_emit(ctx, 1, 0x3f); | 1703 | /* SEEK */ |
1469 | xf_emit(ctx, 0xa, 0); | 1704 | xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ |
1470 | xf_emit(ctx, 1, 2); | 1705 | xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ |
1471 | xf_emit(ctx, 2, 0x04000000); | 1706 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ |
1472 | xf_emit(ctx, 8, 0); | 1707 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1473 | xf_emit(ctx, 1, 4); | 1708 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ |
1474 | xf_emit(ctx, 3, 0); | 1709 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ |
1475 | xf_emit(ctx, 1, 4); | 1710 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ |
1476 | if (dev_priv->chipset == 0x50) | 1711 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ |
1477 | xf_emit(ctx, 0x10, 0); | 1712 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ |
1478 | else | 1713 | xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ |
1479 | xf_emit(ctx, 0x11, 0); | 1714 | xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ |
1480 | xf_emit(ctx, 1, 1); | 1715 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ |
1481 | xf_emit(ctx, 1, 0x1001); | 1716 | xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ |
1482 | xf_emit(ctx, 4, 0xffff); | 1717 | xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ |
1483 | xf_emit(ctx, 0x20, 0); | 1718 | xf_emit(ctx, 1, 0); /* 00000001 */ |
1484 | xf_emit(ctx, 0x10, 0x3f800000); | 1719 | xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ |
1485 | xf_emit(ctx, 1, 0x10); | 1720 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
1486 | if (dev_priv->chipset == 0x50) | 1721 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
1487 | xf_emit(ctx, 1, 0); | 1722 | xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ |
1488 | else | 1723 | xf_emit(ctx, 1, 0); /* 0000ffff */ |
1489 | xf_emit(ctx, 2, 0); | 1724 | xf_emit(ctx, 1, 0); /* 00000001 UNK0FB0 */ |
1490 | xf_emit(ctx, 1, 3); | 1725 | xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ |
1491 | xf_emit(ctx, 2, 0); | 1726 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ |
1727 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
1728 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ | ||
1729 | xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ | ||
1730 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ | ||
1731 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ | ||
1732 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */ | ||
1733 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ | ||
1734 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ | ||
1735 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ | ||
1736 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ | ||
1737 | xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ | ||
1738 | xf_emit(ctx, 1, 0); /* 00000007 */ | ||
1739 | if (dev_priv->chipset != 0x50) | ||
1740 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1108 */ | ||
1741 | xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ | ||
1742 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ | ||
1743 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ | ||
1744 | xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ | ||
1745 | /* SEEK */ | ||
1746 | xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ | ||
1747 | xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ | ||
1748 | xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ | ||
1749 | xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ | ||
1750 | xf_emit(ctx, 1, 0x10); /* 7f/ff/3ff VIEW_VOLUME_CLIP_CTRL */ | ||
1751 | xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ | ||
1752 | xf_emit(ctx, 1, 3); /* 00000003 FP_CTRL_UNK196C */ | ||
1753 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1968 */ | ||
1754 | if (dev_priv->chipset != 0x50) | ||
1755 | xf_emit(ctx, 1, 0); /* 0fffffff tesla UNK1104 */ | ||
1756 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK151C */ | ||
1492 | } | 1757 | } |
1493 | 1758 | ||
1494 | static void | 1759 | static void |
1495 | nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx) | 1760 | nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx) |
1496 | { | 1761 | { |
1497 | /* middle of area 0 on pre-NVA0, middle of area 6 on NVAx */ | 1762 | /* middle of strand 0 on pre-NVA0 [after 24xx], middle of area 6 on NVAx */ |
1498 | xf_emit(ctx, 2, 0x04000000); | 1763 | /* SEEK */ |
1499 | xf_emit(ctx, 1, 0); | 1764 | xf_emit(ctx, 1, 0); /* 00000007 UNK0FB4 */ |
1500 | xf_emit(ctx, 1, 0x80); | 1765 | /* SEEK */ |
1501 | xf_emit(ctx, 3, 0); | 1766 | xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_HORIZ */ |
1502 | xf_emit(ctx, 1, 0x80); | 1767 | xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_VERT */ |
1503 | xf_emit(ctx, 1, 0); | 1768 | xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ |
1769 | xf_emit(ctx, 2, 0x04000000); /* 07ffffff UNK1508 */ | ||
1770 | xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ | ||
1771 | xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_WIDTH */ | ||
1772 | xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ID */ | ||
1773 | xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ADDRESS_HIGH */ | ||
1774 | xf_emit(ctx, 1, 0); /* ffffffff CLIPID_ADDRESS_LOW */ | ||
1775 | xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_HEIGHT */ | ||
1776 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_CLIPID */ | ||
1504 | } | 1777 | } |
1505 | 1778 | ||
1506 | static void | 1779 | static void |
1507 | nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx) | 1780 | nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) |
1508 | { | 1781 | { |
1509 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 1782 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1510 | /* middle of area 0 on pre-NVA0 [after m2mf], end of area 2 on NVAx */ | 1783 | int i; |
1511 | xf_emit(ctx, 2, 4); | 1784 | /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */ |
1512 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 1785 | /* SEEK */ |
1513 | xf_emit(ctx, 0x1c4d, 0); | 1786 | xf_emit(ctx, 0x33, 0); |
1787 | /* SEEK */ | ||
1788 | xf_emit(ctx, 2, 0); | ||
1789 | /* SEEK */ | ||
1790 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1791 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
1792 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
1793 | /* SEEK */ | ||
1794 | if (IS_NVA3F(dev_priv->chipset)) { | ||
1795 | xf_emit(ctx, 4, 0); /* RO */ | ||
1796 | xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ | ||
1797 | xf_emit(ctx, 1, 0); /* 1ff */ | ||
1798 | xf_emit(ctx, 8, 0); /* 0? */ | ||
1799 | xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ | ||
1800 | |||
1801 | xf_emit(ctx, 4, 0); /* RO */ | ||
1802 | xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ | ||
1803 | xf_emit(ctx, 1, 0); /* 1ff */ | ||
1804 | xf_emit(ctx, 8, 0); /* 0? */ | ||
1805 | xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ | ||
1806 | } | ||
1514 | else | 1807 | else |
1515 | xf_emit(ctx, 0x1c4b, 0); | 1808 | { |
1516 | xf_emit(ctx, 2, 4); | 1809 | xf_emit(ctx, 0xc, 0); /* RO */ |
1517 | xf_emit(ctx, 1, 0x8100c12); | 1810 | /* SEEK */ |
1811 | xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ | ||
1812 | xf_emit(ctx, 1, 0); /* 1ff */ | ||
1813 | xf_emit(ctx, 8, 0); /* 0? */ | ||
1814 | |||
1815 | /* SEEK */ | ||
1816 | xf_emit(ctx, 0xc, 0); /* RO */ | ||
1817 | /* SEEK */ | ||
1818 | xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ | ||
1819 | xf_emit(ctx, 1, 0); /* 1ff */ | ||
1820 | xf_emit(ctx, 8, 0); /* 0? */ | ||
1821 | } | ||
1822 | /* SEEK */ | ||
1823 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1824 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
1825 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
1826 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ | ||
1518 | if (dev_priv->chipset != 0x50) | 1827 | if (dev_priv->chipset != 0x50) |
1519 | xf_emit(ctx, 1, 3); | 1828 | xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ |
1520 | xf_emit(ctx, 1, 0); | 1829 | /* SEEK */ |
1521 | xf_emit(ctx, 1, 0x8100c12); | 1830 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1522 | xf_emit(ctx, 1, 0); | 1831 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ |
1523 | xf_emit(ctx, 1, 0x80c14); | 1832 | xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ |
1524 | xf_emit(ctx, 1, 1); | 1833 | xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ |
1834 | xf_emit(ctx, 1, 1); /* 00000001 */ | ||
1835 | /* SEEK */ | ||
1525 | if (dev_priv->chipset >= 0xa0) | 1836 | if (dev_priv->chipset >= 0xa0) |
1526 | xf_emit(ctx, 2, 4); | 1837 | xf_emit(ctx, 2, 4); /* 000000ff */ |
1527 | xf_emit(ctx, 1, 0x80c14); | 1838 | xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ |
1528 | xf_emit(ctx, 2, 0); | 1839 | xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ |
1529 | xf_emit(ctx, 1, 0x8100c12); | 1840 | xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ |
1530 | xf_emit(ctx, 1, 0x27); | 1841 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ |
1531 | xf_emit(ctx, 2, 0); | 1842 | xf_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM_ID */ |
1532 | xf_emit(ctx, 1, 1); | 1843 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1533 | xf_emit(ctx, 0x3c1, 0); | 1844 | xf_emit(ctx, 1, 0); /* 0000000f */ |
1534 | xf_emit(ctx, 1, 1); | 1845 | xf_emit(ctx, 1, 1); /* 00000001 */ |
1535 | xf_emit(ctx, 0x16, 0); | 1846 | for (i = 0; i < 10; i++) { |
1536 | xf_emit(ctx, 1, 0x8100c12); | 1847 | /* SEEK */ |
1537 | xf_emit(ctx, 1, 0); | 1848 | xf_emit(ctx, 0x40, 0); /* ffffffff */ |
1849 | xf_emit(ctx, 0x10, 0); /* 3, 0, 0.... */ | ||
1850 | xf_emit(ctx, 0x10, 0); /* ffffffff */ | ||
1851 | } | ||
1852 | /* SEEK */ | ||
1853 | xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_CTRL */ | ||
1854 | xf_emit(ctx, 1, 1); /* 00000001 */ | ||
1855 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
1856 | xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ | ||
1857 | xf_emit(ctx, 0x10, 0); /* 00ffffff POINT_COORD_REPLACE_MAP */ | ||
1858 | xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ | ||
1859 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ | ||
1860 | if (dev_priv->chipset != 0x50) | ||
1861 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
1538 | } | 1862 | } |
1539 | 1863 | ||
1540 | static void | 1864 | static void |
1541 | nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx) | 1865 | nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) |
1542 | { | 1866 | { |
1543 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 1867 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1544 | /* beginning of area 1 on pre-NVA0 [after m2mf], area 3 on NVAx */ | 1868 | int acnt = 0x10, rep, i; |
1545 | xf_emit(ctx, 4, 0); | 1869 | /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */ |
1546 | xf_emit(ctx, 1, 0xf); | 1870 | if (IS_NVA3F(dev_priv->chipset)) |
1547 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 1871 | acnt = 0x20; |
1548 | xf_emit(ctx, 8, 0); | 1872 | /* SEEK */ |
1549 | else | 1873 | if (dev_priv->chipset >= 0xa0) { |
1550 | xf_emit(ctx, 4, 0); | 1874 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */ |
1551 | xf_emit(ctx, 1, 0x20); | 1875 | xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */ |
1552 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 1876 | } |
1553 | xf_emit(ctx, 0x11, 0); | 1877 | xf_emit(ctx, 1, 0); /* ffffffff VERTEX_BUFFER_FIRST */ |
1878 | xf_emit(ctx, 1, 0); /* 00000001 PRIMITIVE_RESTART_ENABLE */ | ||
1879 | xf_emit(ctx, 1, 0); /* 00000001 UNK0DE8 */ | ||
1880 | xf_emit(ctx, 1, 0); /* ffffffff PRIMITIVE_RESTART_INDEX */ | ||
1881 | xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ | ||
1882 | xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ | ||
1883 | xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATR_MASK_UNK0DD0 */ | ||
1884 | xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ | ||
1885 | xf_emit(ctx, 1, 0x20); /* 0000ffff tesla UNK129C */ | ||
1886 | xf_emit(ctx, 1, 0); /* 000000ff turing UNK370??? */ | ||
1887 | xf_emit(ctx, 1, 0); /* 0000ffff turing USER_PARAM_COUNT */ | ||
1888 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1889 | /* SEEK */ | ||
1890 | if (IS_NVA3F(dev_priv->chipset)) | ||
1891 | xf_emit(ctx, 0xb, 0); /* RO */ | ||
1554 | else if (dev_priv->chipset >= 0xa0) | 1892 | else if (dev_priv->chipset >= 0xa0) |
1555 | xf_emit(ctx, 0xf, 0); | 1893 | xf_emit(ctx, 0x9, 0); /* RO */ |
1556 | else | 1894 | else |
1557 | xf_emit(ctx, 0xe, 0); | 1895 | xf_emit(ctx, 0x8, 0); /* RO */ |
1558 | xf_emit(ctx, 1, 0x1a); | 1896 | /* SEEK */ |
1559 | xf_emit(ctx, 0xd, 0); | 1897 | xf_emit(ctx, 1, 0); /* 00000001 EDGE_FLAG */ |
1560 | xf_emit(ctx, 2, 4); | 1898 | xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ |
1561 | xf_emit(ctx, 1, 0); | 1899 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1562 | xf_emit(ctx, 1, 4); | 1900 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ |
1563 | xf_emit(ctx, 1, 8); | 1901 | /* SEEK */ |
1564 | xf_emit(ctx, 1, 0); | 1902 | xf_emit(ctx, 0xc, 0); /* RO */ |
1903 | /* SEEK */ | ||
1904 | xf_emit(ctx, 1, 0); /* 7f/ff */ | ||
1905 | xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ | ||
1906 | xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ | ||
1907 | xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ | ||
1908 | xf_emit(ctx, 1, 4); /* 000001ff UNK1A28 */ | ||
1909 | xf_emit(ctx, 1, 8); /* 000001ff UNK0DF0 */ | ||
1910 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1565 | if (dev_priv->chipset == 0x50) | 1911 | if (dev_priv->chipset == 0x50) |
1566 | xf_emit(ctx, 1, 0x3ff); | 1912 | xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */ |
1567 | else | 1913 | else |
1568 | xf_emit(ctx, 1, 0x7ff); | 1914 | xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */ |
1569 | if (dev_priv->chipset == 0xa8) | 1915 | if (dev_priv->chipset == 0xa8) |
1570 | xf_emit(ctx, 1, 0x1e00); | 1916 | xf_emit(ctx, 1, 0x1e00); /* 7fff */ |
1571 | xf_emit(ctx, 0xc, 0); | 1917 | /* SEEK */ |
1572 | xf_emit(ctx, 1, 0xf); | 1918 | xf_emit(ctx, 0xc, 0); /* RO or close */ |
1573 | if (dev_priv->chipset == 0x50) | 1919 | /* SEEK */ |
1574 | xf_emit(ctx, 0x125, 0); | 1920 | xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ |
1575 | else if (dev_priv->chipset < 0xa0) | 1921 | xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ |
1576 | xf_emit(ctx, 0x126, 0); | 1922 | xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ |
1577 | else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) | 1923 | if (dev_priv->chipset > 0x50 && dev_priv->chipset < 0xa0) |
1578 | xf_emit(ctx, 0x124, 0); | 1924 | xf_emit(ctx, 2, 0); /* ffffffff */ |
1579 | else | 1925 | else |
1580 | xf_emit(ctx, 0x1f7, 0); | 1926 | xf_emit(ctx, 1, 0); /* ffffffff */ |
1581 | xf_emit(ctx, 1, 0xf); | 1927 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0FD8 */ |
1582 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 1928 | /* SEEK */ |
1583 | xf_emit(ctx, 3, 0); | 1929 | if (IS_NVA3F(dev_priv->chipset)) { |
1930 | xf_emit(ctx, 0x10, 0); /* 0? */ | ||
1931 | xf_emit(ctx, 2, 0); /* weird... */ | ||
1932 | xf_emit(ctx, 2, 0); /* RO */ | ||
1933 | } else { | ||
1934 | xf_emit(ctx, 8, 0); /* 0? */ | ||
1935 | xf_emit(ctx, 1, 0); /* weird... */ | ||
1936 | xf_emit(ctx, 2, 0); /* RO */ | ||
1937 | } | ||
1938 | /* SEEK */ | ||
1939 | xf_emit(ctx, 1, 0); /* ffffffff VB_ELEMENT_BASE */ | ||
1940 | xf_emit(ctx, 1, 0); /* ffffffff UNK1438 */ | ||
1941 | xf_emit(ctx, acnt, 0); /* 1 tesla UNK1000 */ | ||
1942 | if (dev_priv->chipset >= 0xa0) | ||
1943 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */ | ||
1944 | /* SEEK */ | ||
1945 | xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ | ||
1946 | xf_emit(ctx, 1, 0); /* f/1f */ | ||
1947 | /* SEEK */ | ||
1948 | xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ | ||
1949 | xf_emit(ctx, 1, 0); /* f/1f */ | ||
1950 | /* SEEK */ | ||
1951 | xf_emit(ctx, acnt, 0); /* RO */ | ||
1952 | xf_emit(ctx, 2, 0); /* RO */ | ||
1953 | /* SEEK */ | ||
1954 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK111C? */ | ||
1955 | xf_emit(ctx, 1, 0); /* RO */ | ||
1956 | /* SEEK */ | ||
1957 | xf_emit(ctx, 1, 0); /* 000000ff UNK15F4_ADDRESS_HIGH */ | ||
1958 | xf_emit(ctx, 1, 0); /* ffffffff UNK15F4_ADDRESS_LOW */ | ||
1959 | xf_emit(ctx, 1, 0); /* 000000ff UNK0F84_ADDRESS_HIGH */ | ||
1960 | xf_emit(ctx, 1, 0); /* ffffffff UNK0F84_ADDRESS_LOW */ | ||
1961 | /* SEEK */ | ||
1962 | xf_emit(ctx, acnt, 0); /* 00003fff VERTEX_ARRAY_ATTRIB_OFFSET */ | ||
1963 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1964 | /* SEEK */ | ||
1965 | xf_emit(ctx, acnt, 0); /* 00000fff VERTEX_ARRAY_STRIDE */ | ||
1966 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1967 | /* SEEK */ | ||
1968 | xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_LOW */ | ||
1969 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1970 | /* SEEK */ | ||
1971 | xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_ARRAY_HIGH */ | ||
1972 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1973 | /* SEEK */ | ||
1974 | xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_LIMIT_LOW */ | ||
1975 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1976 | /* SEEK */ | ||
1977 | xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */ | ||
1978 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1979 | /* SEEK */ | ||
1980 | if (IS_NVA3F(dev_priv->chipset)) { | ||
1981 | xf_emit(ctx, acnt, 0); /* f */ | ||
1982 | xf_emit(ctx, 3, 0); /* f/1f */ | ||
1983 | } | ||
1984 | /* SEEK */ | ||
1985 | if (IS_NVA3F(dev_priv->chipset)) | ||
1986 | xf_emit(ctx, 2, 0); /* RO */ | ||
1987 | else | ||
1988 | xf_emit(ctx, 5, 0); /* RO */ | ||
1989 | /* SEEK */ | ||
1990 | xf_emit(ctx, 1, 0); /* ffff DMA_VTXBUF */ | ||
1991 | /* SEEK */ | ||
1992 | if (dev_priv->chipset < 0xa0) { | ||
1993 | xf_emit(ctx, 0x41, 0); /* RO */ | ||
1994 | /* SEEK */ | ||
1995 | xf_emit(ctx, 0x11, 0); /* RO */ | ||
1996 | } else if (!IS_NVA3F(dev_priv->chipset)) | ||
1997 | xf_emit(ctx, 0x50, 0); /* RO */ | ||
1584 | else | 1998 | else |
1585 | xf_emit(ctx, 1, 0); | 1999 | xf_emit(ctx, 0x58, 0); /* RO */ |
1586 | xf_emit(ctx, 1, 1); | 2000 | /* SEEK */ |
1587 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2001 | xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ |
1588 | xf_emit(ctx, 0xa1, 0); | 2002 | xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ |
2003 | xf_emit(ctx, 1, 1); /* 1 UNK0DEC */ | ||
2004 | /* SEEK */ | ||
2005 | xf_emit(ctx, acnt*4, 0); /* ffffffff VTX_ATTR */ | ||
2006 | xf_emit(ctx, 4, 0); /* f/1f, 0, 0, 0 */ | ||
2007 | /* SEEK */ | ||
2008 | if (IS_NVA3F(dev_priv->chipset)) | ||
2009 | xf_emit(ctx, 0x1d, 0); /* RO */ | ||
1589 | else | 2010 | else |
1590 | xf_emit(ctx, 0x5a, 0); | 2011 | xf_emit(ctx, 0x16, 0); /* RO */ |
1591 | xf_emit(ctx, 1, 0xf); | 2012 | /* SEEK */ |
2013 | xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ | ||
2014 | xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ | ||
2015 | /* SEEK */ | ||
1592 | if (dev_priv->chipset < 0xa0) | 2016 | if (dev_priv->chipset < 0xa0) |
1593 | xf_emit(ctx, 0x834, 0); | 2017 | xf_emit(ctx, 8, 0); /* RO */ |
1594 | else if (dev_priv->chipset == 0xa0) | 2018 | else if (IS_NVA3F(dev_priv->chipset)) |
1595 | xf_emit(ctx, 0x1873, 0); | 2019 | xf_emit(ctx, 0xc, 0); /* RO */ |
1596 | else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2020 | else |
1597 | xf_emit(ctx, 0x8ba, 0); | 2021 | xf_emit(ctx, 7, 0); /* RO */ |
2022 | /* SEEK */ | ||
2023 | xf_emit(ctx, 0xa, 0); /* RO */ | ||
2024 | if (dev_priv->chipset == 0xa0) | ||
2025 | rep = 0xc; | ||
2026 | else | ||
2027 | rep = 4; | ||
2028 | for (i = 0; i < rep; i++) { | ||
2029 | /* SEEK */ | ||
2030 | if (IS_NVA3F(dev_priv->chipset)) | ||
2031 | xf_emit(ctx, 0x20, 0); /* ffffffff */ | ||
2032 | xf_emit(ctx, 0x200, 0); /* ffffffff */ | ||
2033 | xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */ | ||
2034 | xf_emit(ctx, 4, 0); /* ffffffff */ | ||
2035 | } | ||
2036 | /* SEEK */ | ||
2037 | xf_emit(ctx, 1, 0); /* 113/111 */ | ||
2038 | xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ | ||
2039 | xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ | ||
2040 | xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATTR_MASK_UNK0DD0 */ | ||
2041 | xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ | ||
2042 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
2043 | /* SEEK */ | ||
2044 | if (IS_NVA3F(dev_priv->chipset)) | ||
2045 | xf_emit(ctx, 7, 0); /* weird... */ | ||
1598 | else | 2046 | else |
1599 | xf_emit(ctx, 0x833, 0); | 2047 | xf_emit(ctx, 5, 0); /* weird... */ |
1600 | xf_emit(ctx, 1, 0xf); | ||
1601 | xf_emit(ctx, 0xf, 0); | ||
1602 | } | 2048 | } |
1603 | 2049 | ||
1604 | static void | 2050 | static void |
1605 | nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx) | 2051 | nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) |
1606 | { | 2052 | { |
1607 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 2053 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1608 | /* middle of area 1 on pre-NVA0 [after m2mf], middle of area 6 on NVAx */ | 2054 | /* middle of strand 1 on pre-NVA0 [after vfetch], middle of strand 6 on NVAx */ |
1609 | xf_emit(ctx, 2, 0); | 2055 | /* SEEK */ |
1610 | if (dev_priv->chipset == 0x50) | 2056 | xf_emit(ctx, 2, 0); /* 0001ffff CLIP_X, CLIP_Y */ |
1611 | xf_emit(ctx, 2, 1); | 2057 | xf_emit(ctx, 2, 0); /* 0000ffff CLIP_W, CLIP_H */ |
1612 | else | 2058 | xf_emit(ctx, 1, 0); /* 00000001 CLIP_ENABLE */ |
1613 | xf_emit(ctx, 2, 0); | 2059 | if (dev_priv->chipset < 0xa0) { |
1614 | xf_emit(ctx, 1, 0); | 2060 | /* this is useless on everything but the original NV50, |
1615 | xf_emit(ctx, 1, 1); | 2061 | * guess they forgot to nuke it. Or just didn't bother. */ |
1616 | xf_emit(ctx, 2, 0x100); | 2062 | xf_emit(ctx, 2, 0); /* 0000ffff IFC_CLIP_X, Y */ |
1617 | xf_emit(ctx, 1, 0x11); | 2063 | xf_emit(ctx, 2, 1); /* 0000ffff IFC_CLIP_W, H */ |
1618 | xf_emit(ctx, 1, 0); | 2064 | xf_emit(ctx, 1, 0); /* 00000001 IFC_CLIP_ENABLE */ |
1619 | xf_emit(ctx, 1, 8); | 2065 | } |
1620 | xf_emit(ctx, 5, 0); | 2066 | xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ |
1621 | xf_emit(ctx, 1, 1); | 2067 | xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ |
1622 | xf_emit(ctx, 1, 0); | 2068 | xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ |
1623 | xf_emit(ctx, 3, 1); | 2069 | xf_emit(ctx, 1, 0x11); /* 3f[NV50]/7f[NV84+] DST_FORMAT */ |
1624 | xf_emit(ctx, 1, 0xcf); | 2070 | xf_emit(ctx, 1, 0); /* 0001ffff DRAW_POINT_X */ |
1625 | xf_emit(ctx, 1, 2); | 2071 | xf_emit(ctx, 1, 8); /* 0000000f DRAW_UNK58C */ |
1626 | xf_emit(ctx, 6, 0); | 2072 | xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_X_FRACT */ |
1627 | xf_emit(ctx, 1, 1); | 2073 | xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_X_INT */ |
1628 | xf_emit(ctx, 1, 0); | 2074 | xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_Y_FRACT */ |
1629 | xf_emit(ctx, 3, 1); | 2075 | xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_Y_INT */ |
1630 | xf_emit(ctx, 4, 0); | 2076 | xf_emit(ctx, 1, 0); /* 000fffff SIFC_DX_DU_FRACT */ |
1631 | xf_emit(ctx, 1, 4); | 2077 | xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DX_DU_INT */ |
1632 | xf_emit(ctx, 1, 0); | 2078 | xf_emit(ctx, 1, 0); /* 000fffff SIFC_DY_DV_FRACT */ |
1633 | xf_emit(ctx, 1, 1); | 2079 | xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DY_DV_INT */ |
1634 | xf_emit(ctx, 1, 0x15); | 2080 | xf_emit(ctx, 1, 1); /* 0000ffff SIFC_WIDTH */ |
1635 | xf_emit(ctx, 3, 0); | 2081 | xf_emit(ctx, 1, 1); /* 0000ffff SIFC_HEIGHT */ |
1636 | xf_emit(ctx, 1, 0x4444480); | 2082 | xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ |
1637 | xf_emit(ctx, 0x37, 0); | 2083 | xf_emit(ctx, 1, 2); /* 00000003 SIFC_BITMAP_UNK808 */ |
2084 | xf_emit(ctx, 1, 0); /* 00000003 SIFC_BITMAP_LINE_PACK_MODE */ | ||
2085 | xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_LSB_FIRST */ | ||
2086 | xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_ENABLE */ | ||
2087 | xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_X */ | ||
2088 | xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_Y */ | ||
2089 | xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ | ||
2090 | xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ | ||
2091 | xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ | ||
2092 | xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ | ||
2093 | xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_W */ | ||
2094 | xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_H */ | ||
2095 | xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_X_FRACT */ | ||
2096 | xf_emit(ctx, 1, 0); /* 0001ffff BLIT_SRC_X_INT */ | ||
2097 | xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_Y_FRACT */ | ||
2098 | xf_emit(ctx, 1, 0); /* 00000001 UNK888 */ | ||
2099 | xf_emit(ctx, 1, 4); /* 0000003f UNK884 */ | ||
2100 | xf_emit(ctx, 1, 0); /* 00000007 UNK880 */ | ||
2101 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK0FB8 */ | ||
2102 | xf_emit(ctx, 1, 0x15); /* 000000ff tesla UNK128C */ | ||
2103 | xf_emit(ctx, 2, 0); /* 00000007, ffff0ff3 */ | ||
2104 | xf_emit(ctx, 1, 0); /* 00000001 UNK260 */ | ||
2105 | xf_emit(ctx, 1, 0x4444480); /* 1fffffff UNK870 */ | ||
2106 | /* SEEK */ | ||
2107 | xf_emit(ctx, 0x10, 0); | ||
2108 | /* SEEK */ | ||
2109 | xf_emit(ctx, 0x27, 0); | ||
1638 | } | 2110 | } |
1639 | 2111 | ||
1640 | static void | 2112 | static void |
1641 | nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx) | 2113 | nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) |
1642 | { | 2114 | { |
1643 | /* middle of area 1 on pre-NVA0 [after m2mf], middle of area 0 on NVAx */ | 2115 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1644 | xf_emit(ctx, 4, 0); | 2116 | /* middle of strand 1 on pre-NVA0 [after eng2d], middle of strand 0 on NVAx */ |
1645 | xf_emit(ctx, 1, 0x8100c12); | 2117 | /* SEEK */ |
1646 | xf_emit(ctx, 4, 0); | 2118 | xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY... what is it doing here??? */ |
1647 | xf_emit(ctx, 1, 0x100); | 2119 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ |
1648 | xf_emit(ctx, 2, 0); | 2120 | xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ |
1649 | xf_emit(ctx, 1, 0x10001); | 2121 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ |
1650 | xf_emit(ctx, 1, 0); | 2122 | xf_emit(ctx, 1, 0); /* 000003ff */ |
1651 | xf_emit(ctx, 1, 0x10001); | 2123 | /* SEEK */ |
1652 | xf_emit(ctx, 1, 1); | 2124 | xf_emit(ctx, 1, 0); /* ffffffff turing UNK364 */ |
1653 | xf_emit(ctx, 1, 0x10001); | 2125 | xf_emit(ctx, 1, 0); /* 0000000f turing UNK36C */ |
1654 | xf_emit(ctx, 1, 1); | 2126 | xf_emit(ctx, 1, 0); /* 0000ffff USER_PARAM_COUNT */ |
1655 | xf_emit(ctx, 1, 4); | 2127 | xf_emit(ctx, 1, 0x100); /* 00ffffff turing UNK384 */ |
1656 | xf_emit(ctx, 1, 2); | 2128 | xf_emit(ctx, 1, 0); /* 0000000f turing UNK2A0 */ |
2129 | xf_emit(ctx, 1, 0); /* 0000ffff GRIDID */ | ||
2130 | xf_emit(ctx, 1, 0x10001); /* ffffffff GRIDDIM_XY */ | ||
2131 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
2132 | xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ | ||
2133 | xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ | ||
2134 | xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ | ||
2135 | xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ | ||
2136 | xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ | ||
2137 | xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ | ||
2138 | /* SEEK */ | ||
2139 | xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */ | ||
2140 | switch (dev_priv->chipset) { | ||
2141 | case 0x50: | ||
2142 | case 0x92: | ||
2143 | xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ | ||
2144 | xf_emit(ctx, 0x80, 0); /* fff */ | ||
2145 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2146 | xf_emit(ctx, 0x10*2, 0); /* ffffffff, 1f */ | ||
2147 | break; | ||
2148 | case 0x84: | ||
2149 | xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ | ||
2150 | xf_emit(ctx, 0x60, 0); /* fff */ | ||
2151 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2152 | xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ | ||
2153 | break; | ||
2154 | case 0x94: | ||
2155 | case 0x96: | ||
2156 | xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ | ||
2157 | xf_emit(ctx, 0x40, 0); /* fff */ | ||
2158 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2159 | xf_emit(ctx, 8*2, 0); /* ffffffff, 1f */ | ||
2160 | break; | ||
2161 | case 0x86: | ||
2162 | case 0x98: | ||
2163 | xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ | ||
2164 | xf_emit(ctx, 0x10, 0); /* fff */ | ||
2165 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2166 | xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ | ||
2167 | break; | ||
2168 | case 0xa0: | ||
2169 | xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ | ||
2170 | xf_emit(ctx, 0xf0, 0); /* fff */ | ||
2171 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2172 | xf_emit(ctx, 0x1e*2, 0); /* ffffffff, 1f */ | ||
2173 | break; | ||
2174 | case 0xa3: | ||
2175 | xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ | ||
2176 | xf_emit(ctx, 0x60, 0); /* fff */ | ||
2177 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2178 | xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ | ||
2179 | break; | ||
2180 | case 0xa5: | ||
2181 | case 0xaf: | ||
2182 | xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ | ||
2183 | xf_emit(ctx, 0x30, 0); /* fff */ | ||
2184 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2185 | xf_emit(ctx, 6*2, 0); /* ffffffff, 1f */ | ||
2186 | break; | ||
2187 | case 0xaa: | ||
2188 | xf_emit(ctx, 0x12, 0); | ||
2189 | break; | ||
2190 | case 0xa8: | ||
2191 | case 0xac: | ||
2192 | xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ | ||
2193 | xf_emit(ctx, 0x10, 0); /* fff */ | ||
2194 | xf_emit(ctx, 2, 0); /* ff, fff */ | ||
2195 | xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ | ||
2196 | break; | ||
2197 | } | ||
2198 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
2199 | xf_emit(ctx, 1, 0); /* 00000000 */ | ||
2200 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
2201 | xf_emit(ctx, 1, 0); /* 0000001f */ | ||
2202 | xf_emit(ctx, 4, 0); /* ffffffff */ | ||
2203 | xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ | ||
2204 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
2205 | xf_emit(ctx, 4, 0); /* ffffffff */ | ||
2206 | xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ | ||
2207 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
2208 | xf_emit(ctx, 1, 0); /* 000000ff */ | ||
1657 | } | 2209 | } |
1658 | 2210 | ||
1659 | static void | 2211 | static void |
1660 | nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx) | 2212 | nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) |
1661 | { | 2213 | { |
1662 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 2214 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1663 | /* middle of area 2 on pre-NVA0 [after m2mf], end of area 0 on NVAx */ | 2215 | xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ |
1664 | xf_emit(ctx, 1, 0x3f800000); | 2216 | xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ |
1665 | xf_emit(ctx, 6, 0); | 2217 | xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ |
1666 | xf_emit(ctx, 1, 4); | 2218 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ |
1667 | xf_emit(ctx, 1, 0x1a); | 2219 | xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ |
1668 | xf_emit(ctx, 2, 0); | 2220 | xf_emit(ctx, 3, 0); /* 00000001 POLYGON_OFFSET_*_ENABLE */ |
1669 | xf_emit(ctx, 1, 1); | 2221 | xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ |
1670 | xf_emit(ctx, 0x12, 0); | 2222 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ |
1671 | xf_emit(ctx, 1, 0x00ffff00); | 2223 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ |
1672 | xf_emit(ctx, 6, 0); | 2224 | xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ |
1673 | xf_emit(ctx, 1, 0xf); | 2225 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ |
1674 | xf_emit(ctx, 7, 0); | 2226 | xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ |
1675 | xf_emit(ctx, 1, 0x0fac6881); | 2227 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1676 | xf_emit(ctx, 1, 0x11); | 2228 | xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ |
1677 | xf_emit(ctx, 0xf, 0); | 2229 | xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ |
1678 | xf_emit(ctx, 1, 4); | 2230 | xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_UNITS */ |
1679 | xf_emit(ctx, 2, 0); | 2231 | xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_FACTOR */ |
1680 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2232 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ |
1681 | xf_emit(ctx, 1, 3); | 2233 | xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ |
2234 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ | ||
2235 | xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ | ||
2236 | xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ | ||
2237 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ | ||
2238 | xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ | ||
2239 | xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ | ||
2240 | xf_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_LINEAR */ | ||
2241 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ | ||
2242 | xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ | ||
2243 | xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ | ||
2244 | if (IS_NVA3F(dev_priv->chipset)) | ||
2245 | xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */ | ||
1682 | else if (dev_priv->chipset >= 0xa0) | 2246 | else if (dev_priv->chipset >= 0xa0) |
1683 | xf_emit(ctx, 1, 1); | 2247 | xf_emit(ctx, 1, 1); /* 00000001 UNK16B4 */ |
1684 | xf_emit(ctx, 2, 0); | 2248 | xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ |
1685 | xf_emit(ctx, 1, 2); | 2249 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ |
1686 | xf_emit(ctx, 2, 0x04000000); | 2250 | xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ |
1687 | xf_emit(ctx, 3, 0); | 2251 | xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ |
1688 | xf_emit(ctx, 1, 5); | 2252 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ |
1689 | xf_emit(ctx, 1, 0x52); | 2253 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
1690 | if (dev_priv->chipset == 0x50) { | 2254 | xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ |
1691 | xf_emit(ctx, 0x13, 0); | 2255 | xf_emit(ctx, 1, 5); /* 0000000f UNK1408 */ |
1692 | } else { | 2256 | xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ |
1693 | xf_emit(ctx, 4, 0); | 2257 | xf_emit(ctx, 1, 0); /* ffffffff POINT_SIZE */ |
1694 | xf_emit(ctx, 1, 1); | 2258 | xf_emit(ctx, 1, 0); /* 00000001 */ |
1695 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2259 | xf_emit(ctx, 1, 0); /* 00000007 tesla UNK0FB4 */ |
1696 | xf_emit(ctx, 0x11, 0); | 2260 | if (dev_priv->chipset != 0x50) { |
1697 | else | 2261 | xf_emit(ctx, 1, 0); /* 3ff */ |
1698 | xf_emit(ctx, 0x10, 0); | 2262 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */ |
1699 | } | 2263 | } |
1700 | xf_emit(ctx, 0x10, 0x3f800000); | 2264 | if (IS_NVA3F(dev_priv->chipset)) |
1701 | xf_emit(ctx, 1, 0x10); | 2265 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ |
1702 | xf_emit(ctx, 0x26, 0); | 2266 | xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ |
1703 | xf_emit(ctx, 1, 0x8100c12); | 2267 | xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ |
1704 | xf_emit(ctx, 1, 5); | 2268 | xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ |
1705 | xf_emit(ctx, 2, 0); | 2269 | xf_emit(ctx, 0x20, 0); /* 07ffffff VIEWPORT_HORIZ, then VIEWPORT_VERT. (W&0x3fff)<<13 | (X&0x1fff). */ |
1706 | xf_emit(ctx, 1, 1); | 2270 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK187C */ |
1707 | xf_emit(ctx, 1, 0); | 2271 | xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ |
1708 | xf_emit(ctx, 4, 0xffff); | 2272 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ |
2273 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ | ||
2274 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ | ||
2275 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ | ||
2276 | xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ | ||
2277 | xf_emit(ctx, 1, 5); /* 0000000f tesla UNK1220 */ | ||
2278 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ | ||
2279 | xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1A20 */ | ||
2280 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ | ||
2281 | xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ | ||
2282 | xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ | ||
1709 | if (dev_priv->chipset != 0x50) | 2283 | if (dev_priv->chipset != 0x50) |
1710 | xf_emit(ctx, 1, 3); | 2284 | xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ |
1711 | if (dev_priv->chipset < 0xa0) | 2285 | if (dev_priv->chipset < 0xa0) |
1712 | xf_emit(ctx, 0x1f, 0); | 2286 | xf_emit(ctx, 0x1c, 0); /* RO */ |
1713 | else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2287 | else if (IS_NVA3F(dev_priv->chipset)) |
1714 | xf_emit(ctx, 0xc, 0); | 2288 | xf_emit(ctx, 0x9, 0); |
1715 | else | 2289 | xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ |
1716 | xf_emit(ctx, 3, 0); | 2290 | xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ |
1717 | xf_emit(ctx, 1, 0x00ffff00); | 2291 | xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ |
1718 | xf_emit(ctx, 1, 0x1a); | 2292 | xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ |
2293 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ | ||
2294 | xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ | ||
1719 | if (dev_priv->chipset != 0x50) { | 2295 | if (dev_priv->chipset != 0x50) { |
1720 | xf_emit(ctx, 1, 0); | 2296 | xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ |
1721 | xf_emit(ctx, 1, 3); | 2297 | xf_emit(ctx, 1, 0); /* 3ff */ |
1722 | } | 2298 | } |
2299 | /* XXX: the following block could belong either to unk1cxx, or | ||
2300 | * to STRMOUT. Rather hard to tell. */ | ||
1723 | if (dev_priv->chipset < 0xa0) | 2301 | if (dev_priv->chipset < 0xa0) |
1724 | xf_emit(ctx, 0x26, 0); | 2302 | xf_emit(ctx, 0x25, 0); |
1725 | else | 2303 | else |
1726 | xf_emit(ctx, 0x3c, 0); | 2304 | xf_emit(ctx, 0x3b, 0); |
1727 | xf_emit(ctx, 1, 0x102); | 2305 | } |
1728 | xf_emit(ctx, 1, 0); | 2306 | |
1729 | xf_emit(ctx, 4, 4); | 2307 | static void |
1730 | if (dev_priv->chipset >= 0xa0) | 2308 | nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) |
1731 | xf_emit(ctx, 8, 0); | 2309 | { |
1732 | xf_emit(ctx, 2, 4); | 2310 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1733 | xf_emit(ctx, 1, 0); | 2311 | xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ |
2312 | xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ | ||
2313 | xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ | ||
2314 | if (dev_priv->chipset >= 0xa0) { | ||
2315 | xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ | ||
2316 | xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ | ||
2317 | } | ||
2318 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
2319 | xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ | ||
2320 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
1734 | if (dev_priv->chipset == 0x50) | 2321 | if (dev_priv->chipset == 0x50) |
1735 | xf_emit(ctx, 1, 0x3ff); | 2322 | xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ |
1736 | else | 2323 | else |
1737 | xf_emit(ctx, 1, 0x7ff); | 2324 | xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ |
1738 | xf_emit(ctx, 1, 0); | 2325 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
1739 | xf_emit(ctx, 1, 0x102); | 2326 | /* SEEK */ |
1740 | xf_emit(ctx, 9, 0); | 2327 | xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ |
1741 | xf_emit(ctx, 4, 4); | 2328 | xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ |
1742 | xf_emit(ctx, 0x2c, 0); | 2329 | xf_emit(ctx, 4, 0); /* 000000ff STRMOUT_ADDRESS_HIGH */ |
2330 | xf_emit(ctx, 4, 0); /* ffffffff STRMOUT_ADDRESS_LOW */ | ||
2331 | xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ | ||
2332 | if (dev_priv->chipset >= 0xa0) { | ||
2333 | xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ | ||
2334 | xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ | ||
2335 | } | ||
2336 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_STRMOUT */ | ||
2337 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ | ||
2338 | xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ | ||
2339 | xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW QUERY_COUNTER */ | ||
2340 | xf_emit(ctx, 2, 0); /* ffffffff */ | ||
2341 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
2342 | /* SEEK */ | ||
2343 | xf_emit(ctx, 0x20, 0); /* ffffffff STRMOUT_MAP */ | ||
2344 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
2345 | xf_emit(ctx, 1, 0); /* 00000000? */ | ||
2346 | xf_emit(ctx, 2, 0); /* ffffffff */ | ||
2347 | } | ||
2348 | |||
2349 | static void | ||
2350 | nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) | ||
2351 | { | ||
2352 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
2353 | xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ | ||
2354 | xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ | ||
2355 | xf_emit(ctx, 1, 0); /* 00000007 */ | ||
2356 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
2357 | if (IS_NVA3F(dev_priv->chipset)) | ||
2358 | xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ | ||
2359 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ | ||
2360 | } | ||
2361 | |||
2362 | static void | ||
2363 | nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) | ||
2364 | { | ||
2365 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | ||
2366 | /* SEEK */ | ||
2367 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ | ||
2368 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ | ||
2369 | xf_emit(ctx, 2, 0); /* ffffffff */ | ||
2370 | xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ | ||
2371 | xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ | ||
2372 | xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ | ||
2373 | xf_emit(ctx, 1, 0); /* 7 */ | ||
2374 | /* SEEK */ | ||
2375 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ | ||
2376 | xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ | ||
2377 | xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ | ||
2378 | xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ | ||
2379 | xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ | ||
2380 | xf_emit(ctx, 1, 0); /* 00000001 eng2d UNK260 */ | ||
2381 | xf_emit(ctx, 1, 0); /* ff/3ff */ | ||
2382 | xf_emit(ctx, 1, 0); /* 00000007 */ | ||
2383 | if (IS_NVA3F(dev_priv->chipset)) | ||
2384 | xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ | ||
2385 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ | ||
1743 | } | 2386 | } |
1744 | 2387 | ||
1745 | static void | 2388 | static void |
@@ -1749,443 +2392,709 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) | |||
1749 | int magic2; | 2392 | int magic2; |
1750 | if (dev_priv->chipset == 0x50) { | 2393 | if (dev_priv->chipset == 0x50) { |
1751 | magic2 = 0x00003e60; | 2394 | magic2 = 0x00003e60; |
1752 | } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { | 2395 | } else if (!IS_NVA3F(dev_priv->chipset)) { |
1753 | magic2 = 0x001ffe67; | 2396 | magic2 = 0x001ffe67; |
1754 | } else { | 2397 | } else { |
1755 | magic2 = 0x00087e67; | 2398 | magic2 = 0x00087e67; |
1756 | } | 2399 | } |
1757 | xf_emit(ctx, 8, 0); | 2400 | xf_emit(ctx, 1, 0); /* f/7 MUTISAMPLE_SAMPLES_LOG2 */ |
1758 | xf_emit(ctx, 1, 2); | 2401 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1759 | xf_emit(ctx, 1, 0); | 2402 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ |
1760 | xf_emit(ctx, 1, magic2); | 2403 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ |
1761 | xf_emit(ctx, 4, 0); | 2404 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ |
1762 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2405 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ |
1763 | xf_emit(ctx, 1, 1); | 2406 | xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ |
1764 | xf_emit(ctx, 7, 0); | 2407 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ |
1765 | if (dev_priv->chipset >= 0xa0 && dev_priv->chipset < 0xaa) | 2408 | xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ |
1766 | xf_emit(ctx, 1, 0x15); | 2409 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ |
1767 | xf_emit(ctx, 1, 0); | 2410 | xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ |
1768 | xf_emit(ctx, 1, 1); | 2411 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
1769 | xf_emit(ctx, 1, 0x10); | 2412 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
1770 | xf_emit(ctx, 2, 0); | 2413 | if (IS_NVA3F(dev_priv->chipset)) |
1771 | xf_emit(ctx, 1, 1); | 2414 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ |
1772 | xf_emit(ctx, 4, 0); | 2415 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ |
2416 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ | ||
2417 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ | ||
2418 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ | ||
2419 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ | ||
2420 | if (dev_priv->chipset >= 0xa0 && !IS_NVAAF(dev_priv->chipset)) | ||
2421 | xf_emit(ctx, 1, 0x15); /* 000000ff */ | ||
2422 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ | ||
2423 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ | ||
2424 | xf_emit(ctx, 1, 0x10); /* 3ff/ff VIEW_VOLUME_CLIP_CTRL */ | ||
2425 | xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ | ||
2426 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ | ||
2427 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ | ||
2428 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ | ||
1773 | if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) { | 2429 | if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) { |
1774 | xf_emit(ctx, 1, 4); | 2430 | xf_emit(ctx, 3, 0); /* ff, ffffffff, ffffffff */ |
1775 | xf_emit(ctx, 1, 0x400); | 2431 | xf_emit(ctx, 1, 4); /* 7 */ |
1776 | xf_emit(ctx, 1, 0x300); | 2432 | xf_emit(ctx, 1, 0x400); /* fffffff */ |
1777 | xf_emit(ctx, 1, 0x1001); | 2433 | xf_emit(ctx, 1, 0x300); /* ffff */ |
2434 | xf_emit(ctx, 1, 0x1001); /* 1fff */ | ||
1778 | if (dev_priv->chipset != 0xa0) { | 2435 | if (dev_priv->chipset != 0xa0) { |
1779 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2436 | if (IS_NVA3F(dev_priv->chipset)) |
1780 | xf_emit(ctx, 1, 0); | 2437 | xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */ |
1781 | else | 2438 | else |
1782 | xf_emit(ctx, 1, 0x15); | 2439 | xf_emit(ctx, 1, 0x15); /* ff */ |
1783 | } | 2440 | } |
1784 | xf_emit(ctx, 3, 0); | ||
1785 | } | 2441 | } |
1786 | xf_emit(ctx, 2, 0); | 2442 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ |
1787 | xf_emit(ctx, 1, 2); | 2443 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1788 | xf_emit(ctx, 8, 0); | 2444 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ |
1789 | xf_emit(ctx, 1, 1); | 2445 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ |
1790 | xf_emit(ctx, 1, 0x10); | 2446 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ |
1791 | xf_emit(ctx, 1, 0); | 2447 | xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ |
1792 | xf_emit(ctx, 1, 1); | 2448 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ |
1793 | xf_emit(ctx, 0x13, 0); | 2449 | xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ |
1794 | xf_emit(ctx, 1, 0x10); | 2450 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
1795 | xf_emit(ctx, 0x10, 0); | 2451 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
1796 | xf_emit(ctx, 0x10, 0x3f800000); | 2452 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ |
1797 | xf_emit(ctx, 0x19, 0); | 2453 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ |
1798 | xf_emit(ctx, 1, 0x10); | 2454 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ |
1799 | xf_emit(ctx, 1, 0); | 2455 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ |
1800 | xf_emit(ctx, 1, 0x3f); | 2456 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ |
1801 | xf_emit(ctx, 6, 0); | 2457 | xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ |
1802 | xf_emit(ctx, 1, 1); | 2458 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ |
1803 | xf_emit(ctx, 1, 0); | 2459 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ |
1804 | xf_emit(ctx, 1, 1); | 2460 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ |
1805 | xf_emit(ctx, 1, 0); | 2461 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1806 | xf_emit(ctx, 1, 1); | 2462 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ |
2463 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ | ||
2464 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ | ||
2465 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ | ||
2466 | xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ | ||
2467 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ | ||
2468 | xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ | ||
2469 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ | ||
2470 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ | ||
2471 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
2472 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ | ||
2473 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ | ||
2474 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ | ||
2475 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */ | ||
2476 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ | ||
2477 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ | ||
2478 | xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ | ||
2479 | xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ | ||
2480 | xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ | ||
2481 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ | ||
2482 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ | ||
2483 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ | ||
2484 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ | ||
2485 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ | ||
2486 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ | ||
2487 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ | ||
2488 | xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ | ||
2489 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ | ||
2490 | xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ | ||
2491 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ | ||
2492 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ | ||
2493 | xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ | ||
2494 | xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ | ||
2495 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ | ||
2496 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */ | ||
2497 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ | ||
2498 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ | ||
2499 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ | ||
2500 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ | ||
2501 | xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ | ||
2502 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ | ||
2503 | xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ | ||
2504 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ | ||
2505 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ | ||
2506 | xf_emit(ctx, 2, 0); /* ffff0ff3, ffff */ | ||
2507 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ | ||
2508 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ | ||
2509 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ | ||
2510 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ | ||
2511 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ | ||
2512 | xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ | ||
2513 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ | ||
1807 | if (dev_priv->chipset >= 0xa0) { | 2514 | if (dev_priv->chipset >= 0xa0) { |
1808 | xf_emit(ctx, 2, 0); | 2515 | xf_emit(ctx, 2, 0); |
1809 | xf_emit(ctx, 1, 0x1001); | 2516 | xf_emit(ctx, 1, 0x1001); |
1810 | xf_emit(ctx, 0xb, 0); | 2517 | xf_emit(ctx, 0xb, 0); |
1811 | } else { | 2518 | } else { |
1812 | xf_emit(ctx, 0xc, 0); | 2519 | xf_emit(ctx, 1, 0); /* 00000007 */ |
2520 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ | ||
2521 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ | ||
2522 | xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ | ||
2523 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
1813 | } | 2524 | } |
1814 | xf_emit(ctx, 1, 0x11); | 2525 | xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ |
1815 | xf_emit(ctx, 7, 0); | 2526 | xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ |
1816 | xf_emit(ctx, 1, 0xf); | 2527 | xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ |
1817 | xf_emit(ctx, 7, 0); | 2528 | xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ |
1818 | xf_emit(ctx, 1, 0x11); | 2529 | xf_emit(ctx, 1, 0x11); /* 3f/7f */ |
1819 | if (dev_priv->chipset == 0x50) | 2530 | xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ |
1820 | xf_emit(ctx, 4, 0); | 2531 | if (dev_priv->chipset != 0x50) { |
1821 | else | 2532 | xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ |
1822 | xf_emit(ctx, 6, 0); | 2533 | xf_emit(ctx, 1, 0); /* 000000ff */ |
1823 | xf_emit(ctx, 3, 1); | 2534 | } |
1824 | xf_emit(ctx, 1, 2); | 2535 | xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ |
1825 | xf_emit(ctx, 1, 1); | 2536 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
1826 | xf_emit(ctx, 1, 2); | 2537 | xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ |
1827 | xf_emit(ctx, 1, 1); | 2538 | xf_emit(ctx, 2, 1); /* 00000007 BLEND_EQUATION_RGB, ALPHA */ |
1828 | xf_emit(ctx, 1, 0); | 2539 | xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ |
1829 | xf_emit(ctx, 1, magic2); | 2540 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ |
1830 | xf_emit(ctx, 1, 0); | 2541 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ |
1831 | xf_emit(ctx, 1, 0x0fac6881); | 2542 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ |
1832 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 2543 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ |
1833 | xf_emit(ctx, 1, 0); | 2544 | xf_emit(ctx, 1, 0); /* 00000001 */ |
1834 | xf_emit(ctx, 0x18, 1); | 2545 | xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ |
1835 | xf_emit(ctx, 8, 2); | 2546 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ |
1836 | xf_emit(ctx, 8, 1); | 2547 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ |
1837 | xf_emit(ctx, 8, 2); | 2548 | if (IS_NVA3F(dev_priv->chipset)) { |
1838 | xf_emit(ctx, 8, 1); | 2549 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK12E4 */ |
1839 | xf_emit(ctx, 3, 0); | 2550 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ |
1840 | xf_emit(ctx, 1, 1); | 2551 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ |
1841 | xf_emit(ctx, 5, 0); | 2552 | xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ |
1842 | xf_emit(ctx, 1, 1); | 2553 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ |
1843 | xf_emit(ctx, 0x16, 0); | 2554 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ |
2555 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ | ||
2556 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ | ||
2557 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ | ||
2558 | xf_emit(ctx, 2, 0); /* 00000001 */ | ||
2559 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
2560 | xf_emit(ctx, 1, 0); /* 0000000f */ | ||
2561 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
2562 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
2563 | xf_emit(ctx, 2, 0); /* 00000001 */ | ||
2564 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
2565 | xf_emit(ctx, 1, 0); /* 00000001 */ | ||
2566 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
2567 | } else if (dev_priv->chipset >= 0xa0) { | ||
2568 | xf_emit(ctx, 2, 0); /* 00000001 */ | ||
2569 | xf_emit(ctx, 1, 0); /* 00000007 */ | ||
2570 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
2571 | xf_emit(ctx, 1, 0); /* ffffffff */ | ||
2572 | xf_emit(ctx, 2, 0); /* 00000001 */ | ||
1844 | } else { | 2573 | } else { |
1845 | if (dev_priv->chipset >= 0xa0) | 2574 | xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ |
1846 | xf_emit(ctx, 0x1b, 0); | 2575 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1430 */ |
1847 | else | 2576 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ |
1848 | xf_emit(ctx, 0x15, 0); | ||
1849 | } | 2577 | } |
1850 | xf_emit(ctx, 1, 1); | 2578 | xf_emit(ctx, 4, 0); /* ffffffff CLEAR_COLOR */ |
1851 | xf_emit(ctx, 1, 2); | 2579 | xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR A R G B */ |
1852 | xf_emit(ctx, 2, 1); | 2580 | xf_emit(ctx, 1, 0); /* 00000fff eng2d UNK2B0 */ |
1853 | xf_emit(ctx, 1, 2); | ||
1854 | xf_emit(ctx, 2, 1); | ||
1855 | if (dev_priv->chipset >= 0xa0) | 2581 | if (dev_priv->chipset >= 0xa0) |
1856 | xf_emit(ctx, 4, 0); | 2582 | xf_emit(ctx, 2, 0); /* 00000001 */ |
1857 | else | 2583 | xf_emit(ctx, 1, 0); /* 000003ff */ |
1858 | xf_emit(ctx, 3, 0); | 2584 | xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ |
1859 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 2585 | xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ |
1860 | xf_emit(ctx, 0x10, 1); | 2586 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ |
1861 | xf_emit(ctx, 8, 2); | 2587 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ |
1862 | xf_emit(ctx, 0x10, 1); | 2588 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ |
1863 | xf_emit(ctx, 8, 2); | 2589 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ |
1864 | xf_emit(ctx, 8, 1); | 2590 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ |
1865 | xf_emit(ctx, 3, 0); | 2591 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ |
2592 | xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ | ||
2593 | xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ | ||
2594 | xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ | ||
2595 | if (dev_priv->chipset >= 0xa0) | ||
2596 | xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */ | ||
2597 | if (IS_NVA3F(dev_priv->chipset)) { | ||
2598 | xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ | ||
2599 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ | ||
2600 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ | ||
2601 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ | ||
2602 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ | ||
2603 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ | ||
2604 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ | ||
2605 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK15C4 */ | ||
2606 | xf_emit(ctx, 1, 0); /* 00000001 */ | ||
2607 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ | ||
1866 | } | 2608 | } |
1867 | xf_emit(ctx, 1, 0x11); | 2609 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ |
1868 | xf_emit(ctx, 1, 1); | 2610 | xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ |
1869 | xf_emit(ctx, 0x5b, 0); | 2611 | xf_emit(ctx, 1, 0); /* 00000007 PATTERN_COLOR_FORMAT */ |
2612 | xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_COLOR */ | ||
2613 | xf_emit(ctx, 1, 0); /* 00000001 PATTERN_MONO_FORMAT */ | ||
2614 | xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_BITMAP */ | ||
2615 | xf_emit(ctx, 1, 0); /* 00000003 PATTERN_SELECT */ | ||
2616 | xf_emit(ctx, 1, 0); /* 000000ff ROP */ | ||
2617 | xf_emit(ctx, 1, 0); /* ffffffff BETA1 */ | ||
2618 | xf_emit(ctx, 1, 0); /* ffffffff BETA4 */ | ||
2619 | xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ | ||
2620 | xf_emit(ctx, 0x50, 0); /* 10x ffffff, ffffff, ffffff, ffffff, 3 PATTERN */ | ||
1870 | } | 2621 | } |
1871 | 2622 | ||
1872 | static void | 2623 | static void |
1873 | nv50_graph_construct_xfer_tp_x1(struct nouveau_grctx *ctx) | 2624 | nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) |
1874 | { | 2625 | { |
1875 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 2626 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1876 | int magic3; | 2627 | int magic3; |
1877 | if (dev_priv->chipset == 0x50) | 2628 | switch (dev_priv->chipset) { |
2629 | case 0x50: | ||
1878 | magic3 = 0x1000; | 2630 | magic3 = 0x1000; |
1879 | else if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) | 2631 | break; |
2632 | case 0x86: | ||
2633 | case 0x98: | ||
2634 | case 0xa8: | ||
2635 | case 0xaa: | ||
2636 | case 0xac: | ||
2637 | case 0xaf: | ||
1880 | magic3 = 0x1e00; | 2638 | magic3 = 0x1e00; |
1881 | else | 2639 | break; |
2640 | default: | ||
1882 | magic3 = 0; | 2641 | magic3 = 0; |
1883 | xf_emit(ctx, 1, 0); | 2642 | } |
1884 | xf_emit(ctx, 1, 4); | 2643 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1885 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2644 | xf_emit(ctx, 1, 4); /* 7f/ff[NVA0+] VP_REG_ALLOC_RESULT */ |
1886 | xf_emit(ctx, 0x24, 0); | 2645 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
2646 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
2647 | xf_emit(ctx, 1, 0); /* 111/113[NVA0+] */ | ||
2648 | if (IS_NVA3F(dev_priv->chipset)) | ||
2649 | xf_emit(ctx, 0x1f, 0); /* ffffffff */ | ||
1887 | else if (dev_priv->chipset >= 0xa0) | 2650 | else if (dev_priv->chipset >= 0xa0) |
1888 | xf_emit(ctx, 0x14, 0); | 2651 | xf_emit(ctx, 0x0f, 0); /* ffffffff */ |
1889 | else | 2652 | else |
1890 | xf_emit(ctx, 0x15, 0); | 2653 | xf_emit(ctx, 0x10, 0); /* fffffff VP_RESULT_MAP_1 up */ |
1891 | xf_emit(ctx, 2, 4); | 2654 | xf_emit(ctx, 2, 0); /* f/1f[NVA3], fffffff/ffffffff[NVA0+] */ |
2655 | xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ | ||
2656 | xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ | ||
1892 | if (dev_priv->chipset >= 0xa0) | 2657 | if (dev_priv->chipset >= 0xa0) |
1893 | xf_emit(ctx, 1, 0x03020100); | 2658 | xf_emit(ctx, 1, 0x03020100); /* ffffffff */ |
1894 | else | 2659 | else |
1895 | xf_emit(ctx, 1, 0x00608080); | 2660 | xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */ |
1896 | xf_emit(ctx, 4, 0); | 2661 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1897 | xf_emit(ctx, 1, 4); | 2662 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
1898 | xf_emit(ctx, 2, 0); | 2663 | xf_emit(ctx, 2, 0); /* 111/113, 7f/ff */ |
1899 | xf_emit(ctx, 2, 4); | 2664 | xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ |
1900 | xf_emit(ctx, 1, 0x80); | 2665 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
2666 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
2667 | xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ | ||
2668 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
2669 | xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ | ||
1901 | if (magic3) | 2670 | if (magic3) |
1902 | xf_emit(ctx, 1, magic3); | 2671 | xf_emit(ctx, 1, magic3); /* 00007fff tesla UNK141C */ |
1903 | xf_emit(ctx, 1, 4); | 2672 | xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ |
1904 | xf_emit(ctx, 0x24, 0); | 2673 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
1905 | xf_emit(ctx, 1, 4); | 2674 | xf_emit(ctx, 1, 0); /* 111/113 */ |
1906 | xf_emit(ctx, 1, 0x80); | 2675 | xf_emit(ctx, 0x1f, 0); /* ffffffff GP_RESULT_MAP_1 up */ |
1907 | xf_emit(ctx, 1, 4); | 2676 | xf_emit(ctx, 1, 0); /* 0000001f */ |
1908 | xf_emit(ctx, 1, 0x03020100); | 2677 | xf_emit(ctx, 1, 0); /* ffffffff */ |
1909 | xf_emit(ctx, 1, 3); | 2678 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
2679 | xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ | ||
2680 | xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ | ||
2681 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ | ||
2682 | xf_emit(ctx, 1, 0x03020100); /* ffffffff GP_RESULT_MAP_0 */ | ||
2683 | xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ | ||
1910 | if (magic3) | 2684 | if (magic3) |
1911 | xf_emit(ctx, 1, magic3); | 2685 | xf_emit(ctx, 1, magic3); /* 7fff tesla UNK141C */ |
1912 | xf_emit(ctx, 1, 4); | 2686 | xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ |
1913 | xf_emit(ctx, 4, 0); | 2687 | xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ |
1914 | xf_emit(ctx, 1, 4); | 2688 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
1915 | xf_emit(ctx, 1, 3); | 2689 | xf_emit(ctx, 1, 0); /* 111/113 */ |
1916 | xf_emit(ctx, 3, 0); | 2690 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1917 | xf_emit(ctx, 1, 4); | 2691 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ |
2692 | xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ | ||
2693 | xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ | ||
2694 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
2695 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK13A0 */ | ||
2696 | xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ | ||
2697 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
2698 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
2699 | xf_emit(ctx, 1, 0); /* 111/113 */ | ||
1918 | if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96) | 2700 | if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96) |
1919 | xf_emit(ctx, 0x1024, 0); | 2701 | xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ |
1920 | else if (dev_priv->chipset < 0xa0) | 2702 | else if (dev_priv->chipset < 0xa0) |
1921 | xf_emit(ctx, 0xa24, 0); | 2703 | xf_emit(ctx, 0xa20, 0); /* 4 x (0x280 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ |
1922 | else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) | 2704 | else if (!IS_NVA3F(dev_priv->chipset)) |
1923 | xf_emit(ctx, 0x214, 0); | 2705 | xf_emit(ctx, 0x210, 0); /* ffffffff */ |
1924 | else | 2706 | else |
1925 | xf_emit(ctx, 0x414, 0); | 2707 | xf_emit(ctx, 0x410, 0); /* ffffffff */ |
1926 | xf_emit(ctx, 1, 4); | 2708 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
1927 | xf_emit(ctx, 1, 3); | 2709 | xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ |
1928 | xf_emit(ctx, 2, 0); | 2710 | xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ |
2711 | xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ | ||
2712 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ | ||
1929 | } | 2713 | } |
1930 | 2714 | ||
1931 | static void | 2715 | static void |
1932 | nv50_graph_construct_xfer_tp_x2(struct nouveau_grctx *ctx) | 2716 | nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) |
1933 | { | 2717 | { |
1934 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 2718 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
1935 | int magic1, magic2; | 2719 | int magic1, magic2; |
1936 | if (dev_priv->chipset == 0x50) { | 2720 | if (dev_priv->chipset == 0x50) { |
1937 | magic1 = 0x3ff; | 2721 | magic1 = 0x3ff; |
1938 | magic2 = 0x00003e60; | 2722 | magic2 = 0x00003e60; |
1939 | } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { | 2723 | } else if (!IS_NVA3F(dev_priv->chipset)) { |
1940 | magic1 = 0x7ff; | 2724 | magic1 = 0x7ff; |
1941 | magic2 = 0x001ffe67; | 2725 | magic2 = 0x001ffe67; |
1942 | } else { | 2726 | } else { |
1943 | magic1 = 0x7ff; | 2727 | magic1 = 0x7ff; |
1944 | magic2 = 0x00087e67; | 2728 | magic2 = 0x00087e67; |
1945 | } | 2729 | } |
1946 | xf_emit(ctx, 3, 0); | 2730 | xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ |
1947 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2731 | xf_emit(ctx, 1, 0); /* ffffffff ALPHA_TEST_REF */ |
1948 | xf_emit(ctx, 1, 1); | 2732 | xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ |
1949 | xf_emit(ctx, 0xc, 0); | 2733 | if (IS_NVA3F(dev_priv->chipset)) |
1950 | xf_emit(ctx, 1, 0xf); | 2734 | xf_emit(ctx, 1, 1); /* 0000000f UNK16A0 */ |
1951 | xf_emit(ctx, 0xb, 0); | 2735 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
1952 | xf_emit(ctx, 1, 4); | 2736 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1953 | xf_emit(ctx, 4, 0xffff); | 2737 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ |
1954 | xf_emit(ctx, 8, 0); | 2738 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ |
1955 | xf_emit(ctx, 1, 1); | 2739 | xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR */ |
1956 | xf_emit(ctx, 3, 0); | 2740 | xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ |
1957 | xf_emit(ctx, 1, 1); | 2741 | xf_emit(ctx, 1, 0); /* 00000001 UNK0FDC */ |
1958 | xf_emit(ctx, 5, 0); | 2742 | xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ |
1959 | xf_emit(ctx, 1, 1); | 2743 | xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ |
1960 | xf_emit(ctx, 2, 0); | 2744 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
1961 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 2745 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
1962 | xf_emit(ctx, 1, 3); | 2746 | xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ |
1963 | xf_emit(ctx, 1, 0); | 2747 | xf_emit(ctx, 1, 0); /* ff[NV50]/3ff[NV84+] */ |
1964 | } else if (dev_priv->chipset >= 0xa0) | 2748 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ |
1965 | xf_emit(ctx, 1, 1); | 2749 | xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ |
1966 | xf_emit(ctx, 0xa, 0); | 2750 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ |
1967 | xf_emit(ctx, 2, 1); | 2751 | xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ |
1968 | xf_emit(ctx, 1, 2); | 2752 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ |
1969 | xf_emit(ctx, 2, 1); | 2753 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ |
1970 | xf_emit(ctx, 1, 2); | 2754 | xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ |
1971 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 2755 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ |
1972 | xf_emit(ctx, 1, 0); | 2756 | xf_emit(ctx, 1, 0); /* 7 */ |
1973 | xf_emit(ctx, 0x18, 1); | 2757 | xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ |
1974 | xf_emit(ctx, 8, 2); | 2758 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ |
1975 | xf_emit(ctx, 8, 1); | 2759 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ |
1976 | xf_emit(ctx, 8, 2); | 2760 | xf_emit(ctx, 1, 0); /* ffffffff COLOR_KEY */ |
1977 | xf_emit(ctx, 8, 1); | 2761 | xf_emit(ctx, 1, 0); /* 00000001 COLOR_KEY_ENABLE */ |
1978 | xf_emit(ctx, 1, 0); | 2762 | xf_emit(ctx, 1, 0); /* 00000007 COLOR_KEY_FORMAT */ |
2763 | xf_emit(ctx, 2, 0); /* ffffffff SIFC_BITMAP_COLOR */ | ||
2764 | xf_emit(ctx, 1, 1); /* 00000001 SIFC_BITMAP_WRITE_BIT0_ENABLE */ | ||
2765 | xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ | ||
2766 | xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ | ||
2767 | if (IS_NVA3F(dev_priv->chipset)) { | ||
2768 | xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ | ||
2769 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
2770 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1298 */ | ||
2771 | } else if (dev_priv->chipset >= 0xa0) { | ||
2772 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */ | ||
2773 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
2774 | } else { | ||
2775 | xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ | ||
1979 | } | 2776 | } |
1980 | xf_emit(ctx, 1, 1); | 2777 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
1981 | xf_emit(ctx, 1, 0); | 2778 | xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ |
1982 | xf_emit(ctx, 1, 0x11); | 2779 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ |
1983 | xf_emit(ctx, 7, 0); | 2780 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ |
1984 | xf_emit(ctx, 1, 0x0fac6881); | 2781 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ |
1985 | xf_emit(ctx, 2, 0); | 2782 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ |
1986 | xf_emit(ctx, 1, 4); | 2783 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ |
1987 | xf_emit(ctx, 3, 0); | 2784 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ |
1988 | xf_emit(ctx, 1, 0x11); | 2785 | if (IS_NVA3F(dev_priv->chipset)) { |
1989 | xf_emit(ctx, 1, 1); | 2786 | xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ |
1990 | xf_emit(ctx, 1, 0); | 2787 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ |
1991 | xf_emit(ctx, 3, 0xcf); | 2788 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ |
1992 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2789 | xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ |
1993 | xf_emit(ctx, 1, 1); | 2790 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_RGB */ |
1994 | xf_emit(ctx, 0xa, 0); | 2791 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_RGB */ |
1995 | xf_emit(ctx, 2, 1); | 2792 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_ALPHA */ |
1996 | xf_emit(ctx, 1, 2); | 2793 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_ALPHA */ |
1997 | xf_emit(ctx, 2, 1); | 2794 | xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ |
1998 | xf_emit(ctx, 1, 2); | 2795 | } |
1999 | xf_emit(ctx, 1, 1); | 2796 | xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ |
2000 | xf_emit(ctx, 1, 0); | 2797 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ |
2001 | xf_emit(ctx, 8, 1); | 2798 | xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ |
2002 | xf_emit(ctx, 1, 0x11); | 2799 | xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ |
2003 | xf_emit(ctx, 7, 0); | 2800 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ |
2004 | xf_emit(ctx, 1, 0x0fac6881); | 2801 | xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ |
2005 | xf_emit(ctx, 1, 0xf); | 2802 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2006 | xf_emit(ctx, 7, 0); | 2803 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ |
2007 | xf_emit(ctx, 1, magic2); | 2804 | xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ |
2008 | xf_emit(ctx, 2, 0); | 2805 | xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ |
2009 | xf_emit(ctx, 1, 0x11); | 2806 | xf_emit(ctx, 1, 0); /* 7 */ |
2010 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2807 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ |
2011 | xf_emit(ctx, 2, 1); | 2808 | xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ |
2012 | else | 2809 | xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ |
2013 | xf_emit(ctx, 1, 1); | 2810 | xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ |
2811 | xf_emit(ctx, 1, 0xcf); /* 000000ff DRAW_COLOR_FORMAT */ | ||
2812 | xf_emit(ctx, 1, 0xcf); /* 000000ff SRC_FORMAT */ | ||
2813 | if (IS_NVA3F(dev_priv->chipset)) | ||
2814 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
2815 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ | ||
2816 | xf_emit(ctx, 1, 0); /* 7/f[NVA3] MULTISAMPLE_SAMPLES_LOG2 */ | ||
2817 | xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ | ||
2818 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ | ||
2819 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ | ||
2820 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ | ||
2821 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ | ||
2822 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ | ||
2823 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ | ||
2824 | xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ | ||
2825 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
2826 | xf_emit(ctx, 8, 1); /* 00000001 UNK19E0 */ | ||
2827 | xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ | ||
2828 | xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ | ||
2829 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ | ||
2830 | xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ | ||
2831 | xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ | ||
2832 | xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ | ||
2833 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ | ||
2834 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ | ||
2835 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ | ||
2836 | xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ | ||
2837 | if (IS_NVA3F(dev_priv->chipset)) | ||
2838 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
2014 | if(dev_priv->chipset == 0x50) | 2839 | if(dev_priv->chipset == 0x50) |
2015 | xf_emit(ctx, 1, 0); | 2840 | xf_emit(ctx, 1, 0); /* ff */ |
2016 | else | 2841 | else |
2017 | xf_emit(ctx, 3, 0); | 2842 | xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ |
2018 | xf_emit(ctx, 1, 4); | 2843 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ |
2019 | xf_emit(ctx, 5, 0); | 2844 | xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ |
2020 | xf_emit(ctx, 1, 1); | 2845 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ |
2021 | xf_emit(ctx, 4, 0); | 2846 | xf_emit(ctx, 1, 0); /* 00000007 */ |
2022 | xf_emit(ctx, 1, 0x11); | 2847 | xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ |
2023 | xf_emit(ctx, 7, 0); | 2848 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ |
2024 | xf_emit(ctx, 1, 0x0fac6881); | 2849 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ |
2025 | xf_emit(ctx, 3, 0); | 2850 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ |
2026 | xf_emit(ctx, 1, 0x11); | 2851 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
2027 | xf_emit(ctx, 1, 1); | 2852 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
2028 | xf_emit(ctx, 1, 0); | 2853 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ |
2029 | xf_emit(ctx, 1, 1); | 2854 | xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ |
2030 | xf_emit(ctx, 1, 0); | 2855 | xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ |
2031 | xf_emit(ctx, 1, 1); | 2856 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ |
2032 | xf_emit(ctx, 1, 0); | 2857 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ |
2033 | xf_emit(ctx, 1, magic1); | 2858 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
2034 | xf_emit(ctx, 1, 0); | 2859 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
2035 | xf_emit(ctx, 1, 1); | 2860 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ |
2036 | xf_emit(ctx, 1, 0); | 2861 | xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ |
2037 | xf_emit(ctx, 1, 1); | 2862 | xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ |
2038 | xf_emit(ctx, 2, 0); | 2863 | xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ |
2039 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2864 | xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ |
2040 | xf_emit(ctx, 1, 1); | 2865 | xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ |
2041 | xf_emit(ctx, 0x28, 0); | 2866 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2042 | xf_emit(ctx, 8, 8); | 2867 | xf_emit(ctx, 1, magic1); /* 3ff/7ff tesla UNK0D68 */ |
2043 | xf_emit(ctx, 1, 0x11); | 2868 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ |
2044 | xf_emit(ctx, 7, 0); | 2869 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ |
2045 | xf_emit(ctx, 1, 0x0fac6881); | 2870 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ |
2046 | xf_emit(ctx, 8, 0x400); | 2871 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ |
2047 | xf_emit(ctx, 8, 0x300); | 2872 | xf_emit(ctx, 1, 0); /* 00000007 */ |
2048 | xf_emit(ctx, 1, 1); | 2873 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ |
2049 | xf_emit(ctx, 1, 0xf); | 2874 | if (IS_NVA3F(dev_priv->chipset)) |
2050 | xf_emit(ctx, 7, 0); | 2875 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ |
2051 | xf_emit(ctx, 1, 0x20); | 2876 | xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */ |
2052 | xf_emit(ctx, 1, 0x11); | 2877 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */ |
2053 | xf_emit(ctx, 1, 0x100); | 2878 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_LOCAL */ |
2054 | xf_emit(ctx, 1, 0); | 2879 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_STACK */ |
2055 | xf_emit(ctx, 1, 1); | 2880 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2056 | xf_emit(ctx, 2, 0); | 2881 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_DST */ |
2057 | xf_emit(ctx, 1, 0x40); | 2882 | xf_emit(ctx, 1, 0); /* 7 */ |
2058 | xf_emit(ctx, 1, 0x100); | 2883 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
2059 | xf_emit(ctx, 1, 0); | 2884 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ |
2060 | xf_emit(ctx, 1, 3); | 2885 | xf_emit(ctx, 8, 0); /* 000000ff RT_ADDRESS_HIGH */ |
2061 | xf_emit(ctx, 4, 0); | 2886 | xf_emit(ctx, 8, 0); /* ffffffff RT_LAYER_STRIDE */ |
2062 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2887 | xf_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ |
2063 | xf_emit(ctx, 1, 1); | 2888 | xf_emit(ctx, 8, 8); /* 0000007f RT_TILE_MODE */ |
2064 | xf_emit(ctx, 1, magic2); | 2889 | xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ |
2065 | xf_emit(ctx, 3, 0); | 2890 | xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ |
2066 | xf_emit(ctx, 1, 2); | 2891 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ |
2067 | xf_emit(ctx, 1, 0x0fac6881); | 2892 | xf_emit(ctx, 8, 0x400); /* 0fffffff RT_HORIZ */ |
2068 | xf_emit(ctx, 9, 0); | 2893 | xf_emit(ctx, 8, 0x300); /* 0000ffff RT_VERT */ |
2069 | xf_emit(ctx, 1, 1); | 2894 | xf_emit(ctx, 1, 1); /* 00001fff RT_ARRAY_MODE */ |
2070 | xf_emit(ctx, 4, 0); | 2895 | xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ |
2071 | xf_emit(ctx, 1, 4); | 2896 | xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ |
2072 | xf_emit(ctx, 1, 0); | 2897 | xf_emit(ctx, 1, 0x20); /* 00000fff DST_TILE_MODE */ |
2073 | xf_emit(ctx, 1, 1); | 2898 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ |
2074 | xf_emit(ctx, 1, 0x400); | 2899 | xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ |
2075 | xf_emit(ctx, 1, 0x300); | 2900 | xf_emit(ctx, 1, 0); /* 000007ff DST_LAYER */ |
2076 | xf_emit(ctx, 1, 0x1001); | 2901 | xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ |
2077 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2902 | xf_emit(ctx, 1, 0); /* ffffffff DST_ADDRESS_LOW */ |
2078 | xf_emit(ctx, 4, 0); | 2903 | xf_emit(ctx, 1, 0); /* 000000ff DST_ADDRESS_HIGH */ |
2079 | else | 2904 | xf_emit(ctx, 1, 0x40); /* 0007ffff DST_PITCH */ |
2080 | xf_emit(ctx, 3, 0); | 2905 | xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ |
2081 | xf_emit(ctx, 1, 0x11); | 2906 | xf_emit(ctx, 1, 0); /* 0000ffff */ |
2082 | xf_emit(ctx, 7, 0); | 2907 | xf_emit(ctx, 1, 3); /* 00000003 tesla UNK15AC */ |
2083 | xf_emit(ctx, 1, 0x0fac6881); | 2908 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2084 | xf_emit(ctx, 1, 0xf); | 2909 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ |
2085 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 2910 | xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ |
2086 | xf_emit(ctx, 0x15, 0); | 2911 | xf_emit(ctx, 1, 0); /* 00000007 */ |
2087 | xf_emit(ctx, 1, 1); | 2912 | if (IS_NVA3F(dev_priv->chipset)) |
2088 | xf_emit(ctx, 3, 0); | 2913 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ |
2089 | } else | 2914 | xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ |
2090 | xf_emit(ctx, 0x17, 0); | 2915 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
2916 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ | ||
2917 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
2918 | xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ | ||
2919 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ | ||
2920 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_ZETA */ | ||
2921 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ | ||
2922 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ | ||
2923 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ | ||
2924 | xf_emit(ctx, 2, 0); /* ffff, ff/3ff */ | ||
2925 | xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ | ||
2926 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ | ||
2927 | xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ | ||
2928 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ | ||
2929 | xf_emit(ctx, 1, 0); /* 00000007 */ | ||
2930 | xf_emit(ctx, 1, 0); /* ffffffff ZETA_LAYER_STRIDE */ | ||
2931 | xf_emit(ctx, 1, 0); /* 000000ff ZETA_ADDRESS_HIGH */ | ||
2932 | xf_emit(ctx, 1, 0); /* ffffffff ZETA_ADDRESS_LOW */ | ||
2933 | xf_emit(ctx, 1, 4); /* 00000007 ZETA_TILE_MODE */ | ||
2934 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ | ||
2935 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ | ||
2936 | xf_emit(ctx, 1, 0x400); /* 0fffffff ZETA_HORIZ */ | ||
2937 | xf_emit(ctx, 1, 0x300); /* 0000ffff ZETA_VERT */ | ||
2938 | xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ | ||
2939 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ | ||
2940 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ | ||
2941 | if (IS_NVA3F(dev_priv->chipset)) | ||
2942 | xf_emit(ctx, 1, 0); /* 00000001 */ | ||
2943 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
2944 | xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ | ||
2945 | xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ | ||
2946 | xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ | ||
2947 | xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ | ||
2948 | xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ | ||
2949 | xf_emit(ctx, 1, 0); /* ff/3ff */ | ||
2950 | xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ | ||
2951 | xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ | ||
2952 | xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ | ||
2953 | xf_emit(ctx, 1, 0); /* 7 */ | ||
2954 | xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ | ||
2955 | if (IS_NVA3F(dev_priv->chipset)) { | ||
2956 | xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ | ||
2957 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
2958 | } | ||
2959 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ | ||
2960 | xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ | ||
2961 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
2091 | if (dev_priv->chipset >= 0xa0) | 2962 | if (dev_priv->chipset >= 0xa0) |
2092 | xf_emit(ctx, 1, 0x0fac6881); | 2963 | xf_emit(ctx, 1, 0x0fac6881); /* fffffff */ |
2093 | xf_emit(ctx, 1, magic2); | 2964 | xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ |
2094 | xf_emit(ctx, 3, 0); | 2965 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ |
2095 | xf_emit(ctx, 1, 0x11); | 2966 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
2096 | xf_emit(ctx, 2, 0); | 2967 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ |
2097 | xf_emit(ctx, 1, 4); | 2968 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ |
2098 | xf_emit(ctx, 1, 0); | 2969 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ |
2099 | xf_emit(ctx, 2, 1); | 2970 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2100 | xf_emit(ctx, 3, 0); | 2971 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ |
2101 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2972 | xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ |
2102 | xf_emit(ctx, 2, 1); | 2973 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ |
2103 | else | 2974 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ |
2104 | xf_emit(ctx, 1, 1); | 2975 | xf_emit(ctx, 1, 0); /* 00000007 */ |
2105 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 2976 | xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ |
2106 | xf_emit(ctx, 2, 0); | 2977 | xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ |
2107 | else if (dev_priv->chipset != 0x50) | 2978 | xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ |
2108 | xf_emit(ctx, 1, 0); | 2979 | if (IS_NVA3F(dev_priv->chipset)) { |
2980 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
2981 | xf_emit(ctx, 1, 0); /* 0000000f tesla UNK15C8 */ | ||
2982 | } | ||
2983 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ | ||
2984 | if (dev_priv->chipset >= 0xa0) { | ||
2985 | xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */ | ||
2986 | xf_emit(ctx, 1, 0xfac6881); /* fffffff */ | ||
2987 | xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */ | ||
2988 | xf_emit(ctx, 1, 4); /* 7 */ | ||
2989 | xf_emit(ctx, 1, 0); /* 1 */ | ||
2990 | xf_emit(ctx, 2, 1); /* 1 */ | ||
2991 | xf_emit(ctx, 2, 0); /* 7, f */ | ||
2992 | xf_emit(ctx, 1, 1); /* 1 */ | ||
2993 | xf_emit(ctx, 1, 0); /* 7/f */ | ||
2994 | if (IS_NVA3F(dev_priv->chipset)) | ||
2995 | xf_emit(ctx, 0x9, 0); /* 1 */ | ||
2996 | else | ||
2997 | xf_emit(ctx, 0x8, 0); /* 1 */ | ||
2998 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | ||
2999 | xf_emit(ctx, 8, 1); /* 1 */ | ||
3000 | xf_emit(ctx, 1, 0x11); /* 7f */ | ||
3001 | xf_emit(ctx, 7, 0); /* 7f */ | ||
3002 | xf_emit(ctx, 1, 0xfac6881); /* fffffff */ | ||
3003 | xf_emit(ctx, 1, 0xf); /* f */ | ||
3004 | xf_emit(ctx, 7, 0); /* f */ | ||
3005 | xf_emit(ctx, 1, 0x11); /* 7f */ | ||
3006 | xf_emit(ctx, 1, 1); /* 1 */ | ||
3007 | xf_emit(ctx, 5, 0); /* 1, 7, 3ff, 3, 7 */ | ||
3008 | if (IS_NVA3F(dev_priv->chipset)) { | ||
3009 | xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ | ||
3010 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ | ||
3011 | } | ||
3012 | } | ||
2109 | } | 3013 | } |
2110 | 3014 | ||
2111 | static void | 3015 | static void |
2112 | nv50_graph_construct_xfer_tp_x3(struct nouveau_grctx *ctx) | 3016 | nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) |
2113 | { | 3017 | { |
2114 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 3018 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
2115 | xf_emit(ctx, 3, 0); | 3019 | xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */ |
2116 | xf_emit(ctx, 1, 1); | 3020 | if (dev_priv->chipset != 0x50) |
2117 | xf_emit(ctx, 1, 0); | 3021 | xf_emit(ctx, 1, 0); /* 3 */ |
2118 | xf_emit(ctx, 1, 1); | 3022 | xf_emit(ctx, 1, 1); /* 1ffff BLIT_DU_DX_INT */ |
3023 | xf_emit(ctx, 1, 0); /* fffff BLIT_DU_DX_FRACT */ | ||
3024 | xf_emit(ctx, 1, 1); /* 1ffff BLIT_DV_DY_INT */ | ||
3025 | xf_emit(ctx, 1, 0); /* fffff BLIT_DV_DY_FRACT */ | ||
2119 | if (dev_priv->chipset == 0x50) | 3026 | if (dev_priv->chipset == 0x50) |
2120 | xf_emit(ctx, 2, 0); | 3027 | xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */ |
2121 | else | 3028 | else |
2122 | xf_emit(ctx, 3, 0); | 3029 | xf_emit(ctx, 2, 0); /* 3ff, 1 */ |
2123 | xf_emit(ctx, 1, 0x2a712488); | 3030 | xf_emit(ctx, 1, 0x2a712488); /* ffffffff SRC_TIC_0 */ |
2124 | xf_emit(ctx, 1, 0); | 3031 | xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_1 */ |
2125 | xf_emit(ctx, 1, 0x4085c000); | 3032 | xf_emit(ctx, 1, 0x4085c000); /* ffffffff SRC_TIC_2 */ |
2126 | xf_emit(ctx, 1, 0x40); | 3033 | xf_emit(ctx, 1, 0x40); /* ffffffff SRC_TIC_3 */ |
2127 | xf_emit(ctx, 1, 0x100); | 3034 | xf_emit(ctx, 1, 0x100); /* ffffffff SRC_TIC_4 */ |
2128 | xf_emit(ctx, 1, 0x10100); | 3035 | xf_emit(ctx, 1, 0x10100); /* ffffffff SRC_TIC_5 */ |
2129 | xf_emit(ctx, 1, 0x02800000); | 3036 | xf_emit(ctx, 1, 0x02800000); /* ffffffff SRC_TIC_6 */ |
3037 | xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_7 */ | ||
3038 | if (dev_priv->chipset == 0x50) { | ||
3039 | xf_emit(ctx, 1, 0); /* 00000001 turing UNK358 */ | ||
3040 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ | ||
3041 | xf_emit(ctx, 1, 0); /* 00000003 turing UNK37C tesla UNK1690 */ | ||
3042 | xf_emit(ctx, 1, 0); /* 00000003 BLIT_CONTROL */ | ||
3043 | xf_emit(ctx, 1, 0); /* 00000001 turing UNK32C tesla UNK0F94 */ | ||
3044 | } else if (!IS_NVAAF(dev_priv->chipset)) { | ||
3045 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ | ||
3046 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
3047 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
3048 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
3049 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
3050 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1664 / turing UNK03E8 */ | ||
3051 | xf_emit(ctx, 1, 0); /* 00000003 */ | ||
3052 | xf_emit(ctx, 1, 0); /* 000003ff */ | ||
3053 | } else { | ||
3054 | xf_emit(ctx, 0x6, 0); | ||
3055 | } | ||
3056 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ | ||
3057 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_TEXTURE */ | ||
3058 | xf_emit(ctx, 1, 0); /* 0000ffff DMA_SRC */ | ||
2130 | } | 3059 | } |
2131 | 3060 | ||
2132 | static void | 3061 | static void |
2133 | nv50_graph_construct_xfer_tp_x4(struct nouveau_grctx *ctx) | 3062 | nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) |
2134 | { | 3063 | { |
2135 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 3064 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
2136 | xf_emit(ctx, 2, 0x04e3bfdf); | 3065 | xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ |
2137 | xf_emit(ctx, 1, 1); | 3066 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
2138 | xf_emit(ctx, 1, 0); | 3067 | xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */ |
2139 | xf_emit(ctx, 1, 0x00ffff00); | 3068 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
2140 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 3069 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ |
2141 | xf_emit(ctx, 2, 1); | 3070 | xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ |
2142 | else | 3071 | xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ |
2143 | xf_emit(ctx, 1, 1); | 3072 | xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ |
2144 | xf_emit(ctx, 2, 0); | 3073 | xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ |
2145 | xf_emit(ctx, 1, 0x00ffff00); | 3074 | xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ |
2146 | xf_emit(ctx, 8, 0); | 3075 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK0F98 */ |
2147 | xf_emit(ctx, 1, 1); | 3076 | if (IS_NVA3F(dev_priv->chipset)) |
2148 | xf_emit(ctx, 1, 0); | 3077 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ |
2149 | xf_emit(ctx, 1, 1); | 3078 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ |
2150 | xf_emit(ctx, 1, 0x30201000); | 3079 | xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ |
2151 | xf_emit(ctx, 1, 0x70605040); | 3080 | xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ |
2152 | xf_emit(ctx, 1, 0xb8a89888); | 3081 | xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ |
2153 | xf_emit(ctx, 1, 0xf8e8d8c8); | 3082 | xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ |
2154 | xf_emit(ctx, 1, 0); | 3083 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
2155 | xf_emit(ctx, 1, 0x1a); | 3084 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ |
2156 | } | 3085 | xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ |
2157 | 3086 | xf_emit(ctx, 1, 0); /* ffff0ff3 */ | |
2158 | static void | 3087 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ |
2159 | nv50_graph_construct_xfer_tp_x5(struct nouveau_grctx *ctx) | 3088 | xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ |
2160 | { | 3089 | xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ |
2161 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 3090 | xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ |
2162 | xf_emit(ctx, 3, 0); | 3091 | xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ |
2163 | xf_emit(ctx, 1, 0xfac6881); | 3092 | xf_emit(ctx, 1, 0x30201000); /* ffffffff tesla UNK1670 */ |
2164 | xf_emit(ctx, 4, 0); | 3093 | xf_emit(ctx, 1, 0x70605040); /* ffffffff tesla UNK1670 */ |
2165 | xf_emit(ctx, 1, 4); | 3094 | xf_emit(ctx, 1, 0xb8a89888); /* ffffffff tesla UNK1670 */ |
2166 | xf_emit(ctx, 1, 0); | 3095 | xf_emit(ctx, 1, 0xf8e8d8c8); /* ffffffff tesla UNK1670 */ |
2167 | xf_emit(ctx, 2, 1); | 3096 | xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ |
2168 | xf_emit(ctx, 2, 0); | 3097 | xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ |
2169 | xf_emit(ctx, 1, 1); | ||
2170 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | ||
2171 | xf_emit(ctx, 0xb, 0); | ||
2172 | else | ||
2173 | xf_emit(ctx, 0xa, 0); | ||
2174 | xf_emit(ctx, 8, 1); | ||
2175 | xf_emit(ctx, 1, 0x11); | ||
2176 | xf_emit(ctx, 7, 0); | ||
2177 | xf_emit(ctx, 1, 0xfac6881); | ||
2178 | xf_emit(ctx, 1, 0xf); | ||
2179 | xf_emit(ctx, 7, 0); | ||
2180 | xf_emit(ctx, 1, 0x11); | ||
2181 | xf_emit(ctx, 1, 1); | ||
2182 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | ||
2183 | xf_emit(ctx, 6, 0); | ||
2184 | xf_emit(ctx, 1, 1); | ||
2185 | xf_emit(ctx, 6, 0); | ||
2186 | } else { | ||
2187 | xf_emit(ctx, 0xb, 0); | ||
2188 | } | ||
2189 | } | 3098 | } |
2190 | 3099 | ||
2191 | static void | 3100 | static void |
@@ -2193,108 +3102,136 @@ nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx) | |||
2193 | { | 3102 | { |
2194 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 3103 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
2195 | if (dev_priv->chipset < 0xa0) { | 3104 | if (dev_priv->chipset < 0xa0) { |
2196 | nv50_graph_construct_xfer_tp_x1(ctx); | 3105 | nv50_graph_construct_xfer_unk84xx(ctx); |
2197 | nv50_graph_construct_xfer_tp_x2(ctx); | 3106 | nv50_graph_construct_xfer_tprop(ctx); |
2198 | nv50_graph_construct_xfer_tp_x3(ctx); | 3107 | nv50_graph_construct_xfer_tex(ctx); |
2199 | if (dev_priv->chipset == 0x50) | 3108 | nv50_graph_construct_xfer_unk8cxx(ctx); |
2200 | xf_emit(ctx, 0xf, 0); | ||
2201 | else | ||
2202 | xf_emit(ctx, 0x12, 0); | ||
2203 | nv50_graph_construct_xfer_tp_x4(ctx); | ||
2204 | } else { | 3109 | } else { |
2205 | nv50_graph_construct_xfer_tp_x3(ctx); | 3110 | nv50_graph_construct_xfer_tex(ctx); |
2206 | if (dev_priv->chipset < 0xaa) | 3111 | nv50_graph_construct_xfer_tprop(ctx); |
2207 | xf_emit(ctx, 0xc, 0); | 3112 | nv50_graph_construct_xfer_unk8cxx(ctx); |
2208 | else | 3113 | nv50_graph_construct_xfer_unk84xx(ctx); |
2209 | xf_emit(ctx, 0xa, 0); | ||
2210 | nv50_graph_construct_xfer_tp_x2(ctx); | ||
2211 | nv50_graph_construct_xfer_tp_x5(ctx); | ||
2212 | nv50_graph_construct_xfer_tp_x4(ctx); | ||
2213 | nv50_graph_construct_xfer_tp_x1(ctx); | ||
2214 | } | 3114 | } |
2215 | } | 3115 | } |
2216 | 3116 | ||
2217 | static void | 3117 | static void |
2218 | nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx) | 3118 | nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) |
2219 | { | 3119 | { |
2220 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; | 3120 | struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; |
2221 | int i, mpcnt; | 3121 | int i, mpcnt = 2; |
2222 | if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa) | 3122 | switch (dev_priv->chipset) { |
2223 | mpcnt = 1; | 3123 | case 0x98: |
2224 | else if (dev_priv->chipset < 0xa0 || dev_priv->chipset >= 0xa8) | 3124 | case 0xaa: |
2225 | mpcnt = 2; | 3125 | mpcnt = 1; |
2226 | else | 3126 | break; |
2227 | mpcnt = 3; | 3127 | case 0x50: |
3128 | case 0x84: | ||
3129 | case 0x86: | ||
3130 | case 0x92: | ||
3131 | case 0x94: | ||
3132 | case 0x96: | ||
3133 | case 0xa8: | ||
3134 | case 0xac: | ||
3135 | mpcnt = 2; | ||
3136 | break; | ||
3137 | case 0xa0: | ||
3138 | case 0xa3: | ||
3139 | case 0xa5: | ||
3140 | case 0xaf: | ||
3141 | mpcnt = 3; | ||
3142 | break; | ||
3143 | } | ||
2228 | for (i = 0; i < mpcnt; i++) { | 3144 | for (i = 0; i < mpcnt; i++) { |
2229 | xf_emit(ctx, 1, 0); | 3145 | xf_emit(ctx, 1, 0); /* ff */ |
2230 | xf_emit(ctx, 1, 0x80); | 3146 | xf_emit(ctx, 1, 0x80); /* ffffffff tesla UNK1404 */ |
2231 | xf_emit(ctx, 1, 0x80007004); | 3147 | xf_emit(ctx, 1, 0x80007004); /* ffffffff tesla UNK12B0 */ |
2232 | xf_emit(ctx, 1, 0x04000400); | 3148 | xf_emit(ctx, 1, 0x04000400); /* ffffffff */ |
2233 | if (dev_priv->chipset >= 0xa0) | 3149 | if (dev_priv->chipset >= 0xa0) |
2234 | xf_emit(ctx, 1, 0xc0); | 3150 | xf_emit(ctx, 1, 0xc0); /* 00007fff tesla UNK152C */ |
2235 | xf_emit(ctx, 1, 0x1000); | 3151 | xf_emit(ctx, 1, 0x1000); /* 0000ffff tesla UNK0D60 */ |
2236 | xf_emit(ctx, 2, 0); | 3152 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2237 | if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) { | 3153 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ |
2238 | xf_emit(ctx, 1, 0xe00); | 3154 | if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset == 0xa8 || IS_NVAAF(dev_priv->chipset)) { |
2239 | xf_emit(ctx, 1, 0x1e00); | 3155 | xf_emit(ctx, 1, 0xe00); /* 7fff */ |
3156 | xf_emit(ctx, 1, 0x1e00); /* 7fff */ | ||
2240 | } | 3157 | } |
2241 | xf_emit(ctx, 1, 1); | 3158 | xf_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP */ |
2242 | xf_emit(ctx, 2, 0); | 3159 | xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ |
3160 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ | ||
2243 | if (dev_priv->chipset == 0x50) | 3161 | if (dev_priv->chipset == 0x50) |
2244 | xf_emit(ctx, 2, 0x1000); | 3162 | xf_emit(ctx, 2, 0x1000); /* 7fff tesla UNK141C */ |
2245 | xf_emit(ctx, 1, 1); | 3163 | xf_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP */ |
2246 | xf_emit(ctx, 1, 0); | 3164 | xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ |
2247 | xf_emit(ctx, 1, 4); | 3165 | xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ |
2248 | xf_emit(ctx, 1, 2); | 3166 | xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ |
2249 | if (dev_priv->chipset >= 0xaa) | 3167 | if (IS_NVAAF(dev_priv->chipset)) |
2250 | xf_emit(ctx, 0xb, 0); | 3168 | xf_emit(ctx, 0xb, 0); /* RO */ |
2251 | else if (dev_priv->chipset >= 0xa0) | 3169 | else if (dev_priv->chipset >= 0xa0) |
2252 | xf_emit(ctx, 0xc, 0); | 3170 | xf_emit(ctx, 0xc, 0); /* RO */ |
2253 | else | 3171 | else |
2254 | xf_emit(ctx, 0xa, 0); | 3172 | xf_emit(ctx, 0xa, 0); /* RO */ |
2255 | } | 3173 | } |
2256 | xf_emit(ctx, 1, 0x08100c12); | 3174 | xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ |
2257 | xf_emit(ctx, 1, 0); | 3175 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2258 | if (dev_priv->chipset >= 0xa0) { | 3176 | if (dev_priv->chipset >= 0xa0) { |
2259 | xf_emit(ctx, 1, 0x1fe21); | 3177 | xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */ |
2260 | } | 3178 | } |
2261 | xf_emit(ctx, 5, 0); | 3179 | xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */ |
2262 | xf_emit(ctx, 4, 0xffff); | 3180 | xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ |
2263 | xf_emit(ctx, 1, 1); | 3181 | xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ |
2264 | xf_emit(ctx, 2, 0x10001); | 3182 | xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ |
2265 | xf_emit(ctx, 1, 1); | 3183 | xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ |
2266 | xf_emit(ctx, 1, 0); | 3184 | xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ |
2267 | xf_emit(ctx, 1, 0x1fe21); | 3185 | xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ |
2268 | xf_emit(ctx, 1, 0); | 3186 | xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ |
2269 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 3187 | xf_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ |
2270 | xf_emit(ctx, 1, 1); | 3188 | xf_emit(ctx, 1, 0x1fe21); /* 1ffff/3ffff[NVA0+] tesla UNk0FAC */ |
2271 | xf_emit(ctx, 4, 0); | 3189 | xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ |
2272 | xf_emit(ctx, 1, 0x08100c12); | 3190 | if (IS_NVA3F(dev_priv->chipset)) |
2273 | xf_emit(ctx, 1, 4); | 3191 | xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ |
2274 | xf_emit(ctx, 1, 0); | 3192 | xf_emit(ctx, 1, 0); /* ff/3ff */ |
2275 | xf_emit(ctx, 1, 2); | 3193 | xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */ |
2276 | xf_emit(ctx, 1, 0x11); | 3194 | xf_emit(ctx, 1, 0); /* ff FP_ADDRESS_HIGH */ |
2277 | xf_emit(ctx, 8, 0); | 3195 | xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ |
2278 | xf_emit(ctx, 1, 0xfac6881); | 3196 | xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ |
2279 | xf_emit(ctx, 1, 0); | 3197 | xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ |
2280 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) | 3198 | xf_emit(ctx, 1, 0); /* 000000ff FRAG_COLOR_CLAMP_EN */ |
2281 | xf_emit(ctx, 1, 3); | 3199 | xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ |
2282 | xf_emit(ctx, 3, 0); | 3200 | xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ |
2283 | xf_emit(ctx, 1, 4); | 3201 | xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ |
2284 | xf_emit(ctx, 9, 0); | 3202 | xf_emit(ctx, 1, 0); /* 00000007 */ |
2285 | xf_emit(ctx, 1, 2); | 3203 | xf_emit(ctx, 1, 0xfac6881); /* 0fffffff RT_CONTROL */ |
2286 | xf_emit(ctx, 2, 1); | 3204 | xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ |
2287 | xf_emit(ctx, 1, 2); | 3205 | if (IS_NVA3F(dev_priv->chipset)) |
2288 | xf_emit(ctx, 3, 1); | 3206 | xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ |
2289 | xf_emit(ctx, 1, 0); | 3207 | xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ |
2290 | if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { | 3208 | xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ |
2291 | xf_emit(ctx, 8, 2); | 3209 | xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ |
2292 | xf_emit(ctx, 0x10, 1); | 3210 | xf_emit(ctx, 1, 4); /* ffffffff tesla UNK1400 */ |
2293 | xf_emit(ctx, 8, 2); | 3211 | xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ |
2294 | xf_emit(ctx, 0x18, 1); | 3212 | xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ |
2295 | xf_emit(ctx, 3, 0); | 3213 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ |
3214 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ | ||
3215 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ | ||
3216 | xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ | ||
3217 | xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ | ||
3218 | xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ | ||
3219 | xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ | ||
3220 | if (IS_NVA3F(dev_priv->chipset)) { | ||
3221 | xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ | ||
3222 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ | ||
3223 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ | ||
3224 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ | ||
3225 | xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ | ||
3226 | xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ | ||
3227 | xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ | ||
3228 | xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ | ||
3229 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ | ||
3230 | xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ | ||
2296 | } | 3231 | } |
2297 | xf_emit(ctx, 1, 4); | 3232 | xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ |
3233 | xf_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ | ||
3234 | /* XXX: demagic this part some day */ | ||
2298 | if (dev_priv->chipset == 0x50) | 3235 | if (dev_priv->chipset == 0x50) |
2299 | xf_emit(ctx, 0x3a0, 0); | 3236 | xf_emit(ctx, 0x3a0, 0); |
2300 | else if (dev_priv->chipset < 0x94) | 3237 | else if (dev_priv->chipset < 0x94) |
@@ -2303,9 +3240,9 @@ nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx) | |||
2303 | xf_emit(ctx, 0x39f, 0); | 3240 | xf_emit(ctx, 0x39f, 0); |
2304 | else | 3241 | else |
2305 | xf_emit(ctx, 0x3a3, 0); | 3242 | xf_emit(ctx, 0x3a3, 0); |
2306 | xf_emit(ctx, 1, 0x11); | 3243 | xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ |
2307 | xf_emit(ctx, 1, 0); | 3244 | xf_emit(ctx, 1, 0); /* 7 OPERATION */ |
2308 | xf_emit(ctx, 1, 1); | 3245 | xf_emit(ctx, 1, 1); /* 1 DST_LINEAR */ |
2309 | xf_emit(ctx, 0x2d, 0); | 3246 | xf_emit(ctx, 0x2d, 0); |
2310 | } | 3247 | } |
2311 | 3248 | ||
@@ -2323,52 +3260,56 @@ nv50_graph_construct_xfer2(struct nouveau_grctx *ctx) | |||
2323 | if (dev_priv->chipset < 0xa0) { | 3260 | if (dev_priv->chipset < 0xa0) { |
2324 | for (i = 0; i < 8; i++) { | 3261 | for (i = 0; i < 8; i++) { |
2325 | ctx->ctxvals_pos = offset + i; | 3262 | ctx->ctxvals_pos = offset + i; |
3263 | /* that little bugger belongs to csched. No idea | ||
3264 | * what it's doing here. */ | ||
2326 | if (i == 0) | 3265 | if (i == 0) |
2327 | xf_emit(ctx, 1, 0x08100c12); | 3266 | xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ |
2328 | if (units & (1 << i)) | 3267 | if (units & (1 << i)) |
2329 | nv50_graph_construct_xfer_tp2(ctx); | 3268 | nv50_graph_construct_xfer_mpc(ctx); |
2330 | if ((ctx->ctxvals_pos-offset)/8 > size) | 3269 | if ((ctx->ctxvals_pos-offset)/8 > size) |
2331 | size = (ctx->ctxvals_pos-offset)/8; | 3270 | size = (ctx->ctxvals_pos-offset)/8; |
2332 | } | 3271 | } |
2333 | } else { | 3272 | } else { |
2334 | /* Strand 0: TPs 0, 1 */ | 3273 | /* Strand 0: TPs 0, 1 */ |
2335 | ctx->ctxvals_pos = offset; | 3274 | ctx->ctxvals_pos = offset; |
2336 | xf_emit(ctx, 1, 0x08100c12); | 3275 | /* that little bugger belongs to csched. No idea |
3276 | * what it's doing here. */ | ||
3277 | xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ | ||
2337 | if (units & (1 << 0)) | 3278 | if (units & (1 << 0)) |
2338 | nv50_graph_construct_xfer_tp2(ctx); | 3279 | nv50_graph_construct_xfer_mpc(ctx); |
2339 | if (units & (1 << 1)) | 3280 | if (units & (1 << 1)) |
2340 | nv50_graph_construct_xfer_tp2(ctx); | 3281 | nv50_graph_construct_xfer_mpc(ctx); |
2341 | if ((ctx->ctxvals_pos-offset)/8 > size) | 3282 | if ((ctx->ctxvals_pos-offset)/8 > size) |
2342 | size = (ctx->ctxvals_pos-offset)/8; | 3283 | size = (ctx->ctxvals_pos-offset)/8; |
2343 | 3284 | ||
2344 | /* Strand 0: TPs 2, 3 */ | 3285 | /* Strand 1: TPs 2, 3 */ |
2345 | ctx->ctxvals_pos = offset + 1; | 3286 | ctx->ctxvals_pos = offset + 1; |
2346 | if (units & (1 << 2)) | 3287 | if (units & (1 << 2)) |
2347 | nv50_graph_construct_xfer_tp2(ctx); | 3288 | nv50_graph_construct_xfer_mpc(ctx); |
2348 | if (units & (1 << 3)) | 3289 | if (units & (1 << 3)) |
2349 | nv50_graph_construct_xfer_tp2(ctx); | 3290 | nv50_graph_construct_xfer_mpc(ctx); |
2350 | if ((ctx->ctxvals_pos-offset)/8 > size) | 3291 | if ((ctx->ctxvals_pos-offset)/8 > size) |
2351 | size = (ctx->ctxvals_pos-offset)/8; | 3292 | size = (ctx->ctxvals_pos-offset)/8; |
2352 | 3293 | ||
2353 | /* Strand 0: TPs 4, 5, 6 */ | 3294 | /* Strand 2: TPs 4, 5, 6 */ |
2354 | ctx->ctxvals_pos = offset + 2; | 3295 | ctx->ctxvals_pos = offset + 2; |
2355 | if (units & (1 << 4)) | 3296 | if (units & (1 << 4)) |
2356 | nv50_graph_construct_xfer_tp2(ctx); | 3297 | nv50_graph_construct_xfer_mpc(ctx); |
2357 | if (units & (1 << 5)) | 3298 | if (units & (1 << 5)) |
2358 | nv50_graph_construct_xfer_tp2(ctx); | 3299 | nv50_graph_construct_xfer_mpc(ctx); |
2359 | if (units & (1 << 6)) | 3300 | if (units & (1 << 6)) |
2360 | nv50_graph_construct_xfer_tp2(ctx); | 3301 | nv50_graph_construct_xfer_mpc(ctx); |
2361 | if ((ctx->ctxvals_pos-offset)/8 > size) | 3302 | if ((ctx->ctxvals_pos-offset)/8 > size) |
2362 | size = (ctx->ctxvals_pos-offset)/8; | 3303 | size = (ctx->ctxvals_pos-offset)/8; |
2363 | 3304 | ||
2364 | /* Strand 0: TPs 7, 8, 9 */ | 3305 | /* Strand 3: TPs 7, 8, 9 */ |
2365 | ctx->ctxvals_pos = offset + 3; | 3306 | ctx->ctxvals_pos = offset + 3; |
2366 | if (units & (1 << 7)) | 3307 | if (units & (1 << 7)) |
2367 | nv50_graph_construct_xfer_tp2(ctx); | 3308 | nv50_graph_construct_xfer_mpc(ctx); |
2368 | if (units & (1 << 8)) | 3309 | if (units & (1 << 8)) |
2369 | nv50_graph_construct_xfer_tp2(ctx); | 3310 | nv50_graph_construct_xfer_mpc(ctx); |
2370 | if (units & (1 << 9)) | 3311 | if (units & (1 << 9)) |
2371 | nv50_graph_construct_xfer_tp2(ctx); | 3312 | nv50_graph_construct_xfer_mpc(ctx); |
2372 | if ((ctx->ctxvals_pos-offset)/8 > size) | 3313 | if ((ctx->ctxvals_pos-offset)/8 > size) |
2373 | size = (ctx->ctxvals_pos-offset)/8; | 3314 | size = (ctx->ctxvals_pos-offset)/8; |
2374 | } | 3315 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 91ef93cf1f35..a53fc974332b 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c | |||
@@ -32,39 +32,87 @@ | |||
32 | struct nv50_instmem_priv { | 32 | struct nv50_instmem_priv { |
33 | uint32_t save1700[5]; /* 0x1700->0x1710 */ | 33 | uint32_t save1700[5]; /* 0x1700->0x1710 */ |
34 | 34 | ||
35 | struct nouveau_gpuobj_ref *pramin_pt; | 35 | struct nouveau_gpuobj *pramin_pt; |
36 | struct nouveau_gpuobj_ref *pramin_bar; | 36 | struct nouveau_gpuobj *pramin_bar; |
37 | struct nouveau_gpuobj_ref *fb_bar; | 37 | struct nouveau_gpuobj *fb_bar; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #define NV50_INSTMEM_PAGE_SHIFT 12 | 40 | static void |
41 | #define NV50_INSTMEM_PAGE_SIZE (1 << NV50_INSTMEM_PAGE_SHIFT) | 41 | nv50_channel_del(struct nouveau_channel **pchan) |
42 | #define NV50_INSTMEM_PT_SIZE(a) (((a) >> 12) << 3) | 42 | { |
43 | struct nouveau_channel *chan; | ||
43 | 44 | ||
44 | /*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN | 45 | chan = *pchan; |
45 | */ | 46 | *pchan = NULL; |
46 | #define BAR0_WI32(g, o, v) do { \ | 47 | if (!chan) |
47 | uint32_t offset; \ | 48 | return; |
48 | if ((g)->im_backing) { \ | 49 | |
49 | offset = (g)->im_backing_start; \ | 50 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
50 | } else { \ | 51 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); |
51 | offset = chan->ramin->gpuobj->im_backing_start; \ | 52 | if (chan->ramin_heap.free_stack.next) |
52 | offset += (g)->im_pramin->start; \ | 53 | drm_mm_takedown(&chan->ramin_heap); |
53 | } \ | 54 | nouveau_gpuobj_ref(NULL, &chan->ramin); |
54 | offset += (o); \ | 55 | kfree(chan); |
55 | nv_wr32(dev, NV_RAMIN + (offset & 0xfffff), (v)); \ | 56 | } |
56 | } while (0) | 57 | |
58 | static int | ||
59 | nv50_channel_new(struct drm_device *dev, u32 size, | ||
60 | struct nouveau_channel **pchan) | ||
61 | { | ||
62 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
63 | u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; | ||
64 | u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; | ||
65 | struct nouveau_channel *chan; | ||
66 | int ret; | ||
67 | |||
68 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); | ||
69 | if (!chan) | ||
70 | return -ENOMEM; | ||
71 | chan->dev = dev; | ||
72 | |||
73 | ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin); | ||
74 | if (ret) { | ||
75 | nv50_channel_del(&chan); | ||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | ret = drm_mm_init(&chan->ramin_heap, 0x6000, chan->ramin->size); | ||
80 | if (ret) { | ||
81 | nv50_channel_del(&chan); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : | ||
86 | chan->ramin->pinst + pgd, | ||
87 | chan->ramin->vinst + pgd, | ||
88 | 0x4000, NVOBJ_FLAG_ZERO_ALLOC, | ||
89 | &chan->vm_pd); | ||
90 | if (ret) { | ||
91 | nv50_channel_del(&chan); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : | ||
96 | chan->ramin->pinst + fc, | ||
97 | chan->ramin->vinst + fc, 0x100, | ||
98 | NVOBJ_FLAG_ZERO_ALLOC, &chan->ramfc); | ||
99 | if (ret) { | ||
100 | nv50_channel_del(&chan); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | *pchan = chan; | ||
105 | return 0; | ||
106 | } | ||
57 | 107 | ||
58 | int | 108 | int |
59 | nv50_instmem_init(struct drm_device *dev) | 109 | nv50_instmem_init(struct drm_device *dev) |
60 | { | 110 | { |
61 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 111 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
62 | struct nouveau_channel *chan; | ||
63 | uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size; | ||
64 | uint32_t save_nv001700; | ||
65 | uint64_t v; | ||
66 | struct nv50_instmem_priv *priv; | 112 | struct nv50_instmem_priv *priv; |
113 | struct nouveau_channel *chan; | ||
67 | int ret, i; | 114 | int ret, i; |
115 | u32 tmp; | ||
68 | 116 | ||
69 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 117 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
70 | if (!priv) | 118 | if (!priv) |
@@ -75,212 +123,115 @@ nv50_instmem_init(struct drm_device *dev) | |||
75 | for (i = 0x1700; i <= 0x1710; i += 4) | 123 | for (i = 0x1700; i <= 0x1710; i += 4) |
76 | priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); | 124 | priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); |
77 | 125 | ||
78 | /* Reserve the last MiB of VRAM, we should probably try to avoid | 126 | /* Global PRAMIN heap */ |
79 | * setting up the below tables over the top of the VBIOS image at | 127 | ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); |
80 | * some point. | 128 | if (ret) { |
81 | */ | 129 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); |
82 | dev_priv->ramin_rsvd_vram = 1 << 20; | ||
83 | c_offset = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
84 | c_size = 128 << 10; | ||
85 | c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200; | ||
86 | c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; | ||
87 | c_base = c_vmpd + 0x4000; | ||
88 | pt_size = NV50_INSTMEM_PT_SIZE(dev_priv->ramin_size); | ||
89 | |||
90 | NV_DEBUG(dev, " Rsvd VRAM base: 0x%08x\n", c_offset); | ||
91 | NV_DEBUG(dev, " VBIOS image: 0x%08x\n", | ||
92 | (nv_rd32(dev, 0x619f04) & ~0xff) << 8); | ||
93 | NV_DEBUG(dev, " Aperture size: %d MiB\n", dev_priv->ramin_size >> 20); | ||
94 | NV_DEBUG(dev, " PT size: %d KiB\n", pt_size >> 10); | ||
95 | |||
96 | /* Determine VM layout, we need to do this first to make sure | ||
97 | * we allocate enough memory for all the page tables. | ||
98 | */ | ||
99 | dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); | ||
100 | dev_priv->vm_gart_size = NV50_VM_BLOCK; | ||
101 | |||
102 | dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; | ||
103 | dev_priv->vm_vram_size = dev_priv->vram_size; | ||
104 | if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) | ||
105 | dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; | ||
106 | dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); | ||
107 | dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; | ||
108 | |||
109 | dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; | ||
110 | |||
111 | NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", | ||
112 | dev_priv->vm_gart_base, | ||
113 | dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); | ||
114 | NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", | ||
115 | dev_priv->vm_vram_base, | ||
116 | dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); | ||
117 | |||
118 | c_size += dev_priv->vm_vram_pt_nr * (NV50_VM_BLOCK / 65536 * 8); | ||
119 | |||
120 | /* Map BAR0 PRAMIN aperture over the memory we want to use */ | ||
121 | save_nv001700 = nv_rd32(dev, NV50_PUNK_BAR0_PRAMIN); | ||
122 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16)); | ||
123 | |||
124 | /* Create a fake channel, and use it as our "dummy" channels 0/127. | ||
125 | * The main reason for creating a channel is so we can use the gpuobj | ||
126 | * code. However, it's probably worth noting that NVIDIA also setup | ||
127 | * their channels 0/127 with the same values they configure here. | ||
128 | * So, there may be some other reason for doing this. | ||
129 | * | ||
130 | * Have to create the entire channel manually, as the real channel | ||
131 | * creation code assumes we have PRAMIN access, and we don't until | ||
132 | * we're done here. | ||
133 | */ | ||
134 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); | ||
135 | if (!chan) | ||
136 | return -ENOMEM; | 130 | return -ENOMEM; |
137 | chan->id = 0; | 131 | } |
138 | chan->dev = dev; | ||
139 | chan->file_priv = (struct drm_file *)-2; | ||
140 | dev_priv->fifos[0] = dev_priv->fifos[127] = chan; | ||
141 | |||
142 | INIT_LIST_HEAD(&chan->ramht_refs); | ||
143 | 132 | ||
144 | /* Channel's PRAMIN object + heap */ | 133 | /* we need a channel to plug into the hw to control the BARs */ |
145 | ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, | 134 | ret = nv50_channel_new(dev, 128*1024, &dev_priv->fifos[0]); |
146 | NULL, &chan->ramin); | ||
147 | if (ret) | 135 | if (ret) |
148 | return ret; | 136 | return ret; |
137 | chan = dev_priv->fifos[127] = dev_priv->fifos[0]; | ||
149 | 138 | ||
150 | if (drm_mm_init(&chan->ramin_heap, c_base, c_size - c_base)) | 139 | /* allocate page table for PRAMIN BAR */ |
151 | return -ENOMEM; | 140 | ret = nouveau_gpuobj_new(dev, chan, (dev_priv->ramin_size >> 12) * 8, |
152 | 141 | 0x1000, NVOBJ_FLAG_ZERO_ALLOC, | |
153 | /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ | 142 | &priv->pramin_pt); |
154 | ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc, | ||
155 | 0x4000, 0, NULL, &chan->ramfc); | ||
156 | if (ret) | 143 | if (ret) |
157 | return ret; | 144 | return ret; |
158 | 145 | ||
159 | for (i = 0; i < c_vmpd; i += 4) | 146 | nv_wo32(chan->vm_pd, 0x0000, priv->pramin_pt->vinst | 0x63); |
160 | BAR0_WI32(chan->ramin->gpuobj, i, 0); | 147 | nv_wo32(chan->vm_pd, 0x0004, 0); |
161 | 148 | ||
162 | /* VM page directory */ | 149 | /* DMA object for PRAMIN BAR */ |
163 | ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd, | 150 | ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->pramin_bar); |
164 | 0x4000, 0, &chan->vm_pd, NULL); | ||
165 | if (ret) | 151 | if (ret) |
166 | return ret; | 152 | return ret; |
167 | for (i = 0; i < 0x4000; i += 8) { | 153 | nv_wo32(priv->pramin_bar, 0x00, 0x7fc00000); |
168 | BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000); | 154 | nv_wo32(priv->pramin_bar, 0x04, dev_priv->ramin_size - 1); |
169 | BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000); | 155 | nv_wo32(priv->pramin_bar, 0x08, 0x00000000); |
170 | } | 156 | nv_wo32(priv->pramin_bar, 0x0c, 0x00000000); |
171 | 157 | nv_wo32(priv->pramin_bar, 0x10, 0x00000000); | |
172 | /* PRAMIN page table, cheat and map into VM at 0x0000000000. | 158 | nv_wo32(priv->pramin_bar, 0x14, 0x00000000); |
173 | * We map the entire fake channel into the start of the PRAMIN BAR | 159 | |
174 | */ | 160 | /* map channel into PRAMIN, gpuobj didn't do it for us */ |
175 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, | 161 | ret = nv50_instmem_bind(dev, chan->ramin); |
176 | 0, &priv->pramin_pt); | ||
177 | if (ret) | 162 | if (ret) |
178 | return ret; | 163 | return ret; |
179 | 164 | ||
180 | v = c_offset | 1; | 165 | /* poke regs... */ |
181 | if (dev_priv->vram_sys_base) { | 166 | nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); |
182 | v += dev_priv->vram_sys_base; | 167 | nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); |
183 | v |= 0x30; | 168 | nv_wr32(dev, 0x00170c, 0x80000000 | (priv->pramin_bar->cinst >> 4)); |
184 | } | ||
185 | 169 | ||
186 | i = 0; | 170 | tmp = nv_ri32(dev, 0); |
187 | while (v < dev_priv->vram_sys_base + c_offset + c_size) { | 171 | nv_wi32(dev, 0, ~tmp); |
188 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, lower_32_bits(v)); | 172 | if (nv_ri32(dev, 0) != ~tmp) { |
189 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, upper_32_bits(v)); | 173 | NV_ERROR(dev, "PRAMIN readback failed\n"); |
190 | v += 0x1000; | 174 | return -EIO; |
191 | i += 8; | ||
192 | } | 175 | } |
176 | nv_wi32(dev, 0, tmp); | ||
193 | 177 | ||
194 | while (i < pt_size) { | 178 | dev_priv->ramin_available = true; |
195 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000000); | ||
196 | BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); | ||
197 | i += 8; | ||
198 | } | ||
199 | 179 | ||
200 | BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); | 180 | /* Determine VM layout */ |
201 | BAR0_WI32(chan->vm_pd, 0x04, 0x00000000); | 181 | dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); |
182 | dev_priv->vm_gart_size = NV50_VM_BLOCK; | ||
183 | |||
184 | dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; | ||
185 | dev_priv->vm_vram_size = dev_priv->vram_size; | ||
186 | if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) | ||
187 | dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; | ||
188 | dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); | ||
189 | dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; | ||
190 | |||
191 | dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; | ||
192 | |||
193 | NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", | ||
194 | dev_priv->vm_gart_base, | ||
195 | dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); | ||
196 | NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", | ||
197 | dev_priv->vm_vram_base, | ||
198 | dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); | ||
202 | 199 | ||
203 | /* VRAM page table(s), mapped into VM at +1GiB */ | 200 | /* VRAM page table(s), mapped into VM at +1GiB */ |
204 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { | 201 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { |
205 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, | 202 | ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8, |
206 | NV50_VM_BLOCK/65536*8, 0, 0, | 203 | 0, NVOBJ_FLAG_ZERO_ALLOC, |
207 | &chan->vm_vram_pt[i]); | 204 | &chan->vm_vram_pt[i]); |
208 | if (ret) { | 205 | if (ret) { |
209 | NV_ERROR(dev, "Error creating VRAM page tables: %d\n", | 206 | NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret); |
210 | ret); | ||
211 | dev_priv->vm_vram_pt_nr = i; | 207 | dev_priv->vm_vram_pt_nr = i; |
212 | return ret; | 208 | return ret; |
213 | } | 209 | } |
214 | dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]->gpuobj; | 210 | dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]; |
215 | 211 | ||
216 | for (v = 0; v < dev_priv->vm_vram_pt[i]->im_pramin->size; | 212 | nv_wo32(chan->vm_pd, 0x10 + (i*8), |
217 | v += 4) | 213 | chan->vm_vram_pt[i]->vinst | 0x61); |
218 | BAR0_WI32(dev_priv->vm_vram_pt[i], v, 0); | 214 | nv_wo32(chan->vm_pd, 0x14 + (i*8), 0); |
219 | |||
220 | BAR0_WI32(chan->vm_pd, 0x10 + (i*8), | ||
221 | chan->vm_vram_pt[i]->instance | 0x61); | ||
222 | BAR0_WI32(chan->vm_pd, 0x14 + (i*8), 0); | ||
223 | } | 215 | } |
224 | 216 | ||
225 | /* DMA object for PRAMIN BAR */ | ||
226 | ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, | ||
227 | &priv->pramin_bar); | ||
228 | if (ret) | ||
229 | return ret; | ||
230 | BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000); | ||
231 | BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin_size - 1); | ||
232 | BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000); | ||
233 | BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000); | ||
234 | BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000); | ||
235 | BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000); | ||
236 | |||
237 | /* DMA object for FB BAR */ | 217 | /* DMA object for FB BAR */ |
238 | ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, | 218 | ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->fb_bar); |
239 | &priv->fb_bar); | ||
240 | if (ret) | 219 | if (ret) |
241 | return ret; | 220 | return ret; |
242 | BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000); | 221 | nv_wo32(priv->fb_bar, 0x00, 0x7fc00000); |
243 | BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 + | 222 | nv_wo32(priv->fb_bar, 0x04, 0x40000000 + |
244 | pci_resource_len(dev->pdev, 1) - 1); | 223 | pci_resource_len(dev->pdev, 1) - 1); |
245 | BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000); | 224 | nv_wo32(priv->fb_bar, 0x08, 0x40000000); |
246 | BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000); | 225 | nv_wo32(priv->fb_bar, 0x0c, 0x00000000); |
247 | BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000); | 226 | nv_wo32(priv->fb_bar, 0x10, 0x00000000); |
248 | BAR0_WI32(priv->fb_bar->gpuobj, 0x14, 0x00000000); | 227 | nv_wo32(priv->fb_bar, 0x14, 0x00000000); |
249 | 228 | ||
250 | /* Poke the relevant regs, and pray it works :) */ | 229 | dev_priv->engine.instmem.flush(dev); |
251 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); | ||
252 | nv_wr32(dev, NV50_PUNK_UNK1710, 0); | ||
253 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | | ||
254 | NV50_PUNK_BAR_CFG_BASE_VALID); | ||
255 | nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) | | ||
256 | NV50_PUNK_BAR1_CTXDMA_VALID); | ||
257 | nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | | ||
258 | NV50_PUNK_BAR3_CTXDMA_VALID); | ||
259 | 230 | ||
231 | nv_wr32(dev, 0x001708, 0x80000000 | (priv->fb_bar->cinst >> 4)); | ||
260 | for (i = 0; i < 8; i++) | 232 | for (i = 0; i < 8; i++) |
261 | nv_wr32(dev, 0x1900 + (i*4), 0); | 233 | nv_wr32(dev, 0x1900 + (i*4), 0); |
262 | 234 | ||
263 | /* Assume that praying isn't enough, check that we can re-read the | ||
264 | * entire fake channel back from the PRAMIN BAR */ | ||
265 | for (i = 0; i < c_size; i += 4) { | ||
266 | if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { | ||
267 | NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", | ||
268 | i); | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); | ||
274 | |||
275 | /* Global PRAMIN heap */ | ||
276 | if (drm_mm_init(&dev_priv->ramin_heap, c_size, dev_priv->ramin_size - c_size)) { | ||
277 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | ||
278 | } | ||
279 | |||
280 | /*XXX: incorrect, but needed to make hash func "work" */ | ||
281 | dev_priv->ramht_offset = 0x10000; | ||
282 | dev_priv->ramht_bits = 9; | ||
283 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; | ||
284 | return 0; | 235 | return 0; |
285 | } | 236 | } |
286 | 237 | ||
@@ -297,29 +248,24 @@ nv50_instmem_takedown(struct drm_device *dev) | |||
297 | if (!priv) | 248 | if (!priv) |
298 | return; | 249 | return; |
299 | 250 | ||
251 | dev_priv->ramin_available = false; | ||
252 | |||
300 | /* Restore state from before init */ | 253 | /* Restore state from before init */ |
301 | for (i = 0x1700; i <= 0x1710; i += 4) | 254 | for (i = 0x1700; i <= 0x1710; i += 4) |
302 | nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); | 255 | nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); |
303 | 256 | ||
304 | nouveau_gpuobj_ref_del(dev, &priv->fb_bar); | 257 | nouveau_gpuobj_ref(NULL, &priv->fb_bar); |
305 | nouveau_gpuobj_ref_del(dev, &priv->pramin_bar); | 258 | nouveau_gpuobj_ref(NULL, &priv->pramin_bar); |
306 | nouveau_gpuobj_ref_del(dev, &priv->pramin_pt); | 259 | nouveau_gpuobj_ref(NULL, &priv->pramin_pt); |
307 | 260 | ||
308 | /* Destroy dummy channel */ | 261 | /* Destroy dummy channel */ |
309 | if (chan) { | 262 | if (chan) { |
310 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { | 263 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) |
311 | nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); | 264 | nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); |
312 | dev_priv->vm_vram_pt[i] = NULL; | ||
313 | } | ||
314 | dev_priv->vm_vram_pt_nr = 0; | 265 | dev_priv->vm_vram_pt_nr = 0; |
315 | 266 | ||
316 | nouveau_gpuobj_del(dev, &chan->vm_pd); | 267 | nv50_channel_del(&dev_priv->fifos[0]); |
317 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | 268 | dev_priv->fifos[127] = NULL; |
318 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | ||
319 | drm_mm_takedown(&chan->ramin_heap); | ||
320 | |||
321 | dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; | ||
322 | kfree(chan); | ||
323 | } | 269 | } |
324 | 270 | ||
325 | dev_priv->engine.instmem.priv = NULL; | 271 | dev_priv->engine.instmem.priv = NULL; |
@@ -331,14 +277,14 @@ nv50_instmem_suspend(struct drm_device *dev) | |||
331 | { | 277 | { |
332 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 278 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
333 | struct nouveau_channel *chan = dev_priv->fifos[0]; | 279 | struct nouveau_channel *chan = dev_priv->fifos[0]; |
334 | struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; | 280 | struct nouveau_gpuobj *ramin = chan->ramin; |
335 | int i; | 281 | int i; |
336 | 282 | ||
337 | ramin->im_backing_suspend = vmalloc(ramin->im_pramin->size); | 283 | ramin->im_backing_suspend = vmalloc(ramin->size); |
338 | if (!ramin->im_backing_suspend) | 284 | if (!ramin->im_backing_suspend) |
339 | return -ENOMEM; | 285 | return -ENOMEM; |
340 | 286 | ||
341 | for (i = 0; i < ramin->im_pramin->size; i += 4) | 287 | for (i = 0; i < ramin->size; i += 4) |
342 | ramin->im_backing_suspend[i/4] = nv_ri32(dev, i); | 288 | ramin->im_backing_suspend[i/4] = nv_ri32(dev, i); |
343 | return 0; | 289 | return 0; |
344 | } | 290 | } |
@@ -349,23 +295,25 @@ nv50_instmem_resume(struct drm_device *dev) | |||
349 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 295 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
350 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 296 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; |
351 | struct nouveau_channel *chan = dev_priv->fifos[0]; | 297 | struct nouveau_channel *chan = dev_priv->fifos[0]; |
352 | struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; | 298 | struct nouveau_gpuobj *ramin = chan->ramin; |
353 | int i; | 299 | int i; |
354 | 300 | ||
355 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (ramin->im_backing_start >> 16)); | 301 | dev_priv->ramin_available = false; |
356 | for (i = 0; i < ramin->im_pramin->size; i += 4) | 302 | dev_priv->ramin_base = ~0; |
357 | BAR0_WI32(ramin, i, ramin->im_backing_suspend[i/4]); | 303 | for (i = 0; i < ramin->size; i += 4) |
304 | nv_wo32(ramin, i, ramin->im_backing_suspend[i/4]); | ||
305 | dev_priv->ramin_available = true; | ||
358 | vfree(ramin->im_backing_suspend); | 306 | vfree(ramin->im_backing_suspend); |
359 | ramin->im_backing_suspend = NULL; | 307 | ramin->im_backing_suspend = NULL; |
360 | 308 | ||
361 | /* Poke the relevant regs, and pray it works :) */ | 309 | /* Poke the relevant regs, and pray it works :) */ |
362 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); | 310 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12)); |
363 | nv_wr32(dev, NV50_PUNK_UNK1710, 0); | 311 | nv_wr32(dev, NV50_PUNK_UNK1710, 0); |
364 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | | 312 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | |
365 | NV50_PUNK_BAR_CFG_BASE_VALID); | 313 | NV50_PUNK_BAR_CFG_BASE_VALID); |
366 | nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) | | 314 | nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->cinst >> 4) | |
367 | NV50_PUNK_BAR1_CTXDMA_VALID); | 315 | NV50_PUNK_BAR1_CTXDMA_VALID); |
368 | nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | | 316 | nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->cinst >> 4) | |
369 | NV50_PUNK_BAR3_CTXDMA_VALID); | 317 | NV50_PUNK_BAR3_CTXDMA_VALID); |
370 | 318 | ||
371 | for (i = 0; i < 8; i++) | 319 | for (i = 0; i < 8; i++) |
@@ -381,7 +329,7 @@ nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | |||
381 | if (gpuobj->im_backing) | 329 | if (gpuobj->im_backing) |
382 | return -EINVAL; | 330 | return -EINVAL; |
383 | 331 | ||
384 | *sz = ALIGN(*sz, NV50_INSTMEM_PAGE_SIZE); | 332 | *sz = ALIGN(*sz, 4096); |
385 | if (*sz == 0) | 333 | if (*sz == 0) |
386 | return -EINVAL; | 334 | return -EINVAL; |
387 | 335 | ||
@@ -399,9 +347,7 @@ nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | |||
399 | return ret; | 347 | return ret; |
400 | } | 348 | } |
401 | 349 | ||
402 | gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; | 350 | gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; |
403 | gpuobj->im_backing_start <<= PAGE_SHIFT; | ||
404 | |||
405 | return 0; | 351 | return 0; |
406 | } | 352 | } |
407 | 353 | ||
@@ -424,7 +370,7 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
424 | { | 370 | { |
425 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 371 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
426 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 372 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; |
427 | struct nouveau_gpuobj *pramin_pt = priv->pramin_pt->gpuobj; | 373 | struct nouveau_gpuobj *pramin_pt = priv->pramin_pt; |
428 | uint32_t pte, pte_end; | 374 | uint32_t pte, pte_end; |
429 | uint64_t vram; | 375 | uint64_t vram; |
430 | 376 | ||
@@ -436,11 +382,11 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
436 | 382 | ||
437 | pte = (gpuobj->im_pramin->start >> 12) << 1; | 383 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
438 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; | 384 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
439 | vram = gpuobj->im_backing_start; | 385 | vram = gpuobj->vinst; |
440 | 386 | ||
441 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", | 387 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", |
442 | gpuobj->im_pramin->start, pte, pte_end); | 388 | gpuobj->im_pramin->start, pte, pte_end); |
443 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | 389 | NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); |
444 | 390 | ||
445 | vram |= 1; | 391 | vram |= 1; |
446 | if (dev_priv->vram_sys_base) { | 392 | if (dev_priv->vram_sys_base) { |
@@ -449,9 +395,10 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
449 | } | 395 | } |
450 | 396 | ||
451 | while (pte < pte_end) { | 397 | while (pte < pte_end) { |
452 | nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); | 398 | nv_wo32(pramin_pt, (pte * 4) + 0, lower_32_bits(vram)); |
453 | nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); | 399 | nv_wo32(pramin_pt, (pte * 4) + 4, upper_32_bits(vram)); |
454 | vram += NV50_INSTMEM_PAGE_SIZE; | 400 | vram += 0x1000; |
401 | pte += 2; | ||
455 | } | 402 | } |
456 | dev_priv->engine.instmem.flush(dev); | 403 | dev_priv->engine.instmem.flush(dev); |
457 | 404 | ||
@@ -472,12 +419,17 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
472 | if (gpuobj->im_bound == 0) | 419 | if (gpuobj->im_bound == 0) |
473 | return -EINVAL; | 420 | return -EINVAL; |
474 | 421 | ||
422 | /* can happen during late takedown */ | ||
423 | if (unlikely(!dev_priv->ramin_available)) | ||
424 | return 0; | ||
425 | |||
475 | pte = (gpuobj->im_pramin->start >> 12) << 1; | 426 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
476 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; | 427 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
477 | 428 | ||
478 | while (pte < pte_end) { | 429 | while (pte < pte_end) { |
479 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); | 430 | nv_wo32(priv->pramin_pt, (pte * 4) + 0, 0x00000000); |
480 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); | 431 | nv_wo32(priv->pramin_pt, (pte * 4) + 4, 0x00000000); |
432 | pte += 2; | ||
481 | } | 433 | } |
482 | dev_priv->engine.instmem.flush(dev); | 434 | dev_priv->engine.instmem.flush(dev); |
483 | 435 | ||
@@ -489,7 +441,7 @@ void | |||
489 | nv50_instmem_flush(struct drm_device *dev) | 441 | nv50_instmem_flush(struct drm_device *dev) |
490 | { | 442 | { |
491 | nv_wr32(dev, 0x00330c, 0x00000001); | 443 | nv_wr32(dev, 0x00330c, 0x00000001); |
492 | if (!nv_wait(0x00330c, 0x00000002, 0x00000000)) | 444 | if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) |
493 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | 445 | NV_ERROR(dev, "PRAMIN flush timeout\n"); |
494 | } | 446 | } |
495 | 447 | ||
@@ -497,7 +449,7 @@ void | |||
497 | nv84_instmem_flush(struct drm_device *dev) | 449 | nv84_instmem_flush(struct drm_device *dev) |
498 | { | 450 | { |
499 | nv_wr32(dev, 0x070000, 0x00000001); | 451 | nv_wr32(dev, 0x070000, 0x00000001); |
500 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) | 452 | if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) |
501 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | 453 | NV_ERROR(dev, "PRAMIN flush timeout\n"); |
502 | } | 454 | } |
503 | 455 | ||
@@ -505,7 +457,7 @@ void | |||
505 | nv50_vm_flush(struct drm_device *dev, int engine) | 457 | nv50_vm_flush(struct drm_device *dev, int engine) |
506 | { | 458 | { |
507 | nv_wr32(dev, 0x100c80, (engine << 16) | 1); | 459 | nv_wr32(dev, 0x100c80, (engine << 16) | 1); |
508 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) | 460 | if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) |
509 | NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); | 461 | NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); |
510 | } | 462 | } |
511 | 463 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c new file mode 100644 index 000000000000..7dbb305d7e63 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_pm.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | #include "nouveau_drv.h" | ||
27 | #include "nouveau_bios.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | struct nv50_pm_state { | ||
31 | struct nouveau_pm_level *perflvl; | ||
32 | struct pll_lims pll; | ||
33 | enum pll_types type; | ||
34 | int N, M, P; | ||
35 | }; | ||
36 | |||
37 | int | ||
38 | nv50_pm_clock_get(struct drm_device *dev, u32 id) | ||
39 | { | ||
40 | struct pll_lims pll; | ||
41 | int P, N, M, ret; | ||
42 | u32 reg0, reg1; | ||
43 | |||
44 | ret = get_pll_limits(dev, id, &pll); | ||
45 | if (ret) | ||
46 | return ret; | ||
47 | |||
48 | reg0 = nv_rd32(dev, pll.reg + 0); | ||
49 | reg1 = nv_rd32(dev, pll.reg + 4); | ||
50 | P = (reg0 & 0x00070000) >> 16; | ||
51 | N = (reg1 & 0x0000ff00) >> 8; | ||
52 | M = (reg1 & 0x000000ff); | ||
53 | |||
54 | return ((pll.refclk * N / M) >> P); | ||
55 | } | ||
56 | |||
57 | void * | ||
58 | nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||
59 | u32 id, int khz) | ||
60 | { | ||
61 | struct nv50_pm_state *state; | ||
62 | int dummy, ret; | ||
63 | |||
64 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
65 | if (!state) | ||
66 | return ERR_PTR(-ENOMEM); | ||
67 | state->type = id; | ||
68 | state->perflvl = perflvl; | ||
69 | |||
70 | ret = get_pll_limits(dev, id, &state->pll); | ||
71 | if (ret < 0) { | ||
72 | kfree(state); | ||
73 | return (ret == -ENOENT) ? NULL : ERR_PTR(ret); | ||
74 | } | ||
75 | |||
76 | ret = nv50_calc_pll(dev, &state->pll, khz, &state->N, &state->M, | ||
77 | &dummy, &dummy, &state->P); | ||
78 | if (ret < 0) { | ||
79 | kfree(state); | ||
80 | return ERR_PTR(ret); | ||
81 | } | ||
82 | |||
83 | return state; | ||
84 | } | ||
85 | |||
86 | void | ||
87 | nv50_pm_clock_set(struct drm_device *dev, void *pre_state) | ||
88 | { | ||
89 | struct nv50_pm_state *state = pre_state; | ||
90 | struct nouveau_pm_level *perflvl = state->perflvl; | ||
91 | u32 reg = state->pll.reg, tmp; | ||
92 | struct bit_entry BIT_M; | ||
93 | u16 script; | ||
94 | int N = state->N; | ||
95 | int M = state->M; | ||
96 | int P = state->P; | ||
97 | |||
98 | if (state->type == PLL_MEMORY && perflvl->memscript && | ||
99 | bit_table(dev, 'M', &BIT_M) == 0 && | ||
100 | BIT_M.version == 1 && BIT_M.length >= 0x0b) { | ||
101 | script = ROM16(BIT_M.data[0x05]); | ||
102 | if (script) | ||
103 | nouveau_bios_run_init_table(dev, script, NULL); | ||
104 | script = ROM16(BIT_M.data[0x07]); | ||
105 | if (script) | ||
106 | nouveau_bios_run_init_table(dev, script, NULL); | ||
107 | script = ROM16(BIT_M.data[0x09]); | ||
108 | if (script) | ||
109 | nouveau_bios_run_init_table(dev, script, NULL); | ||
110 | |||
111 | nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); | ||
112 | } | ||
113 | |||
114 | if (state->type == PLL_MEMORY) { | ||
115 | nv_wr32(dev, 0x100210, 0); | ||
116 | nv_wr32(dev, 0x1002dc, 1); | ||
117 | } | ||
118 | |||
119 | tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; | ||
120 | tmp |= 0x80000000 | (P << 16); | ||
121 | nv_wr32(dev, reg + 0, tmp); | ||
122 | nv_wr32(dev, reg + 4, (N << 8) | M); | ||
123 | |||
124 | if (state->type == PLL_MEMORY) { | ||
125 | nv_wr32(dev, 0x1002dc, 0); | ||
126 | nv_wr32(dev, 0x100210, 0x80000000); | ||
127 | } | ||
128 | |||
129 | kfree(state); | ||
130 | } | ||
131 | |||
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index bcd4cf84a7e6..b4a5ecb199f9 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
@@ -92,7 +92,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /* wait for it to be done */ | 94 | /* wait for it to be done */ |
95 | if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), | 95 | if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), |
96 | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { | 96 | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { |
97 | NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); | 97 | NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); |
98 | NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, | 98 | NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, |
@@ -108,7 +108,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
108 | 108 | ||
109 | nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | | 109 | nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | |
110 | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); | 110 | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); |
111 | if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or), | 111 | if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or), |
112 | NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { | 112 | NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { |
113 | NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); | 113 | NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); |
114 | NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, | 114 | NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, |
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c new file mode 100644 index 000000000000..dbbafed36406 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nva3_pm.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | #include "nouveau_drv.h" | ||
27 | #include "nouveau_bios.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | /*XXX: boards using limits 0x40 need fixing, the register layout | ||
31 | * is correct here, but, there's some other funny magic | ||
32 | * that modifies things, so it's not likely we'll set/read | ||
33 | * the correct timings yet.. working on it... | ||
34 | */ | ||
35 | |||
36 | struct nva3_pm_state { | ||
37 | struct pll_lims pll; | ||
38 | int N, M, P; | ||
39 | }; | ||
40 | |||
41 | int | ||
42 | nva3_pm_clock_get(struct drm_device *dev, u32 id) | ||
43 | { | ||
44 | struct pll_lims pll; | ||
45 | int P, N, M, ret; | ||
46 | u32 reg; | ||
47 | |||
48 | ret = get_pll_limits(dev, id, &pll); | ||
49 | if (ret) | ||
50 | return ret; | ||
51 | |||
52 | reg = nv_rd32(dev, pll.reg + 4); | ||
53 | P = (reg & 0x003f0000) >> 16; | ||
54 | N = (reg & 0x0000ff00) >> 8; | ||
55 | M = (reg & 0x000000ff); | ||
56 | return pll.refclk * N / M / P; | ||
57 | } | ||
58 | |||
59 | void * | ||
60 | nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||
61 | u32 id, int khz) | ||
62 | { | ||
63 | struct nva3_pm_state *state; | ||
64 | int dummy, ret; | ||
65 | |||
66 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
67 | if (!state) | ||
68 | return ERR_PTR(-ENOMEM); | ||
69 | |||
70 | ret = get_pll_limits(dev, id, &state->pll); | ||
71 | if (ret < 0) { | ||
72 | kfree(state); | ||
73 | return (ret == -ENOENT) ? NULL : ERR_PTR(ret); | ||
74 | } | ||
75 | |||
76 | ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, | ||
77 | &state->M, &state->P); | ||
78 | if (ret < 0) { | ||
79 | kfree(state); | ||
80 | return ERR_PTR(ret); | ||
81 | } | ||
82 | |||
83 | return state; | ||
84 | } | ||
85 | |||
86 | void | ||
87 | nva3_pm_clock_set(struct drm_device *dev, void *pre_state) | ||
88 | { | ||
89 | struct nva3_pm_state *state = pre_state; | ||
90 | u32 reg = state->pll.reg; | ||
91 | |||
92 | nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); | ||
93 | kfree(state); | ||
94 | } | ||
95 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c index d64375871979..890c2b95fbc1 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fifo.c +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c | |||
@@ -43,12 +43,6 @@ nvc0_fifo_reassign(struct drm_device *dev, bool enable) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | bool | 45 | bool |
46 | nvc0_fifo_cache_flush(struct drm_device *dev) | ||
47 | { | ||
48 | return true; | ||
49 | } | ||
50 | |||
51 | bool | ||
52 | nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) | 46 | nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) |
53 | { | 47 | { |
54 | return false; | 48 | return false; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c index 6b451f864783..13a0f78a9088 100644 --- a/drivers/gpu/drm/nouveau/nvc0_instmem.c +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c | |||
@@ -50,8 +50,7 @@ nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | |||
50 | return ret; | 50 | return ret; |
51 | } | 51 | } |
52 | 52 | ||
53 | gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; | 53 | gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; |
54 | gpuobj->im_backing_start <<= PAGE_SHIFT; | ||
55 | return 0; | 54 | return 0; |
56 | } | 55 | } |
57 | 56 | ||
@@ -84,11 +83,11 @@ nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
84 | 83 | ||
85 | pte = gpuobj->im_pramin->start >> 12; | 84 | pte = gpuobj->im_pramin->start >> 12; |
86 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | 85 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; |
87 | vram = gpuobj->im_backing_start; | 86 | vram = gpuobj->vinst; |
88 | 87 | ||
89 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", | 88 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", |
90 | gpuobj->im_pramin->start, pte, pte_end); | 89 | gpuobj->im_pramin->start, pte, pte_end); |
91 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | 90 | NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); |
92 | 91 | ||
93 | while (pte < pte_end) { | 92 | while (pte < pte_end) { |
94 | nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); | 93 | nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); |
@@ -134,7 +133,7 @@ void | |||
134 | nvc0_instmem_flush(struct drm_device *dev) | 133 | nvc0_instmem_flush(struct drm_device *dev) |
135 | { | 134 | { |
136 | nv_wr32(dev, 0x070000, 1); | 135 | nv_wr32(dev, 0x070000, 1); |
137 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) | 136 | if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) |
138 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | 137 | NV_ERROR(dev, "PRAMIN flush timeout\n"); |
139 | } | 138 | } |
140 | 139 | ||
@@ -221,10 +220,6 @@ nvc0_instmem_init(struct drm_device *dev) | |||
221 | return -ENOMEM; | 220 | return -ENOMEM; |
222 | } | 221 | } |
223 | 222 | ||
224 | /*XXX: incorrect, but needed to make hash func "work" */ | ||
225 | dev_priv->ramht_offset = 0x10000; | ||
226 | dev_priv->ramht_bits = 9; | ||
227 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; | ||
228 | return 0; | 223 | return 0; |
229 | } | 224 | } |
230 | 225 | ||
diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h index ad64673ace1f..881f8a585613 100644 --- a/drivers/gpu/drm/nouveau/nvreg.h +++ b/drivers/gpu/drm/nouveau/nvreg.h | |||
@@ -263,6 +263,7 @@ | |||
263 | # define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2 | 263 | # define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2 |
264 | # define NV_CIO_CRE_LCD__INDEX 0x33 | 264 | # define NV_CIO_CRE_LCD__INDEX 0x33 |
265 | # define NV_CIO_CRE_LCD_LCD_SELECT 0:0 | 265 | # define NV_CIO_CRE_LCD_LCD_SELECT 0:0 |
266 | # define NV_CIO_CRE_LCD_ROUTE_MASK 0x3b | ||
266 | # define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36 | 267 | # define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36 |
267 | # define NV_CIO_CRE_DDC0_WR__INDEX 0x37 | 268 | # define NV_CIO_CRE_DDC0_WR__INDEX 0x37 |
268 | # define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */ | 269 | # define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */ |
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 1e2971f13aa1..67309f84f16d 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c | |||
@@ -56,8 +56,6 @@ static struct drm_driver driver = { | |||
56 | .irq_uninstall = r128_driver_irq_uninstall, | 56 | .irq_uninstall = r128_driver_irq_uninstall, |
57 | .irq_handler = r128_driver_irq_handler, | 57 | .irq_handler = r128_driver_irq_handler, |
58 | .reclaim_buffers = drm_core_reclaim_buffers, | 58 | .reclaim_buffers = drm_core_reclaim_buffers, |
59 | .get_map_ofs = drm_core_get_map_ofs, | ||
60 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
61 | .ioctls = r128_ioctls, | 59 | .ioctls = r128_ioctls, |
62 | .dma_ioctl = r128_cce_buffers, | 60 | .dma_ioctl = r128_cce_buffers, |
63 | .fops = { | 61 | .fops = { |
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index aebe00875041..6cae4f2028d2 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -65,7 +65,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ | |||
65 | rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ | 65 | rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ |
66 | r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ | 66 | r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ |
67 | r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ | 67 | r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ |
68 | evergreen.o evergreen_cs.o | 68 | evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o |
69 | 69 | ||
70 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 70 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
71 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o | 71 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index cd0290f946cf..037e3260cb7c 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -398,65 +398,76 @@ static void atombios_disable_ss(struct drm_crtc *crtc) | |||
398 | 398 | ||
399 | 399 | ||
400 | union atom_enable_ss { | 400 | union atom_enable_ss { |
401 | ENABLE_LVDS_SS_PARAMETERS legacy; | 401 | ENABLE_LVDS_SS_PARAMETERS lvds_ss; |
402 | ENABLE_LVDS_SS_PARAMETERS_V2 lvds_ss_2; | ||
402 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; | 403 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; |
404 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 v2; | ||
403 | }; | 405 | }; |
404 | 406 | ||
405 | static void atombios_enable_ss(struct drm_crtc *crtc) | 407 | static void atombios_crtc_program_ss(struct drm_crtc *crtc, |
408 | int enable, | ||
409 | int pll_id, | ||
410 | struct radeon_atom_ss *ss) | ||
406 | { | 411 | { |
407 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
408 | struct drm_device *dev = crtc->dev; | 412 | struct drm_device *dev = crtc->dev; |
409 | struct radeon_device *rdev = dev->dev_private; | 413 | struct radeon_device *rdev = dev->dev_private; |
410 | struct drm_encoder *encoder = NULL; | ||
411 | struct radeon_encoder *radeon_encoder = NULL; | ||
412 | struct radeon_encoder_atom_dig *dig = NULL; | ||
413 | int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); | 414 | int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); |
414 | union atom_enable_ss args; | 415 | union atom_enable_ss args; |
415 | uint16_t percentage = 0; | ||
416 | uint8_t type = 0, step = 0, delay = 0, range = 0; | ||
417 | 416 | ||
418 | /* XXX add ss support for DCE4 */ | 417 | memset(&args, 0, sizeof(args)); |
419 | if (ASIC_IS_DCE4(rdev)) | ||
420 | return; | ||
421 | 418 | ||
422 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 419 | if (ASIC_IS_DCE4(rdev)) { |
423 | if (encoder->crtc == crtc) { | 420 | args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); |
424 | radeon_encoder = to_radeon_encoder(encoder); | 421 | args.v2.ucSpreadSpectrumType = ss->type; |
425 | /* only enable spread spectrum on LVDS */ | 422 | switch (pll_id) { |
426 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 423 | case ATOM_PPLL1: |
427 | dig = radeon_encoder->enc_priv; | 424 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; |
428 | if (dig && dig->ss) { | 425 | args.v2.usSpreadSpectrumAmount = ss->amount; |
429 | percentage = dig->ss->percentage; | 426 | args.v2.usSpreadSpectrumStep = ss->step; |
430 | type = dig->ss->type; | ||
431 | step = dig->ss->step; | ||
432 | delay = dig->ss->delay; | ||
433 | range = dig->ss->range; | ||
434 | } else | ||
435 | return; | ||
436 | } else | ||
437 | return; | ||
438 | break; | 427 | break; |
428 | case ATOM_PPLL2: | ||
429 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; | ||
430 | args.v2.usSpreadSpectrumAmount = ss->amount; | ||
431 | args.v2.usSpreadSpectrumStep = ss->step; | ||
432 | break; | ||
433 | case ATOM_DCPLL: | ||
434 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; | ||
435 | args.v2.usSpreadSpectrumAmount = 0; | ||
436 | args.v2.usSpreadSpectrumStep = 0; | ||
437 | break; | ||
438 | case ATOM_PPLL_INVALID: | ||
439 | return; | ||
439 | } | 440 | } |
440 | } | 441 | args.v2.ucEnable = enable; |
441 | 442 | } else if (ASIC_IS_DCE3(rdev)) { | |
442 | if (!radeon_encoder) | 443 | args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); |
443 | return; | 444 | args.v1.ucSpreadSpectrumType = ss->type; |
444 | 445 | args.v1.ucSpreadSpectrumStep = ss->step; | |
445 | memset(&args, 0, sizeof(args)); | 446 | args.v1.ucSpreadSpectrumDelay = ss->delay; |
446 | if (ASIC_IS_AVIVO(rdev)) { | 447 | args.v1.ucSpreadSpectrumRange = ss->range; |
447 | args.v1.usSpreadSpectrumPercentage = cpu_to_le16(percentage); | 448 | args.v1.ucPpll = pll_id; |
448 | args.v1.ucSpreadSpectrumType = type; | 449 | args.v1.ucEnable = enable; |
449 | args.v1.ucSpreadSpectrumStep = step; | 450 | } else if (ASIC_IS_AVIVO(rdev)) { |
450 | args.v1.ucSpreadSpectrumDelay = delay; | 451 | if (enable == ATOM_DISABLE) { |
451 | args.v1.ucSpreadSpectrumRange = range; | 452 | atombios_disable_ss(crtc); |
452 | args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 453 | return; |
453 | args.v1.ucEnable = ATOM_ENABLE; | 454 | } |
455 | args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); | ||
456 | args.lvds_ss_2.ucSpreadSpectrumType = ss->type; | ||
457 | args.lvds_ss_2.ucSpreadSpectrumStep = ss->step; | ||
458 | args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay; | ||
459 | args.lvds_ss_2.ucSpreadSpectrumRange = ss->range; | ||
460 | args.lvds_ss_2.ucEnable = enable; | ||
454 | } else { | 461 | } else { |
455 | args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage); | 462 | if (enable == ATOM_DISABLE) { |
456 | args.legacy.ucSpreadSpectrumType = type; | 463 | atombios_disable_ss(crtc); |
457 | args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; | 464 | return; |
458 | args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; | 465 | } |
459 | args.legacy.ucEnable = ATOM_ENABLE; | 466 | args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); |
467 | args.lvds_ss.ucSpreadSpectrumType = ss->type; | ||
468 | args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2; | ||
469 | args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4; | ||
470 | args.lvds_ss.ucEnable = enable; | ||
460 | } | 471 | } |
461 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 472 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
462 | } | 473 | } |
@@ -468,7 +479,9 @@ union adjust_pixel_clock { | |||
468 | 479 | ||
469 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, | 480 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, |
470 | struct drm_display_mode *mode, | 481 | struct drm_display_mode *mode, |
471 | struct radeon_pll *pll) | 482 | struct radeon_pll *pll, |
483 | bool ss_enabled, | ||
484 | struct radeon_atom_ss *ss) | ||
472 | { | 485 | { |
473 | struct drm_device *dev = crtc->dev; | 486 | struct drm_device *dev = crtc->dev; |
474 | struct radeon_device *rdev = dev->dev_private; | 487 | struct radeon_device *rdev = dev->dev_private; |
@@ -482,40 +495,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
482 | /* reset the pll flags */ | 495 | /* reset the pll flags */ |
483 | pll->flags = 0; | 496 | pll->flags = 0; |
484 | 497 | ||
485 | /* select the PLL algo */ | ||
486 | if (ASIC_IS_AVIVO(rdev)) { | ||
487 | if (radeon_new_pll == 0) | ||
488 | pll->algo = PLL_ALGO_LEGACY; | ||
489 | else | ||
490 | pll->algo = PLL_ALGO_NEW; | ||
491 | } else { | ||
492 | if (radeon_new_pll == 1) | ||
493 | pll->algo = PLL_ALGO_NEW; | ||
494 | else | ||
495 | pll->algo = PLL_ALGO_LEGACY; | ||
496 | } | ||
497 | |||
498 | if (ASIC_IS_AVIVO(rdev)) { | 498 | if (ASIC_IS_AVIVO(rdev)) { |
499 | if ((rdev->family == CHIP_RS600) || | 499 | if ((rdev->family == CHIP_RS600) || |
500 | (rdev->family == CHIP_RS690) || | 500 | (rdev->family == CHIP_RS690) || |
501 | (rdev->family == CHIP_RS740)) | 501 | (rdev->family == CHIP_RS740)) |
502 | pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/ | 502 | pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/ |
503 | RADEON_PLL_PREFER_CLOSEST_LOWER); | 503 | RADEON_PLL_PREFER_CLOSEST_LOWER); |
504 | 504 | } else | |
505 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ | ||
506 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | ||
507 | else | ||
508 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | ||
509 | } else { | ||
510 | pll->flags |= RADEON_PLL_LEGACY; | 505 | pll->flags |= RADEON_PLL_LEGACY; |
511 | 506 | ||
512 | if (mode->clock > 200000) /* range limits??? */ | ||
513 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | ||
514 | else | ||
515 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | ||
516 | |||
517 | } | ||
518 | |||
519 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 507 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
520 | if (encoder->crtc == crtc) { | 508 | if (encoder->crtc == crtc) { |
521 | radeon_encoder = to_radeon_encoder(encoder); | 509 | radeon_encoder = to_radeon_encoder(encoder); |
@@ -531,29 +519,22 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
531 | } | 519 | } |
532 | } | 520 | } |
533 | 521 | ||
522 | /* use recommended ref_div for ss */ | ||
523 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
524 | if (ss_enabled) { | ||
525 | if (ss->refdiv) { | ||
526 | pll->flags |= RADEON_PLL_USE_REF_DIV; | ||
527 | pll->reference_div = ss->refdiv; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | |||
534 | if (ASIC_IS_AVIVO(rdev)) { | 532 | if (ASIC_IS_AVIVO(rdev)) { |
535 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 533 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ |
536 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | 534 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) |
537 | adjusted_clock = mode->clock * 2; | 535 | adjusted_clock = mode->clock * 2; |
538 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { | 536 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
539 | pll->algo = PLL_ALGO_LEGACY; | ||
540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 537 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
541 | } | ||
542 | /* There is some evidence (often anecdotal) that RV515/RV620 LVDS | ||
543 | * (on some boards at least) prefers the legacy algo. I'm not | ||
544 | * sure whether this should handled generically or on a | ||
545 | * case-by-case quirk basis. Both algos should work fine in the | ||
546 | * majority of cases. | ||
547 | */ | ||
548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && | ||
549 | ((rdev->family == CHIP_RV515) || | ||
550 | (rdev->family == CHIP_RV620))) { | ||
551 | /* allow the user to overrride just in case */ | ||
552 | if (radeon_new_pll == 1) | ||
553 | pll->algo = PLL_ALGO_NEW; | ||
554 | else | ||
555 | pll->algo = PLL_ALGO_LEGACY; | ||
556 | } | ||
557 | } else { | 538 | } else { |
558 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 539 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
559 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | 540 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; |
@@ -589,9 +570,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
589 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | 570 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; |
590 | args.v1.ucEncodeMode = encoder_mode; | 571 | args.v1.ucEncodeMode = encoder_mode; |
591 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | 572 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
592 | /* may want to enable SS on DP eventually */ | 573 | if (ss_enabled) |
593 | /* args.v1.ucConfig |= | 574 | args.v1.ucConfig |= |
594 | ADJUST_DISPLAY_CONFIG_SS_ENABLE;*/ | 575 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; |
595 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { | 576 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { |
596 | args.v1.ucConfig |= | 577 | args.v1.ucConfig |= |
597 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; | 578 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; |
@@ -608,11 +589,10 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
608 | args.v3.sInput.ucDispPllConfig = 0; | 589 | args.v3.sInput.ucDispPllConfig = 0; |
609 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | 590 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { |
610 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 591 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
611 | |||
612 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | 592 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
613 | /* may want to enable SS on DP/eDP eventually */ | 593 | if (ss_enabled) |
614 | /*args.v3.sInput.ucDispPllConfig |= | 594 | args.v3.sInput.ucDispPllConfig |= |
615 | DISPPLL_CONFIG_SS_ENABLE;*/ | 595 | DISPPLL_CONFIG_SS_ENABLE; |
616 | args.v3.sInput.ucDispPllConfig |= | 596 | args.v3.sInput.ucDispPllConfig |= |
617 | DISPPLL_CONFIG_COHERENT_MODE; | 597 | DISPPLL_CONFIG_COHERENT_MODE; |
618 | /* 16200 or 27000 */ | 598 | /* 16200 or 27000 */ |
@@ -632,17 +612,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
632 | } | 612 | } |
633 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 613 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
634 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | 614 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
635 | /* may want to enable SS on DP/eDP eventually */ | 615 | if (ss_enabled) |
636 | /*args.v3.sInput.ucDispPllConfig |= | 616 | args.v3.sInput.ucDispPllConfig |= |
637 | DISPPLL_CONFIG_SS_ENABLE;*/ | 617 | DISPPLL_CONFIG_SS_ENABLE; |
638 | args.v3.sInput.ucDispPllConfig |= | 618 | args.v3.sInput.ucDispPllConfig |= |
639 | DISPPLL_CONFIG_COHERENT_MODE; | 619 | DISPPLL_CONFIG_COHERENT_MODE; |
640 | /* 16200 or 27000 */ | 620 | /* 16200 or 27000 */ |
641 | args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); | 621 | args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); |
642 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { | 622 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { |
643 | /* want to enable SS on LVDS eventually */ | 623 | if (ss_enabled) |
644 | /*args.v3.sInput.ucDispPllConfig |= | 624 | args.v3.sInput.ucDispPllConfig |= |
645 | DISPPLL_CONFIG_SS_ENABLE;*/ | 625 | DISPPLL_CONFIG_SS_ENABLE; |
646 | } else { | 626 | } else { |
647 | if (mode->clock > 165000) | 627 | if (mode->clock > 165000) |
648 | args.v3.sInput.ucDispPllConfig |= | 628 | args.v3.sInput.ucDispPllConfig |= |
@@ -816,6 +796,8 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
816 | struct radeon_pll *pll; | 796 | struct radeon_pll *pll; |
817 | u32 adjusted_clock; | 797 | u32 adjusted_clock; |
818 | int encoder_mode = 0; | 798 | int encoder_mode = 0; |
799 | struct radeon_atom_ss ss; | ||
800 | bool ss_enabled = false; | ||
819 | 801 | ||
820 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 802 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
821 | if (encoder->crtc == crtc) { | 803 | if (encoder->crtc == crtc) { |
@@ -842,25 +824,123 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
842 | break; | 824 | break; |
843 | } | 825 | } |
844 | 826 | ||
827 | if (radeon_encoder->active_device & | ||
828 | (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { | ||
829 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
830 | struct drm_connector *connector = | ||
831 | radeon_get_connector_for_encoder(encoder); | ||
832 | struct radeon_connector *radeon_connector = | ||
833 | to_radeon_connector(connector); | ||
834 | struct radeon_connector_atom_dig *dig_connector = | ||
835 | radeon_connector->con_priv; | ||
836 | int dp_clock; | ||
837 | |||
838 | switch (encoder_mode) { | ||
839 | case ATOM_ENCODER_MODE_DP: | ||
840 | /* DP/eDP */ | ||
841 | dp_clock = dig_connector->dp_clock / 10; | ||
842 | if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
843 | if (ASIC_IS_DCE4(rdev)) | ||
844 | ss_enabled = | ||
845 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
846 | dig->lcd_ss_id, | ||
847 | dp_clock); | ||
848 | else | ||
849 | ss_enabled = | ||
850 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
851 | dig->lcd_ss_id); | ||
852 | } else { | ||
853 | if (ASIC_IS_DCE4(rdev)) | ||
854 | ss_enabled = | ||
855 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
856 | ASIC_INTERNAL_SS_ON_DP, | ||
857 | dp_clock); | ||
858 | else { | ||
859 | if (dp_clock == 16200) { | ||
860 | ss_enabled = | ||
861 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
862 | ATOM_DP_SS_ID2); | ||
863 | if (!ss_enabled) | ||
864 | ss_enabled = | ||
865 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
866 | ATOM_DP_SS_ID1); | ||
867 | } else | ||
868 | ss_enabled = | ||
869 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
870 | ATOM_DP_SS_ID1); | ||
871 | } | ||
872 | } | ||
873 | break; | ||
874 | case ATOM_ENCODER_MODE_LVDS: | ||
875 | if (ASIC_IS_DCE4(rdev)) | ||
876 | ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
877 | dig->lcd_ss_id, | ||
878 | mode->clock / 10); | ||
879 | else | ||
880 | ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &ss, | ||
881 | dig->lcd_ss_id); | ||
882 | break; | ||
883 | case ATOM_ENCODER_MODE_DVI: | ||
884 | if (ASIC_IS_DCE4(rdev)) | ||
885 | ss_enabled = | ||
886 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
887 | ASIC_INTERNAL_SS_ON_TMDS, | ||
888 | mode->clock / 10); | ||
889 | break; | ||
890 | case ATOM_ENCODER_MODE_HDMI: | ||
891 | if (ASIC_IS_DCE4(rdev)) | ||
892 | ss_enabled = | ||
893 | radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
894 | ASIC_INTERNAL_SS_ON_HDMI, | ||
895 | mode->clock / 10); | ||
896 | break; | ||
897 | default: | ||
898 | break; | ||
899 | } | ||
900 | } | ||
901 | |||
845 | /* adjust pixel clock as needed */ | 902 | /* adjust pixel clock as needed */ |
846 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll); | 903 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss); |
847 | 904 | ||
848 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 905 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, |
849 | &ref_div, &post_div); | 906 | &ref_div, &post_div); |
850 | 907 | ||
908 | atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); | ||
909 | |||
851 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, | 910 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, |
852 | encoder_mode, radeon_encoder->encoder_id, mode->clock, | 911 | encoder_mode, radeon_encoder->encoder_id, mode->clock, |
853 | ref_div, fb_div, frac_fb_div, post_div); | 912 | ref_div, fb_div, frac_fb_div, post_div); |
854 | 913 | ||
914 | if (ss_enabled) { | ||
915 | /* calculate ss amount and step size */ | ||
916 | if (ASIC_IS_DCE4(rdev)) { | ||
917 | u32 step_size; | ||
918 | u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000; | ||
919 | ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; | ||
920 | ss.amount |= ((amount - (ss.amount * 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & | ||
921 | ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; | ||
922 | if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) | ||
923 | step_size = (4 * amount * ref_div * (ss.rate * 2048)) / | ||
924 | (125 * 25 * pll->reference_freq / 100); | ||
925 | else | ||
926 | step_size = (2 * amount * ref_div * (ss.rate * 2048)) / | ||
927 | (125 * 25 * pll->reference_freq / 100); | ||
928 | ss.step = step_size; | ||
929 | } | ||
930 | |||
931 | atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss); | ||
932 | } | ||
855 | } | 933 | } |
856 | 934 | ||
857 | static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 935 | static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, |
858 | struct drm_framebuffer *old_fb) | 936 | struct drm_framebuffer *fb, |
937 | int x, int y, int atomic) | ||
859 | { | 938 | { |
860 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 939 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
861 | struct drm_device *dev = crtc->dev; | 940 | struct drm_device *dev = crtc->dev; |
862 | struct radeon_device *rdev = dev->dev_private; | 941 | struct radeon_device *rdev = dev->dev_private; |
863 | struct radeon_framebuffer *radeon_fb; | 942 | struct radeon_framebuffer *radeon_fb; |
943 | struct drm_framebuffer *target_fb; | ||
864 | struct drm_gem_object *obj; | 944 | struct drm_gem_object *obj; |
865 | struct radeon_bo *rbo; | 945 | struct radeon_bo *rbo; |
866 | uint64_t fb_location; | 946 | uint64_t fb_location; |
@@ -868,28 +948,43 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
868 | int r; | 948 | int r; |
869 | 949 | ||
870 | /* no fb bound */ | 950 | /* no fb bound */ |
871 | if (!crtc->fb) { | 951 | if (!atomic && !crtc->fb) { |
872 | DRM_DEBUG_KMS("No FB bound\n"); | 952 | DRM_DEBUG_KMS("No FB bound\n"); |
873 | return 0; | 953 | return 0; |
874 | } | 954 | } |
875 | 955 | ||
876 | radeon_fb = to_radeon_framebuffer(crtc->fb); | 956 | if (atomic) { |
957 | radeon_fb = to_radeon_framebuffer(fb); | ||
958 | target_fb = fb; | ||
959 | } | ||
960 | else { | ||
961 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
962 | target_fb = crtc->fb; | ||
963 | } | ||
877 | 964 | ||
878 | /* Pin framebuffer & get tilling informations */ | 965 | /* If atomic, assume fb object is pinned & idle & fenced and |
966 | * just update base pointers | ||
967 | */ | ||
879 | obj = radeon_fb->obj; | 968 | obj = radeon_fb->obj; |
880 | rbo = obj->driver_private; | 969 | rbo = obj->driver_private; |
881 | r = radeon_bo_reserve(rbo, false); | 970 | r = radeon_bo_reserve(rbo, false); |
882 | if (unlikely(r != 0)) | 971 | if (unlikely(r != 0)) |
883 | return r; | 972 | return r; |
884 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | 973 | |
885 | if (unlikely(r != 0)) { | 974 | if (atomic) |
886 | radeon_bo_unreserve(rbo); | 975 | fb_location = radeon_bo_gpu_offset(rbo); |
887 | return -EINVAL; | 976 | else { |
977 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | ||
978 | if (unlikely(r != 0)) { | ||
979 | radeon_bo_unreserve(rbo); | ||
980 | return -EINVAL; | ||
981 | } | ||
888 | } | 982 | } |
983 | |||
889 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | 984 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); |
890 | radeon_bo_unreserve(rbo); | 985 | radeon_bo_unreserve(rbo); |
891 | 986 | ||
892 | switch (crtc->fb->bits_per_pixel) { | 987 | switch (target_fb->bits_per_pixel) { |
893 | case 8: | 988 | case 8: |
894 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | | 989 | fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | |
895 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); | 990 | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); |
@@ -909,7 +1004,7 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
909 | break; | 1004 | break; |
910 | default: | 1005 | default: |
911 | DRM_ERROR("Unsupported screen depth %d\n", | 1006 | DRM_ERROR("Unsupported screen depth %d\n", |
912 | crtc->fb->bits_per_pixel); | 1007 | target_fb->bits_per_pixel); |
913 | return -EINVAL; | 1008 | return -EINVAL; |
914 | } | 1009 | } |
915 | 1010 | ||
@@ -955,10 +1050,10 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
955 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); | 1050 | WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); |
956 | WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); | 1051 | WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); |
957 | WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); | 1052 | WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); |
958 | WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); | 1053 | WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); |
959 | WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); | 1054 | WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); |
960 | 1055 | ||
961 | fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | 1056 | fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); |
962 | WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); | 1057 | WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); |
963 | WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); | 1058 | WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); |
964 | 1059 | ||
@@ -977,8 +1072,8 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
977 | else | 1072 | else |
978 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); | 1073 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); |
979 | 1074 | ||
980 | if (old_fb && old_fb != crtc->fb) { | 1075 | if (!atomic && fb && fb != crtc->fb) { |
981 | radeon_fb = to_radeon_framebuffer(old_fb); | 1076 | radeon_fb = to_radeon_framebuffer(fb); |
982 | rbo = radeon_fb->obj->driver_private; | 1077 | rbo = radeon_fb->obj->driver_private; |
983 | r = radeon_bo_reserve(rbo, false); | 1078 | r = radeon_bo_reserve(rbo, false); |
984 | if (unlikely(r != 0)) | 1079 | if (unlikely(r != 0)) |
@@ -993,8 +1088,9 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
993 | return 0; | 1088 | return 0; |
994 | } | 1089 | } |
995 | 1090 | ||
996 | static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 1091 | static int avivo_crtc_do_set_base(struct drm_crtc *crtc, |
997 | struct drm_framebuffer *old_fb) | 1092 | struct drm_framebuffer *fb, |
1093 | int x, int y, int atomic) | ||
998 | { | 1094 | { |
999 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1095 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
1000 | struct drm_device *dev = crtc->dev; | 1096 | struct drm_device *dev = crtc->dev; |
@@ -1002,33 +1098,48 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1002 | struct radeon_framebuffer *radeon_fb; | 1098 | struct radeon_framebuffer *radeon_fb; |
1003 | struct drm_gem_object *obj; | 1099 | struct drm_gem_object *obj; |
1004 | struct radeon_bo *rbo; | 1100 | struct radeon_bo *rbo; |
1101 | struct drm_framebuffer *target_fb; | ||
1005 | uint64_t fb_location; | 1102 | uint64_t fb_location; |
1006 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; | 1103 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; |
1007 | int r; | 1104 | int r; |
1008 | 1105 | ||
1009 | /* no fb bound */ | 1106 | /* no fb bound */ |
1010 | if (!crtc->fb) { | 1107 | if (!atomic && !crtc->fb) { |
1011 | DRM_DEBUG_KMS("No FB bound\n"); | 1108 | DRM_DEBUG_KMS("No FB bound\n"); |
1012 | return 0; | 1109 | return 0; |
1013 | } | 1110 | } |
1014 | 1111 | ||
1015 | radeon_fb = to_radeon_framebuffer(crtc->fb); | 1112 | if (atomic) { |
1113 | radeon_fb = to_radeon_framebuffer(fb); | ||
1114 | target_fb = fb; | ||
1115 | } | ||
1116 | else { | ||
1117 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
1118 | target_fb = crtc->fb; | ||
1119 | } | ||
1016 | 1120 | ||
1017 | /* Pin framebuffer & get tilling informations */ | ||
1018 | obj = radeon_fb->obj; | 1121 | obj = radeon_fb->obj; |
1019 | rbo = obj->driver_private; | 1122 | rbo = obj->driver_private; |
1020 | r = radeon_bo_reserve(rbo, false); | 1123 | r = radeon_bo_reserve(rbo, false); |
1021 | if (unlikely(r != 0)) | 1124 | if (unlikely(r != 0)) |
1022 | return r; | 1125 | return r; |
1023 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | 1126 | |
1024 | if (unlikely(r != 0)) { | 1127 | /* If atomic, assume fb object is pinned & idle & fenced and |
1025 | radeon_bo_unreserve(rbo); | 1128 | * just update base pointers |
1026 | return -EINVAL; | 1129 | */ |
1130 | if (atomic) | ||
1131 | fb_location = radeon_bo_gpu_offset(rbo); | ||
1132 | else { | ||
1133 | r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location); | ||
1134 | if (unlikely(r != 0)) { | ||
1135 | radeon_bo_unreserve(rbo); | ||
1136 | return -EINVAL; | ||
1137 | } | ||
1027 | } | 1138 | } |
1028 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | 1139 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); |
1029 | radeon_bo_unreserve(rbo); | 1140 | radeon_bo_unreserve(rbo); |
1030 | 1141 | ||
1031 | switch (crtc->fb->bits_per_pixel) { | 1142 | switch (target_fb->bits_per_pixel) { |
1032 | case 8: | 1143 | case 8: |
1033 | fb_format = | 1144 | fb_format = |
1034 | AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | | 1145 | AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | |
@@ -1052,7 +1163,7 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1052 | break; | 1163 | break; |
1053 | default: | 1164 | default: |
1054 | DRM_ERROR("Unsupported screen depth %d\n", | 1165 | DRM_ERROR("Unsupported screen depth %d\n", |
1055 | crtc->fb->bits_per_pixel); | 1166 | target_fb->bits_per_pixel); |
1056 | return -EINVAL; | 1167 | return -EINVAL; |
1057 | } | 1168 | } |
1058 | 1169 | ||
@@ -1093,10 +1204,10 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1093 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); | 1204 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); |
1094 | WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); | 1205 | WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); |
1095 | WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); | 1206 | WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); |
1096 | WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); | 1207 | WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); |
1097 | WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); | 1208 | WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); |
1098 | 1209 | ||
1099 | fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | 1210 | fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); |
1100 | WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); | 1211 | WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); |
1101 | WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); | 1212 | WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); |
1102 | 1213 | ||
@@ -1115,8 +1226,8 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1115 | else | 1226 | else |
1116 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); | 1227 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); |
1117 | 1228 | ||
1118 | if (old_fb && old_fb != crtc->fb) { | 1229 | if (!atomic && fb && fb != crtc->fb) { |
1119 | radeon_fb = to_radeon_framebuffer(old_fb); | 1230 | radeon_fb = to_radeon_framebuffer(fb); |
1120 | rbo = radeon_fb->obj->driver_private; | 1231 | rbo = radeon_fb->obj->driver_private; |
1121 | r = radeon_bo_reserve(rbo, false); | 1232 | r = radeon_bo_reserve(rbo, false); |
1122 | if (unlikely(r != 0)) | 1233 | if (unlikely(r != 0)) |
@@ -1138,11 +1249,26 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1138 | struct radeon_device *rdev = dev->dev_private; | 1249 | struct radeon_device *rdev = dev->dev_private; |
1139 | 1250 | ||
1140 | if (ASIC_IS_DCE4(rdev)) | 1251 | if (ASIC_IS_DCE4(rdev)) |
1141 | return evergreen_crtc_set_base(crtc, x, y, old_fb); | 1252 | return evergreen_crtc_do_set_base(crtc, old_fb, x, y, 0); |
1253 | else if (ASIC_IS_AVIVO(rdev)) | ||
1254 | return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0); | ||
1255 | else | ||
1256 | return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); | ||
1257 | } | ||
1258 | |||
1259 | int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, | ||
1260 | struct drm_framebuffer *fb, | ||
1261 | int x, int y, int enter) | ||
1262 | { | ||
1263 | struct drm_device *dev = crtc->dev; | ||
1264 | struct radeon_device *rdev = dev->dev_private; | ||
1265 | |||
1266 | if (ASIC_IS_DCE4(rdev)) | ||
1267 | return evergreen_crtc_do_set_base(crtc, fb, x, y, 1); | ||
1142 | else if (ASIC_IS_AVIVO(rdev)) | 1268 | else if (ASIC_IS_AVIVO(rdev)) |
1143 | return avivo_crtc_set_base(crtc, x, y, old_fb); | 1269 | return avivo_crtc_do_set_base(crtc, fb, x, y, 1); |
1144 | else | 1270 | else |
1145 | return radeon_crtc_set_base(crtc, x, y, old_fb); | 1271 | return radeon_crtc_do_set_base(crtc, fb, x, y, 1); |
1146 | } | 1272 | } |
1147 | 1273 | ||
1148 | /* properly set additional regs when using atombios */ | 1274 | /* properly set additional regs when using atombios */ |
@@ -1230,12 +1356,19 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
1230 | } | 1356 | } |
1231 | } | 1357 | } |
1232 | 1358 | ||
1233 | atombios_disable_ss(crtc); | ||
1234 | /* always set DCPLL */ | 1359 | /* always set DCPLL */ |
1235 | if (ASIC_IS_DCE4(rdev)) | 1360 | if (ASIC_IS_DCE4(rdev)) { |
1361 | struct radeon_atom_ss ss; | ||
1362 | bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
1363 | ASIC_INTERNAL_SS_ON_DCPLL, | ||
1364 | rdev->clock.default_dispclk); | ||
1365 | if (ss_enabled) | ||
1366 | atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss); | ||
1236 | atombios_crtc_set_dcpll(crtc); | 1367 | atombios_crtc_set_dcpll(crtc); |
1368 | if (ss_enabled) | ||
1369 | atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss); | ||
1370 | } | ||
1237 | atombios_crtc_set_pll(crtc, adjusted_mode); | 1371 | atombios_crtc_set_pll(crtc, adjusted_mode); |
1238 | atombios_enable_ss(crtc); | ||
1239 | 1372 | ||
1240 | if (ASIC_IS_DCE4(rdev)) | 1373 | if (ASIC_IS_DCE4(rdev)) |
1241 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1374 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
@@ -1311,6 +1444,7 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = { | |||
1311 | .mode_fixup = atombios_crtc_mode_fixup, | 1444 | .mode_fixup = atombios_crtc_mode_fixup, |
1312 | .mode_set = atombios_crtc_mode_set, | 1445 | .mode_set = atombios_crtc_mode_set, |
1313 | .mode_set_base = atombios_crtc_set_base, | 1446 | .mode_set_base = atombios_crtc_set_base, |
1447 | .mode_set_base_atomic = atombios_crtc_set_base_atomic, | ||
1314 | .prepare = atombios_crtc_prepare, | 1448 | .prepare = atombios_crtc_prepare, |
1315 | .commit = atombios_crtc_commit, | 1449 | .commit = atombios_crtc_commit, |
1316 | .load_lut = radeon_crtc_load_lut, | 1450 | .load_lut = radeon_crtc_load_lut, |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 2f93d46ae69a..77ebcbc1b6e3 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -731,7 +731,7 @@ int evergreen_cp_resume(struct radeon_device *rdev) | |||
731 | 731 | ||
732 | /* Set ring buffer size */ | 732 | /* Set ring buffer size */ |
733 | rb_bufsz = drm_order(rdev->cp.ring_size / 8); | 733 | rb_bufsz = drm_order(rdev->cp.ring_size / 8); |
734 | tmp = RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | 734 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; |
735 | #ifdef __BIG_ENDIAN | 735 | #ifdef __BIG_ENDIAN |
736 | tmp |= BUF_SWAP_32BIT; | 736 | tmp |= BUF_SWAP_32BIT; |
737 | #endif | 737 | #endif |
@@ -745,8 +745,19 @@ int evergreen_cp_resume(struct radeon_device *rdev) | |||
745 | WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); | 745 | WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); |
746 | WREG32(CP_RB_RPTR_WR, 0); | 746 | WREG32(CP_RB_RPTR_WR, 0); |
747 | WREG32(CP_RB_WPTR, 0); | 747 | WREG32(CP_RB_WPTR, 0); |
748 | WREG32(CP_RB_RPTR_ADDR, rdev->cp.gpu_addr & 0xFFFFFFFF); | 748 | |
749 | WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->cp.gpu_addr)); | 749 | /* set the wb address wether it's enabled or not */ |
750 | WREG32(CP_RB_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); | ||
751 | WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); | ||
752 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); | ||
753 | |||
754 | if (rdev->wb.enabled) | ||
755 | WREG32(SCRATCH_UMSK, 0xff); | ||
756 | else { | ||
757 | tmp |= RB_NO_UPDATE; | ||
758 | WREG32(SCRATCH_UMSK, 0); | ||
759 | } | ||
760 | |||
750 | mdelay(1); | 761 | mdelay(1); |
751 | WREG32(CP_RB_CNTL, tmp); | 762 | WREG32(CP_RB_CNTL, tmp); |
752 | 763 | ||
@@ -1584,6 +1595,7 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
1584 | if (rdev->irq.sw_int) { | 1595 | if (rdev->irq.sw_int) { |
1585 | DRM_DEBUG("evergreen_irq_set: sw int\n"); | 1596 | DRM_DEBUG("evergreen_irq_set: sw int\n"); |
1586 | cp_int_cntl |= RB_INT_ENABLE; | 1597 | cp_int_cntl |= RB_INT_ENABLE; |
1598 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | ||
1587 | } | 1599 | } |
1588 | if (rdev->irq.crtc_vblank_int[0]) { | 1600 | if (rdev->irq.crtc_vblank_int[0]) { |
1589 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); | 1601 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); |
@@ -1760,8 +1772,10 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) | |||
1760 | { | 1772 | { |
1761 | u32 wptr, tmp; | 1773 | u32 wptr, tmp; |
1762 | 1774 | ||
1763 | /* XXX use writeback */ | 1775 | if (rdev->wb.enabled) |
1764 | wptr = RREG32(IH_RB_WPTR); | 1776 | wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]; |
1777 | else | ||
1778 | wptr = RREG32(IH_RB_WPTR); | ||
1765 | 1779 | ||
1766 | if (wptr & RB_OVERFLOW) { | 1780 | if (wptr & RB_OVERFLOW) { |
1767 | /* When a ring buffer overflow happen start parsing interrupt | 1781 | /* When a ring buffer overflow happen start parsing interrupt |
@@ -2000,6 +2014,7 @@ restart_ih: | |||
2000 | break; | 2014 | break; |
2001 | case 181: /* CP EOP event */ | 2015 | case 181: /* CP EOP event */ |
2002 | DRM_DEBUG("IH: CP EOP\n"); | 2016 | DRM_DEBUG("IH: CP EOP\n"); |
2017 | radeon_fence_process(rdev); | ||
2003 | break; | 2018 | break; |
2004 | case 233: /* GUI IDLE */ | 2019 | case 233: /* GUI IDLE */ |
2005 | DRM_DEBUG("IH: CP EOP\n"); | 2020 | DRM_DEBUG("IH: CP EOP\n"); |
@@ -2048,26 +2063,18 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
2048 | return r; | 2063 | return r; |
2049 | } | 2064 | } |
2050 | evergreen_gpu_init(rdev); | 2065 | evergreen_gpu_init(rdev); |
2051 | #if 0 | ||
2052 | if (!rdev->r600_blit.shader_obj) { | ||
2053 | r = r600_blit_init(rdev); | ||
2054 | if (r) { | ||
2055 | DRM_ERROR("radeon: failed blitter (%d).\n", r); | ||
2056 | return r; | ||
2057 | } | ||
2058 | } | ||
2059 | 2066 | ||
2060 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 2067 | r = evergreen_blit_init(rdev); |
2061 | if (unlikely(r != 0)) | ||
2062 | return r; | ||
2063 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
2064 | &rdev->r600_blit.shader_gpu_addr); | ||
2065 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
2066 | if (r) { | 2068 | if (r) { |
2067 | DRM_ERROR("failed to pin blit object %d\n", r); | 2069 | evergreen_blit_fini(rdev); |
2068 | return r; | 2070 | rdev->asic->copy = NULL; |
2071 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); | ||
2069 | } | 2072 | } |
2070 | #endif | 2073 | |
2074 | /* allocate wb buffer */ | ||
2075 | r = radeon_wb_init(rdev); | ||
2076 | if (r) | ||
2077 | return r; | ||
2071 | 2078 | ||
2072 | /* Enable IRQ */ | 2079 | /* Enable IRQ */ |
2073 | r = r600_irq_init(rdev); | 2080 | r = r600_irq_init(rdev); |
@@ -2087,8 +2094,6 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
2087 | r = evergreen_cp_resume(rdev); | 2094 | r = evergreen_cp_resume(rdev); |
2088 | if (r) | 2095 | if (r) |
2089 | return r; | 2096 | return r; |
2090 | /* write back buffer are not vital so don't worry about failure */ | ||
2091 | r600_wb_enable(rdev); | ||
2092 | 2097 | ||
2093 | return 0; | 2098 | return 0; |
2094 | } | 2099 | } |
@@ -2122,23 +2127,43 @@ int evergreen_resume(struct radeon_device *rdev) | |||
2122 | 2127 | ||
2123 | int evergreen_suspend(struct radeon_device *rdev) | 2128 | int evergreen_suspend(struct radeon_device *rdev) |
2124 | { | 2129 | { |
2125 | #if 0 | ||
2126 | int r; | 2130 | int r; |
2127 | #endif | 2131 | |
2128 | /* FIXME: we should wait for ring to be empty */ | 2132 | /* FIXME: we should wait for ring to be empty */ |
2129 | r700_cp_stop(rdev); | 2133 | r700_cp_stop(rdev); |
2130 | rdev->cp.ready = false; | 2134 | rdev->cp.ready = false; |
2131 | evergreen_irq_suspend(rdev); | 2135 | evergreen_irq_suspend(rdev); |
2132 | r600_wb_disable(rdev); | 2136 | radeon_wb_disable(rdev); |
2133 | evergreen_pcie_gart_disable(rdev); | 2137 | evergreen_pcie_gart_disable(rdev); |
2134 | #if 0 | 2138 | |
2135 | /* unpin shaders bo */ | 2139 | /* unpin shaders bo */ |
2136 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 2140 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); |
2137 | if (likely(r == 0)) { | 2141 | if (likely(r == 0)) { |
2138 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | 2142 | radeon_bo_unpin(rdev->r600_blit.shader_obj); |
2139 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 2143 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
2140 | } | 2144 | } |
2141 | #endif | 2145 | |
2146 | return 0; | ||
2147 | } | ||
2148 | |||
2149 | int evergreen_copy_blit(struct radeon_device *rdev, | ||
2150 | uint64_t src_offset, uint64_t dst_offset, | ||
2151 | unsigned num_pages, struct radeon_fence *fence) | ||
2152 | { | ||
2153 | int r; | ||
2154 | |||
2155 | mutex_lock(&rdev->r600_blit.mutex); | ||
2156 | rdev->r600_blit.vb_ib = NULL; | ||
2157 | r = evergreen_blit_prepare_copy(rdev, num_pages * RADEON_GPU_PAGE_SIZE); | ||
2158 | if (r) { | ||
2159 | if (rdev->r600_blit.vb_ib) | ||
2160 | radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); | ||
2161 | mutex_unlock(&rdev->r600_blit.mutex); | ||
2162 | return r; | ||
2163 | } | ||
2164 | evergreen_kms_blit_copy(rdev, src_offset, dst_offset, num_pages * RADEON_GPU_PAGE_SIZE); | ||
2165 | evergreen_blit_done_copy(rdev, fence); | ||
2166 | mutex_unlock(&rdev->r600_blit.mutex); | ||
2142 | return 0; | 2167 | return 0; |
2143 | } | 2168 | } |
2144 | 2169 | ||
@@ -2246,8 +2271,8 @@ int evergreen_init(struct radeon_device *rdev) | |||
2246 | if (r) { | 2271 | if (r) { |
2247 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 2272 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
2248 | r700_cp_fini(rdev); | 2273 | r700_cp_fini(rdev); |
2249 | r600_wb_fini(rdev); | ||
2250 | r600_irq_fini(rdev); | 2274 | r600_irq_fini(rdev); |
2275 | radeon_wb_fini(rdev); | ||
2251 | radeon_irq_kms_fini(rdev); | 2276 | radeon_irq_kms_fini(rdev); |
2252 | evergreen_pcie_gart_fini(rdev); | 2277 | evergreen_pcie_gart_fini(rdev); |
2253 | rdev->accel_working = false; | 2278 | rdev->accel_working = false; |
@@ -2269,10 +2294,10 @@ int evergreen_init(struct radeon_device *rdev) | |||
2269 | 2294 | ||
2270 | void evergreen_fini(struct radeon_device *rdev) | 2295 | void evergreen_fini(struct radeon_device *rdev) |
2271 | { | 2296 | { |
2272 | /*r600_blit_fini(rdev);*/ | 2297 | evergreen_blit_fini(rdev); |
2273 | r700_cp_fini(rdev); | 2298 | r700_cp_fini(rdev); |
2274 | r600_wb_fini(rdev); | ||
2275 | r600_irq_fini(rdev); | 2299 | r600_irq_fini(rdev); |
2300 | radeon_wb_fini(rdev); | ||
2276 | radeon_irq_kms_fini(rdev); | 2301 | radeon_irq_kms_fini(rdev); |
2277 | evergreen_pcie_gart_fini(rdev); | 2302 | evergreen_pcie_gart_fini(rdev); |
2278 | radeon_gem_fini(rdev); | 2303 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c new file mode 100644 index 000000000000..a9825aa324b4 --- /dev/null +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c | |||
@@ -0,0 +1,776 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Advanced Micro Devices, Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Alex Deucher <alexander.deucher@amd.com> | ||
25 | */ | ||
26 | |||
27 | #include "drmP.h" | ||
28 | #include "drm.h" | ||
29 | #include "radeon_drm.h" | ||
30 | #include "radeon.h" | ||
31 | |||
32 | #include "evergreend.h" | ||
33 | #include "evergreen_blit_shaders.h" | ||
34 | |||
35 | #define DI_PT_RECTLIST 0x11 | ||
36 | #define DI_INDEX_SIZE_16_BIT 0x0 | ||
37 | #define DI_SRC_SEL_AUTO_INDEX 0x2 | ||
38 | |||
39 | #define FMT_8 0x1 | ||
40 | #define FMT_5_6_5 0x8 | ||
41 | #define FMT_8_8_8_8 0x1a | ||
42 | #define COLOR_8 0x1 | ||
43 | #define COLOR_5_6_5 0x8 | ||
44 | #define COLOR_8_8_8_8 0x1a | ||
45 | |||
46 | /* emits 17 */ | ||
47 | static void | ||
48 | set_render_target(struct radeon_device *rdev, int format, | ||
49 | int w, int h, u64 gpu_addr) | ||
50 | { | ||
51 | u32 cb_color_info; | ||
52 | int pitch, slice; | ||
53 | |||
54 | h = ALIGN(h, 8); | ||
55 | if (h < 8) | ||
56 | h = 8; | ||
57 | |||
58 | cb_color_info = ((format << 2) | (1 << 24)); | ||
59 | pitch = (w / 8) - 1; | ||
60 | slice = ((w * h) / 64) - 1; | ||
61 | |||
62 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 15)); | ||
63 | radeon_ring_write(rdev, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_START) >> 2); | ||
64 | radeon_ring_write(rdev, gpu_addr >> 8); | ||
65 | radeon_ring_write(rdev, pitch); | ||
66 | radeon_ring_write(rdev, slice); | ||
67 | radeon_ring_write(rdev, 0); | ||
68 | radeon_ring_write(rdev, cb_color_info); | ||
69 | radeon_ring_write(rdev, (1 << 4)); | ||
70 | radeon_ring_write(rdev, (w - 1) | ((h - 1) << 16)); | ||
71 | radeon_ring_write(rdev, 0); | ||
72 | radeon_ring_write(rdev, 0); | ||
73 | radeon_ring_write(rdev, 0); | ||
74 | radeon_ring_write(rdev, 0); | ||
75 | radeon_ring_write(rdev, 0); | ||
76 | radeon_ring_write(rdev, 0); | ||
77 | radeon_ring_write(rdev, 0); | ||
78 | radeon_ring_write(rdev, 0); | ||
79 | } | ||
80 | |||
81 | /* emits 5dw */ | ||
82 | static void | ||
83 | cp_set_surface_sync(struct radeon_device *rdev, | ||
84 | u32 sync_type, u32 size, | ||
85 | u64 mc_addr) | ||
86 | { | ||
87 | u32 cp_coher_size; | ||
88 | |||
89 | if (size == 0xffffffff) | ||
90 | cp_coher_size = 0xffffffff; | ||
91 | else | ||
92 | cp_coher_size = ((size + 255) >> 8); | ||
93 | |||
94 | radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3)); | ||
95 | radeon_ring_write(rdev, sync_type); | ||
96 | radeon_ring_write(rdev, cp_coher_size); | ||
97 | radeon_ring_write(rdev, mc_addr >> 8); | ||
98 | radeon_ring_write(rdev, 10); /* poll interval */ | ||
99 | } | ||
100 | |||
101 | /* emits 11dw + 1 surface sync = 16dw */ | ||
102 | static void | ||
103 | set_shaders(struct radeon_device *rdev) | ||
104 | { | ||
105 | u64 gpu_addr; | ||
106 | |||
107 | /* VS */ | ||
108 | gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; | ||
109 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 3)); | ||
110 | radeon_ring_write(rdev, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_START) >> 2); | ||
111 | radeon_ring_write(rdev, gpu_addr >> 8); | ||
112 | radeon_ring_write(rdev, 2); | ||
113 | radeon_ring_write(rdev, 0); | ||
114 | |||
115 | /* PS */ | ||
116 | gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.ps_offset; | ||
117 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 4)); | ||
118 | radeon_ring_write(rdev, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_START) >> 2); | ||
119 | radeon_ring_write(rdev, gpu_addr >> 8); | ||
120 | radeon_ring_write(rdev, 1); | ||
121 | radeon_ring_write(rdev, 0); | ||
122 | radeon_ring_write(rdev, 2); | ||
123 | |||
124 | gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset; | ||
125 | cp_set_surface_sync(rdev, PACKET3_SH_ACTION_ENA, 512, gpu_addr); | ||
126 | } | ||
127 | |||
128 | /* emits 10 + 1 sync (5) = 15 */ | ||
129 | static void | ||
130 | set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) | ||
131 | { | ||
132 | u32 sq_vtx_constant_word2, sq_vtx_constant_word3; | ||
133 | |||
134 | /* high addr, stride */ | ||
135 | sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8)); | ||
136 | /* xyzw swizzles */ | ||
137 | sq_vtx_constant_word3 = (0 << 3) | (1 << 6) | (2 << 9) | (3 << 12); | ||
138 | |||
139 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8)); | ||
140 | radeon_ring_write(rdev, 0x580); | ||
141 | radeon_ring_write(rdev, gpu_addr & 0xffffffff); | ||
142 | radeon_ring_write(rdev, 48 - 1); /* size */ | ||
143 | radeon_ring_write(rdev, sq_vtx_constant_word2); | ||
144 | radeon_ring_write(rdev, sq_vtx_constant_word3); | ||
145 | radeon_ring_write(rdev, 0); | ||
146 | radeon_ring_write(rdev, 0); | ||
147 | radeon_ring_write(rdev, 0); | ||
148 | radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30); | ||
149 | |||
150 | if (rdev->family == CHIP_CEDAR) | ||
151 | cp_set_surface_sync(rdev, | ||
152 | PACKET3_TC_ACTION_ENA, 48, gpu_addr); | ||
153 | else | ||
154 | cp_set_surface_sync(rdev, | ||
155 | PACKET3_VC_ACTION_ENA, 48, gpu_addr); | ||
156 | |||
157 | } | ||
158 | |||
159 | /* emits 10 */ | ||
160 | static void | ||
161 | set_tex_resource(struct radeon_device *rdev, | ||
162 | int format, int w, int h, int pitch, | ||
163 | u64 gpu_addr) | ||
164 | { | ||
165 | u32 sq_tex_resource_word0, sq_tex_resource_word1; | ||
166 | u32 sq_tex_resource_word4, sq_tex_resource_word7; | ||
167 | |||
168 | if (h < 1) | ||
169 | h = 1; | ||
170 | |||
171 | sq_tex_resource_word0 = (1 << 0); /* 2D */ | ||
172 | sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 6) | | ||
173 | ((w - 1) << 18)); | ||
174 | sq_tex_resource_word1 = ((h - 1) << 0); | ||
175 | /* xyzw swizzles */ | ||
176 | sq_tex_resource_word4 = (0 << 16) | (1 << 19) | (2 << 22) | (3 << 25); | ||
177 | |||
178 | sq_tex_resource_word7 = format | (SQ_TEX_VTX_VALID_TEXTURE << 30); | ||
179 | |||
180 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8)); | ||
181 | radeon_ring_write(rdev, 0); | ||
182 | radeon_ring_write(rdev, sq_tex_resource_word0); | ||
183 | radeon_ring_write(rdev, sq_tex_resource_word1); | ||
184 | radeon_ring_write(rdev, gpu_addr >> 8); | ||
185 | radeon_ring_write(rdev, gpu_addr >> 8); | ||
186 | radeon_ring_write(rdev, sq_tex_resource_word4); | ||
187 | radeon_ring_write(rdev, 0); | ||
188 | radeon_ring_write(rdev, 0); | ||
189 | radeon_ring_write(rdev, sq_tex_resource_word7); | ||
190 | } | ||
191 | |||
192 | /* emits 12 */ | ||
193 | static void | ||
194 | set_scissors(struct radeon_device *rdev, int x1, int y1, | ||
195 | int x2, int y2) | ||
196 | { | ||
197 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); | ||
198 | radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); | ||
199 | radeon_ring_write(rdev, (x1 << 0) | (y1 << 16)); | ||
200 | radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); | ||
201 | |||
202 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); | ||
203 | radeon_ring_write(rdev, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); | ||
204 | radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31)); | ||
205 | radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); | ||
206 | |||
207 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); | ||
208 | radeon_ring_write(rdev, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); | ||
209 | radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31)); | ||
210 | radeon_ring_write(rdev, (x2 << 0) | (y2 << 16)); | ||
211 | } | ||
212 | |||
213 | /* emits 10 */ | ||
214 | static void | ||
215 | draw_auto(struct radeon_device *rdev) | ||
216 | { | ||
217 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
218 | radeon_ring_write(rdev, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_START) >> 2); | ||
219 | radeon_ring_write(rdev, DI_PT_RECTLIST); | ||
220 | |||
221 | radeon_ring_write(rdev, PACKET3(PACKET3_INDEX_TYPE, 0)); | ||
222 | radeon_ring_write(rdev, DI_INDEX_SIZE_16_BIT); | ||
223 | |||
224 | radeon_ring_write(rdev, PACKET3(PACKET3_NUM_INSTANCES, 0)); | ||
225 | radeon_ring_write(rdev, 1); | ||
226 | |||
227 | radeon_ring_write(rdev, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1)); | ||
228 | radeon_ring_write(rdev, 3); | ||
229 | radeon_ring_write(rdev, DI_SRC_SEL_AUTO_INDEX); | ||
230 | |||
231 | } | ||
232 | |||
233 | /* emits 20 */ | ||
234 | static void | ||
235 | set_default_state(struct radeon_device *rdev) | ||
236 | { | ||
237 | u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2, sq_gpr_resource_mgmt_3; | ||
238 | u32 sq_thread_resource_mgmt, sq_thread_resource_mgmt_2; | ||
239 | u32 sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2, sq_stack_resource_mgmt_3; | ||
240 | int num_ps_gprs, num_vs_gprs, num_temp_gprs; | ||
241 | int num_gs_gprs, num_es_gprs, num_hs_gprs, num_ls_gprs; | ||
242 | int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads; | ||
243 | int num_hs_threads, num_ls_threads; | ||
244 | int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; | ||
245 | int num_hs_stack_entries, num_ls_stack_entries; | ||
246 | u64 gpu_addr; | ||
247 | int dwords; | ||
248 | |||
249 | switch (rdev->family) { | ||
250 | case CHIP_CEDAR: | ||
251 | default: | ||
252 | num_ps_gprs = 93; | ||
253 | num_vs_gprs = 46; | ||
254 | num_temp_gprs = 4; | ||
255 | num_gs_gprs = 31; | ||
256 | num_es_gprs = 31; | ||
257 | num_hs_gprs = 23; | ||
258 | num_ls_gprs = 23; | ||
259 | num_ps_threads = 96; | ||
260 | num_vs_threads = 16; | ||
261 | num_gs_threads = 16; | ||
262 | num_es_threads = 16; | ||
263 | num_hs_threads = 16; | ||
264 | num_ls_threads = 16; | ||
265 | num_ps_stack_entries = 42; | ||
266 | num_vs_stack_entries = 42; | ||
267 | num_gs_stack_entries = 42; | ||
268 | num_es_stack_entries = 42; | ||
269 | num_hs_stack_entries = 42; | ||
270 | num_ls_stack_entries = 42; | ||
271 | break; | ||
272 | case CHIP_REDWOOD: | ||
273 | num_ps_gprs = 93; | ||
274 | num_vs_gprs = 46; | ||
275 | num_temp_gprs = 4; | ||
276 | num_gs_gprs = 31; | ||
277 | num_es_gprs = 31; | ||
278 | num_hs_gprs = 23; | ||
279 | num_ls_gprs = 23; | ||
280 | num_ps_threads = 128; | ||
281 | num_vs_threads = 20; | ||
282 | num_gs_threads = 20; | ||
283 | num_es_threads = 20; | ||
284 | num_hs_threads = 20; | ||
285 | num_ls_threads = 20; | ||
286 | num_ps_stack_entries = 42; | ||
287 | num_vs_stack_entries = 42; | ||
288 | num_gs_stack_entries = 42; | ||
289 | num_es_stack_entries = 42; | ||
290 | num_hs_stack_entries = 42; | ||
291 | num_ls_stack_entries = 42; | ||
292 | break; | ||
293 | case CHIP_JUNIPER: | ||
294 | num_ps_gprs = 93; | ||
295 | num_vs_gprs = 46; | ||
296 | num_temp_gprs = 4; | ||
297 | num_gs_gprs = 31; | ||
298 | num_es_gprs = 31; | ||
299 | num_hs_gprs = 23; | ||
300 | num_ls_gprs = 23; | ||
301 | num_ps_threads = 128; | ||
302 | num_vs_threads = 20; | ||
303 | num_gs_threads = 20; | ||
304 | num_es_threads = 20; | ||
305 | num_hs_threads = 20; | ||
306 | num_ls_threads = 20; | ||
307 | num_ps_stack_entries = 85; | ||
308 | num_vs_stack_entries = 85; | ||
309 | num_gs_stack_entries = 85; | ||
310 | num_es_stack_entries = 85; | ||
311 | num_hs_stack_entries = 85; | ||
312 | num_ls_stack_entries = 85; | ||
313 | break; | ||
314 | case CHIP_CYPRESS: | ||
315 | case CHIP_HEMLOCK: | ||
316 | num_ps_gprs = 93; | ||
317 | num_vs_gprs = 46; | ||
318 | num_temp_gprs = 4; | ||
319 | num_gs_gprs = 31; | ||
320 | num_es_gprs = 31; | ||
321 | num_hs_gprs = 23; | ||
322 | num_ls_gprs = 23; | ||
323 | num_ps_threads = 128; | ||
324 | num_vs_threads = 20; | ||
325 | num_gs_threads = 20; | ||
326 | num_es_threads = 20; | ||
327 | num_hs_threads = 20; | ||
328 | num_ls_threads = 20; | ||
329 | num_ps_stack_entries = 85; | ||
330 | num_vs_stack_entries = 85; | ||
331 | num_gs_stack_entries = 85; | ||
332 | num_es_stack_entries = 85; | ||
333 | num_hs_stack_entries = 85; | ||
334 | num_ls_stack_entries = 85; | ||
335 | break; | ||
336 | } | ||
337 | |||
338 | if (rdev->family == CHIP_CEDAR) | ||
339 | sq_config = 0; | ||
340 | else | ||
341 | sq_config = VC_ENABLE; | ||
342 | |||
343 | sq_config |= (EXPORT_SRC_C | | ||
344 | CS_PRIO(0) | | ||
345 | LS_PRIO(0) | | ||
346 | HS_PRIO(0) | | ||
347 | PS_PRIO(0) | | ||
348 | VS_PRIO(1) | | ||
349 | GS_PRIO(2) | | ||
350 | ES_PRIO(3)); | ||
351 | |||
352 | sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | | ||
353 | NUM_VS_GPRS(num_vs_gprs) | | ||
354 | NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); | ||
355 | sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | | ||
356 | NUM_ES_GPRS(num_es_gprs)); | ||
357 | sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | | ||
358 | NUM_LS_GPRS(num_ls_gprs)); | ||
359 | sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | | ||
360 | NUM_VS_THREADS(num_vs_threads) | | ||
361 | NUM_GS_THREADS(num_gs_threads) | | ||
362 | NUM_ES_THREADS(num_es_threads)); | ||
363 | sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | | ||
364 | NUM_LS_THREADS(num_ls_threads)); | ||
365 | sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | | ||
366 | NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); | ||
367 | sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | | ||
368 | NUM_ES_STACK_ENTRIES(num_es_stack_entries)); | ||
369 | sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | | ||
370 | NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); | ||
371 | |||
372 | /* emit an IB pointing at default state */ | ||
373 | dwords = ALIGN(rdev->r600_blit.state_len, 0x10); | ||
374 | gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; | ||
375 | radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | ||
376 | radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC); | ||
377 | radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF); | ||
378 | radeon_ring_write(rdev, dwords); | ||
379 | |||
380 | /* disable dyn gprs */ | ||
381 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
382 | radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); | ||
383 | radeon_ring_write(rdev, 0); | ||
384 | |||
385 | /* SQ config */ | ||
386 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); | ||
387 | radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); | ||
388 | radeon_ring_write(rdev, sq_config); | ||
389 | radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); | ||
390 | radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); | ||
391 | radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); | ||
392 | radeon_ring_write(rdev, 0); | ||
393 | radeon_ring_write(rdev, 0); | ||
394 | radeon_ring_write(rdev, sq_thread_resource_mgmt); | ||
395 | radeon_ring_write(rdev, sq_thread_resource_mgmt_2); | ||
396 | radeon_ring_write(rdev, sq_stack_resource_mgmt_1); | ||
397 | radeon_ring_write(rdev, sq_stack_resource_mgmt_2); | ||
398 | radeon_ring_write(rdev, sq_stack_resource_mgmt_3); | ||
399 | } | ||
400 | |||
401 | static inline uint32_t i2f(uint32_t input) | ||
402 | { | ||
403 | u32 result, i, exponent, fraction; | ||
404 | |||
405 | if ((input & 0x3fff) == 0) | ||
406 | result = 0; /* 0 is a special case */ | ||
407 | else { | ||
408 | exponent = 140; /* exponent biased by 127; */ | ||
409 | fraction = (input & 0x3fff) << 10; /* cheat and only | ||
410 | handle numbers below 2^^15 */ | ||
411 | for (i = 0; i < 14; i++) { | ||
412 | if (fraction & 0x800000) | ||
413 | break; | ||
414 | else { | ||
415 | fraction = fraction << 1; /* keep | ||
416 | shifting left until top bit = 1 */ | ||
417 | exponent = exponent - 1; | ||
418 | } | ||
419 | } | ||
420 | result = exponent << 23 | (fraction & 0x7fffff); /* mask | ||
421 | off top bit; assumed 1 */ | ||
422 | } | ||
423 | return result; | ||
424 | } | ||
425 | |||
426 | int evergreen_blit_init(struct radeon_device *rdev) | ||
427 | { | ||
428 | u32 obj_size; | ||
429 | int r, dwords; | ||
430 | void *ptr; | ||
431 | u32 packet2s[16]; | ||
432 | int num_packet2s = 0; | ||
433 | |||
434 | /* pin copy shader into vram if already initialized */ | ||
435 | if (rdev->r600_blit.shader_obj) | ||
436 | goto done; | ||
437 | |||
438 | mutex_init(&rdev->r600_blit.mutex); | ||
439 | rdev->r600_blit.state_offset = 0; | ||
440 | |||
441 | rdev->r600_blit.state_len = evergreen_default_size; | ||
442 | |||
443 | dwords = rdev->r600_blit.state_len; | ||
444 | while (dwords & 0xf) { | ||
445 | packet2s[num_packet2s++] = PACKET2(0); | ||
446 | dwords++; | ||
447 | } | ||
448 | |||
449 | obj_size = dwords * 4; | ||
450 | obj_size = ALIGN(obj_size, 256); | ||
451 | |||
452 | rdev->r600_blit.vs_offset = obj_size; | ||
453 | obj_size += evergreen_vs_size * 4; | ||
454 | obj_size = ALIGN(obj_size, 256); | ||
455 | |||
456 | rdev->r600_blit.ps_offset = obj_size; | ||
457 | obj_size += evergreen_ps_size * 4; | ||
458 | obj_size = ALIGN(obj_size, 256); | ||
459 | |||
460 | r = radeon_bo_create(rdev, NULL, obj_size, true, RADEON_GEM_DOMAIN_VRAM, | ||
461 | &rdev->r600_blit.shader_obj); | ||
462 | if (r) { | ||
463 | DRM_ERROR("evergreen failed to allocate shader\n"); | ||
464 | return r; | ||
465 | } | ||
466 | |||
467 | DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", | ||
468 | obj_size, | ||
469 | rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset); | ||
470 | |||
471 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
472 | if (unlikely(r != 0)) | ||
473 | return r; | ||
474 | r = radeon_bo_kmap(rdev->r600_blit.shader_obj, &ptr); | ||
475 | if (r) { | ||
476 | DRM_ERROR("failed to map blit object %d\n", r); | ||
477 | return r; | ||
478 | } | ||
479 | |||
480 | memcpy_toio(ptr + rdev->r600_blit.state_offset, | ||
481 | evergreen_default_state, rdev->r600_blit.state_len * 4); | ||
482 | |||
483 | if (num_packet2s) | ||
484 | memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), | ||
485 | packet2s, num_packet2s * 4); | ||
486 | memcpy(ptr + rdev->r600_blit.vs_offset, evergreen_vs, evergreen_vs_size * 4); | ||
487 | memcpy(ptr + rdev->r600_blit.ps_offset, evergreen_ps, evergreen_ps_size * 4); | ||
488 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | ||
489 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
490 | |||
491 | done: | ||
492 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
493 | if (unlikely(r != 0)) | ||
494 | return r; | ||
495 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
496 | &rdev->r600_blit.shader_gpu_addr); | ||
497 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
498 | if (r) { | ||
499 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
500 | return r; | ||
501 | } | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | void evergreen_blit_fini(struct radeon_device *rdev) | ||
506 | { | ||
507 | int r; | ||
508 | |||
509 | if (rdev->r600_blit.shader_obj == NULL) | ||
510 | return; | ||
511 | /* If we can't reserve the bo, unref should be enough to destroy | ||
512 | * it when it becomes idle. | ||
513 | */ | ||
514 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
515 | if (!r) { | ||
516 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | ||
517 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
518 | } | ||
519 | radeon_bo_unref(&rdev->r600_blit.shader_obj); | ||
520 | } | ||
521 | |||
522 | static int evergreen_vb_ib_get(struct radeon_device *rdev) | ||
523 | { | ||
524 | int r; | ||
525 | r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib); | ||
526 | if (r) { | ||
527 | DRM_ERROR("failed to get IB for vertex buffer\n"); | ||
528 | return r; | ||
529 | } | ||
530 | |||
531 | rdev->r600_blit.vb_total = 64*1024; | ||
532 | rdev->r600_blit.vb_used = 0; | ||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static void evergreen_vb_ib_put(struct radeon_device *rdev) | ||
537 | { | ||
538 | radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence); | ||
539 | radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); | ||
540 | } | ||
541 | |||
542 | int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) | ||
543 | { | ||
544 | int r; | ||
545 | int ring_size, line_size; | ||
546 | int max_size; | ||
547 | /* loops of emits + fence emit possible */ | ||
548 | int dwords_per_loop = 74, num_loops; | ||
549 | |||
550 | r = evergreen_vb_ib_get(rdev); | ||
551 | if (r) | ||
552 | return r; | ||
553 | |||
554 | /* 8 bpp vs 32 bpp for xfer unit */ | ||
555 | if (size_bytes & 3) | ||
556 | line_size = 8192; | ||
557 | else | ||
558 | line_size = 8192 * 4; | ||
559 | |||
560 | max_size = 8192 * line_size; | ||
561 | |||
562 | /* major loops cover the max size transfer */ | ||
563 | num_loops = ((size_bytes + max_size) / max_size); | ||
564 | /* minor loops cover the extra non aligned bits */ | ||
565 | num_loops += ((size_bytes % line_size) ? 1 : 0); | ||
566 | /* calculate number of loops correctly */ | ||
567 | ring_size = num_loops * dwords_per_loop; | ||
568 | /* set default + shaders */ | ||
569 | ring_size += 36; /* shaders + def state */ | ||
570 | ring_size += 10; /* fence emit for VB IB */ | ||
571 | ring_size += 5; /* done copy */ | ||
572 | ring_size += 10; /* fence emit for done copy */ | ||
573 | r = radeon_ring_lock(rdev, ring_size); | ||
574 | if (r) | ||
575 | return r; | ||
576 | |||
577 | set_default_state(rdev); /* 20 */ | ||
578 | set_shaders(rdev); /* 16 */ | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence) | ||
583 | { | ||
584 | int r; | ||
585 | |||
586 | if (rdev->r600_blit.vb_ib) | ||
587 | evergreen_vb_ib_put(rdev); | ||
588 | |||
589 | if (fence) | ||
590 | r = radeon_fence_emit(rdev, fence); | ||
591 | |||
592 | radeon_ring_unlock_commit(rdev); | ||
593 | } | ||
594 | |||
595 | void evergreen_kms_blit_copy(struct radeon_device *rdev, | ||
596 | u64 src_gpu_addr, u64 dst_gpu_addr, | ||
597 | int size_bytes) | ||
598 | { | ||
599 | int max_bytes; | ||
600 | u64 vb_gpu_addr; | ||
601 | u32 *vb; | ||
602 | |||
603 | DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr, | ||
604 | size_bytes, rdev->r600_blit.vb_used); | ||
605 | vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used); | ||
606 | if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) { | ||
607 | max_bytes = 8192; | ||
608 | |||
609 | while (size_bytes) { | ||
610 | int cur_size = size_bytes; | ||
611 | int src_x = src_gpu_addr & 255; | ||
612 | int dst_x = dst_gpu_addr & 255; | ||
613 | int h = 1; | ||
614 | src_gpu_addr = src_gpu_addr & ~255ULL; | ||
615 | dst_gpu_addr = dst_gpu_addr & ~255ULL; | ||
616 | |||
617 | if (!src_x && !dst_x) { | ||
618 | h = (cur_size / max_bytes); | ||
619 | if (h > 8192) | ||
620 | h = 8192; | ||
621 | if (h == 0) | ||
622 | h = 1; | ||
623 | else | ||
624 | cur_size = max_bytes; | ||
625 | } else { | ||
626 | if (cur_size > max_bytes) | ||
627 | cur_size = max_bytes; | ||
628 | if (cur_size > (max_bytes - dst_x)) | ||
629 | cur_size = (max_bytes - dst_x); | ||
630 | if (cur_size > (max_bytes - src_x)) | ||
631 | cur_size = (max_bytes - src_x); | ||
632 | } | ||
633 | |||
634 | if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) { | ||
635 | WARN_ON(1); | ||
636 | } | ||
637 | |||
638 | vb[0] = i2f(dst_x); | ||
639 | vb[1] = 0; | ||
640 | vb[2] = i2f(src_x); | ||
641 | vb[3] = 0; | ||
642 | |||
643 | vb[4] = i2f(dst_x); | ||
644 | vb[5] = i2f(h); | ||
645 | vb[6] = i2f(src_x); | ||
646 | vb[7] = i2f(h); | ||
647 | |||
648 | vb[8] = i2f(dst_x + cur_size); | ||
649 | vb[9] = i2f(h); | ||
650 | vb[10] = i2f(src_x + cur_size); | ||
651 | vb[11] = i2f(h); | ||
652 | |||
653 | /* src 10 */ | ||
654 | set_tex_resource(rdev, FMT_8, | ||
655 | src_x + cur_size, h, src_x + cur_size, | ||
656 | src_gpu_addr); | ||
657 | |||
658 | /* 5 */ | ||
659 | cp_set_surface_sync(rdev, | ||
660 | PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr); | ||
661 | |||
662 | |||
663 | /* dst 17 */ | ||
664 | set_render_target(rdev, COLOR_8, | ||
665 | dst_x + cur_size, h, | ||
666 | dst_gpu_addr); | ||
667 | |||
668 | /* scissors 12 */ | ||
669 | set_scissors(rdev, dst_x, 0, dst_x + cur_size, h); | ||
670 | |||
671 | /* 15 */ | ||
672 | vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used; | ||
673 | set_vtx_resource(rdev, vb_gpu_addr); | ||
674 | |||
675 | /* draw 10 */ | ||
676 | draw_auto(rdev); | ||
677 | |||
678 | /* 5 */ | ||
679 | cp_set_surface_sync(rdev, | ||
680 | PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA, | ||
681 | cur_size * h, dst_gpu_addr); | ||
682 | |||
683 | vb += 12; | ||
684 | rdev->r600_blit.vb_used += 12 * 4; | ||
685 | |||
686 | src_gpu_addr += cur_size * h; | ||
687 | dst_gpu_addr += cur_size * h; | ||
688 | size_bytes -= cur_size * h; | ||
689 | } | ||
690 | } else { | ||
691 | max_bytes = 8192 * 4; | ||
692 | |||
693 | while (size_bytes) { | ||
694 | int cur_size = size_bytes; | ||
695 | int src_x = (src_gpu_addr & 255); | ||
696 | int dst_x = (dst_gpu_addr & 255); | ||
697 | int h = 1; | ||
698 | src_gpu_addr = src_gpu_addr & ~255ULL; | ||
699 | dst_gpu_addr = dst_gpu_addr & ~255ULL; | ||
700 | |||
701 | if (!src_x && !dst_x) { | ||
702 | h = (cur_size / max_bytes); | ||
703 | if (h > 8192) | ||
704 | h = 8192; | ||
705 | if (h == 0) | ||
706 | h = 1; | ||
707 | else | ||
708 | cur_size = max_bytes; | ||
709 | } else { | ||
710 | if (cur_size > max_bytes) | ||
711 | cur_size = max_bytes; | ||
712 | if (cur_size > (max_bytes - dst_x)) | ||
713 | cur_size = (max_bytes - dst_x); | ||
714 | if (cur_size > (max_bytes - src_x)) | ||
715 | cur_size = (max_bytes - src_x); | ||
716 | } | ||
717 | |||
718 | if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) { | ||
719 | WARN_ON(1); | ||
720 | } | ||
721 | |||
722 | vb[0] = i2f(dst_x / 4); | ||
723 | vb[1] = 0; | ||
724 | vb[2] = i2f(src_x / 4); | ||
725 | vb[3] = 0; | ||
726 | |||
727 | vb[4] = i2f(dst_x / 4); | ||
728 | vb[5] = i2f(h); | ||
729 | vb[6] = i2f(src_x / 4); | ||
730 | vb[7] = i2f(h); | ||
731 | |||
732 | vb[8] = i2f((dst_x + cur_size) / 4); | ||
733 | vb[9] = i2f(h); | ||
734 | vb[10] = i2f((src_x + cur_size) / 4); | ||
735 | vb[11] = i2f(h); | ||
736 | |||
737 | /* src 10 */ | ||
738 | set_tex_resource(rdev, FMT_8_8_8_8, | ||
739 | (src_x + cur_size) / 4, | ||
740 | h, (src_x + cur_size) / 4, | ||
741 | src_gpu_addr); | ||
742 | /* 5 */ | ||
743 | cp_set_surface_sync(rdev, | ||
744 | PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr); | ||
745 | |||
746 | /* dst 17 */ | ||
747 | set_render_target(rdev, COLOR_8_8_8_8, | ||
748 | (dst_x + cur_size) / 4, h, | ||
749 | dst_gpu_addr); | ||
750 | |||
751 | /* scissors 12 */ | ||
752 | set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h); | ||
753 | |||
754 | /* Vertex buffer setup 15 */ | ||
755 | vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used; | ||
756 | set_vtx_resource(rdev, vb_gpu_addr); | ||
757 | |||
758 | /* draw 10 */ | ||
759 | draw_auto(rdev); | ||
760 | |||
761 | /* 5 */ | ||
762 | cp_set_surface_sync(rdev, | ||
763 | PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA, | ||
764 | cur_size * h, dst_gpu_addr); | ||
765 | |||
766 | /* 74 ring dwords per loop */ | ||
767 | vb += 12; | ||
768 | rdev->r600_blit.vb_used += 12 * 4; | ||
769 | |||
770 | src_gpu_addr += cur_size * h; | ||
771 | dst_gpu_addr += cur_size * h; | ||
772 | size_bytes -= cur_size * h; | ||
773 | } | ||
774 | } | ||
775 | } | ||
776 | |||
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c new file mode 100644 index 000000000000..5d5045027b46 --- /dev/null +++ b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c | |||
@@ -0,0 +1,359 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Advanced Micro Devices, Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Alex Deucher <alexander.deucher@amd.com> | ||
25 | */ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/kernel.h> | ||
29 | |||
30 | /* | ||
31 | * evergreen cards need to use the 3D engine to blit data which requires | ||
32 | * quite a bit of hw state setup. Rather than pull the whole 3D driver | ||
33 | * (which normally generates the 3D state) into the DRM, we opt to use | ||
34 | * statically generated state tables. The regsiter state and shaders | ||
35 | * were hand generated to support blitting functionality. See the 3D | ||
36 | * driver or documentation for descriptions of the registers and | ||
37 | * shader instructions. | ||
38 | */ | ||
39 | |||
40 | const u32 evergreen_default_state[] = | ||
41 | { | ||
42 | 0xc0012800, /* CONTEXT_CONTROL */ | ||
43 | 0x80000000, | ||
44 | 0x80000000, | ||
45 | |||
46 | 0xc0016900, | ||
47 | 0x0000023b, | ||
48 | 0x00000000, /* SQ_LDS_ALLOC_PS */ | ||
49 | |||
50 | 0xc0066900, | ||
51 | 0x00000240, | ||
52 | 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ | ||
53 | 0x00000000, | ||
54 | 0x00000000, | ||
55 | 0x00000000, | ||
56 | 0x00000000, | ||
57 | 0x00000000, | ||
58 | |||
59 | 0xc0046900, | ||
60 | 0x00000247, | ||
61 | 0x00000000, /* SQ_GS_VERT_ITEMSIZE */ | ||
62 | 0x00000000, | ||
63 | 0x00000000, | ||
64 | 0x00000000, | ||
65 | |||
66 | 0xc0026f00, | ||
67 | 0x00000000, | ||
68 | 0x00000000, /* SQ_VTX_BASE_VTX_LOC */ | ||
69 | 0x00000000, | ||
70 | |||
71 | 0xc0026900, | ||
72 | 0x00000010, | ||
73 | 0x00000000, /* DB_Z_INFO */ | ||
74 | 0x00000000, /* DB_STENCIL_INFO */ | ||
75 | |||
76 | |||
77 | 0xc0016900, | ||
78 | 0x00000200, | ||
79 | 0x00000000, /* DB_DEPTH_CONTROL */ | ||
80 | |||
81 | 0xc0066900, | ||
82 | 0x00000000, | ||
83 | 0x00000060, /* DB_RENDER_CONTROL */ | ||
84 | 0x00000000, /* DB_COUNT_CONTROL */ | ||
85 | 0x00000000, /* DB_DEPTH_VIEW */ | ||
86 | 0x0000002a, /* DB_RENDER_OVERRIDE */ | ||
87 | 0x00000000, /* DB_RENDER_OVERRIDE2 */ | ||
88 | 0x00000000, /* DB_HTILE_DATA_BASE */ | ||
89 | |||
90 | 0xc0026900, | ||
91 | 0x0000000a, | ||
92 | 0x00000000, /* DB_STENCIL_CLEAR */ | ||
93 | 0x00000000, /* DB_DEPTH_CLEAR */ | ||
94 | |||
95 | 0xc0016900, | ||
96 | 0x000002dc, | ||
97 | 0x0000aa00, /* DB_ALPHA_TO_MASK */ | ||
98 | |||
99 | 0xc0016900, | ||
100 | 0x00000080, | ||
101 | 0x00000000, /* PA_SC_WINDOW_OFFSET */ | ||
102 | |||
103 | 0xc00d6900, | ||
104 | 0x00000083, | ||
105 | 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ | ||
106 | 0x00000000, /* PA_SC_CLIPRECT_0_TL */ | ||
107 | 0x20002000, /* PA_SC_CLIPRECT_0_BR */ | ||
108 | 0x00000000, | ||
109 | 0x20002000, | ||
110 | 0x00000000, | ||
111 | 0x20002000, | ||
112 | 0x00000000, | ||
113 | 0x20002000, | ||
114 | 0xaaaaaaaa, /* PA_SC_EDGERULE */ | ||
115 | 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ | ||
116 | 0x0000000f, /* CB_TARGET_MASK */ | ||
117 | 0x0000000f, /* CB_SHADER_MASK */ | ||
118 | |||
119 | 0xc0226900, | ||
120 | 0x00000094, | ||
121 | 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ | ||
122 | 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ | ||
123 | 0x80000000, | ||
124 | 0x20002000, | ||
125 | 0x80000000, | ||
126 | 0x20002000, | ||
127 | 0x80000000, | ||
128 | 0x20002000, | ||
129 | 0x80000000, | ||
130 | 0x20002000, | ||
131 | 0x80000000, | ||
132 | 0x20002000, | ||
133 | 0x80000000, | ||
134 | 0x20002000, | ||
135 | 0x80000000, | ||
136 | 0x20002000, | ||
137 | 0x80000000, | ||
138 | 0x20002000, | ||
139 | 0x80000000, | ||
140 | 0x20002000, | ||
141 | 0x80000000, | ||
142 | 0x20002000, | ||
143 | 0x80000000, | ||
144 | 0x20002000, | ||
145 | 0x80000000, | ||
146 | 0x20002000, | ||
147 | 0x80000000, | ||
148 | 0x20002000, | ||
149 | 0x80000000, | ||
150 | 0x20002000, | ||
151 | 0x80000000, | ||
152 | 0x20002000, | ||
153 | 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ | ||
154 | 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ | ||
155 | |||
156 | 0xc0016900, | ||
157 | 0x000000d4, | ||
158 | 0x00000000, /* SX_MISC */ | ||
159 | |||
160 | 0xc0026900, | ||
161 | 0x00000292, | ||
162 | 0x00000000, /* PA_SC_MODE_CNTL_0 */ | ||
163 | 0x00000000, /* PA_SC_MODE_CNTL_1 */ | ||
164 | |||
165 | 0xc0106900, | ||
166 | 0x00000300, | ||
167 | 0x00000000, /* PA_SC_LINE_CNTL */ | ||
168 | 0x00000000, /* PA_SC_AA_CONFIG */ | ||
169 | 0x00000005, /* PA_SU_VTX_CNTL */ | ||
170 | 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ | ||
171 | 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ | ||
172 | 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ | ||
173 | 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ | ||
174 | 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_0 */ | ||
175 | 0x00000000, /* */ | ||
176 | 0x00000000, /* */ | ||
177 | 0x00000000, /* */ | ||
178 | 0x00000000, /* */ | ||
179 | 0x00000000, /* */ | ||
180 | 0x00000000, /* */ | ||
181 | 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_7 */ | ||
182 | 0xffffffff, /* PA_SC_AA_MASK */ | ||
183 | |||
184 | 0xc00d6900, | ||
185 | 0x00000202, | ||
186 | 0x00cc0010, /* CB_COLOR_CONTROL */ | ||
187 | 0x00000210, /* DB_SHADER_CONTROL */ | ||
188 | 0x00010000, /* PA_CL_CLIP_CNTL */ | ||
189 | 0x00000004, /* PA_SU_SC_MODE_CNTL */ | ||
190 | 0x00000100, /* PA_CL_VTE_CNTL */ | ||
191 | 0x00000000, /* PA_CL_VS_OUT_CNTL */ | ||
192 | 0x00000000, /* PA_CL_NANINF_CNTL */ | ||
193 | 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ | ||
194 | 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ | ||
195 | 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ | ||
196 | 0x00000000, /* */ | ||
197 | 0x00000000, /* */ | ||
198 | 0x00000000, /* SQ_DYN_GPR_RESOURCE_LIMIT_1 */ | ||
199 | |||
200 | 0xc0066900, | ||
201 | 0x000002de, | ||
202 | 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ | ||
203 | 0x00000000, /* */ | ||
204 | 0x00000000, /* */ | ||
205 | 0x00000000, /* */ | ||
206 | 0x00000000, /* */ | ||
207 | 0x00000000, /* */ | ||
208 | |||
209 | 0xc0016900, | ||
210 | 0x00000229, | ||
211 | 0x00000000, /* SQ_PGM_START_FS */ | ||
212 | |||
213 | 0xc0016900, | ||
214 | 0x0000022a, | ||
215 | 0x00000000, /* SQ_PGM_RESOURCES_FS */ | ||
216 | |||
217 | 0xc0096900, | ||
218 | 0x00000100, | ||
219 | 0x00ffffff, /* VGT_MAX_VTX_INDX */ | ||
220 | 0x00000000, /* */ | ||
221 | 0x00000000, /* */ | ||
222 | 0x00000000, /* */ | ||
223 | 0x00000000, /* SX_ALPHA_TEST_CONTROL */ | ||
224 | 0x00000000, /* CB_BLEND_RED */ | ||
225 | 0x00000000, /* CB_BLEND_GREEN */ | ||
226 | 0x00000000, /* CB_BLEND_BLUE */ | ||
227 | 0x00000000, /* CB_BLEND_ALPHA */ | ||
228 | |||
229 | 0xc0026900, | ||
230 | 0x000002a8, | ||
231 | 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ | ||
232 | 0x00000000, /* */ | ||
233 | |||
234 | 0xc0026900, | ||
235 | 0x000002ad, | ||
236 | 0x00000000, /* VGT_REUSE_OFF */ | ||
237 | 0x00000000, /* */ | ||
238 | |||
239 | 0xc0116900, | ||
240 | 0x00000280, | ||
241 | 0x00000000, /* PA_SU_POINT_SIZE */ | ||
242 | 0x00000000, /* PA_SU_POINT_MINMAX */ | ||
243 | 0x00000008, /* PA_SU_LINE_CNTL */ | ||
244 | 0x00000000, /* PA_SC_LINE_STIPPLE */ | ||
245 | 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ | ||
246 | 0x00000000, /* VGT_HOS_CNTL */ | ||
247 | 0x00000000, /* */ | ||
248 | 0x00000000, /* */ | ||
249 | 0x00000000, /* */ | ||
250 | 0x00000000, /* */ | ||
251 | 0x00000000, /* */ | ||
252 | 0x00000000, /* */ | ||
253 | 0x00000000, /* */ | ||
254 | 0x00000000, /* */ | ||
255 | 0x00000000, /* */ | ||
256 | 0x00000000, /* */ | ||
257 | 0x00000000, /* VGT_GS_MODE */ | ||
258 | |||
259 | 0xc0016900, | ||
260 | 0x000002a1, | ||
261 | 0x00000000, /* VGT_PRIMITIVEID_EN */ | ||
262 | |||
263 | 0xc0016900, | ||
264 | 0x000002a5, | ||
265 | 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ | ||
266 | |||
267 | 0xc0016900, | ||
268 | 0x000002d5, | ||
269 | 0x00000000, /* VGT_SHADER_STAGES_EN */ | ||
270 | |||
271 | 0xc0026900, | ||
272 | 0x000002e5, | ||
273 | 0x00000000, /* VGT_STRMOUT_CONFIG */ | ||
274 | 0x00000000, /* */ | ||
275 | |||
276 | 0xc0016900, | ||
277 | 0x000001e0, | ||
278 | 0x00000000, /* CB_BLEND0_CONTROL */ | ||
279 | |||
280 | 0xc0016900, | ||
281 | 0x000001b1, | ||
282 | 0x00000000, /* SPI_VS_OUT_CONFIG */ | ||
283 | |||
284 | 0xc0016900, | ||
285 | 0x00000187, | ||
286 | 0x00000000, /* SPI_VS_OUT_ID_0 */ | ||
287 | |||
288 | 0xc0016900, | ||
289 | 0x00000191, | ||
290 | 0x00000100, /* SPI_PS_INPUT_CNTL_0 */ | ||
291 | |||
292 | 0xc00b6900, | ||
293 | 0x000001b3, | ||
294 | 0x20000001, /* SPI_PS_IN_CONTROL_0 */ | ||
295 | 0x00000000, /* SPI_PS_IN_CONTROL_1 */ | ||
296 | 0x00000000, /* SPI_INTERP_CONTROL_0 */ | ||
297 | 0x00000000, /* SPI_INPUT_Z */ | ||
298 | 0x00000000, /* SPI_FOG_CNTL */ | ||
299 | 0x00100000, /* SPI_BARYC_CNTL */ | ||
300 | 0x00000000, /* SPI_PS_IN_CONTROL_2 */ | ||
301 | 0x00000000, /* */ | ||
302 | 0x00000000, /* */ | ||
303 | 0x00000000, /* */ | ||
304 | 0x00000000, /* */ | ||
305 | |||
306 | 0xc0036e00, /* SET_SAMPLER */ | ||
307 | 0x00000000, | ||
308 | 0x00000012, | ||
309 | 0x00000000, | ||
310 | 0x00000000, | ||
311 | }; | ||
312 | |||
313 | const u32 evergreen_vs[] = | ||
314 | { | ||
315 | 0x00000004, | ||
316 | 0x80800400, | ||
317 | 0x0000a03c, | ||
318 | 0x95000688, | ||
319 | 0x00004000, | ||
320 | 0x15200688, | ||
321 | 0x00000000, | ||
322 | 0x00000000, | ||
323 | 0x3c000000, | ||
324 | 0x67961001, | ||
325 | 0x00080000, | ||
326 | 0x00000000, | ||
327 | 0x1c000000, | ||
328 | 0x67961000, | ||
329 | 0x00000008, | ||
330 | 0x00000000, | ||
331 | }; | ||
332 | |||
333 | const u32 evergreen_ps[] = | ||
334 | { | ||
335 | 0x00000003, | ||
336 | 0xa00c0000, | ||
337 | 0x00000008, | ||
338 | 0x80400000, | ||
339 | 0x00000000, | ||
340 | 0x95200688, | ||
341 | 0x00380400, | ||
342 | 0x00146b10, | ||
343 | 0x00380000, | ||
344 | 0x20146b10, | ||
345 | 0x00380400, | ||
346 | 0x40146b00, | ||
347 | 0x80380000, | ||
348 | 0x60146b00, | ||
349 | 0x00000000, | ||
350 | 0x00000000, | ||
351 | 0x00000010, | ||
352 | 0x000d1000, | ||
353 | 0xb0800000, | ||
354 | 0x00000000, | ||
355 | }; | ||
356 | |||
357 | const u32 evergreen_ps_size = ARRAY_SIZE(evergreen_ps); | ||
358 | const u32 evergreen_vs_size = ARRAY_SIZE(evergreen_vs); | ||
359 | const u32 evergreen_default_size = ARRAY_SIZE(evergreen_default_state); | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_shaders.h b/drivers/gpu/drm/radeon/evergreen_blit_shaders.h new file mode 100644 index 000000000000..bb8d6c751595 --- /dev/null +++ b/drivers/gpu/drm/radeon/evergreen_blit_shaders.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef EVERGREEN_BLIT_SHADERS_H | ||
26 | #define EVERGREEN_BLIT_SHADERS_H | ||
27 | |||
28 | extern const u32 evergreen_ps[]; | ||
29 | extern const u32 evergreen_vs[]; | ||
30 | extern const u32 evergreen_default_state[]; | ||
31 | |||
32 | extern const u32 evergreen_ps_size, evergreen_vs_size; | ||
33 | extern const u32 evergreen_default_size; | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 9b7532dd30f7..319aa9752d40 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
@@ -802,6 +802,11 @@ | |||
802 | #define SQ_ALU_CONST_CACHE_LS_14 0x28f78 | 802 | #define SQ_ALU_CONST_CACHE_LS_14 0x28f78 |
803 | #define SQ_ALU_CONST_CACHE_LS_15 0x28f7c | 803 | #define SQ_ALU_CONST_CACHE_LS_15 0x28f7c |
804 | 804 | ||
805 | #define PA_SC_SCREEN_SCISSOR_TL 0x28030 | ||
806 | #define PA_SC_GENERIC_SCISSOR_TL 0x28240 | ||
807 | #define PA_SC_WINDOW_SCISSOR_TL 0x28204 | ||
808 | #define VGT_PRIMITIVE_TYPE 0x8958 | ||
809 | |||
805 | #define DB_DEPTH_CONTROL 0x28800 | 810 | #define DB_DEPTH_CONTROL 0x28800 |
806 | #define DB_DEPTH_VIEW 0x28008 | 811 | #define DB_DEPTH_VIEW 0x28008 |
807 | #define DB_HTILE_DATA_BASE 0x28014 | 812 | #define DB_HTILE_DATA_BASE 0x28014 |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e59422320bb6..6112ac99ccd7 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -675,67 +675,6 @@ void r100_fence_ring_emit(struct radeon_device *rdev, | |||
675 | radeon_ring_write(rdev, RADEON_SW_INT_FIRE); | 675 | radeon_ring_write(rdev, RADEON_SW_INT_FIRE); |
676 | } | 676 | } |
677 | 677 | ||
678 | int r100_wb_init(struct radeon_device *rdev) | ||
679 | { | ||
680 | int r; | ||
681 | |||
682 | if (rdev->wb.wb_obj == NULL) { | ||
683 | r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, | ||
684 | RADEON_GEM_DOMAIN_GTT, | ||
685 | &rdev->wb.wb_obj); | ||
686 | if (r) { | ||
687 | dev_err(rdev->dev, "(%d) create WB buffer failed\n", r); | ||
688 | return r; | ||
689 | } | ||
690 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
691 | if (unlikely(r != 0)) | ||
692 | return r; | ||
693 | r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, | ||
694 | &rdev->wb.gpu_addr); | ||
695 | if (r) { | ||
696 | dev_err(rdev->dev, "(%d) pin WB buffer failed\n", r); | ||
697 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
698 | return r; | ||
699 | } | ||
700 | r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | ||
701 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
702 | if (r) { | ||
703 | dev_err(rdev->dev, "(%d) map WB buffer failed\n", r); | ||
704 | return r; | ||
705 | } | ||
706 | } | ||
707 | WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr); | ||
708 | WREG32(R_00070C_CP_RB_RPTR_ADDR, | ||
709 | S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + 1024) >> 2)); | ||
710 | WREG32(R_000770_SCRATCH_UMSK, 0xff); | ||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | void r100_wb_disable(struct radeon_device *rdev) | ||
715 | { | ||
716 | WREG32(R_000770_SCRATCH_UMSK, 0); | ||
717 | } | ||
718 | |||
719 | void r100_wb_fini(struct radeon_device *rdev) | ||
720 | { | ||
721 | int r; | ||
722 | |||
723 | r100_wb_disable(rdev); | ||
724 | if (rdev->wb.wb_obj) { | ||
725 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
726 | if (unlikely(r != 0)) { | ||
727 | dev_err(rdev->dev, "(%d) can't finish WB\n", r); | ||
728 | return; | ||
729 | } | ||
730 | radeon_bo_kunmap(rdev->wb.wb_obj); | ||
731 | radeon_bo_unpin(rdev->wb.wb_obj); | ||
732 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
733 | radeon_bo_unref(&rdev->wb.wb_obj); | ||
734 | rdev->wb.wb = NULL; | ||
735 | rdev->wb.wb_obj = NULL; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | int r100_copy_blit(struct radeon_device *rdev, | 678 | int r100_copy_blit(struct radeon_device *rdev, |
740 | uint64_t src_offset, | 679 | uint64_t src_offset, |
741 | uint64_t dst_offset, | 680 | uint64_t dst_offset, |
@@ -996,20 +935,32 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | |||
996 | WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); | 935 | WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); |
997 | tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | | 936 | tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | |
998 | REG_SET(RADEON_RB_BLKSZ, rb_blksz) | | 937 | REG_SET(RADEON_RB_BLKSZ, rb_blksz) | |
999 | REG_SET(RADEON_MAX_FETCH, max_fetch) | | 938 | REG_SET(RADEON_MAX_FETCH, max_fetch)); |
1000 | RADEON_RB_NO_UPDATE); | ||
1001 | #ifdef __BIG_ENDIAN | 939 | #ifdef __BIG_ENDIAN |
1002 | tmp |= RADEON_BUF_SWAP_32BIT; | 940 | tmp |= RADEON_BUF_SWAP_32BIT; |
1003 | #endif | 941 | #endif |
1004 | WREG32(RADEON_CP_RB_CNTL, tmp); | 942 | WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_NO_UPDATE); |
1005 | 943 | ||
1006 | /* Set ring address */ | 944 | /* Set ring address */ |
1007 | DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); | 945 | DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); |
1008 | WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); | 946 | WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); |
1009 | /* Force read & write ptr to 0 */ | 947 | /* Force read & write ptr to 0 */ |
1010 | WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); | 948 | WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE); |
1011 | WREG32(RADEON_CP_RB_RPTR_WR, 0); | 949 | WREG32(RADEON_CP_RB_RPTR_WR, 0); |
1012 | WREG32(RADEON_CP_RB_WPTR, 0); | 950 | WREG32(RADEON_CP_RB_WPTR, 0); |
951 | |||
952 | /* set the wb address whether it's enabled or not */ | ||
953 | WREG32(R_00070C_CP_RB_RPTR_ADDR, | ||
954 | S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) >> 2)); | ||
955 | WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET); | ||
956 | |||
957 | if (rdev->wb.enabled) | ||
958 | WREG32(R_000770_SCRATCH_UMSK, 0xff); | ||
959 | else { | ||
960 | tmp |= RADEON_RB_NO_UPDATE; | ||
961 | WREG32(R_000770_SCRATCH_UMSK, 0); | ||
962 | } | ||
963 | |||
1013 | WREG32(RADEON_CP_RB_CNTL, tmp); | 964 | WREG32(RADEON_CP_RB_CNTL, tmp); |
1014 | udelay(10); | 965 | udelay(10); |
1015 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); | 966 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); |
@@ -1052,6 +1003,7 @@ void r100_cp_disable(struct radeon_device *rdev) | |||
1052 | rdev->cp.ready = false; | 1003 | rdev->cp.ready = false; |
1053 | WREG32(RADEON_CP_CSQ_MODE, 0); | 1004 | WREG32(RADEON_CP_CSQ_MODE, 0); |
1054 | WREG32(RADEON_CP_CSQ_CNTL, 0); | 1005 | WREG32(RADEON_CP_CSQ_CNTL, 0); |
1006 | WREG32(R_000770_SCRATCH_UMSK, 0); | ||
1055 | if (r100_gui_wait_for_idle(rdev)) { | 1007 | if (r100_gui_wait_for_idle(rdev)) { |
1056 | printk(KERN_WARNING "Failed to wait GUI idle while " | 1008 | printk(KERN_WARNING "Failed to wait GUI idle while " |
1057 | "programming pipes. Bad things might happen.\n"); | 1009 | "programming pipes. Bad things might happen.\n"); |
@@ -3737,6 +3689,12 @@ static int r100_startup(struct radeon_device *rdev) | |||
3737 | if (r) | 3689 | if (r) |
3738 | return r; | 3690 | return r; |
3739 | } | 3691 | } |
3692 | |||
3693 | /* allocate wb buffer */ | ||
3694 | r = radeon_wb_init(rdev); | ||
3695 | if (r) | ||
3696 | return r; | ||
3697 | |||
3740 | /* Enable IRQ */ | 3698 | /* Enable IRQ */ |
3741 | r100_irq_set(rdev); | 3699 | r100_irq_set(rdev); |
3742 | rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 3700 | rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -3746,9 +3704,6 @@ static int r100_startup(struct radeon_device *rdev) | |||
3746 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 3704 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
3747 | return r; | 3705 | return r; |
3748 | } | 3706 | } |
3749 | r = r100_wb_init(rdev); | ||
3750 | if (r) | ||
3751 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
3752 | r = r100_ib_init(rdev); | 3707 | r = r100_ib_init(rdev); |
3753 | if (r) { | 3708 | if (r) { |
3754 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 3709 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -3782,7 +3737,7 @@ int r100_resume(struct radeon_device *rdev) | |||
3782 | int r100_suspend(struct radeon_device *rdev) | 3737 | int r100_suspend(struct radeon_device *rdev) |
3783 | { | 3738 | { |
3784 | r100_cp_disable(rdev); | 3739 | r100_cp_disable(rdev); |
3785 | r100_wb_disable(rdev); | 3740 | radeon_wb_disable(rdev); |
3786 | r100_irq_disable(rdev); | 3741 | r100_irq_disable(rdev); |
3787 | if (rdev->flags & RADEON_IS_PCI) | 3742 | if (rdev->flags & RADEON_IS_PCI) |
3788 | r100_pci_gart_disable(rdev); | 3743 | r100_pci_gart_disable(rdev); |
@@ -3792,7 +3747,7 @@ int r100_suspend(struct radeon_device *rdev) | |||
3792 | void r100_fini(struct radeon_device *rdev) | 3747 | void r100_fini(struct radeon_device *rdev) |
3793 | { | 3748 | { |
3794 | r100_cp_fini(rdev); | 3749 | r100_cp_fini(rdev); |
3795 | r100_wb_fini(rdev); | 3750 | radeon_wb_fini(rdev); |
3796 | r100_ib_fini(rdev); | 3751 | r100_ib_fini(rdev); |
3797 | radeon_gem_fini(rdev); | 3752 | radeon_gem_fini(rdev); |
3798 | if (rdev->flags & RADEON_IS_PCI) | 3753 | if (rdev->flags & RADEON_IS_PCI) |
@@ -3905,7 +3860,7 @@ int r100_init(struct radeon_device *rdev) | |||
3905 | /* Somethings want wront with the accel init stop accel */ | 3860 | /* Somethings want wront with the accel init stop accel */ |
3906 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 3861 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
3907 | r100_cp_fini(rdev); | 3862 | r100_cp_fini(rdev); |
3908 | r100_wb_fini(rdev); | 3863 | radeon_wb_fini(rdev); |
3909 | r100_ib_fini(rdev); | 3864 | r100_ib_fini(rdev); |
3910 | radeon_irq_kms_fini(rdev); | 3865 | radeon_irq_kms_fini(rdev); |
3911 | if (rdev->flags & RADEON_IS_PCI) | 3866 | if (rdev->flags & RADEON_IS_PCI) |
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index c827738ad7dd..34527e600fe9 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
@@ -1332,6 +1332,12 @@ static int r300_startup(struct radeon_device *rdev) | |||
1332 | if (r) | 1332 | if (r) |
1333 | return r; | 1333 | return r; |
1334 | } | 1334 | } |
1335 | |||
1336 | /* allocate wb buffer */ | ||
1337 | r = radeon_wb_init(rdev); | ||
1338 | if (r) | ||
1339 | return r; | ||
1340 | |||
1335 | /* Enable IRQ */ | 1341 | /* Enable IRQ */ |
1336 | r100_irq_set(rdev); | 1342 | r100_irq_set(rdev); |
1337 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 1343 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -1341,9 +1347,6 @@ static int r300_startup(struct radeon_device *rdev) | |||
1341 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 1347 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
1342 | return r; | 1348 | return r; |
1343 | } | 1349 | } |
1344 | r = r100_wb_init(rdev); | ||
1345 | if (r) | ||
1346 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
1347 | r = r100_ib_init(rdev); | 1350 | r = r100_ib_init(rdev); |
1348 | if (r) { | 1351 | if (r) { |
1349 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 1352 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -1379,7 +1382,7 @@ int r300_resume(struct radeon_device *rdev) | |||
1379 | int r300_suspend(struct radeon_device *rdev) | 1382 | int r300_suspend(struct radeon_device *rdev) |
1380 | { | 1383 | { |
1381 | r100_cp_disable(rdev); | 1384 | r100_cp_disable(rdev); |
1382 | r100_wb_disable(rdev); | 1385 | radeon_wb_disable(rdev); |
1383 | r100_irq_disable(rdev); | 1386 | r100_irq_disable(rdev); |
1384 | if (rdev->flags & RADEON_IS_PCIE) | 1387 | if (rdev->flags & RADEON_IS_PCIE) |
1385 | rv370_pcie_gart_disable(rdev); | 1388 | rv370_pcie_gart_disable(rdev); |
@@ -1391,7 +1394,7 @@ int r300_suspend(struct radeon_device *rdev) | |||
1391 | void r300_fini(struct radeon_device *rdev) | 1394 | void r300_fini(struct radeon_device *rdev) |
1392 | { | 1395 | { |
1393 | r100_cp_fini(rdev); | 1396 | r100_cp_fini(rdev); |
1394 | r100_wb_fini(rdev); | 1397 | radeon_wb_fini(rdev); |
1395 | r100_ib_fini(rdev); | 1398 | r100_ib_fini(rdev); |
1396 | radeon_gem_fini(rdev); | 1399 | radeon_gem_fini(rdev); |
1397 | if (rdev->flags & RADEON_IS_PCIE) | 1400 | if (rdev->flags & RADEON_IS_PCIE) |
@@ -1484,7 +1487,7 @@ int r300_init(struct radeon_device *rdev) | |||
1484 | /* Somethings want wront with the accel init stop accel */ | 1487 | /* Somethings want wront with the accel init stop accel */ |
1485 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 1488 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
1486 | r100_cp_fini(rdev); | 1489 | r100_cp_fini(rdev); |
1487 | r100_wb_fini(rdev); | 1490 | radeon_wb_fini(rdev); |
1488 | r100_ib_fini(rdev); | 1491 | r100_ib_fini(rdev); |
1489 | radeon_irq_kms_fini(rdev); | 1492 | radeon_irq_kms_fini(rdev); |
1490 | if (rdev->flags & RADEON_IS_PCIE) | 1493 | if (rdev->flags & RADEON_IS_PCIE) |
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 59f7bccc5be0..c387346f93a9 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
@@ -248,6 +248,12 @@ static int r420_startup(struct radeon_device *rdev) | |||
248 | return r; | 248 | return r; |
249 | } | 249 | } |
250 | r420_pipes_init(rdev); | 250 | r420_pipes_init(rdev); |
251 | |||
252 | /* allocate wb buffer */ | ||
253 | r = radeon_wb_init(rdev); | ||
254 | if (r) | ||
255 | return r; | ||
256 | |||
251 | /* Enable IRQ */ | 257 | /* Enable IRQ */ |
252 | r100_irq_set(rdev); | 258 | r100_irq_set(rdev); |
253 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 259 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -258,10 +264,6 @@ static int r420_startup(struct radeon_device *rdev) | |||
258 | return r; | 264 | return r; |
259 | } | 265 | } |
260 | r420_cp_errata_init(rdev); | 266 | r420_cp_errata_init(rdev); |
261 | r = r100_wb_init(rdev); | ||
262 | if (r) { | ||
263 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
264 | } | ||
265 | r = r100_ib_init(rdev); | 267 | r = r100_ib_init(rdev); |
266 | if (r) { | 268 | if (r) { |
267 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 269 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -302,7 +304,7 @@ int r420_suspend(struct radeon_device *rdev) | |||
302 | { | 304 | { |
303 | r420_cp_errata_fini(rdev); | 305 | r420_cp_errata_fini(rdev); |
304 | r100_cp_disable(rdev); | 306 | r100_cp_disable(rdev); |
305 | r100_wb_disable(rdev); | 307 | radeon_wb_disable(rdev); |
306 | r100_irq_disable(rdev); | 308 | r100_irq_disable(rdev); |
307 | if (rdev->flags & RADEON_IS_PCIE) | 309 | if (rdev->flags & RADEON_IS_PCIE) |
308 | rv370_pcie_gart_disable(rdev); | 310 | rv370_pcie_gart_disable(rdev); |
@@ -314,7 +316,7 @@ int r420_suspend(struct radeon_device *rdev) | |||
314 | void r420_fini(struct radeon_device *rdev) | 316 | void r420_fini(struct radeon_device *rdev) |
315 | { | 317 | { |
316 | r100_cp_fini(rdev); | 318 | r100_cp_fini(rdev); |
317 | r100_wb_fini(rdev); | 319 | radeon_wb_fini(rdev); |
318 | r100_ib_fini(rdev); | 320 | r100_ib_fini(rdev); |
319 | radeon_gem_fini(rdev); | 321 | radeon_gem_fini(rdev); |
320 | if (rdev->flags & RADEON_IS_PCIE) | 322 | if (rdev->flags & RADEON_IS_PCIE) |
@@ -418,7 +420,7 @@ int r420_init(struct radeon_device *rdev) | |||
418 | /* Somethings want wront with the accel init stop accel */ | 420 | /* Somethings want wront with the accel init stop accel */ |
419 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 421 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
420 | r100_cp_fini(rdev); | 422 | r100_cp_fini(rdev); |
421 | r100_wb_fini(rdev); | 423 | radeon_wb_fini(rdev); |
422 | r100_ib_fini(rdev); | 424 | r100_ib_fini(rdev); |
423 | radeon_irq_kms_fini(rdev); | 425 | radeon_irq_kms_fini(rdev); |
424 | if (rdev->flags & RADEON_IS_PCIE) | 426 | if (rdev->flags & RADEON_IS_PCIE) |
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 1458dee902dd..3c8677f9e385 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c | |||
@@ -181,6 +181,12 @@ static int r520_startup(struct radeon_device *rdev) | |||
181 | if (r) | 181 | if (r) |
182 | return r; | 182 | return r; |
183 | } | 183 | } |
184 | |||
185 | /* allocate wb buffer */ | ||
186 | r = radeon_wb_init(rdev); | ||
187 | if (r) | ||
188 | return r; | ||
189 | |||
184 | /* Enable IRQ */ | 190 | /* Enable IRQ */ |
185 | rs600_irq_set(rdev); | 191 | rs600_irq_set(rdev); |
186 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 192 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -190,9 +196,6 @@ static int r520_startup(struct radeon_device *rdev) | |||
190 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 196 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
191 | return r; | 197 | return r; |
192 | } | 198 | } |
193 | r = r100_wb_init(rdev); | ||
194 | if (r) | ||
195 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
196 | r = r100_ib_init(rdev); | 199 | r = r100_ib_init(rdev); |
197 | if (r) { | 200 | if (r) { |
198 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 201 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -295,7 +298,7 @@ int r520_init(struct radeon_device *rdev) | |||
295 | /* Somethings want wront with the accel init stop accel */ | 298 | /* Somethings want wront with the accel init stop accel */ |
296 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 299 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
297 | r100_cp_fini(rdev); | 300 | r100_cp_fini(rdev); |
298 | r100_wb_fini(rdev); | 301 | radeon_wb_fini(rdev); |
299 | r100_ib_fini(rdev); | 302 | r100_ib_fini(rdev); |
300 | radeon_irq_kms_fini(rdev); | 303 | radeon_irq_kms_fini(rdev); |
301 | rv370_pcie_gart_fini(rdev); | 304 | rv370_pcie_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 7b65e4efe8af..83ba9644dcb9 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1920,6 +1920,7 @@ void r600_cp_stop(struct radeon_device *rdev) | |||
1920 | { | 1920 | { |
1921 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 1921 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; |
1922 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); | 1922 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); |
1923 | WREG32(SCRATCH_UMSK, 0); | ||
1923 | } | 1924 | } |
1924 | 1925 | ||
1925 | int r600_init_microcode(struct radeon_device *rdev) | 1926 | int r600_init_microcode(struct radeon_device *rdev) |
@@ -2152,7 +2153,7 @@ int r600_cp_resume(struct radeon_device *rdev) | |||
2152 | 2153 | ||
2153 | /* Set ring buffer size */ | 2154 | /* Set ring buffer size */ |
2154 | rb_bufsz = drm_order(rdev->cp.ring_size / 8); | 2155 | rb_bufsz = drm_order(rdev->cp.ring_size / 8); |
2155 | tmp = RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | 2156 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; |
2156 | #ifdef __BIG_ENDIAN | 2157 | #ifdef __BIG_ENDIAN |
2157 | tmp |= BUF_SWAP_32BIT; | 2158 | tmp |= BUF_SWAP_32BIT; |
2158 | #endif | 2159 | #endif |
@@ -2166,8 +2167,19 @@ int r600_cp_resume(struct radeon_device *rdev) | |||
2166 | WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); | 2167 | WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); |
2167 | WREG32(CP_RB_RPTR_WR, 0); | 2168 | WREG32(CP_RB_RPTR_WR, 0); |
2168 | WREG32(CP_RB_WPTR, 0); | 2169 | WREG32(CP_RB_WPTR, 0); |
2169 | WREG32(CP_RB_RPTR_ADDR, rdev->cp.gpu_addr & 0xFFFFFFFF); | 2170 | |
2170 | WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->cp.gpu_addr)); | 2171 | /* set the wb address whether it's enabled or not */ |
2172 | WREG32(CP_RB_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); | ||
2173 | WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); | ||
2174 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); | ||
2175 | |||
2176 | if (rdev->wb.enabled) | ||
2177 | WREG32(SCRATCH_UMSK, 0xff); | ||
2178 | else { | ||
2179 | tmp |= RB_NO_UPDATE; | ||
2180 | WREG32(SCRATCH_UMSK, 0); | ||
2181 | } | ||
2182 | |||
2171 | mdelay(1); | 2183 | mdelay(1); |
2172 | WREG32(CP_RB_CNTL, tmp); | 2184 | WREG32(CP_RB_CNTL, tmp); |
2173 | 2185 | ||
@@ -2219,9 +2231,10 @@ void r600_scratch_init(struct radeon_device *rdev) | |||
2219 | int i; | 2231 | int i; |
2220 | 2232 | ||
2221 | rdev->scratch.num_reg = 7; | 2233 | rdev->scratch.num_reg = 7; |
2234 | rdev->scratch.reg_base = SCRATCH_REG0; | ||
2222 | for (i = 0; i < rdev->scratch.num_reg; i++) { | 2235 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
2223 | rdev->scratch.free[i] = true; | 2236 | rdev->scratch.free[i] = true; |
2224 | rdev->scratch.reg[i] = SCRATCH_REG0 + (i * 4); | 2237 | rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); |
2225 | } | 2238 | } |
2226 | } | 2239 | } |
2227 | 2240 | ||
@@ -2265,88 +2278,34 @@ int r600_ring_test(struct radeon_device *rdev) | |||
2265 | return r; | 2278 | return r; |
2266 | } | 2279 | } |
2267 | 2280 | ||
2268 | void r600_wb_disable(struct radeon_device *rdev) | ||
2269 | { | ||
2270 | int r; | ||
2271 | |||
2272 | WREG32(SCRATCH_UMSK, 0); | ||
2273 | if (rdev->wb.wb_obj) { | ||
2274 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
2275 | if (unlikely(r != 0)) | ||
2276 | return; | ||
2277 | radeon_bo_kunmap(rdev->wb.wb_obj); | ||
2278 | radeon_bo_unpin(rdev->wb.wb_obj); | ||
2279 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
2280 | } | ||
2281 | } | ||
2282 | |||
2283 | void r600_wb_fini(struct radeon_device *rdev) | ||
2284 | { | ||
2285 | r600_wb_disable(rdev); | ||
2286 | if (rdev->wb.wb_obj) { | ||
2287 | radeon_bo_unref(&rdev->wb.wb_obj); | ||
2288 | rdev->wb.wb = NULL; | ||
2289 | rdev->wb.wb_obj = NULL; | ||
2290 | } | ||
2291 | } | ||
2292 | |||
2293 | int r600_wb_enable(struct radeon_device *rdev) | ||
2294 | { | ||
2295 | int r; | ||
2296 | |||
2297 | if (rdev->wb.wb_obj == NULL) { | ||
2298 | r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, | ||
2299 | RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); | ||
2300 | if (r) { | ||
2301 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); | ||
2302 | return r; | ||
2303 | } | ||
2304 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
2305 | if (unlikely(r != 0)) { | ||
2306 | r600_wb_fini(rdev); | ||
2307 | return r; | ||
2308 | } | ||
2309 | r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, | ||
2310 | &rdev->wb.gpu_addr); | ||
2311 | if (r) { | ||
2312 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
2313 | dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); | ||
2314 | r600_wb_fini(rdev); | ||
2315 | return r; | ||
2316 | } | ||
2317 | r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | ||
2318 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
2319 | if (r) { | ||
2320 | dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); | ||
2321 | r600_wb_fini(rdev); | ||
2322 | return r; | ||
2323 | } | ||
2324 | } | ||
2325 | WREG32(SCRATCH_ADDR, (rdev->wb.gpu_addr >> 8) & 0xFFFFFFFF); | ||
2326 | WREG32(CP_RB_RPTR_ADDR, (rdev->wb.gpu_addr + 1024) & 0xFFFFFFFC); | ||
2327 | WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + 1024) & 0xFF); | ||
2328 | WREG32(SCRATCH_UMSK, 0xff); | ||
2329 | return 0; | ||
2330 | } | ||
2331 | |||
2332 | void r600_fence_ring_emit(struct radeon_device *rdev, | 2281 | void r600_fence_ring_emit(struct radeon_device *rdev, |
2333 | struct radeon_fence *fence) | 2282 | struct radeon_fence *fence) |
2334 | { | 2283 | { |
2335 | /* Also consider EVENT_WRITE_EOP. it handles the interrupts + timestamps + events */ | 2284 | if (rdev->wb.use_event) { |
2336 | 2285 | u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET + | |
2337 | radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0)); | 2286 | (u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base); |
2338 | radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT); | 2287 | /* EVENT_WRITE_EOP - flush caches, send int */ |
2339 | /* wait for 3D idle clean */ | 2288 | radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); |
2340 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 2289 | radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); |
2341 | radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); | 2290 | radeon_ring_write(rdev, addr & 0xffffffff); |
2342 | radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); | 2291 | radeon_ring_write(rdev, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); |
2343 | /* Emit fence sequence & fire IRQ */ | 2292 | radeon_ring_write(rdev, fence->seq); |
2344 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 2293 | radeon_ring_write(rdev, 0); |
2345 | radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | 2294 | } else { |
2346 | radeon_ring_write(rdev, fence->seq); | 2295 | radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0)); |
2347 | /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ | 2296 | radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); |
2348 | radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); | 2297 | /* wait for 3D idle clean */ |
2349 | radeon_ring_write(rdev, RB_INT_STAT); | 2298 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); |
2299 | radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); | ||
2300 | radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); | ||
2301 | /* Emit fence sequence & fire IRQ */ | ||
2302 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
2303 | radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | ||
2304 | radeon_ring_write(rdev, fence->seq); | ||
2305 | /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ | ||
2306 | radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); | ||
2307 | radeon_ring_write(rdev, RB_INT_STAT); | ||
2308 | } | ||
2350 | } | 2309 | } |
2351 | 2310 | ||
2352 | int r600_copy_blit(struct radeon_device *rdev, | 2311 | int r600_copy_blit(struct radeon_device *rdev, |
@@ -2428,19 +2387,12 @@ int r600_startup(struct radeon_device *rdev) | |||
2428 | rdev->asic->copy = NULL; | 2387 | rdev->asic->copy = NULL; |
2429 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); | 2388 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); |
2430 | } | 2389 | } |
2431 | /* pin copy shader into vram */ | 2390 | |
2432 | if (rdev->r600_blit.shader_obj) { | 2391 | /* allocate wb buffer */ |
2433 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 2392 | r = radeon_wb_init(rdev); |
2434 | if (unlikely(r != 0)) | 2393 | if (r) |
2435 | return r; | 2394 | return r; |
2436 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | 2395 | |
2437 | &rdev->r600_blit.shader_gpu_addr); | ||
2438 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
2439 | if (r) { | ||
2440 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
2441 | return r; | ||
2442 | } | ||
2443 | } | ||
2444 | /* Enable IRQ */ | 2396 | /* Enable IRQ */ |
2445 | r = r600_irq_init(rdev); | 2397 | r = r600_irq_init(rdev); |
2446 | if (r) { | 2398 | if (r) { |
@@ -2459,8 +2411,7 @@ int r600_startup(struct radeon_device *rdev) | |||
2459 | r = r600_cp_resume(rdev); | 2411 | r = r600_cp_resume(rdev); |
2460 | if (r) | 2412 | if (r) |
2461 | return r; | 2413 | return r; |
2462 | /* write back buffer are not vital so don't worry about failure */ | 2414 | |
2463 | r600_wb_enable(rdev); | ||
2464 | return 0; | 2415 | return 0; |
2465 | } | 2416 | } |
2466 | 2417 | ||
@@ -2519,7 +2470,7 @@ int r600_suspend(struct radeon_device *rdev) | |||
2519 | r600_cp_stop(rdev); | 2470 | r600_cp_stop(rdev); |
2520 | rdev->cp.ready = false; | 2471 | rdev->cp.ready = false; |
2521 | r600_irq_suspend(rdev); | 2472 | r600_irq_suspend(rdev); |
2522 | r600_wb_disable(rdev); | 2473 | radeon_wb_disable(rdev); |
2523 | r600_pcie_gart_disable(rdev); | 2474 | r600_pcie_gart_disable(rdev); |
2524 | /* unpin shaders bo */ | 2475 | /* unpin shaders bo */ |
2525 | if (rdev->r600_blit.shader_obj) { | 2476 | if (rdev->r600_blit.shader_obj) { |
@@ -2616,8 +2567,8 @@ int r600_init(struct radeon_device *rdev) | |||
2616 | if (r) { | 2567 | if (r) { |
2617 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 2568 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
2618 | r600_cp_fini(rdev); | 2569 | r600_cp_fini(rdev); |
2619 | r600_wb_fini(rdev); | ||
2620 | r600_irq_fini(rdev); | 2570 | r600_irq_fini(rdev); |
2571 | radeon_wb_fini(rdev); | ||
2621 | radeon_irq_kms_fini(rdev); | 2572 | radeon_irq_kms_fini(rdev); |
2622 | r600_pcie_gart_fini(rdev); | 2573 | r600_pcie_gart_fini(rdev); |
2623 | rdev->accel_working = false; | 2574 | rdev->accel_working = false; |
@@ -2647,8 +2598,8 @@ void r600_fini(struct radeon_device *rdev) | |||
2647 | r600_audio_fini(rdev); | 2598 | r600_audio_fini(rdev); |
2648 | r600_blit_fini(rdev); | 2599 | r600_blit_fini(rdev); |
2649 | r600_cp_fini(rdev); | 2600 | r600_cp_fini(rdev); |
2650 | r600_wb_fini(rdev); | ||
2651 | r600_irq_fini(rdev); | 2601 | r600_irq_fini(rdev); |
2602 | radeon_wb_fini(rdev); | ||
2652 | radeon_irq_kms_fini(rdev); | 2603 | radeon_irq_kms_fini(rdev); |
2653 | r600_pcie_gart_fini(rdev); | 2604 | r600_pcie_gart_fini(rdev); |
2654 | radeon_agp_fini(rdev); | 2605 | radeon_agp_fini(rdev); |
@@ -2983,10 +2934,13 @@ int r600_irq_init(struct radeon_device *rdev) | |||
2983 | ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | | 2934 | ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | |
2984 | IH_WPTR_OVERFLOW_CLEAR | | 2935 | IH_WPTR_OVERFLOW_CLEAR | |
2985 | (rb_bufsz << 1)); | 2936 | (rb_bufsz << 1)); |
2986 | /* WPTR writeback, not yet */ | 2937 | |
2987 | /*ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;*/ | 2938 | if (rdev->wb.enabled) |
2988 | WREG32(IH_RB_WPTR_ADDR_LO, 0); | 2939 | ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; |
2989 | WREG32(IH_RB_WPTR_ADDR_HI, 0); | 2940 | |
2941 | /* set the writeback address whether it's enabled or not */ | ||
2942 | WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); | ||
2943 | WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); | ||
2990 | 2944 | ||
2991 | WREG32(IH_RB_CNTL, ih_rb_cntl); | 2945 | WREG32(IH_RB_CNTL, ih_rb_cntl); |
2992 | 2946 | ||
@@ -3070,6 +3024,7 @@ int r600_irq_set(struct radeon_device *rdev) | |||
3070 | if (rdev->irq.sw_int) { | 3024 | if (rdev->irq.sw_int) { |
3071 | DRM_DEBUG("r600_irq_set: sw int\n"); | 3025 | DRM_DEBUG("r600_irq_set: sw int\n"); |
3072 | cp_int_cntl |= RB_INT_ENABLE; | 3026 | cp_int_cntl |= RB_INT_ENABLE; |
3027 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | ||
3073 | } | 3028 | } |
3074 | if (rdev->irq.crtc_vblank_int[0]) { | 3029 | if (rdev->irq.crtc_vblank_int[0]) { |
3075 | DRM_DEBUG("r600_irq_set: vblank 0\n"); | 3030 | DRM_DEBUG("r600_irq_set: vblank 0\n"); |
@@ -3244,8 +3199,10 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) | |||
3244 | { | 3199 | { |
3245 | u32 wptr, tmp; | 3200 | u32 wptr, tmp; |
3246 | 3201 | ||
3247 | /* XXX use writeback */ | 3202 | if (rdev->wb.enabled) |
3248 | wptr = RREG32(IH_RB_WPTR); | 3203 | wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]; |
3204 | else | ||
3205 | wptr = RREG32(IH_RB_WPTR); | ||
3249 | 3206 | ||
3250 | if (wptr & RB_OVERFLOW) { | 3207 | if (wptr & RB_OVERFLOW) { |
3251 | /* When a ring buffer overflow happen start parsing interrupt | 3208 | /* When a ring buffer overflow happen start parsing interrupt |
@@ -3433,6 +3390,7 @@ restart_ih: | |||
3433 | break; | 3390 | break; |
3434 | case 181: /* CP EOP event */ | 3391 | case 181: /* CP EOP event */ |
3435 | DRM_DEBUG("IH: CP EOP\n"); | 3392 | DRM_DEBUG("IH: CP EOP\n"); |
3393 | radeon_fence_process(rdev); | ||
3436 | break; | 3394 | break; |
3437 | case 233: /* GUI IDLE */ | 3395 | case 233: /* GUI IDLE */ |
3438 | DRM_DEBUG("IH: CP EOP\n"); | 3396 | DRM_DEBUG("IH: CP EOP\n"); |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 3473c00781ff..8362974ef41a 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -472,9 +472,10 @@ int r600_blit_init(struct radeon_device *rdev) | |||
472 | u32 packet2s[16]; | 472 | u32 packet2s[16]; |
473 | int num_packet2s = 0; | 473 | int num_packet2s = 0; |
474 | 474 | ||
475 | /* don't reinitialize blit */ | 475 | /* pin copy shader into vram if already initialized */ |
476 | if (rdev->r600_blit.shader_obj) | 476 | if (rdev->r600_blit.shader_obj) |
477 | return 0; | 477 | goto done; |
478 | |||
478 | mutex_init(&rdev->r600_blit.mutex); | 479 | mutex_init(&rdev->r600_blit.mutex); |
479 | rdev->r600_blit.state_offset = 0; | 480 | rdev->r600_blit.state_offset = 0; |
480 | 481 | ||
@@ -532,6 +533,18 @@ int r600_blit_init(struct radeon_device *rdev) | |||
532 | memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); | 533 | memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); |
533 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | 534 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); |
534 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 535 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
536 | |||
537 | done: | ||
538 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
539 | if (unlikely(r != 0)) | ||
540 | return r; | ||
541 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
542 | &rdev->r600_blit.shader_gpu_addr); | ||
543 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
544 | if (r) { | ||
545 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
546 | return r; | ||
547 | } | ||
535 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; | 548 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; |
536 | return 0; | 549 | return 0; |
537 | } | 550 | } |
@@ -554,7 +567,7 @@ void r600_blit_fini(struct radeon_device *rdev) | |||
554 | radeon_bo_unref(&rdev->r600_blit.shader_obj); | 567 | radeon_bo_unref(&rdev->r600_blit.shader_obj); |
555 | } | 568 | } |
556 | 569 | ||
557 | int r600_vb_ib_get(struct radeon_device *rdev) | 570 | static int r600_vb_ib_get(struct radeon_device *rdev) |
558 | { | 571 | { |
559 | int r; | 572 | int r; |
560 | r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib); | 573 | r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib); |
@@ -568,7 +581,7 @@ int r600_vb_ib_get(struct radeon_device *rdev) | |||
568 | return 0; | 581 | return 0; |
569 | } | 582 | } |
570 | 583 | ||
571 | void r600_vb_ib_put(struct radeon_device *rdev) | 584 | static void r600_vb_ib_put(struct radeon_device *rdev) |
572 | { | 585 | { |
573 | radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence); | 586 | radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence); |
574 | radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); | 587 | radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); |
@@ -650,8 +663,8 @@ void r600_kms_blit_copy(struct radeon_device *rdev, | |||
650 | int src_x = src_gpu_addr & 255; | 663 | int src_x = src_gpu_addr & 255; |
651 | int dst_x = dst_gpu_addr & 255; | 664 | int dst_x = dst_gpu_addr & 255; |
652 | int h = 1; | 665 | int h = 1; |
653 | src_gpu_addr = src_gpu_addr & ~255; | 666 | src_gpu_addr = src_gpu_addr & ~255ULL; |
654 | dst_gpu_addr = dst_gpu_addr & ~255; | 667 | dst_gpu_addr = dst_gpu_addr & ~255ULL; |
655 | 668 | ||
656 | if (!src_x && !dst_x) { | 669 | if (!src_x && !dst_x) { |
657 | h = (cur_size / max_bytes); | 670 | h = (cur_size / max_bytes); |
@@ -672,17 +685,6 @@ void r600_kms_blit_copy(struct radeon_device *rdev, | |||
672 | 685 | ||
673 | if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) { | 686 | if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) { |
674 | WARN_ON(1); | 687 | WARN_ON(1); |
675 | |||
676 | #if 0 | ||
677 | r600_vb_ib_put(rdev); | ||
678 | |||
679 | r600_nomm_put_vb(dev); | ||
680 | r600_nomm_get_vb(dev); | ||
681 | if (!dev_priv->blit_vb) | ||
682 | return; | ||
683 | set_shaders(dev); | ||
684 | vb = r600_nomm_get_vb_ptr(dev); | ||
685 | #endif | ||
686 | } | 688 | } |
687 | 689 | ||
688 | vb[0] = i2f(dst_x); | 690 | vb[0] = i2f(dst_x); |
@@ -744,8 +746,8 @@ void r600_kms_blit_copy(struct radeon_device *rdev, | |||
744 | int src_x = (src_gpu_addr & 255); | 746 | int src_x = (src_gpu_addr & 255); |
745 | int dst_x = (dst_gpu_addr & 255); | 747 | int dst_x = (dst_gpu_addr & 255); |
746 | int h = 1; | 748 | int h = 1; |
747 | src_gpu_addr = src_gpu_addr & ~255; | 749 | src_gpu_addr = src_gpu_addr & ~255ULL; |
748 | dst_gpu_addr = dst_gpu_addr & ~255; | 750 | dst_gpu_addr = dst_gpu_addr & ~255ULL; |
749 | 751 | ||
750 | if (!src_x && !dst_x) { | 752 | if (!src_x && !dst_x) { |
751 | h = (cur_size / max_bytes); | 753 | h = (cur_size / max_bytes); |
@@ -767,17 +769,6 @@ void r600_kms_blit_copy(struct radeon_device *rdev, | |||
767 | if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) { | 769 | if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) { |
768 | WARN_ON(1); | 770 | WARN_ON(1); |
769 | } | 771 | } |
770 | #if 0 | ||
771 | if ((rdev->blit_vb->used + 48) > rdev->blit_vb->total) { | ||
772 | r600_nomm_put_vb(dev); | ||
773 | r600_nomm_get_vb(dev); | ||
774 | if (!rdev->blit_vb) | ||
775 | return; | ||
776 | |||
777 | set_shaders(dev); | ||
778 | vb = r600_nomm_get_vb_ptr(dev); | ||
779 | } | ||
780 | #endif | ||
781 | 772 | ||
782 | vb[0] = i2f(dst_x / 4); | 773 | vb[0] = i2f(dst_x / 4); |
783 | vb[1] = 0; | 774 | vb[1] = 0; |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 858a1920c0d7..966a793e225b 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -474,6 +474,7 @@ | |||
474 | #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 | 474 | #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 |
475 | #define VTX_REUSE_DEPTH_MASK 0x000000FF | 475 | #define VTX_REUSE_DEPTH_MASK 0x000000FF |
476 | #define VGT_EVENT_INITIATOR 0x28a90 | 476 | #define VGT_EVENT_INITIATOR 0x28a90 |
477 | # define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0) | ||
477 | # define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) | 478 | # define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) |
478 | 479 | ||
479 | #define VM_CONTEXT0_CNTL 0x1410 | 480 | #define VM_CONTEXT0_CNTL 0x1410 |
@@ -775,7 +776,27 @@ | |||
775 | #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) | 776 | #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) |
776 | #define PACKET3_COND_WRITE 0x45 | 777 | #define PACKET3_COND_WRITE 0x45 |
777 | #define PACKET3_EVENT_WRITE 0x46 | 778 | #define PACKET3_EVENT_WRITE 0x46 |
779 | #define EVENT_TYPE(x) ((x) << 0) | ||
780 | #define EVENT_INDEX(x) ((x) << 8) | ||
781 | /* 0 - any non-TS event | ||
782 | * 1 - ZPASS_DONE | ||
783 | * 2 - SAMPLE_PIPELINESTAT | ||
784 | * 3 - SAMPLE_STREAMOUTSTAT* | ||
785 | * 4 - *S_PARTIAL_FLUSH | ||
786 | * 5 - TS events | ||
787 | */ | ||
778 | #define PACKET3_EVENT_WRITE_EOP 0x47 | 788 | #define PACKET3_EVENT_WRITE_EOP 0x47 |
789 | #define DATA_SEL(x) ((x) << 29) | ||
790 | /* 0 - discard | ||
791 | * 1 - send low 32bit data | ||
792 | * 2 - send 64bit data | ||
793 | * 3 - send 64bit counter value | ||
794 | */ | ||
795 | #define INT_SEL(x) ((x) << 24) | ||
796 | /* 0 - none | ||
797 | * 1 - interrupt only (DATA_SEL = 0) | ||
798 | * 2 - interrupt when data write is confirmed | ||
799 | */ | ||
779 | #define PACKET3_ONE_REG_WRITE 0x57 | 800 | #define PACKET3_ONE_REG_WRITE 0x57 |
780 | #define PACKET3_SET_CONFIG_REG 0x68 | 801 | #define PACKET3_SET_CONFIG_REG 0x68 |
781 | #define PACKET3_SET_CONFIG_REG_OFFSET 0x00008000 | 802 | #define PACKET3_SET_CONFIG_REG_OFFSET 0x00008000 |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9ff38c99a6ea..73f600d39ad4 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -88,7 +88,6 @@ extern int radeon_benchmarking; | |||
88 | extern int radeon_testing; | 88 | extern int radeon_testing; |
89 | extern int radeon_connector_table; | 89 | extern int radeon_connector_table; |
90 | extern int radeon_tv; | 90 | extern int radeon_tv; |
91 | extern int radeon_new_pll; | ||
92 | extern int radeon_audio; | 91 | extern int radeon_audio; |
93 | extern int radeon_disp_priority; | 92 | extern int radeon_disp_priority; |
94 | extern int radeon_hw_i2c; | 93 | extern int radeon_hw_i2c; |
@@ -366,6 +365,7 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev); | |||
366 | */ | 365 | */ |
367 | struct radeon_scratch { | 366 | struct radeon_scratch { |
368 | unsigned num_reg; | 367 | unsigned num_reg; |
368 | uint32_t reg_base; | ||
369 | bool free[32]; | 369 | bool free[32]; |
370 | uint32_t reg[32]; | 370 | uint32_t reg[32]; |
371 | }; | 371 | }; |
@@ -594,8 +594,15 @@ struct radeon_wb { | |||
594 | struct radeon_bo *wb_obj; | 594 | struct radeon_bo *wb_obj; |
595 | volatile uint32_t *wb; | 595 | volatile uint32_t *wb; |
596 | uint64_t gpu_addr; | 596 | uint64_t gpu_addr; |
597 | bool enabled; | ||
598 | bool use_event; | ||
597 | }; | 599 | }; |
598 | 600 | ||
601 | #define RADEON_WB_SCRATCH_OFFSET 0 | ||
602 | #define RADEON_WB_CP_RPTR_OFFSET 1024 | ||
603 | #define R600_WB_IH_WPTR_OFFSET 2048 | ||
604 | #define R600_WB_EVENT_OFFSET 3072 | ||
605 | |||
599 | /** | 606 | /** |
600 | * struct radeon_pm - power management datas | 607 | * struct radeon_pm - power management datas |
601 | * @max_bandwidth: maximum bandwidth the gpu has (MByte/s) | 608 | * @max_bandwidth: maximum bandwidth the gpu has (MByte/s) |
@@ -1124,6 +1131,12 @@ void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence) | |||
1124 | void r600_kms_blit_copy(struct radeon_device *rdev, | 1131 | void r600_kms_blit_copy(struct radeon_device *rdev, |
1125 | u64 src_gpu_addr, u64 dst_gpu_addr, | 1132 | u64 src_gpu_addr, u64 dst_gpu_addr, |
1126 | int size_bytes); | 1133 | int size_bytes); |
1134 | /* evergreen blit */ | ||
1135 | int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes); | ||
1136 | void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence); | ||
1137 | void evergreen_kms_blit_copy(struct radeon_device *rdev, | ||
1138 | u64 src_gpu_addr, u64 dst_gpu_addr, | ||
1139 | int size_bytes); | ||
1127 | 1140 | ||
1128 | static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | 1141 | static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) |
1129 | { | 1142 | { |
@@ -1341,6 +1354,9 @@ extern void radeon_update_bandwidth_info(struct radeon_device *rdev); | |||
1341 | extern void radeon_update_display_priority(struct radeon_device *rdev); | 1354 | extern void radeon_update_display_priority(struct radeon_device *rdev); |
1342 | extern bool radeon_boot_test_post_card(struct radeon_device *rdev); | 1355 | extern bool radeon_boot_test_post_card(struct radeon_device *rdev); |
1343 | extern void radeon_scratch_init(struct radeon_device *rdev); | 1356 | extern void radeon_scratch_init(struct radeon_device *rdev); |
1357 | extern void radeon_wb_fini(struct radeon_device *rdev); | ||
1358 | extern int radeon_wb_init(struct radeon_device *rdev); | ||
1359 | extern void radeon_wb_disable(struct radeon_device *rdev); | ||
1344 | extern void radeon_surface_init(struct radeon_device *rdev); | 1360 | extern void radeon_surface_init(struct radeon_device *rdev); |
1345 | extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); | 1361 | extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); |
1346 | extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); | 1362 | extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); |
@@ -1425,9 +1441,6 @@ extern int r600_pcie_gart_init(struct radeon_device *rdev); | |||
1425 | extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); | 1441 | extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); |
1426 | extern int r600_ib_test(struct radeon_device *rdev); | 1442 | extern int r600_ib_test(struct radeon_device *rdev); |
1427 | extern int r600_ring_test(struct radeon_device *rdev); | 1443 | extern int r600_ring_test(struct radeon_device *rdev); |
1428 | extern void r600_wb_fini(struct radeon_device *rdev); | ||
1429 | extern int r600_wb_enable(struct radeon_device *rdev); | ||
1430 | extern void r600_wb_disable(struct radeon_device *rdev); | ||
1431 | extern void r600_scratch_init(struct radeon_device *rdev); | 1444 | extern void r600_scratch_init(struct radeon_device *rdev); |
1432 | extern int r600_blit_init(struct radeon_device *rdev); | 1445 | extern int r600_blit_init(struct radeon_device *rdev); |
1433 | extern void r600_blit_fini(struct radeon_device *rdev); | 1446 | extern void r600_blit_fini(struct radeon_device *rdev); |
@@ -1465,6 +1478,8 @@ extern void r700_cp_stop(struct radeon_device *rdev); | |||
1465 | extern void r700_cp_fini(struct radeon_device *rdev); | 1478 | extern void r700_cp_fini(struct radeon_device *rdev); |
1466 | extern void evergreen_disable_interrupt_state(struct radeon_device *rdev); | 1479 | extern void evergreen_disable_interrupt_state(struct radeon_device *rdev); |
1467 | extern int evergreen_irq_set(struct radeon_device *rdev); | 1480 | extern int evergreen_irq_set(struct radeon_device *rdev); |
1481 | extern int evergreen_blit_init(struct radeon_device *rdev); | ||
1482 | extern void evergreen_blit_fini(struct radeon_device *rdev); | ||
1468 | 1483 | ||
1469 | /* radeon_acpi.c */ | 1484 | /* radeon_acpi.c */ |
1470 | #if defined(CONFIG_ACPI) | 1485 | #if defined(CONFIG_ACPI) |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 25e1dd197791..64fb89ecbf74 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -726,9 +726,9 @@ static struct radeon_asic evergreen_asic = { | |||
726 | .get_vblank_counter = &evergreen_get_vblank_counter, | 726 | .get_vblank_counter = &evergreen_get_vblank_counter, |
727 | .fence_ring_emit = &r600_fence_ring_emit, | 727 | .fence_ring_emit = &r600_fence_ring_emit, |
728 | .cs_parse = &evergreen_cs_parse, | 728 | .cs_parse = &evergreen_cs_parse, |
729 | .copy_blit = NULL, | 729 | .copy_blit = &evergreen_copy_blit, |
730 | .copy_dma = NULL, | 730 | .copy_dma = &evergreen_copy_blit, |
731 | .copy = NULL, | 731 | .copy = &evergreen_copy_blit, |
732 | .get_engine_clock = &radeon_atom_get_engine_clock, | 732 | .get_engine_clock = &radeon_atom_get_engine_clock, |
733 | .set_engine_clock = &radeon_atom_set_engine_clock, | 733 | .set_engine_clock = &radeon_atom_set_engine_clock, |
734 | .get_memory_clock = &radeon_atom_get_memory_clock, | 734 | .get_memory_clock = &radeon_atom_get_memory_clock, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index a5aff755f0d2..740988244143 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -108,9 +108,6 @@ void r100_irq_disable(struct radeon_device *rdev); | |||
108 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); | 108 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); |
109 | void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save); | 109 | void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save); |
110 | void r100_vram_init_sizes(struct radeon_device *rdev); | 110 | void r100_vram_init_sizes(struct radeon_device *rdev); |
111 | void r100_wb_disable(struct radeon_device *rdev); | ||
112 | void r100_wb_fini(struct radeon_device *rdev); | ||
113 | int r100_wb_init(struct radeon_device *rdev); | ||
114 | int r100_cp_reset(struct radeon_device *rdev); | 111 | int r100_cp_reset(struct radeon_device *rdev); |
115 | void r100_vga_render_disable(struct radeon_device *rdev); | 112 | void r100_vga_render_disable(struct radeon_device *rdev); |
116 | void r100_restore_sanity(struct radeon_device *rdev); | 113 | void r100_restore_sanity(struct radeon_device *rdev); |
@@ -257,11 +254,6 @@ void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | |||
257 | int r600_cs_parse(struct radeon_cs_parser *p); | 254 | int r600_cs_parse(struct radeon_cs_parser *p); |
258 | void r600_fence_ring_emit(struct radeon_device *rdev, | 255 | void r600_fence_ring_emit(struct radeon_device *rdev, |
259 | struct radeon_fence *fence); | 256 | struct radeon_fence *fence); |
260 | int r600_copy_dma(struct radeon_device *rdev, | ||
261 | uint64_t src_offset, | ||
262 | uint64_t dst_offset, | ||
263 | unsigned num_pages, | ||
264 | struct radeon_fence *fence); | ||
265 | int r600_irq_process(struct radeon_device *rdev); | 257 | int r600_irq_process(struct radeon_device *rdev); |
266 | int r600_irq_set(struct radeon_device *rdev); | 258 | int r600_irq_set(struct radeon_device *rdev); |
267 | bool r600_gpu_is_lockup(struct radeon_device *rdev); | 259 | bool r600_gpu_is_lockup(struct radeon_device *rdev); |
@@ -307,6 +299,9 @@ int evergreen_resume(struct radeon_device *rdev); | |||
307 | bool evergreen_gpu_is_lockup(struct radeon_device *rdev); | 299 | bool evergreen_gpu_is_lockup(struct radeon_device *rdev); |
308 | int evergreen_asic_reset(struct radeon_device *rdev); | 300 | int evergreen_asic_reset(struct radeon_device *rdev); |
309 | void evergreen_bandwidth_update(struct radeon_device *rdev); | 301 | void evergreen_bandwidth_update(struct radeon_device *rdev); |
302 | int evergreen_copy_blit(struct radeon_device *rdev, | ||
303 | uint64_t src_offset, uint64_t dst_offset, | ||
304 | unsigned num_pages, struct radeon_fence *fence); | ||
310 | void evergreen_hpd_init(struct radeon_device *rdev); | 305 | void evergreen_hpd_init(struct radeon_device *rdev); |
311 | void evergreen_hpd_fini(struct radeon_device *rdev); | 306 | void evergreen_hpd_fini(struct radeon_device *rdev); |
312 | bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); | 307 | bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 8e43ddae70cc..04cac7ec9039 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -1112,8 +1112,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
1112 | * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per | 1112 | * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per |
1113 | * family. | 1113 | * family. |
1114 | */ | 1114 | */ |
1115 | if (!radeon_new_pll) | 1115 | p1pll->pll_out_min = 64800; |
1116 | p1pll->pll_out_min = 64800; | ||
1117 | } | 1116 | } |
1118 | 1117 | ||
1119 | p1pll->pll_in_min = | 1118 | p1pll->pll_in_min = |
@@ -1277,36 +1276,27 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, | |||
1277 | return false; | 1276 | return false; |
1278 | } | 1277 | } |
1279 | 1278 | ||
1280 | static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | 1279 | bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, |
1281 | radeon_encoder | 1280 | struct radeon_atom_ss *ss, |
1282 | *encoder, | 1281 | int id) |
1283 | int id) | ||
1284 | { | 1282 | { |
1285 | struct drm_device *dev = encoder->base.dev; | ||
1286 | struct radeon_device *rdev = dev->dev_private; | ||
1287 | struct radeon_mode_info *mode_info = &rdev->mode_info; | 1283 | struct radeon_mode_info *mode_info = &rdev->mode_info; |
1288 | int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); | 1284 | int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); |
1289 | uint16_t data_offset; | 1285 | uint16_t data_offset, size; |
1290 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; | 1286 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; |
1291 | uint8_t frev, crev; | 1287 | uint8_t frev, crev; |
1292 | struct radeon_atom_ss *ss = NULL; | 1288 | int i, num_indices; |
1293 | int i; | ||
1294 | |||
1295 | if (id > ATOM_MAX_SS_ENTRY) | ||
1296 | return NULL; | ||
1297 | 1289 | ||
1298 | if (atom_parse_data_header(mode_info->atom_context, index, NULL, | 1290 | memset(ss, 0, sizeof(struct radeon_atom_ss)); |
1291 | if (atom_parse_data_header(mode_info->atom_context, index, &size, | ||
1299 | &frev, &crev, &data_offset)) { | 1292 | &frev, &crev, &data_offset)) { |
1300 | ss_info = | 1293 | ss_info = |
1301 | (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); | 1294 | (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); |
1302 | 1295 | ||
1303 | ss = | 1296 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / |
1304 | kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL); | 1297 | sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); |
1305 | |||
1306 | if (!ss) | ||
1307 | return NULL; | ||
1308 | 1298 | ||
1309 | for (i = 0; i < ATOM_MAX_SS_ENTRY; i++) { | 1299 | for (i = 0; i < num_indices; i++) { |
1310 | if (ss_info->asSS_Info[i].ucSS_Id == id) { | 1300 | if (ss_info->asSS_Info[i].ucSS_Id == id) { |
1311 | ss->percentage = | 1301 | ss->percentage = |
1312 | le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); | 1302 | le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); |
@@ -1315,11 +1305,88 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | |||
1315 | ss->delay = ss_info->asSS_Info[i].ucSS_Delay; | 1305 | ss->delay = ss_info->asSS_Info[i].ucSS_Delay; |
1316 | ss->range = ss_info->asSS_Info[i].ucSS_Range; | 1306 | ss->range = ss_info->asSS_Info[i].ucSS_Range; |
1317 | ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; | 1307 | ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; |
1318 | break; | 1308 | return true; |
1309 | } | ||
1310 | } | ||
1311 | } | ||
1312 | return false; | ||
1313 | } | ||
1314 | |||
1315 | union asic_ss_info { | ||
1316 | struct _ATOM_ASIC_INTERNAL_SS_INFO info; | ||
1317 | struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; | ||
1318 | struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3; | ||
1319 | }; | ||
1320 | |||
1321 | bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, | ||
1322 | struct radeon_atom_ss *ss, | ||
1323 | int id, u32 clock) | ||
1324 | { | ||
1325 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
1326 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
1327 | uint16_t data_offset, size; | ||
1328 | union asic_ss_info *ss_info; | ||
1329 | uint8_t frev, crev; | ||
1330 | int i, num_indices; | ||
1331 | |||
1332 | memset(ss, 0, sizeof(struct radeon_atom_ss)); | ||
1333 | if (atom_parse_data_header(mode_info->atom_context, index, &size, | ||
1334 | &frev, &crev, &data_offset)) { | ||
1335 | |||
1336 | ss_info = | ||
1337 | (union asic_ss_info *)(mode_info->atom_context->bios + data_offset); | ||
1338 | |||
1339 | switch (frev) { | ||
1340 | case 1: | ||
1341 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
1342 | sizeof(ATOM_ASIC_SS_ASSIGNMENT); | ||
1343 | |||
1344 | for (i = 0; i < num_indices; i++) { | ||
1345 | if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) && | ||
1346 | (clock <= ss_info->info.asSpreadSpectrum[i].ulTargetClockRange)) { | ||
1347 | ss->percentage = | ||
1348 | le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | ||
1349 | ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode; | ||
1350 | ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz); | ||
1351 | return true; | ||
1352 | } | ||
1353 | } | ||
1354 | break; | ||
1355 | case 2: | ||
1356 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
1357 | sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); | ||
1358 | for (i = 0; i < num_indices; i++) { | ||
1359 | if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) && | ||
1360 | (clock <= ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange)) { | ||
1361 | ss->percentage = | ||
1362 | le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | ||
1363 | ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode; | ||
1364 | ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz); | ||
1365 | return true; | ||
1366 | } | ||
1319 | } | 1367 | } |
1368 | break; | ||
1369 | case 3: | ||
1370 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
1371 | sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); | ||
1372 | for (i = 0; i < num_indices; i++) { | ||
1373 | if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) && | ||
1374 | (clock <= ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange)) { | ||
1375 | ss->percentage = | ||
1376 | le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | ||
1377 | ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; | ||
1378 | ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); | ||
1379 | return true; | ||
1380 | } | ||
1381 | } | ||
1382 | break; | ||
1383 | default: | ||
1384 | DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev); | ||
1385 | break; | ||
1320 | } | 1386 | } |
1387 | |||
1321 | } | 1388 | } |
1322 | return ss; | 1389 | return false; |
1323 | } | 1390 | } |
1324 | 1391 | ||
1325 | union lvds_info { | 1392 | union lvds_info { |
@@ -1371,7 +1438,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
1371 | le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); | 1438 | le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); |
1372 | lvds->panel_pwr_delay = | 1439 | lvds->panel_pwr_delay = |
1373 | le16_to_cpu(lvds_info->info.usOffDelayInMs); | 1440 | le16_to_cpu(lvds_info->info.usOffDelayInMs); |
1374 | lvds->lvds_misc = lvds_info->info.ucLVDS_Misc; | 1441 | lvds->lcd_misc = lvds_info->info.ucLVDS_Misc; |
1375 | 1442 | ||
1376 | misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); | 1443 | misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); |
1377 | if (misc & ATOM_VSYNC_POLARITY) | 1444 | if (misc & ATOM_VSYNC_POLARITY) |
@@ -1388,19 +1455,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
1388 | /* set crtc values */ | 1455 | /* set crtc values */ |
1389 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); | 1456 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); |
1390 | 1457 | ||
1391 | lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id); | 1458 | lvds->lcd_ss_id = lvds_info->info.ucSS_Id; |
1392 | |||
1393 | if (ASIC_IS_AVIVO(rdev)) { | ||
1394 | if (radeon_new_pll == 0) | ||
1395 | lvds->pll_algo = PLL_ALGO_LEGACY; | ||
1396 | else | ||
1397 | lvds->pll_algo = PLL_ALGO_NEW; | ||
1398 | } else { | ||
1399 | if (radeon_new_pll == 1) | ||
1400 | lvds->pll_algo = PLL_ALGO_NEW; | ||
1401 | else | ||
1402 | lvds->pll_algo = PLL_ALGO_LEGACY; | ||
1403 | } | ||
1404 | 1459 | ||
1405 | encoder->native_mode = lvds->native_mode; | 1460 | encoder->native_mode = lvds->native_mode; |
1406 | 1461 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ecc1a8fafbfd..64c3ddf02167 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -326,6 +326,34 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr | |||
326 | } | 326 | } |
327 | } | 327 | } |
328 | 328 | ||
329 | if (property == rdev->mode_info.underscan_hborder_property) { | ||
330 | /* need to find digital encoder on connector */ | ||
331 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); | ||
332 | if (!encoder) | ||
333 | return 0; | ||
334 | |||
335 | radeon_encoder = to_radeon_encoder(encoder); | ||
336 | |||
337 | if (radeon_encoder->underscan_hborder != val) { | ||
338 | radeon_encoder->underscan_hborder = val; | ||
339 | radeon_property_change_mode(&radeon_encoder->base); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | if (property == rdev->mode_info.underscan_vborder_property) { | ||
344 | /* need to find digital encoder on connector */ | ||
345 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); | ||
346 | if (!encoder) | ||
347 | return 0; | ||
348 | |||
349 | radeon_encoder = to_radeon_encoder(encoder); | ||
350 | |||
351 | if (radeon_encoder->underscan_vborder != val) { | ||
352 | radeon_encoder->underscan_vborder = val; | ||
353 | radeon_property_change_mode(&radeon_encoder->base); | ||
354 | } | ||
355 | } | ||
356 | |||
329 | if (property == rdev->mode_info.tv_std_property) { | 357 | if (property == rdev->mode_info.tv_std_property) { |
330 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); | 358 | encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); |
331 | if (!encoder) { | 359 | if (!encoder) { |
@@ -1153,10 +1181,17 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1153 | drm_connector_attach_property(&radeon_connector->base, | 1181 | drm_connector_attach_property(&radeon_connector->base, |
1154 | rdev->mode_info.coherent_mode_property, | 1182 | rdev->mode_info.coherent_mode_property, |
1155 | 1); | 1183 | 1); |
1156 | if (ASIC_IS_AVIVO(rdev)) | 1184 | if (ASIC_IS_AVIVO(rdev)) { |
1157 | drm_connector_attach_property(&radeon_connector->base, | 1185 | drm_connector_attach_property(&radeon_connector->base, |
1158 | rdev->mode_info.underscan_property, | 1186 | rdev->mode_info.underscan_property, |
1159 | UNDERSCAN_AUTO); | 1187 | UNDERSCAN_AUTO); |
1188 | drm_connector_attach_property(&radeon_connector->base, | ||
1189 | rdev->mode_info.underscan_hborder_property, | ||
1190 | 0); | ||
1191 | drm_connector_attach_property(&radeon_connector->base, | ||
1192 | rdev->mode_info.underscan_vborder_property, | ||
1193 | 0); | ||
1194 | } | ||
1160 | if (connector_type == DRM_MODE_CONNECTOR_DVII) { | 1195 | if (connector_type == DRM_MODE_CONNECTOR_DVII) { |
1161 | radeon_connector->dac_load_detect = true; | 1196 | radeon_connector->dac_load_detect = true; |
1162 | drm_connector_attach_property(&radeon_connector->base, | 1197 | drm_connector_attach_property(&radeon_connector->base, |
@@ -1181,10 +1216,17 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1181 | drm_connector_attach_property(&radeon_connector->base, | 1216 | drm_connector_attach_property(&radeon_connector->base, |
1182 | rdev->mode_info.coherent_mode_property, | 1217 | rdev->mode_info.coherent_mode_property, |
1183 | 1); | 1218 | 1); |
1184 | if (ASIC_IS_AVIVO(rdev)) | 1219 | if (ASIC_IS_AVIVO(rdev)) { |
1185 | drm_connector_attach_property(&radeon_connector->base, | 1220 | drm_connector_attach_property(&radeon_connector->base, |
1186 | rdev->mode_info.underscan_property, | 1221 | rdev->mode_info.underscan_property, |
1187 | UNDERSCAN_AUTO); | 1222 | UNDERSCAN_AUTO); |
1223 | drm_connector_attach_property(&radeon_connector->base, | ||
1224 | rdev->mode_info.underscan_hborder_property, | ||
1225 | 0); | ||
1226 | drm_connector_attach_property(&radeon_connector->base, | ||
1227 | rdev->mode_info.underscan_vborder_property, | ||
1228 | 0); | ||
1229 | } | ||
1188 | subpixel_order = SubPixelHorizontalRGB; | 1230 | subpixel_order = SubPixelHorizontalRGB; |
1189 | break; | 1231 | break; |
1190 | case DRM_MODE_CONNECTOR_DisplayPort: | 1232 | case DRM_MODE_CONNECTOR_DisplayPort: |
@@ -1212,10 +1254,17 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1212 | drm_connector_attach_property(&radeon_connector->base, | 1254 | drm_connector_attach_property(&radeon_connector->base, |
1213 | rdev->mode_info.coherent_mode_property, | 1255 | rdev->mode_info.coherent_mode_property, |
1214 | 1); | 1256 | 1); |
1215 | if (ASIC_IS_AVIVO(rdev)) | 1257 | if (ASIC_IS_AVIVO(rdev)) { |
1216 | drm_connector_attach_property(&radeon_connector->base, | 1258 | drm_connector_attach_property(&radeon_connector->base, |
1217 | rdev->mode_info.underscan_property, | 1259 | rdev->mode_info.underscan_property, |
1218 | UNDERSCAN_AUTO); | 1260 | UNDERSCAN_AUTO); |
1261 | drm_connector_attach_property(&radeon_connector->base, | ||
1262 | rdev->mode_info.underscan_hborder_property, | ||
1263 | 0); | ||
1264 | drm_connector_attach_property(&radeon_connector->base, | ||
1265 | rdev->mode_info.underscan_vborder_property, | ||
1266 | 0); | ||
1267 | } | ||
1219 | break; | 1268 | break; |
1220 | case DRM_MODE_CONNECTOR_SVIDEO: | 1269 | case DRM_MODE_CONNECTOR_SVIDEO: |
1221 | case DRM_MODE_CONNECTOR_Composite: | 1270 | case DRM_MODE_CONNECTOR_Composite: |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 3eef567b0421..017ac54920fb 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
@@ -118,22 +118,25 @@ static void radeon_show_cursor(struct drm_crtc *crtc) | |||
118 | } | 118 | } |
119 | 119 | ||
120 | static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, | 120 | static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, |
121 | uint32_t gpu_addr) | 121 | uint64_t gpu_addr) |
122 | { | 122 | { |
123 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 123 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
124 | struct radeon_device *rdev = crtc->dev->dev_private; | 124 | struct radeon_device *rdev = crtc->dev->dev_private; |
125 | 125 | ||
126 | if (ASIC_IS_DCE4(rdev)) { | 126 | if (ASIC_IS_DCE4(rdev)) { |
127 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 0); | 127 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, |
128 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); | 128 | upper_32_bits(gpu_addr)); |
129 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
130 | gpu_addr & 0xffffffff); | ||
129 | } else if (ASIC_IS_AVIVO(rdev)) { | 131 | } else if (ASIC_IS_AVIVO(rdev)) { |
130 | if (rdev->family >= CHIP_RV770) { | 132 | if (rdev->family >= CHIP_RV770) { |
131 | if (radeon_crtc->crtc_id) | 133 | if (radeon_crtc->crtc_id) |
132 | WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, 0); | 134 | WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); |
133 | else | 135 | else |
134 | WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0); | 136 | WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); |
135 | } | 137 | } |
136 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); | 138 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, |
139 | gpu_addr & 0xffffffff); | ||
137 | } else { | 140 | } else { |
138 | radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; | 141 | radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; |
139 | /* offset is from DISP(2)_BASE_ADDRESS */ | 142 | /* offset is from DISP(2)_BASE_ADDRESS */ |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 256d204a6d24..8adfedfe547f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -117,9 +117,10 @@ void radeon_scratch_init(struct radeon_device *rdev) | |||
117 | } else { | 117 | } else { |
118 | rdev->scratch.num_reg = 7; | 118 | rdev->scratch.num_reg = 7; |
119 | } | 119 | } |
120 | rdev->scratch.reg_base = RADEON_SCRATCH_REG0; | ||
120 | for (i = 0; i < rdev->scratch.num_reg; i++) { | 121 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
121 | rdev->scratch.free[i] = true; | 122 | rdev->scratch.free[i] = true; |
122 | rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4); | 123 | rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); |
123 | } | 124 | } |
124 | } | 125 | } |
125 | 126 | ||
@@ -149,6 +150,86 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | |||
149 | } | 150 | } |
150 | } | 151 | } |
151 | 152 | ||
153 | void radeon_wb_disable(struct radeon_device *rdev) | ||
154 | { | ||
155 | int r; | ||
156 | |||
157 | if (rdev->wb.wb_obj) { | ||
158 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
159 | if (unlikely(r != 0)) | ||
160 | return; | ||
161 | radeon_bo_kunmap(rdev->wb.wb_obj); | ||
162 | radeon_bo_unpin(rdev->wb.wb_obj); | ||
163 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
164 | } | ||
165 | rdev->wb.enabled = false; | ||
166 | } | ||
167 | |||
168 | void radeon_wb_fini(struct radeon_device *rdev) | ||
169 | { | ||
170 | radeon_wb_disable(rdev); | ||
171 | if (rdev->wb.wb_obj) { | ||
172 | radeon_bo_unref(&rdev->wb.wb_obj); | ||
173 | rdev->wb.wb = NULL; | ||
174 | rdev->wb.wb_obj = NULL; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | int radeon_wb_init(struct radeon_device *rdev) | ||
179 | { | ||
180 | int r; | ||
181 | |||
182 | if (rdev->wb.wb_obj == NULL) { | ||
183 | r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, | ||
184 | RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); | ||
185 | if (r) { | ||
186 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); | ||
187 | return r; | ||
188 | } | ||
189 | } | ||
190 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
191 | if (unlikely(r != 0)) { | ||
192 | radeon_wb_fini(rdev); | ||
193 | return r; | ||
194 | } | ||
195 | r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, | ||
196 | &rdev->wb.gpu_addr); | ||
197 | if (r) { | ||
198 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
199 | dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); | ||
200 | radeon_wb_fini(rdev); | ||
201 | return r; | ||
202 | } | ||
203 | r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | ||
204 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
205 | if (r) { | ||
206 | dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); | ||
207 | radeon_wb_fini(rdev); | ||
208 | return r; | ||
209 | } | ||
210 | |||
211 | /* disable event_write fences */ | ||
212 | rdev->wb.use_event = false; | ||
213 | /* disabled via module param */ | ||
214 | if (radeon_no_wb == 1) | ||
215 | rdev->wb.enabled = false; | ||
216 | else { | ||
217 | /* often unreliable on AGP */ | ||
218 | if (rdev->flags & RADEON_IS_AGP) { | ||
219 | rdev->wb.enabled = false; | ||
220 | } else { | ||
221 | rdev->wb.enabled = true; | ||
222 | /* event_write fences are only available on r600+ */ | ||
223 | if (rdev->family >= CHIP_R600) | ||
224 | rdev->wb.use_event = true; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
152 | /** | 233 | /** |
153 | * radeon_vram_location - try to find VRAM location | 234 | * radeon_vram_location - try to find VRAM location |
154 | * @rdev: radeon device structure holding all necessary informations | 235 | * @rdev: radeon device structure holding all necessary informations |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b92d2f2fcbed..6c6846cdaa30 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -138,6 +138,38 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc) | |||
138 | legacy_crtc_load_lut(crtc); | 138 | legacy_crtc_load_lut(crtc); |
139 | } | 139 | } |
140 | 140 | ||
141 | void radeon_crtc_save_lut(struct drm_crtc *crtc) | ||
142 | { | ||
143 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
144 | int i; | ||
145 | |||
146 | if (!crtc->enabled) | ||
147 | return; | ||
148 | |||
149 | for (i = 0; i < 256; i++) { | ||
150 | radeon_crtc->lut_r_copy[i] = radeon_crtc->lut_r[i]; | ||
151 | radeon_crtc->lut_g_copy[i] = radeon_crtc->lut_g[i]; | ||
152 | radeon_crtc->lut_b_copy[i] = radeon_crtc->lut_b[i]; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | void radeon_crtc_restore_lut(struct drm_crtc *crtc) | ||
157 | { | ||
158 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
159 | int i; | ||
160 | |||
161 | if (!crtc->enabled) | ||
162 | return; | ||
163 | |||
164 | for (i = 0; i < 256; i++) { | ||
165 | radeon_crtc->lut_r[i] = radeon_crtc->lut_r_copy[i]; | ||
166 | radeon_crtc->lut_g[i] = radeon_crtc->lut_g_copy[i]; | ||
167 | radeon_crtc->lut_b[i] = radeon_crtc->lut_b_copy[i]; | ||
168 | } | ||
169 | |||
170 | radeon_crtc_load_lut(crtc); | ||
171 | } | ||
172 | |||
141 | /** Sets the color ramps on behalf of fbcon */ | 173 | /** Sets the color ramps on behalf of fbcon */ |
142 | void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | 174 | void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, |
143 | u16 blue, int regno) | 175 | u16 blue, int regno) |
@@ -454,13 +486,13 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d) | |||
454 | return n; | 486 | return n; |
455 | } | 487 | } |
456 | 488 | ||
457 | static void radeon_compute_pll_legacy(struct radeon_pll *pll, | 489 | void radeon_compute_pll(struct radeon_pll *pll, |
458 | uint64_t freq, | 490 | uint64_t freq, |
459 | uint32_t *dot_clock_p, | 491 | uint32_t *dot_clock_p, |
460 | uint32_t *fb_div_p, | 492 | uint32_t *fb_div_p, |
461 | uint32_t *frac_fb_div_p, | 493 | uint32_t *frac_fb_div_p, |
462 | uint32_t *ref_div_p, | 494 | uint32_t *ref_div_p, |
463 | uint32_t *post_div_p) | 495 | uint32_t *post_div_p) |
464 | { | 496 | { |
465 | uint32_t min_ref_div = pll->min_ref_div; | 497 | uint32_t min_ref_div = pll->min_ref_div; |
466 | uint32_t max_ref_div = pll->max_ref_div; | 498 | uint32_t max_ref_div = pll->max_ref_div; |
@@ -513,7 +545,7 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
513 | max_fractional_feed_div = pll->max_frac_feedback_div; | 545 | max_fractional_feed_div = pll->max_frac_feedback_div; |
514 | } | 546 | } |
515 | 547 | ||
516 | for (post_div = min_post_div; post_div <= max_post_div; ++post_div) { | 548 | for (post_div = max_post_div; post_div >= min_post_div; --post_div) { |
517 | uint32_t ref_div; | 549 | uint32_t ref_div; |
518 | 550 | ||
519 | if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) | 551 | if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) |
@@ -579,7 +611,8 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
579 | if ((best_vco == 0 && error < best_error) || | 611 | if ((best_vco == 0 && error < best_error) || |
580 | (best_vco != 0 && | 612 | (best_vco != 0 && |
581 | ((best_error > 100 && error < best_error - 100) || | 613 | ((best_error > 100 && error < best_error - 100) || |
582 | (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) { | 614 | (abs(error - best_error) < 100 && |
615 | vco_diff < best_vco_diff)))) { | ||
583 | best_post_div = post_div; | 616 | best_post_div = post_div; |
584 | best_ref_div = ref_div; | 617 | best_ref_div = ref_div; |
585 | best_feedback_div = feedback_div; | 618 | best_feedback_div = feedback_div; |
@@ -587,29 +620,6 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
587 | best_freq = current_freq; | 620 | best_freq = current_freq; |
588 | best_error = error; | 621 | best_error = error; |
589 | best_vco_diff = vco_diff; | 622 | best_vco_diff = vco_diff; |
590 | } else if (current_freq == freq) { | ||
591 | if (best_freq == -1) { | ||
592 | best_post_div = post_div; | ||
593 | best_ref_div = ref_div; | ||
594 | best_feedback_div = feedback_div; | ||
595 | best_frac_feedback_div = frac_feedback_div; | ||
596 | best_freq = current_freq; | ||
597 | best_error = error; | ||
598 | best_vco_diff = vco_diff; | ||
599 | } else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || | ||
600 | ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || | ||
601 | ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || | ||
602 | ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || | ||
603 | ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || | ||
604 | ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { | ||
605 | best_post_div = post_div; | ||
606 | best_ref_div = ref_div; | ||
607 | best_feedback_div = feedback_div; | ||
608 | best_frac_feedback_div = frac_feedback_div; | ||
609 | best_freq = current_freq; | ||
610 | best_error = error; | ||
611 | best_vco_diff = vco_diff; | ||
612 | } | ||
613 | } | 623 | } |
614 | if (current_freq < freq) | 624 | if (current_freq < freq) |
615 | min_frac_feed_div = frac_feedback_div + 1; | 625 | min_frac_feed_div = frac_feedback_div + 1; |
@@ -631,214 +641,6 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
631 | *post_div_p = best_post_div; | 641 | *post_div_p = best_post_div; |
632 | } | 642 | } |
633 | 643 | ||
634 | static bool | ||
635 | calc_fb_div(struct radeon_pll *pll, | ||
636 | uint32_t freq, | ||
637 | uint32_t post_div, | ||
638 | uint32_t ref_div, | ||
639 | uint32_t *fb_div, | ||
640 | uint32_t *fb_div_frac) | ||
641 | { | ||
642 | fixed20_12 feedback_divider, a, b; | ||
643 | u32 vco_freq; | ||
644 | |||
645 | vco_freq = freq * post_div; | ||
646 | /* feedback_divider = vco_freq * ref_div / pll->reference_freq; */ | ||
647 | a.full = dfixed_const(pll->reference_freq); | ||
648 | feedback_divider.full = dfixed_const(vco_freq); | ||
649 | feedback_divider.full = dfixed_div(feedback_divider, a); | ||
650 | a.full = dfixed_const(ref_div); | ||
651 | feedback_divider.full = dfixed_mul(feedback_divider, a); | ||
652 | |||
653 | if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { | ||
654 | /* feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1; */ | ||
655 | a.full = dfixed_const(10); | ||
656 | feedback_divider.full = dfixed_mul(feedback_divider, a); | ||
657 | feedback_divider.full += dfixed_const_half(0); | ||
658 | feedback_divider.full = dfixed_floor(feedback_divider); | ||
659 | feedback_divider.full = dfixed_div(feedback_divider, a); | ||
660 | |||
661 | /* *fb_div = floor(feedback_divider); */ | ||
662 | a.full = dfixed_floor(feedback_divider); | ||
663 | *fb_div = dfixed_trunc(a); | ||
664 | /* *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0; */ | ||
665 | a.full = dfixed_const(10); | ||
666 | b.full = dfixed_mul(feedback_divider, a); | ||
667 | |||
668 | feedback_divider.full = dfixed_floor(feedback_divider); | ||
669 | feedback_divider.full = dfixed_mul(feedback_divider, a); | ||
670 | feedback_divider.full = b.full - feedback_divider.full; | ||
671 | *fb_div_frac = dfixed_trunc(feedback_divider); | ||
672 | } else { | ||
673 | /* *fb_div = floor(feedback_divider + 0.5); */ | ||
674 | feedback_divider.full += dfixed_const_half(0); | ||
675 | feedback_divider.full = dfixed_floor(feedback_divider); | ||
676 | |||
677 | *fb_div = dfixed_trunc(feedback_divider); | ||
678 | *fb_div_frac = 0; | ||
679 | } | ||
680 | |||
681 | if (((*fb_div) < pll->min_feedback_div) || ((*fb_div) > pll->max_feedback_div)) | ||
682 | return false; | ||
683 | else | ||
684 | return true; | ||
685 | } | ||
686 | |||
687 | static bool | ||
688 | calc_fb_ref_div(struct radeon_pll *pll, | ||
689 | uint32_t freq, | ||
690 | uint32_t post_div, | ||
691 | uint32_t *fb_div, | ||
692 | uint32_t *fb_div_frac, | ||
693 | uint32_t *ref_div) | ||
694 | { | ||
695 | fixed20_12 ffreq, max_error, error, pll_out, a; | ||
696 | u32 vco; | ||
697 | u32 pll_out_min, pll_out_max; | ||
698 | |||
699 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
700 | pll_out_min = pll->lcd_pll_out_min; | ||
701 | pll_out_max = pll->lcd_pll_out_max; | ||
702 | } else { | ||
703 | pll_out_min = pll->pll_out_min; | ||
704 | pll_out_max = pll->pll_out_max; | ||
705 | } | ||
706 | |||
707 | ffreq.full = dfixed_const(freq); | ||
708 | /* max_error = ffreq * 0.0025; */ | ||
709 | a.full = dfixed_const(400); | ||
710 | max_error.full = dfixed_div(ffreq, a); | ||
711 | |||
712 | for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) { | ||
713 | if (calc_fb_div(pll, freq, post_div, (*ref_div), fb_div, fb_div_frac)) { | ||
714 | vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac)); | ||
715 | vco = vco / ((*ref_div) * 10); | ||
716 | |||
717 | if ((vco < pll_out_min) || (vco > pll_out_max)) | ||
718 | continue; | ||
719 | |||
720 | /* pll_out = vco / post_div; */ | ||
721 | a.full = dfixed_const(post_div); | ||
722 | pll_out.full = dfixed_const(vco); | ||
723 | pll_out.full = dfixed_div(pll_out, a); | ||
724 | |||
725 | if (pll_out.full >= ffreq.full) { | ||
726 | error.full = pll_out.full - ffreq.full; | ||
727 | if (error.full <= max_error.full) | ||
728 | return true; | ||
729 | } | ||
730 | } | ||
731 | } | ||
732 | return false; | ||
733 | } | ||
734 | |||
735 | static void radeon_compute_pll_new(struct radeon_pll *pll, | ||
736 | uint64_t freq, | ||
737 | uint32_t *dot_clock_p, | ||
738 | uint32_t *fb_div_p, | ||
739 | uint32_t *frac_fb_div_p, | ||
740 | uint32_t *ref_div_p, | ||
741 | uint32_t *post_div_p) | ||
742 | { | ||
743 | u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0; | ||
744 | u32 best_freq = 0, vco_frequency; | ||
745 | u32 pll_out_min, pll_out_max; | ||
746 | |||
747 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
748 | pll_out_min = pll->lcd_pll_out_min; | ||
749 | pll_out_max = pll->lcd_pll_out_max; | ||
750 | } else { | ||
751 | pll_out_min = pll->pll_out_min; | ||
752 | pll_out_max = pll->pll_out_max; | ||
753 | } | ||
754 | |||
755 | /* freq = freq / 10; */ | ||
756 | do_div(freq, 10); | ||
757 | |||
758 | if (pll->flags & RADEON_PLL_USE_POST_DIV) { | ||
759 | post_div = pll->post_div; | ||
760 | if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div)) | ||
761 | goto done; | ||
762 | |||
763 | vco_frequency = freq * post_div; | ||
764 | if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max)) | ||
765 | goto done; | ||
766 | |||
767 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { | ||
768 | ref_div = pll->reference_div; | ||
769 | if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div)) | ||
770 | goto done; | ||
771 | if (!calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac)) | ||
772 | goto done; | ||
773 | } | ||
774 | } else { | ||
775 | for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) { | ||
776 | if (pll->flags & RADEON_PLL_LEGACY) { | ||
777 | if ((post_div == 5) || | ||
778 | (post_div == 7) || | ||
779 | (post_div == 9) || | ||
780 | (post_div == 10) || | ||
781 | (post_div == 11)) | ||
782 | continue; | ||
783 | } | ||
784 | |||
785 | if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) | ||
786 | continue; | ||
787 | |||
788 | vco_frequency = freq * post_div; | ||
789 | if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max)) | ||
790 | continue; | ||
791 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { | ||
792 | ref_div = pll->reference_div; | ||
793 | if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div)) | ||
794 | goto done; | ||
795 | if (calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac)) | ||
796 | break; | ||
797 | } else { | ||
798 | if (calc_fb_ref_div(pll, freq, post_div, &fb_div, &fb_div_frac, &ref_div)) | ||
799 | break; | ||
800 | } | ||
801 | } | ||
802 | } | ||
803 | |||
804 | best_freq = pll->reference_freq * 10 * fb_div; | ||
805 | best_freq += pll->reference_freq * fb_div_frac; | ||
806 | best_freq = best_freq / (ref_div * post_div); | ||
807 | |||
808 | done: | ||
809 | if (best_freq == 0) | ||
810 | DRM_ERROR("Couldn't find valid PLL dividers\n"); | ||
811 | |||
812 | *dot_clock_p = best_freq / 10; | ||
813 | *fb_div_p = fb_div; | ||
814 | *frac_fb_div_p = fb_div_frac; | ||
815 | *ref_div_p = ref_div; | ||
816 | *post_div_p = post_div; | ||
817 | |||
818 | DRM_DEBUG_KMS("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); | ||
819 | } | ||
820 | |||
821 | void radeon_compute_pll(struct radeon_pll *pll, | ||
822 | uint64_t freq, | ||
823 | uint32_t *dot_clock_p, | ||
824 | uint32_t *fb_div_p, | ||
825 | uint32_t *frac_fb_div_p, | ||
826 | uint32_t *ref_div_p, | ||
827 | uint32_t *post_div_p) | ||
828 | { | ||
829 | switch (pll->algo) { | ||
830 | case PLL_ALGO_NEW: | ||
831 | radeon_compute_pll_new(pll, freq, dot_clock_p, fb_div_p, | ||
832 | frac_fb_div_p, ref_div_p, post_div_p); | ||
833 | break; | ||
834 | case PLL_ALGO_LEGACY: | ||
835 | default: | ||
836 | radeon_compute_pll_legacy(pll, freq, dot_clock_p, fb_div_p, | ||
837 | frac_fb_div_p, ref_div_p, post_div_p); | ||
838 | break; | ||
839 | } | ||
840 | } | ||
841 | |||
842 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | 644 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) |
843 | { | 645 | { |
844 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); | 646 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); |
@@ -1002,6 +804,24 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) | |||
1002 | radeon_underscan_enum_list[i].name); | 804 | radeon_underscan_enum_list[i].name); |
1003 | } | 805 | } |
1004 | 806 | ||
807 | rdev->mode_info.underscan_hborder_property = | ||
808 | drm_property_create(rdev->ddev, | ||
809 | DRM_MODE_PROP_RANGE, | ||
810 | "underscan hborder", 2); | ||
811 | if (!rdev->mode_info.underscan_hborder_property) | ||
812 | return -ENOMEM; | ||
813 | rdev->mode_info.underscan_hborder_property->values[0] = 0; | ||
814 | rdev->mode_info.underscan_hborder_property->values[1] = 128; | ||
815 | |||
816 | rdev->mode_info.underscan_vborder_property = | ||
817 | drm_property_create(rdev->ddev, | ||
818 | DRM_MODE_PROP_RANGE, | ||
819 | "underscan vborder", 2); | ||
820 | if (!rdev->mode_info.underscan_vborder_property) | ||
821 | return -ENOMEM; | ||
822 | rdev->mode_info.underscan_vborder_property->values[0] = 0; | ||
823 | rdev->mode_info.underscan_vborder_property->values[1] = 128; | ||
824 | |||
1005 | return 0; | 825 | return 0; |
1006 | } | 826 | } |
1007 | 827 | ||
@@ -1159,8 +979,14 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1159 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && | 979 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && |
1160 | drm_detect_hdmi_monitor(radeon_connector->edid) && | 980 | drm_detect_hdmi_monitor(radeon_connector->edid) && |
1161 | is_hdtv_mode(mode)))) { | 981 | is_hdtv_mode(mode)))) { |
1162 | radeon_crtc->h_border = (mode->hdisplay >> 5) + 16; | 982 | if (radeon_encoder->underscan_hborder != 0) |
1163 | radeon_crtc->v_border = (mode->vdisplay >> 5) + 16; | 983 | radeon_crtc->h_border = radeon_encoder->underscan_hborder; |
984 | else | ||
985 | radeon_crtc->h_border = (mode->hdisplay >> 5) + 16; | ||
986 | if (radeon_encoder->underscan_vborder != 0) | ||
987 | radeon_crtc->v_border = radeon_encoder->underscan_vborder; | ||
988 | else | ||
989 | radeon_crtc->v_border = (mode->vdisplay >> 5) + 16; | ||
1164 | radeon_crtc->rmx_type = RMX_FULL; | 990 | radeon_crtc->rmx_type = RMX_FULL; |
1165 | src_v = crtc->mode.vdisplay; | 991 | src_v = crtc->mode.vdisplay; |
1166 | dst_v = crtc->mode.vdisplay - (radeon_crtc->v_border * 2); | 992 | dst_v = crtc->mode.vdisplay - (radeon_crtc->v_border * 2); |
@@ -1195,3 +1021,156 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1195 | } | 1021 | } |
1196 | return true; | 1022 | return true; |
1197 | } | 1023 | } |
1024 | |||
1025 | /* | ||
1026 | * Retrieve current video scanout position of crtc on a given gpu. | ||
1027 | * | ||
1028 | * \param rdev Device to query. | ||
1029 | * \param crtc Crtc to query. | ||
1030 | * \param *vpos Location where vertical scanout position should be stored. | ||
1031 | * \param *hpos Location where horizontal scanout position should go. | ||
1032 | * | ||
1033 | * Returns vpos as a positive number while in active scanout area. | ||
1034 | * Returns vpos as a negative number inside vblank, counting the number | ||
1035 | * of scanlines to go until end of vblank, e.g., -1 means "one scanline | ||
1036 | * until start of active scanout / end of vblank." | ||
1037 | * | ||
1038 | * \return Flags, or'ed together as follows: | ||
1039 | * | ||
1040 | * RADEON_SCANOUTPOS_VALID = Query successfull. | ||
1041 | * RADEON_SCANOUTPOS_INVBL = Inside vblank. | ||
1042 | * RADEON_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of | ||
1043 | * this flag means that returned position may be offset by a constant but | ||
1044 | * unknown small number of scanlines wrt. real scanout position. | ||
1045 | * | ||
1046 | */ | ||
1047 | int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos) | ||
1048 | { | ||
1049 | u32 stat_crtc = 0, vbl = 0, position = 0; | ||
1050 | int vbl_start, vbl_end, vtotal, ret = 0; | ||
1051 | bool in_vbl = true; | ||
1052 | |||
1053 | if (ASIC_IS_DCE4(rdev)) { | ||
1054 | if (crtc == 0) { | ||
1055 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
1056 | EVERGREEN_CRTC0_REGISTER_OFFSET); | ||
1057 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
1058 | EVERGREEN_CRTC0_REGISTER_OFFSET); | ||
1059 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1060 | } | ||
1061 | if (crtc == 1) { | ||
1062 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
1063 | EVERGREEN_CRTC1_REGISTER_OFFSET); | ||
1064 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
1065 | EVERGREEN_CRTC1_REGISTER_OFFSET); | ||
1066 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1067 | } | ||
1068 | if (crtc == 2) { | ||
1069 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
1070 | EVERGREEN_CRTC2_REGISTER_OFFSET); | ||
1071 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
1072 | EVERGREEN_CRTC2_REGISTER_OFFSET); | ||
1073 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1074 | } | ||
1075 | if (crtc == 3) { | ||
1076 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
1077 | EVERGREEN_CRTC3_REGISTER_OFFSET); | ||
1078 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
1079 | EVERGREEN_CRTC3_REGISTER_OFFSET); | ||
1080 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1081 | } | ||
1082 | if (crtc == 4) { | ||
1083 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
1084 | EVERGREEN_CRTC4_REGISTER_OFFSET); | ||
1085 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
1086 | EVERGREEN_CRTC4_REGISTER_OFFSET); | ||
1087 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1088 | } | ||
1089 | if (crtc == 5) { | ||
1090 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
1091 | EVERGREEN_CRTC5_REGISTER_OFFSET); | ||
1092 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
1093 | EVERGREEN_CRTC5_REGISTER_OFFSET); | ||
1094 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1095 | } | ||
1096 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
1097 | if (crtc == 0) { | ||
1098 | vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); | ||
1099 | position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); | ||
1100 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1101 | } | ||
1102 | if (crtc == 1) { | ||
1103 | vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); | ||
1104 | position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); | ||
1105 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1106 | } | ||
1107 | } else { | ||
1108 | /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ | ||
1109 | if (crtc == 0) { | ||
1110 | /* Assume vbl_end == 0, get vbl_start from | ||
1111 | * upper 16 bits. | ||
1112 | */ | ||
1113 | vbl = (RREG32(RADEON_CRTC_V_TOTAL_DISP) & | ||
1114 | RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT; | ||
1115 | /* Only retrieve vpos from upper 16 bits, set hpos == 0. */ | ||
1116 | position = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; | ||
1117 | stat_crtc = RREG32(RADEON_CRTC_STATUS); | ||
1118 | if (!(stat_crtc & 1)) | ||
1119 | in_vbl = false; | ||
1120 | |||
1121 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1122 | } | ||
1123 | if (crtc == 1) { | ||
1124 | vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & | ||
1125 | RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT; | ||
1126 | position = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; | ||
1127 | stat_crtc = RREG32(RADEON_CRTC2_STATUS); | ||
1128 | if (!(stat_crtc & 1)) | ||
1129 | in_vbl = false; | ||
1130 | |||
1131 | ret |= RADEON_SCANOUTPOS_VALID; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | /* Decode into vertical and horizontal scanout position. */ | ||
1136 | *vpos = position & 0x1fff; | ||
1137 | *hpos = (position >> 16) & 0x1fff; | ||
1138 | |||
1139 | /* Valid vblank area boundaries from gpu retrieved? */ | ||
1140 | if (vbl > 0) { | ||
1141 | /* Yes: Decode. */ | ||
1142 | ret |= RADEON_SCANOUTPOS_ACCURATE; | ||
1143 | vbl_start = vbl & 0x1fff; | ||
1144 | vbl_end = (vbl >> 16) & 0x1fff; | ||
1145 | } | ||
1146 | else { | ||
1147 | /* No: Fake something reasonable which gives at least ok results. */ | ||
1148 | vbl_start = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vdisplay; | ||
1149 | vbl_end = 0; | ||
1150 | } | ||
1151 | |||
1152 | /* Test scanout position against vblank region. */ | ||
1153 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) | ||
1154 | in_vbl = false; | ||
1155 | |||
1156 | /* Check if inside vblank area and apply corrective offsets: | ||
1157 | * vpos will then be >=0 in video scanout area, but negative | ||
1158 | * within vblank area, counting down the number of lines until | ||
1159 | * start of scanout. | ||
1160 | */ | ||
1161 | |||
1162 | /* Inside "upper part" of vblank area? Apply corrective offset if so: */ | ||
1163 | if (in_vbl && (*vpos >= vbl_start)) { | ||
1164 | vtotal = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vtotal; | ||
1165 | *vpos = *vpos - vtotal; | ||
1166 | } | ||
1167 | |||
1168 | /* Correct for shifted end of vbl at vbl_end. */ | ||
1169 | *vpos = *vpos - vbl_end; | ||
1170 | |||
1171 | /* In vblank? */ | ||
1172 | if (in_vbl) | ||
1173 | ret |= RADEON_SCANOUTPOS_INVBL; | ||
1174 | |||
1175 | return ret; | ||
1176 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 795403b0e2cd..f29a2695d961 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -93,7 +93,6 @@ int radeon_benchmarking = 0; | |||
93 | int radeon_testing = 0; | 93 | int radeon_testing = 0; |
94 | int radeon_connector_table = 0; | 94 | int radeon_connector_table = 0; |
95 | int radeon_tv = 1; | 95 | int radeon_tv = 1; |
96 | int radeon_new_pll = -1; | ||
97 | int radeon_audio = 1; | 96 | int radeon_audio = 1; |
98 | int radeon_disp_priority = 0; | 97 | int radeon_disp_priority = 0; |
99 | int radeon_hw_i2c = 0; | 98 | int radeon_hw_i2c = 0; |
@@ -131,9 +130,6 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); | |||
131 | MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); | 130 | MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); |
132 | module_param_named(tv, radeon_tv, int, 0444); | 131 | module_param_named(tv, radeon_tv, int, 0444); |
133 | 132 | ||
134 | MODULE_PARM_DESC(new_pll, "Select new PLL code"); | ||
135 | module_param_named(new_pll, radeon_new_pll, int, 0444); | ||
136 | |||
137 | MODULE_PARM_DESC(audio, "Audio enable (0 = disable)"); | 133 | MODULE_PARM_DESC(audio, "Audio enable (0 = disable)"); |
138 | module_param_named(audio, radeon_audio, int, 0444); | 134 | module_param_named(audio, radeon_audio, int, 0444); |
139 | 135 | ||
@@ -203,8 +199,6 @@ static struct drm_driver driver_old = { | |||
203 | .irq_uninstall = radeon_driver_irq_uninstall, | 199 | .irq_uninstall = radeon_driver_irq_uninstall, |
204 | .irq_handler = radeon_driver_irq_handler, | 200 | .irq_handler = radeon_driver_irq_handler, |
205 | .reclaim_buffers = drm_core_reclaim_buffers, | 201 | .reclaim_buffers = drm_core_reclaim_buffers, |
206 | .get_map_ofs = drm_core_get_map_ofs, | ||
207 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
208 | .ioctls = radeon_ioctls, | 202 | .ioctls = radeon_ioctls, |
209 | .dma_ioctl = radeon_cp_buffers, | 203 | .dma_ioctl = radeon_cp_buffers, |
210 | .fops = { | 204 | .fops = { |
@@ -290,8 +284,6 @@ static struct drm_driver kms_driver = { | |||
290 | .irq_uninstall = radeon_driver_irq_uninstall_kms, | 284 | .irq_uninstall = radeon_driver_irq_uninstall_kms, |
291 | .irq_handler = radeon_driver_irq_handler_kms, | 285 | .irq_handler = radeon_driver_irq_handler_kms, |
292 | .reclaim_buffers = drm_core_reclaim_buffers, | 286 | .reclaim_buffers = drm_core_reclaim_buffers, |
293 | .get_map_ofs = drm_core_get_map_ofs, | ||
294 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
295 | .ioctls = radeon_ioctls_kms, | 287 | .ioctls = radeon_ioctls_kms, |
296 | .gem_init_object = radeon_gem_object_init, | 288 | .gem_init_object = radeon_gem_object_init, |
297 | .gem_free_object = radeon_gem_object_free, | 289 | .gem_free_object = radeon_gem_object_free, |
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 2c293e8304d6..ae58b6849a2e 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
@@ -529,9 +529,9 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
529 | args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; | 529 | args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; |
530 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | 530 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
531 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 531 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
532 | if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) | 532 | if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) |
533 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; | 533 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; |
534 | if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) | 534 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) |
535 | args.v1.ucMisc |= (1 << 1); | 535 | args.v1.ucMisc |= (1 << 1); |
536 | } else { | 536 | } else { |
537 | if (dig->linkb) | 537 | if (dig->linkb) |
@@ -558,18 +558,18 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
558 | args.v2.ucTemporal = 0; | 558 | args.v2.ucTemporal = 0; |
559 | args.v2.ucFRC = 0; | 559 | args.v2.ucFRC = 0; |
560 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 560 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
561 | if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) | 561 | if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) |
562 | args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; | 562 | args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; |
563 | if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) { | 563 | if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { |
564 | args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; | 564 | args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; |
565 | if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) | 565 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) |
566 | args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; | 566 | args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; |
567 | } | 567 | } |
568 | if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) { | 568 | if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { |
569 | args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; | 569 | args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; |
570 | if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) | 570 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) |
571 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; | 571 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; |
572 | if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) | 572 | if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) |
573 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; | 573 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; |
574 | } | 574 | } |
575 | } else { | 575 | } else { |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 40b0c087b592..efa211898fe6 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -59,6 +59,8 @@ static struct fb_ops radeonfb_ops = { | |||
59 | .fb_pan_display = drm_fb_helper_pan_display, | 59 | .fb_pan_display = drm_fb_helper_pan_display, |
60 | .fb_blank = drm_fb_helper_blank, | 60 | .fb_blank = drm_fb_helper_blank, |
61 | .fb_setcmap = drm_fb_helper_setcmap, | 61 | .fb_setcmap = drm_fb_helper_setcmap, |
62 | .fb_debug_enter = drm_fb_helper_debug_enter, | ||
63 | .fb_debug_leave = drm_fb_helper_debug_leave, | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | 66 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index b1f9a81b5d1d..216392d0353b 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -72,7 +72,15 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) | |||
72 | bool wake = false; | 72 | bool wake = false; |
73 | unsigned long cjiffies; | 73 | unsigned long cjiffies; |
74 | 74 | ||
75 | seq = RREG32(rdev->fence_drv.scratch_reg); | 75 | if (rdev->wb.enabled) { |
76 | u32 scratch_index; | ||
77 | if (rdev->wb.use_event) | ||
78 | scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; | ||
79 | else | ||
80 | scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; | ||
81 | seq = rdev->wb.wb[scratch_index/4]; | ||
82 | } else | ||
83 | seq = RREG32(rdev->fence_drv.scratch_reg); | ||
76 | if (seq != rdev->fence_drv.last_seq) { | 84 | if (seq != rdev->fence_drv.last_seq) { |
77 | rdev->fence_drv.last_seq = seq; | 85 | rdev->fence_drv.last_seq = seq; |
78 | rdev->fence_drv.last_jiffies = jiffies; | 86 | rdev->fence_drv.last_jiffies = jiffies; |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 305049afde15..c0bf8b7cc56c 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -348,10 +348,30 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
348 | int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 348 | int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
349 | struct drm_framebuffer *old_fb) | 349 | struct drm_framebuffer *old_fb) |
350 | { | 350 | { |
351 | return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); | ||
352 | } | ||
353 | |||
354 | int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, | ||
355 | struct drm_framebuffer *fb, | ||
356 | int x, int y, int enter) | ||
357 | { | ||
358 | if (enter) | ||
359 | radeon_crtc_save_lut(crtc); | ||
360 | else | ||
361 | radeon_crtc_restore_lut(crtc); | ||
362 | |||
363 | return radeon_crtc_do_set_base(crtc, fb, x, y, 1); | ||
364 | } | ||
365 | |||
366 | int radeon_crtc_do_set_base(struct drm_crtc *crtc, | ||
367 | struct drm_framebuffer *fb, | ||
368 | int x, int y, int atomic) | ||
369 | { | ||
351 | struct drm_device *dev = crtc->dev; | 370 | struct drm_device *dev = crtc->dev; |
352 | struct radeon_device *rdev = dev->dev_private; | 371 | struct radeon_device *rdev = dev->dev_private; |
353 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 372 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
354 | struct radeon_framebuffer *radeon_fb; | 373 | struct radeon_framebuffer *radeon_fb; |
374 | struct drm_framebuffer *target_fb; | ||
355 | struct drm_gem_object *obj; | 375 | struct drm_gem_object *obj; |
356 | struct radeon_bo *rbo; | 376 | struct radeon_bo *rbo; |
357 | uint64_t base; | 377 | uint64_t base; |
@@ -364,14 +384,21 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
364 | 384 | ||
365 | DRM_DEBUG_KMS("\n"); | 385 | DRM_DEBUG_KMS("\n"); |
366 | /* no fb bound */ | 386 | /* no fb bound */ |
367 | if (!crtc->fb) { | 387 | if (!atomic && !crtc->fb) { |
368 | DRM_DEBUG_KMS("No FB bound\n"); | 388 | DRM_DEBUG_KMS("No FB bound\n"); |
369 | return 0; | 389 | return 0; |
370 | } | 390 | } |
371 | 391 | ||
372 | radeon_fb = to_radeon_framebuffer(crtc->fb); | 392 | if (atomic) { |
393 | radeon_fb = to_radeon_framebuffer(fb); | ||
394 | target_fb = fb; | ||
395 | } | ||
396 | else { | ||
397 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
398 | target_fb = crtc->fb; | ||
399 | } | ||
373 | 400 | ||
374 | switch (crtc->fb->bits_per_pixel) { | 401 | switch (target_fb->bits_per_pixel) { |
375 | case 8: | 402 | case 8: |
376 | format = 2; | 403 | format = 2; |
377 | break; | 404 | break; |
@@ -415,10 +442,10 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
415 | 442 | ||
416 | crtc_offset_cntl = 0; | 443 | crtc_offset_cntl = 0; |
417 | 444 | ||
418 | pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | 445 | pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); |
419 | crtc_pitch = (((pitch_pixels * crtc->fb->bits_per_pixel) + | 446 | crtc_pitch = (((pitch_pixels * target_fb->bits_per_pixel) + |
420 | ((crtc->fb->bits_per_pixel * 8) - 1)) / | 447 | ((target_fb->bits_per_pixel * 8) - 1)) / |
421 | (crtc->fb->bits_per_pixel * 8)); | 448 | (target_fb->bits_per_pixel * 8)); |
422 | crtc_pitch |= crtc_pitch << 16; | 449 | crtc_pitch |= crtc_pitch << 16; |
423 | 450 | ||
424 | 451 | ||
@@ -443,14 +470,14 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
443 | crtc_tile_x0_y0 = x | (y << 16); | 470 | crtc_tile_x0_y0 = x | (y << 16); |
444 | base &= ~0x7ff; | 471 | base &= ~0x7ff; |
445 | } else { | 472 | } else { |
446 | int byteshift = crtc->fb->bits_per_pixel >> 4; | 473 | int byteshift = target_fb->bits_per_pixel >> 4; |
447 | int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; | 474 | int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; |
448 | base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); | 475 | base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); |
449 | crtc_offset_cntl |= (y % 16); | 476 | crtc_offset_cntl |= (y % 16); |
450 | } | 477 | } |
451 | } else { | 478 | } else { |
452 | int offset = y * pitch_pixels + x; | 479 | int offset = y * pitch_pixels + x; |
453 | switch (crtc->fb->bits_per_pixel) { | 480 | switch (target_fb->bits_per_pixel) { |
454 | case 8: | 481 | case 8: |
455 | offset *= 1; | 482 | offset *= 1; |
456 | break; | 483 | break; |
@@ -496,8 +523,8 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
496 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); | 523 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); |
497 | WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); | 524 | WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); |
498 | 525 | ||
499 | if (old_fb && old_fb != crtc->fb) { | 526 | if (!atomic && fb && fb != crtc->fb) { |
500 | radeon_fb = to_radeon_framebuffer(old_fb); | 527 | radeon_fb = to_radeon_framebuffer(fb); |
501 | rbo = radeon_fb->obj->driver_private; | 528 | rbo = radeon_fb->obj->driver_private; |
502 | r = radeon_bo_reserve(rbo, false); | 529 | r = radeon_bo_reserve(rbo, false); |
503 | if (unlikely(r != 0)) | 530 | if (unlikely(r != 0)) |
@@ -717,15 +744,6 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
717 | pll = &rdev->clock.p1pll; | 744 | pll = &rdev->clock.p1pll; |
718 | 745 | ||
719 | pll->flags = RADEON_PLL_LEGACY; | 746 | pll->flags = RADEON_PLL_LEGACY; |
720 | if (radeon_new_pll == 1) | ||
721 | pll->algo = PLL_ALGO_NEW; | ||
722 | else | ||
723 | pll->algo = PLL_ALGO_LEGACY; | ||
724 | |||
725 | if (mode->clock > 200000) /* range limits??? */ | ||
726 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | ||
727 | else | ||
728 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | ||
729 | 747 | ||
730 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 748 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
731 | if (encoder->crtc == crtc) { | 749 | if (encoder->crtc == crtc) { |
@@ -1040,6 +1058,7 @@ static const struct drm_crtc_helper_funcs legacy_helper_funcs = { | |||
1040 | .mode_fixup = radeon_crtc_mode_fixup, | 1058 | .mode_fixup = radeon_crtc_mode_fixup, |
1041 | .mode_set = radeon_crtc_mode_set, | 1059 | .mode_set = radeon_crtc_mode_set, |
1042 | .mode_set_base = radeon_crtc_set_base, | 1060 | .mode_set_base = radeon_crtc_set_base, |
1061 | .mode_set_base_atomic = radeon_crtc_set_base_atomic, | ||
1043 | .prepare = radeon_crtc_prepare, | 1062 | .prepare = radeon_crtc_prepare, |
1044 | .commit = radeon_crtc_commit, | 1063 | .commit = radeon_crtc_commit, |
1045 | .load_lut = radeon_crtc_load_lut, | 1064 | .load_lut = radeon_crtc_load_lut, |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 17a6602b5885..3cda63e37b28 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -139,22 +139,10 @@ struct radeon_tmds_pll { | |||
139 | #define RADEON_PLL_NO_ODD_POST_DIV (1 << 1) | 139 | #define RADEON_PLL_NO_ODD_POST_DIV (1 << 1) |
140 | #define RADEON_PLL_USE_REF_DIV (1 << 2) | 140 | #define RADEON_PLL_USE_REF_DIV (1 << 2) |
141 | #define RADEON_PLL_LEGACY (1 << 3) | 141 | #define RADEON_PLL_LEGACY (1 << 3) |
142 | #define RADEON_PLL_PREFER_LOW_REF_DIV (1 << 4) | 142 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 4) |
143 | #define RADEON_PLL_PREFER_HIGH_REF_DIV (1 << 5) | 143 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 5) |
144 | #define RADEON_PLL_PREFER_LOW_FB_DIV (1 << 6) | 144 | #define RADEON_PLL_USE_POST_DIV (1 << 6) |
145 | #define RADEON_PLL_PREFER_HIGH_FB_DIV (1 << 7) | 145 | #define RADEON_PLL_IS_LCD (1 << 7) |
146 | #define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) | ||
147 | #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) | ||
148 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) | ||
149 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) | ||
150 | #define RADEON_PLL_USE_POST_DIV (1 << 12) | ||
151 | #define RADEON_PLL_IS_LCD (1 << 13) | ||
152 | |||
153 | /* pll algo */ | ||
154 | enum radeon_pll_algo { | ||
155 | PLL_ALGO_LEGACY, | ||
156 | PLL_ALGO_NEW | ||
157 | }; | ||
158 | 146 | ||
159 | struct radeon_pll { | 147 | struct radeon_pll { |
160 | /* reference frequency */ | 148 | /* reference frequency */ |
@@ -188,8 +176,6 @@ struct radeon_pll { | |||
188 | 176 | ||
189 | /* pll id */ | 177 | /* pll id */ |
190 | uint32_t id; | 178 | uint32_t id; |
191 | /* pll algo */ | ||
192 | enum radeon_pll_algo algo; | ||
193 | }; | 179 | }; |
194 | 180 | ||
195 | struct radeon_i2c_chan { | 181 | struct radeon_i2c_chan { |
@@ -241,6 +227,8 @@ struct radeon_mode_info { | |||
241 | struct drm_property *tmds_pll_property; | 227 | struct drm_property *tmds_pll_property; |
242 | /* underscan */ | 228 | /* underscan */ |
243 | struct drm_property *underscan_property; | 229 | struct drm_property *underscan_property; |
230 | struct drm_property *underscan_hborder_property; | ||
231 | struct drm_property *underscan_vborder_property; | ||
244 | /* hardcoded DFP edid from BIOS */ | 232 | /* hardcoded DFP edid from BIOS */ |
245 | struct edid *bios_hardcoded_edid; | 233 | struct edid *bios_hardcoded_edid; |
246 | 234 | ||
@@ -267,6 +255,7 @@ struct radeon_crtc { | |||
267 | struct drm_crtc base; | 255 | struct drm_crtc base; |
268 | int crtc_id; | 256 | int crtc_id; |
269 | u16 lut_r[256], lut_g[256], lut_b[256]; | 257 | u16 lut_r[256], lut_g[256], lut_b[256]; |
258 | u16 lut_r_copy[256], lut_g_copy[256], lut_b_copy[256]; | ||
270 | bool enabled; | 259 | bool enabled; |
271 | bool can_tile; | 260 | bool can_tile; |
272 | uint32_t crtc_offset; | 261 | uint32_t crtc_offset; |
@@ -336,22 +325,24 @@ struct radeon_encoder_ext_tmds { | |||
336 | struct radeon_atom_ss { | 325 | struct radeon_atom_ss { |
337 | uint16_t percentage; | 326 | uint16_t percentage; |
338 | uint8_t type; | 327 | uint8_t type; |
339 | uint8_t step; | 328 | uint16_t step; |
340 | uint8_t delay; | 329 | uint8_t delay; |
341 | uint8_t range; | 330 | uint8_t range; |
342 | uint8_t refdiv; | 331 | uint8_t refdiv; |
332 | /* asic_ss */ | ||
333 | uint16_t rate; | ||
334 | uint16_t amount; | ||
343 | }; | 335 | }; |
344 | 336 | ||
345 | struct radeon_encoder_atom_dig { | 337 | struct radeon_encoder_atom_dig { |
346 | bool linkb; | 338 | bool linkb; |
347 | /* atom dig */ | 339 | /* atom dig */ |
348 | bool coherent_mode; | 340 | bool coherent_mode; |
349 | int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB */ | 341 | int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB, etc. */ |
350 | /* atom lvds */ | 342 | /* atom lvds/edp */ |
351 | uint32_t lvds_misc; | 343 | uint32_t lcd_misc; |
352 | uint16_t panel_pwr_delay; | 344 | uint16_t panel_pwr_delay; |
353 | enum radeon_pll_algo pll_algo; | 345 | uint32_t lcd_ss_id; |
354 | struct radeon_atom_ss *ss; | ||
355 | /* panel mode */ | 346 | /* panel mode */ |
356 | struct drm_display_mode native_mode; | 347 | struct drm_display_mode native_mode; |
357 | }; | 348 | }; |
@@ -370,6 +361,8 @@ struct radeon_encoder { | |||
370 | uint32_t pixel_clock; | 361 | uint32_t pixel_clock; |
371 | enum radeon_rmx_type rmx_type; | 362 | enum radeon_rmx_type rmx_type; |
372 | enum radeon_underscan_type underscan_type; | 363 | enum radeon_underscan_type underscan_type; |
364 | uint32_t underscan_hborder; | ||
365 | uint32_t underscan_vborder; | ||
373 | struct drm_display_mode native_mode; | 366 | struct drm_display_mode native_mode; |
374 | void *enc_priv; | 367 | void *enc_priv; |
375 | int audio_polling_active; | 368 | int audio_polling_active; |
@@ -436,6 +429,11 @@ struct radeon_framebuffer { | |||
436 | struct drm_gem_object *obj; | 429 | struct drm_gem_object *obj; |
437 | }; | 430 | }; |
438 | 431 | ||
432 | /* radeon_get_crtc_scanoutpos() return flags */ | ||
433 | #define RADEON_SCANOUTPOS_VALID (1 << 0) | ||
434 | #define RADEON_SCANOUTPOS_INVBL (1 << 1) | ||
435 | #define RADEON_SCANOUTPOS_ACCURATE (1 << 2) | ||
436 | |||
439 | extern enum radeon_tv_std | 437 | extern enum radeon_tv_std |
440 | radeon_combios_get_tv_info(struct radeon_device *rdev); | 438 | radeon_combios_get_tv_info(struct radeon_device *rdev); |
441 | extern enum radeon_tv_std | 439 | extern enum radeon_tv_std |
@@ -491,6 +489,13 @@ extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); | |||
491 | 489 | ||
492 | extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); | 490 | extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); |
493 | 491 | ||
492 | extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, | ||
493 | struct radeon_atom_ss *ss, | ||
494 | int id); | ||
495 | extern bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, | ||
496 | struct radeon_atom_ss *ss, | ||
497 | int id, u32 clock); | ||
498 | |||
494 | extern void radeon_compute_pll(struct radeon_pll *pll, | 499 | extern void radeon_compute_pll(struct radeon_pll *pll, |
495 | uint64_t freq, | 500 | uint64_t freq, |
496 | uint32_t *dot_clock_p, | 501 | uint32_t *dot_clock_p, |
@@ -512,8 +517,13 @@ extern int atombios_get_encoder_mode(struct drm_encoder *encoder); | |||
512 | extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); | 517 | extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); |
513 | 518 | ||
514 | extern void radeon_crtc_load_lut(struct drm_crtc *crtc); | 519 | extern void radeon_crtc_load_lut(struct drm_crtc *crtc); |
520 | extern void radeon_crtc_save_lut(struct drm_crtc *crtc); | ||
521 | extern void radeon_crtc_restore_lut(struct drm_crtc *crtc); | ||
515 | extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 522 | extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
516 | struct drm_framebuffer *old_fb); | 523 | struct drm_framebuffer *old_fb); |
524 | extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, | ||
525 | struct drm_framebuffer *fb, | ||
526 | int x, int y, int enter); | ||
517 | extern int atombios_crtc_mode_set(struct drm_crtc *crtc, | 527 | extern int atombios_crtc_mode_set(struct drm_crtc *crtc, |
518 | struct drm_display_mode *mode, | 528 | struct drm_display_mode *mode, |
519 | struct drm_display_mode *adjusted_mode, | 529 | struct drm_display_mode *adjusted_mode, |
@@ -523,7 +533,12 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); | |||
523 | 533 | ||
524 | extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 534 | extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
525 | struct drm_framebuffer *old_fb); | 535 | struct drm_framebuffer *old_fb); |
526 | 536 | extern int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, | |
537 | struct drm_framebuffer *fb, | ||
538 | int x, int y, int enter); | ||
539 | extern int radeon_crtc_do_set_base(struct drm_crtc *crtc, | ||
540 | struct drm_framebuffer *fb, | ||
541 | int x, int y, int atomic); | ||
527 | extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, | 542 | extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, |
528 | struct drm_file *file_priv, | 543 | struct drm_file *file_priv, |
529 | uint32_t handle, | 544 | uint32_t handle, |
@@ -532,6 +547,8 @@ extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, | |||
532 | extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, | 547 | extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, |
533 | int x, int y); | 548 | int x, int y); |
534 | 549 | ||
550 | extern int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos); | ||
551 | |||
535 | extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); | 552 | extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); |
536 | extern struct edid * | 553 | extern struct edid * |
537 | radeon_combios_get_hardcoded_edid(struct radeon_device *rdev); | 554 | radeon_combios_get_hardcoded_edid(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index b3b5306bb578..d7ab91416410 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -435,7 +435,7 @@ int radeon_bo_get_surface_reg(struct radeon_bo *bo) | |||
435 | 435 | ||
436 | out: | 436 | out: |
437 | radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch, | 437 | radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch, |
438 | bo->tbo.mem.mm_node->start << PAGE_SHIFT, | 438 | bo->tbo.mem.start << PAGE_SHIFT, |
439 | bo->tbo.num_pages << PAGE_SHIFT); | 439 | bo->tbo.num_pages << PAGE_SHIFT); |
440 | return 0; | 440 | return 0; |
441 | } | 441 | } |
@@ -532,7 +532,7 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) | |||
532 | rdev = rbo->rdev; | 532 | rdev = rbo->rdev; |
533 | if (bo->mem.mem_type == TTM_PL_VRAM) { | 533 | if (bo->mem.mem_type == TTM_PL_VRAM) { |
534 | size = bo->mem.num_pages << PAGE_SHIFT; | 534 | size = bo->mem.num_pages << PAGE_SHIFT; |
535 | offset = bo->mem.mm_node->start << PAGE_SHIFT; | 535 | offset = bo->mem.start << PAGE_SHIFT; |
536 | if ((offset + size) > rdev->mc.visible_vram_size) { | 536 | if ((offset + size) > rdev->mc.visible_vram_size) { |
537 | /* hurrah the memory is not visible ! */ | 537 | /* hurrah the memory is not visible ! */ |
538 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); | 538 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); |
@@ -540,7 +540,7 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) | |||
540 | r = ttm_bo_validate(bo, &rbo->placement, false, true, false); | 540 | r = ttm_bo_validate(bo, &rbo->placement, false, true, false); |
541 | if (unlikely(r != 0)) | 541 | if (unlikely(r != 0)) |
542 | return r; | 542 | return r; |
543 | offset = bo->mem.mm_node->start << PAGE_SHIFT; | 543 | offset = bo->mem.start << PAGE_SHIFT; |
544 | /* this should not happen */ | 544 | /* this should not happen */ |
545 | if ((offset + size) > rdev->mc.visible_vram_size) | 545 | if ((offset + size) > rdev->mc.visible_vram_size) |
546 | return -EINVAL; | 546 | return -EINVAL; |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f87efec76236..8c9b2ef32c68 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -712,73 +712,21 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
712 | 712 | ||
713 | static bool radeon_pm_in_vbl(struct radeon_device *rdev) | 713 | static bool radeon_pm_in_vbl(struct radeon_device *rdev) |
714 | { | 714 | { |
715 | u32 stat_crtc = 0, vbl = 0, position = 0; | 715 | int crtc, vpos, hpos, vbl_status; |
716 | bool in_vbl = true; | 716 | bool in_vbl = true; |
717 | 717 | ||
718 | if (ASIC_IS_DCE4(rdev)) { | 718 | /* Iterate over all active crtc's. All crtc's must be in vblank, |
719 | if (rdev->pm.active_crtcs & (1 << 0)) { | 719 | * otherwise return in_vbl == false. |
720 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 720 | */ |
721 | EVERGREEN_CRTC0_REGISTER_OFFSET) & 0xfff; | 721 | for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { |
722 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 722 | if (rdev->pm.active_crtcs & (1 << crtc)) { |
723 | EVERGREEN_CRTC0_REGISTER_OFFSET) & 0xfff; | 723 | vbl_status = radeon_get_crtc_scanoutpos(rdev, crtc, &vpos, &hpos); |
724 | } | 724 | if ((vbl_status & RADEON_SCANOUTPOS_VALID) && |
725 | if (rdev->pm.active_crtcs & (1 << 1)) { | 725 | !(vbl_status & RADEON_SCANOUTPOS_INVBL)) |
726 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
727 | EVERGREEN_CRTC1_REGISTER_OFFSET) & 0xfff; | ||
728 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
729 | EVERGREEN_CRTC1_REGISTER_OFFSET) & 0xfff; | ||
730 | } | ||
731 | if (rdev->pm.active_crtcs & (1 << 2)) { | ||
732 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
733 | EVERGREEN_CRTC2_REGISTER_OFFSET) & 0xfff; | ||
734 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
735 | EVERGREEN_CRTC2_REGISTER_OFFSET) & 0xfff; | ||
736 | } | ||
737 | if (rdev->pm.active_crtcs & (1 << 3)) { | ||
738 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
739 | EVERGREEN_CRTC3_REGISTER_OFFSET) & 0xfff; | ||
740 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
741 | EVERGREEN_CRTC3_REGISTER_OFFSET) & 0xfff; | ||
742 | } | ||
743 | if (rdev->pm.active_crtcs & (1 << 4)) { | ||
744 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
745 | EVERGREEN_CRTC4_REGISTER_OFFSET) & 0xfff; | ||
746 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
747 | EVERGREEN_CRTC4_REGISTER_OFFSET) & 0xfff; | ||
748 | } | ||
749 | if (rdev->pm.active_crtcs & (1 << 5)) { | ||
750 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | ||
751 | EVERGREEN_CRTC5_REGISTER_OFFSET) & 0xfff; | ||
752 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | ||
753 | EVERGREEN_CRTC5_REGISTER_OFFSET) & 0xfff; | ||
754 | } | ||
755 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
756 | if (rdev->pm.active_crtcs & (1 << 0)) { | ||
757 | vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END) & 0xfff; | ||
758 | position = RREG32(AVIVO_D1CRTC_STATUS_POSITION) & 0xfff; | ||
759 | } | ||
760 | if (rdev->pm.active_crtcs & (1 << 1)) { | ||
761 | vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END) & 0xfff; | ||
762 | position = RREG32(AVIVO_D2CRTC_STATUS_POSITION) & 0xfff; | ||
763 | } | ||
764 | if (position < vbl && position > 1) | ||
765 | in_vbl = false; | ||
766 | } else { | ||
767 | if (rdev->pm.active_crtcs & (1 << 0)) { | ||
768 | stat_crtc = RREG32(RADEON_CRTC_STATUS); | ||
769 | if (!(stat_crtc & 1)) | ||
770 | in_vbl = false; | ||
771 | } | ||
772 | if (rdev->pm.active_crtcs & (1 << 1)) { | ||
773 | stat_crtc = RREG32(RADEON_CRTC2_STATUS); | ||
774 | if (!(stat_crtc & 1)) | ||
775 | in_vbl = false; | 726 | in_vbl = false; |
776 | } | 727 | } |
777 | } | 728 | } |
778 | 729 | ||
779 | if (position < vbl && position > 1) | ||
780 | in_vbl = false; | ||
781 | |||
782 | return in_vbl; | 730 | return in_vbl; |
783 | } | 731 | } |
784 | 732 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 261e98a276db..6ea798ce8218 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -247,10 +247,14 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) | |||
247 | */ | 247 | */ |
248 | void radeon_ring_free_size(struct radeon_device *rdev) | 248 | void radeon_ring_free_size(struct radeon_device *rdev) |
249 | { | 249 | { |
250 | if (rdev->family >= CHIP_R600) | 250 | if (rdev->wb.enabled) |
251 | rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); | 251 | rdev->cp.rptr = rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4]; |
252 | else | 252 | else { |
253 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); | 253 | if (rdev->family >= CHIP_R600) |
254 | rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); | ||
255 | else | ||
256 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); | ||
257 | } | ||
254 | /* This works because ring_size is a power of 2 */ | 258 | /* This works because ring_size is a power of 2 */ |
255 | rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); | 259 | rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); |
256 | rdev->cp.ring_free_dw -= rdev->cp.wptr; | 260 | rdev->cp.ring_free_dw -= rdev->cp.wptr; |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 84c53e41a88f..0921910698d4 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
@@ -152,6 +152,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
152 | man->default_caching = TTM_PL_FLAG_CACHED; | 152 | man->default_caching = TTM_PL_FLAG_CACHED; |
153 | break; | 153 | break; |
154 | case TTM_PL_TT: | 154 | case TTM_PL_TT: |
155 | man->func = &ttm_bo_manager_func; | ||
155 | man->gpu_offset = rdev->mc.gtt_start; | 156 | man->gpu_offset = rdev->mc.gtt_start; |
156 | man->available_caching = TTM_PL_MASK_CACHING; | 157 | man->available_caching = TTM_PL_MASK_CACHING; |
157 | man->default_caching = TTM_PL_FLAG_CACHED; | 158 | man->default_caching = TTM_PL_FLAG_CACHED; |
@@ -173,6 +174,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
173 | break; | 174 | break; |
174 | case TTM_PL_VRAM: | 175 | case TTM_PL_VRAM: |
175 | /* "On-card" video ram */ | 176 | /* "On-card" video ram */ |
177 | man->func = &ttm_bo_manager_func; | ||
176 | man->gpu_offset = rdev->mc.vram_start; | 178 | man->gpu_offset = rdev->mc.vram_start; |
177 | man->flags = TTM_MEMTYPE_FLAG_FIXED | | 179 | man->flags = TTM_MEMTYPE_FLAG_FIXED | |
178 | TTM_MEMTYPE_FLAG_MAPPABLE; | 180 | TTM_MEMTYPE_FLAG_MAPPABLE; |
@@ -246,8 +248,8 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
246 | if (unlikely(r)) { | 248 | if (unlikely(r)) { |
247 | return r; | 249 | return r; |
248 | } | 250 | } |
249 | old_start = old_mem->mm_node->start << PAGE_SHIFT; | 251 | old_start = old_mem->start << PAGE_SHIFT; |
250 | new_start = new_mem->mm_node->start << PAGE_SHIFT; | 252 | new_start = new_mem->start << PAGE_SHIFT; |
251 | 253 | ||
252 | switch (old_mem->mem_type) { | 254 | switch (old_mem->mem_type) { |
253 | case TTM_PL_VRAM: | 255 | case TTM_PL_VRAM: |
@@ -326,14 +328,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, | |||
326 | } | 328 | } |
327 | r = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem); | 329 | r = ttm_bo_move_ttm(bo, true, no_wait_reserve, no_wait_gpu, new_mem); |
328 | out_cleanup: | 330 | out_cleanup: |
329 | if (tmp_mem.mm_node) { | 331 | ttm_bo_mem_put(bo, &tmp_mem); |
330 | struct ttm_bo_global *glob = rdev->mman.bdev.glob; | ||
331 | |||
332 | spin_lock(&glob->lru_lock); | ||
333 | drm_mm_put_block(tmp_mem.mm_node); | ||
334 | spin_unlock(&glob->lru_lock); | ||
335 | return r; | ||
336 | } | ||
337 | return r; | 332 | return r; |
338 | } | 333 | } |
339 | 334 | ||
@@ -372,14 +367,7 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, | |||
372 | goto out_cleanup; | 367 | goto out_cleanup; |
373 | } | 368 | } |
374 | out_cleanup: | 369 | out_cleanup: |
375 | if (tmp_mem.mm_node) { | 370 | ttm_bo_mem_put(bo, &tmp_mem); |
376 | struct ttm_bo_global *glob = rdev->mman.bdev.glob; | ||
377 | |||
378 | spin_lock(&glob->lru_lock); | ||
379 | drm_mm_put_block(tmp_mem.mm_node); | ||
380 | spin_unlock(&glob->lru_lock); | ||
381 | return r; | ||
382 | } | ||
383 | return r; | 371 | return r; |
384 | } | 372 | } |
385 | 373 | ||
@@ -449,14 +437,14 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_ | |||
449 | #if __OS_HAS_AGP | 437 | #if __OS_HAS_AGP |
450 | if (rdev->flags & RADEON_IS_AGP) { | 438 | if (rdev->flags & RADEON_IS_AGP) { |
451 | /* RADEON_IS_AGP is set only if AGP is active */ | 439 | /* RADEON_IS_AGP is set only if AGP is active */ |
452 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; | 440 | mem->bus.offset = mem->start << PAGE_SHIFT; |
453 | mem->bus.base = rdev->mc.agp_base; | 441 | mem->bus.base = rdev->mc.agp_base; |
454 | mem->bus.is_iomem = !rdev->ddev->agp->cant_use_aperture; | 442 | mem->bus.is_iomem = !rdev->ddev->agp->cant_use_aperture; |
455 | } | 443 | } |
456 | #endif | 444 | #endif |
457 | break; | 445 | break; |
458 | case TTM_PL_VRAM: | 446 | case TTM_PL_VRAM: |
459 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; | 447 | mem->bus.offset = mem->start << PAGE_SHIFT; |
460 | /* check if it's visible */ | 448 | /* check if it's visible */ |
461 | if ((mem->bus.offset + mem->bus.size) > rdev->mc.visible_vram_size) | 449 | if ((mem->bus.offset + mem->bus.size) > rdev->mc.visible_vram_size) |
462 | return -EINVAL; | 450 | return -EINVAL; |
@@ -699,7 +687,7 @@ static int radeon_ttm_backend_bind(struct ttm_backend *backend, | |||
699 | int r; | 687 | int r; |
700 | 688 | ||
701 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | 689 | gtt = container_of(backend, struct radeon_ttm_backend, backend); |
702 | gtt->offset = bo_mem->mm_node->start << PAGE_SHIFT; | 690 | gtt->offset = bo_mem->start << PAGE_SHIFT; |
703 | if (!gtt->num_pages) { | 691 | if (!gtt->num_pages) { |
704 | WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend); | 692 | WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend); |
705 | } | 693 | } |
@@ -798,9 +786,9 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev) | |||
798 | radeon_mem_types_list[i].show = &radeon_mm_dump_table; | 786 | radeon_mem_types_list[i].show = &radeon_mm_dump_table; |
799 | radeon_mem_types_list[i].driver_features = 0; | 787 | radeon_mem_types_list[i].driver_features = 0; |
800 | if (i == 0) | 788 | if (i == 0) |
801 | radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].manager; | 789 | radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].priv; |
802 | else | 790 | else |
803 | radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].manager; | 791 | radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].priv; |
804 | 792 | ||
805 | } | 793 | } |
806 | /* Add ttm page pool to debugfs */ | 794 | /* Add ttm page pool to debugfs */ |
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index ae2b76b9a388..f683e51a2a06 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
@@ -397,6 +397,12 @@ static int rs400_startup(struct radeon_device *rdev) | |||
397 | r = rs400_gart_enable(rdev); | 397 | r = rs400_gart_enable(rdev); |
398 | if (r) | 398 | if (r) |
399 | return r; | 399 | return r; |
400 | |||
401 | /* allocate wb buffer */ | ||
402 | r = radeon_wb_init(rdev); | ||
403 | if (r) | ||
404 | return r; | ||
405 | |||
400 | /* Enable IRQ */ | 406 | /* Enable IRQ */ |
401 | r100_irq_set(rdev); | 407 | r100_irq_set(rdev); |
402 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 408 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -406,9 +412,6 @@ static int rs400_startup(struct radeon_device *rdev) | |||
406 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 412 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
407 | return r; | 413 | return r; |
408 | } | 414 | } |
409 | r = r100_wb_init(rdev); | ||
410 | if (r) | ||
411 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
412 | r = r100_ib_init(rdev); | 415 | r = r100_ib_init(rdev); |
413 | if (r) { | 416 | if (r) { |
414 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 417 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -443,7 +446,7 @@ int rs400_resume(struct radeon_device *rdev) | |||
443 | int rs400_suspend(struct radeon_device *rdev) | 446 | int rs400_suspend(struct radeon_device *rdev) |
444 | { | 447 | { |
445 | r100_cp_disable(rdev); | 448 | r100_cp_disable(rdev); |
446 | r100_wb_disable(rdev); | 449 | radeon_wb_disable(rdev); |
447 | r100_irq_disable(rdev); | 450 | r100_irq_disable(rdev); |
448 | rs400_gart_disable(rdev); | 451 | rs400_gart_disable(rdev); |
449 | return 0; | 452 | return 0; |
@@ -452,7 +455,7 @@ int rs400_suspend(struct radeon_device *rdev) | |||
452 | void rs400_fini(struct radeon_device *rdev) | 455 | void rs400_fini(struct radeon_device *rdev) |
453 | { | 456 | { |
454 | r100_cp_fini(rdev); | 457 | r100_cp_fini(rdev); |
455 | r100_wb_fini(rdev); | 458 | radeon_wb_fini(rdev); |
456 | r100_ib_fini(rdev); | 459 | r100_ib_fini(rdev); |
457 | radeon_gem_fini(rdev); | 460 | radeon_gem_fini(rdev); |
458 | rs400_gart_fini(rdev); | 461 | rs400_gart_fini(rdev); |
@@ -526,7 +529,7 @@ int rs400_init(struct radeon_device *rdev) | |||
526 | /* Somethings want wront with the accel init stop accel */ | 529 | /* Somethings want wront with the accel init stop accel */ |
527 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 530 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
528 | r100_cp_fini(rdev); | 531 | r100_cp_fini(rdev); |
529 | r100_wb_fini(rdev); | 532 | radeon_wb_fini(rdev); |
530 | r100_ib_fini(rdev); | 533 | r100_ib_fini(rdev); |
531 | rs400_gart_fini(rdev); | 534 | rs400_gart_fini(rdev); |
532 | radeon_irq_kms_fini(rdev); | 535 | radeon_irq_kms_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 51d5f7b5ab21..b091a1f6fa4e 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -796,6 +796,12 @@ static int rs600_startup(struct radeon_device *rdev) | |||
796 | r = rs600_gart_enable(rdev); | 796 | r = rs600_gart_enable(rdev); |
797 | if (r) | 797 | if (r) |
798 | return r; | 798 | return r; |
799 | |||
800 | /* allocate wb buffer */ | ||
801 | r = radeon_wb_init(rdev); | ||
802 | if (r) | ||
803 | return r; | ||
804 | |||
799 | /* Enable IRQ */ | 805 | /* Enable IRQ */ |
800 | rs600_irq_set(rdev); | 806 | rs600_irq_set(rdev); |
801 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 807 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -805,9 +811,6 @@ static int rs600_startup(struct radeon_device *rdev) | |||
805 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 811 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
806 | return r; | 812 | return r; |
807 | } | 813 | } |
808 | r = r100_wb_init(rdev); | ||
809 | if (r) | ||
810 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
811 | r = r100_ib_init(rdev); | 814 | r = r100_ib_init(rdev); |
812 | if (r) { | 815 | if (r) { |
813 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 816 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -848,7 +851,7 @@ int rs600_suspend(struct radeon_device *rdev) | |||
848 | { | 851 | { |
849 | r600_audio_fini(rdev); | 852 | r600_audio_fini(rdev); |
850 | r100_cp_disable(rdev); | 853 | r100_cp_disable(rdev); |
851 | r100_wb_disable(rdev); | 854 | radeon_wb_disable(rdev); |
852 | rs600_irq_disable(rdev); | 855 | rs600_irq_disable(rdev); |
853 | rs600_gart_disable(rdev); | 856 | rs600_gart_disable(rdev); |
854 | return 0; | 857 | return 0; |
@@ -858,7 +861,7 @@ void rs600_fini(struct radeon_device *rdev) | |||
858 | { | 861 | { |
859 | r600_audio_fini(rdev); | 862 | r600_audio_fini(rdev); |
860 | r100_cp_fini(rdev); | 863 | r100_cp_fini(rdev); |
861 | r100_wb_fini(rdev); | 864 | radeon_wb_fini(rdev); |
862 | r100_ib_fini(rdev); | 865 | r100_ib_fini(rdev); |
863 | radeon_gem_fini(rdev); | 866 | radeon_gem_fini(rdev); |
864 | rs600_gart_fini(rdev); | 867 | rs600_gart_fini(rdev); |
@@ -932,7 +935,7 @@ int rs600_init(struct radeon_device *rdev) | |||
932 | /* Somethings want wront with the accel init stop accel */ | 935 | /* Somethings want wront with the accel init stop accel */ |
933 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 936 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
934 | r100_cp_fini(rdev); | 937 | r100_cp_fini(rdev); |
935 | r100_wb_fini(rdev); | 938 | radeon_wb_fini(rdev); |
936 | r100_ib_fini(rdev); | 939 | r100_ib_fini(rdev); |
937 | rs600_gart_fini(rdev); | 940 | rs600_gart_fini(rdev); |
938 | radeon_irq_kms_fini(rdev); | 941 | radeon_irq_kms_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 4dc2a87ea680..0137d3e3728d 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
@@ -616,6 +616,12 @@ static int rs690_startup(struct radeon_device *rdev) | |||
616 | r = rs400_gart_enable(rdev); | 616 | r = rs400_gart_enable(rdev); |
617 | if (r) | 617 | if (r) |
618 | return r; | 618 | return r; |
619 | |||
620 | /* allocate wb buffer */ | ||
621 | r = radeon_wb_init(rdev); | ||
622 | if (r) | ||
623 | return r; | ||
624 | |||
619 | /* Enable IRQ */ | 625 | /* Enable IRQ */ |
620 | rs600_irq_set(rdev); | 626 | rs600_irq_set(rdev); |
621 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 627 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -625,9 +631,6 @@ static int rs690_startup(struct radeon_device *rdev) | |||
625 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 631 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
626 | return r; | 632 | return r; |
627 | } | 633 | } |
628 | r = r100_wb_init(rdev); | ||
629 | if (r) | ||
630 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
631 | r = r100_ib_init(rdev); | 634 | r = r100_ib_init(rdev); |
632 | if (r) { | 635 | if (r) { |
633 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 636 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -668,7 +671,7 @@ int rs690_suspend(struct radeon_device *rdev) | |||
668 | { | 671 | { |
669 | r600_audio_fini(rdev); | 672 | r600_audio_fini(rdev); |
670 | r100_cp_disable(rdev); | 673 | r100_cp_disable(rdev); |
671 | r100_wb_disable(rdev); | 674 | radeon_wb_disable(rdev); |
672 | rs600_irq_disable(rdev); | 675 | rs600_irq_disable(rdev); |
673 | rs400_gart_disable(rdev); | 676 | rs400_gart_disable(rdev); |
674 | return 0; | 677 | return 0; |
@@ -678,7 +681,7 @@ void rs690_fini(struct radeon_device *rdev) | |||
678 | { | 681 | { |
679 | r600_audio_fini(rdev); | 682 | r600_audio_fini(rdev); |
680 | r100_cp_fini(rdev); | 683 | r100_cp_fini(rdev); |
681 | r100_wb_fini(rdev); | 684 | radeon_wb_fini(rdev); |
682 | r100_ib_fini(rdev); | 685 | r100_ib_fini(rdev); |
683 | radeon_gem_fini(rdev); | 686 | radeon_gem_fini(rdev); |
684 | rs400_gart_fini(rdev); | 687 | rs400_gart_fini(rdev); |
@@ -753,7 +756,7 @@ int rs690_init(struct radeon_device *rdev) | |||
753 | /* Somethings want wront with the accel init stop accel */ | 756 | /* Somethings want wront with the accel init stop accel */ |
754 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 757 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
755 | r100_cp_fini(rdev); | 758 | r100_cp_fini(rdev); |
756 | r100_wb_fini(rdev); | 759 | radeon_wb_fini(rdev); |
757 | r100_ib_fini(rdev); | 760 | r100_ib_fini(rdev); |
758 | rs400_gart_fini(rdev); | 761 | rs400_gart_fini(rdev); |
759 | radeon_irq_kms_fini(rdev); | 762 | radeon_irq_kms_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 4d6e86041a9f..5d569f41f4ae 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
@@ -386,6 +386,12 @@ static int rv515_startup(struct radeon_device *rdev) | |||
386 | if (r) | 386 | if (r) |
387 | return r; | 387 | return r; |
388 | } | 388 | } |
389 | |||
390 | /* allocate wb buffer */ | ||
391 | r = radeon_wb_init(rdev); | ||
392 | if (r) | ||
393 | return r; | ||
394 | |||
389 | /* Enable IRQ */ | 395 | /* Enable IRQ */ |
390 | rs600_irq_set(rdev); | 396 | rs600_irq_set(rdev); |
391 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | 397 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
@@ -395,9 +401,6 @@ static int rv515_startup(struct radeon_device *rdev) | |||
395 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 401 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
396 | return r; | 402 | return r; |
397 | } | 403 | } |
398 | r = r100_wb_init(rdev); | ||
399 | if (r) | ||
400 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
401 | r = r100_ib_init(rdev); | 404 | r = r100_ib_init(rdev); |
402 | if (r) { | 405 | if (r) { |
403 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | 406 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
@@ -431,7 +434,7 @@ int rv515_resume(struct radeon_device *rdev) | |||
431 | int rv515_suspend(struct radeon_device *rdev) | 434 | int rv515_suspend(struct radeon_device *rdev) |
432 | { | 435 | { |
433 | r100_cp_disable(rdev); | 436 | r100_cp_disable(rdev); |
434 | r100_wb_disable(rdev); | 437 | radeon_wb_disable(rdev); |
435 | rs600_irq_disable(rdev); | 438 | rs600_irq_disable(rdev); |
436 | if (rdev->flags & RADEON_IS_PCIE) | 439 | if (rdev->flags & RADEON_IS_PCIE) |
437 | rv370_pcie_gart_disable(rdev); | 440 | rv370_pcie_gart_disable(rdev); |
@@ -447,7 +450,7 @@ void rv515_set_safe_registers(struct radeon_device *rdev) | |||
447 | void rv515_fini(struct radeon_device *rdev) | 450 | void rv515_fini(struct radeon_device *rdev) |
448 | { | 451 | { |
449 | r100_cp_fini(rdev); | 452 | r100_cp_fini(rdev); |
450 | r100_wb_fini(rdev); | 453 | radeon_wb_fini(rdev); |
451 | r100_ib_fini(rdev); | 454 | r100_ib_fini(rdev); |
452 | radeon_gem_fini(rdev); | 455 | radeon_gem_fini(rdev); |
453 | rv370_pcie_gart_fini(rdev); | 456 | rv370_pcie_gart_fini(rdev); |
@@ -527,7 +530,7 @@ int rv515_init(struct radeon_device *rdev) | |||
527 | /* Somethings want wront with the accel init stop accel */ | 530 | /* Somethings want wront with the accel init stop accel */ |
528 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 531 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
529 | r100_cp_fini(rdev); | 532 | r100_cp_fini(rdev); |
530 | r100_wb_fini(rdev); | 533 | radeon_wb_fini(rdev); |
531 | r100_ib_fini(rdev); | 534 | r100_ib_fini(rdev); |
532 | radeon_irq_kms_fini(rdev); | 535 | radeon_irq_kms_fini(rdev); |
533 | rv370_pcie_gart_fini(rdev); | 536 | rv370_pcie_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 9490da700749..ab83f688263a 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -269,6 +269,7 @@ void r700_cp_stop(struct radeon_device *rdev) | |||
269 | { | 269 | { |
270 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 270 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; |
271 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); | 271 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); |
272 | WREG32(SCRATCH_UMSK, 0); | ||
272 | } | 273 | } |
273 | 274 | ||
274 | static int rv770_cp_load_microcode(struct radeon_device *rdev) | 275 | static int rv770_cp_load_microcode(struct radeon_device *rdev) |
@@ -1030,19 +1031,12 @@ static int rv770_startup(struct radeon_device *rdev) | |||
1030 | rdev->asic->copy = NULL; | 1031 | rdev->asic->copy = NULL; |
1031 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); | 1032 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); |
1032 | } | 1033 | } |
1033 | /* pin copy shader into vram */ | 1034 | |
1034 | if (rdev->r600_blit.shader_obj) { | 1035 | /* allocate wb buffer */ |
1035 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 1036 | r = radeon_wb_init(rdev); |
1036 | if (unlikely(r != 0)) | 1037 | if (r) |
1037 | return r; | 1038 | return r; |
1038 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | 1039 | |
1039 | &rdev->r600_blit.shader_gpu_addr); | ||
1040 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
1041 | if (r) { | ||
1042 | DRM_ERROR("failed to pin blit object %d\n", r); | ||
1043 | return r; | ||
1044 | } | ||
1045 | } | ||
1046 | /* Enable IRQ */ | 1040 | /* Enable IRQ */ |
1047 | r = r600_irq_init(rdev); | 1041 | r = r600_irq_init(rdev); |
1048 | if (r) { | 1042 | if (r) { |
@@ -1061,8 +1055,7 @@ static int rv770_startup(struct radeon_device *rdev) | |||
1061 | r = r600_cp_resume(rdev); | 1055 | r = r600_cp_resume(rdev); |
1062 | if (r) | 1056 | if (r) |
1063 | return r; | 1057 | return r; |
1064 | /* write back buffer are not vital so don't worry about failure */ | 1058 | |
1065 | r600_wb_enable(rdev); | ||
1066 | return 0; | 1059 | return 0; |
1067 | } | 1060 | } |
1068 | 1061 | ||
@@ -1108,7 +1101,7 @@ int rv770_suspend(struct radeon_device *rdev) | |||
1108 | r700_cp_stop(rdev); | 1101 | r700_cp_stop(rdev); |
1109 | rdev->cp.ready = false; | 1102 | rdev->cp.ready = false; |
1110 | r600_irq_suspend(rdev); | 1103 | r600_irq_suspend(rdev); |
1111 | r600_wb_disable(rdev); | 1104 | radeon_wb_disable(rdev); |
1112 | rv770_pcie_gart_disable(rdev); | 1105 | rv770_pcie_gart_disable(rdev); |
1113 | /* unpin shaders bo */ | 1106 | /* unpin shaders bo */ |
1114 | if (rdev->r600_blit.shader_obj) { | 1107 | if (rdev->r600_blit.shader_obj) { |
@@ -1203,8 +1196,8 @@ int rv770_init(struct radeon_device *rdev) | |||
1203 | if (r) { | 1196 | if (r) { |
1204 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 1197 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
1205 | r700_cp_fini(rdev); | 1198 | r700_cp_fini(rdev); |
1206 | r600_wb_fini(rdev); | ||
1207 | r600_irq_fini(rdev); | 1199 | r600_irq_fini(rdev); |
1200 | radeon_wb_fini(rdev); | ||
1208 | radeon_irq_kms_fini(rdev); | 1201 | radeon_irq_kms_fini(rdev); |
1209 | rv770_pcie_gart_fini(rdev); | 1202 | rv770_pcie_gart_fini(rdev); |
1210 | rdev->accel_working = false; | 1203 | rdev->accel_working = false; |
@@ -1236,8 +1229,8 @@ void rv770_fini(struct radeon_device *rdev) | |||
1236 | { | 1229 | { |
1237 | r600_blit_fini(rdev); | 1230 | r600_blit_fini(rdev); |
1238 | r700_cp_fini(rdev); | 1231 | r700_cp_fini(rdev); |
1239 | r600_wb_fini(rdev); | ||
1240 | r600_irq_fini(rdev); | 1232 | r600_irq_fini(rdev); |
1233 | radeon_wb_fini(rdev); | ||
1241 | radeon_irq_kms_fini(rdev); | 1234 | radeon_irq_kms_fini(rdev); |
1242 | rv770_pcie_gart_fini(rdev); | 1235 | rv770_pcie_gart_fini(rdev); |
1243 | rv770_vram_scratch_fini(rdev); | 1236 | rv770_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 021de44c15ab..c0385633667d 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c | |||
@@ -42,8 +42,6 @@ static struct drm_driver driver = { | |||
42 | .lastclose = savage_driver_lastclose, | 42 | .lastclose = savage_driver_lastclose, |
43 | .unload = savage_driver_unload, | 43 | .unload = savage_driver_unload, |
44 | .reclaim_buffers = savage_reclaim_buffers, | 44 | .reclaim_buffers = savage_reclaim_buffers, |
45 | .get_map_ofs = drm_core_get_map_ofs, | ||
46 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
47 | .ioctls = savage_ioctls, | 45 | .ioctls = savage_ioctls, |
48 | .dma_ioctl = savage_bci_buffers, | 46 | .dma_ioctl = savage_bci_buffers, |
49 | .fops = { | 47 | .fops = { |
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 776bf9e9ea1a..4d9f311d249d 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c | |||
@@ -67,13 +67,10 @@ static struct drm_driver driver = { | |||
67 | .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, | 67 | .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, |
68 | .load = sis_driver_load, | 68 | .load = sis_driver_load, |
69 | .unload = sis_driver_unload, | 69 | .unload = sis_driver_unload, |
70 | .context_dtor = NULL, | ||
71 | .dma_quiescent = sis_idle, | 70 | .dma_quiescent = sis_idle, |
72 | .reclaim_buffers = NULL, | 71 | .reclaim_buffers = NULL, |
73 | .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, | 72 | .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, |
74 | .lastclose = sis_lastclose, | 73 | .lastclose = sis_lastclose, |
75 | .get_map_ofs = drm_core_get_map_ofs, | ||
76 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
77 | .ioctls = sis_ioctls, | 74 | .ioctls = sis_ioctls, |
78 | .fops = { | 75 | .fops = { |
79 | .owner = THIS_MODULE, | 76 | .owner = THIS_MODULE, |
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index ec5a43e65722..e0768adbeccd 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c | |||
@@ -42,8 +42,6 @@ static struct pci_device_id pciidlist[] = { | |||
42 | static struct drm_driver driver = { | 42 | static struct drm_driver driver = { |
43 | .driver_features = DRIVER_USE_MTRR, | 43 | .driver_features = DRIVER_USE_MTRR, |
44 | .reclaim_buffers = drm_core_reclaim_buffers, | 44 | .reclaim_buffers = drm_core_reclaim_buffers, |
45 | .get_map_ofs = drm_core_get_map_ofs, | ||
46 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
47 | .fops = { | 45 | .fops = { |
48 | .owner = THIS_MODULE, | 46 | .owner = THIS_MODULE, |
49 | .open = drm_open, | 47 | .open = drm_open, |
diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile index b256d4adfafe..f3cf6f02c997 100644 --- a/drivers/gpu/drm/ttm/Makefile +++ b/drivers/gpu/drm/ttm/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | ccflags-y := -Iinclude/drm | 4 | ccflags-y := -Iinclude/drm |
5 | ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ | 5 | ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ |
6 | ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ | 6 | ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ |
7 | ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o | 7 | ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \ |
8 | ttm_bo_manager.o | ||
8 | 9 | ||
9 | obj-$(CONFIG_DRM_TTM) += ttm.o | 10 | obj-$(CONFIG_DRM_TTM) += ttm.o |
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 4bf69c404491..f999e36f30b4 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c | |||
@@ -74,6 +74,7 @@ static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem) | |||
74 | { | 74 | { |
75 | struct ttm_agp_backend *agp_be = | 75 | struct ttm_agp_backend *agp_be = |
76 | container_of(backend, struct ttm_agp_backend, backend); | 76 | container_of(backend, struct ttm_agp_backend, backend); |
77 | struct drm_mm_node *node = bo_mem->mm_node; | ||
77 | struct agp_memory *mem = agp_be->mem; | 78 | struct agp_memory *mem = agp_be->mem; |
78 | int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); | 79 | int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); |
79 | int ret; | 80 | int ret; |
@@ -81,7 +82,7 @@ static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem) | |||
81 | mem->is_flushed = 1; | 82 | mem->is_flushed = 1; |
82 | mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; | 83 | mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; |
83 | 84 | ||
84 | ret = agp_bind_memory(mem, bo_mem->mm_node->start); | 85 | ret = agp_bind_memory(mem, node->start); |
85 | if (ret) | 86 | if (ret) |
86 | printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n"); | 87 | printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n"); |
87 | 88 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index db809e034cc4..1e9bb2156dcf 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -84,11 +84,8 @@ static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type) | |||
84 | man->available_caching); | 84 | man->available_caching); |
85 | printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", | 85 | printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", |
86 | man->default_caching); | 86 | man->default_caching); |
87 | if (mem_type != TTM_PL_SYSTEM) { | 87 | if (mem_type != TTM_PL_SYSTEM) |
88 | spin_lock(&bdev->glob->lru_lock); | 88 | (*man->func->debug)(man, TTM_PFX); |
89 | drm_mm_debug_table(&man->manager, TTM_PFX); | ||
90 | spin_unlock(&bdev->glob->lru_lock); | ||
91 | } | ||
92 | } | 89 | } |
93 | 90 | ||
94 | static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, | 91 | static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, |
@@ -421,7 +418,7 @@ moved: | |||
421 | 418 | ||
422 | if (bo->mem.mm_node) { | 419 | if (bo->mem.mm_node) { |
423 | spin_lock(&bo->lock); | 420 | spin_lock(&bo->lock); |
424 | bo->offset = (bo->mem.mm_node->start << PAGE_SHIFT) + | 421 | bo->offset = (bo->mem.start << PAGE_SHIFT) + |
425 | bdev->man[bo->mem.mem_type].gpu_offset; | 422 | bdev->man[bo->mem.mem_type].gpu_offset; |
426 | bo->cur_placement = bo->mem.placement; | 423 | bo->cur_placement = bo->mem.placement; |
427 | spin_unlock(&bo->lock); | 424 | spin_unlock(&bo->lock); |
@@ -468,8 +465,7 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) | |||
468 | } | 465 | } |
469 | 466 | ||
470 | if (bo->mem.mm_node) { | 467 | if (bo->mem.mm_node) { |
471 | drm_mm_put_block(bo->mem.mm_node); | 468 | ttm_bo_mem_put(bo, &bo->mem); |
472 | bo->mem.mm_node = NULL; | ||
473 | } | 469 | } |
474 | 470 | ||
475 | atomic_set(&bo->reserved, 0); | 471 | atomic_set(&bo->reserved, 0); |
@@ -680,7 +676,6 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, | |||
680 | bool no_wait_reserve, bool no_wait_gpu) | 676 | bool no_wait_reserve, bool no_wait_gpu) |
681 | { | 677 | { |
682 | struct ttm_bo_device *bdev = bo->bdev; | 678 | struct ttm_bo_device *bdev = bo->bdev; |
683 | struct ttm_bo_global *glob = bo->glob; | ||
684 | struct ttm_mem_reg evict_mem; | 679 | struct ttm_mem_reg evict_mem; |
685 | struct ttm_placement placement; | 680 | struct ttm_placement placement; |
686 | int ret = 0; | 681 | int ret = 0; |
@@ -726,12 +721,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, | |||
726 | if (ret) { | 721 | if (ret) { |
727 | if (ret != -ERESTARTSYS) | 722 | if (ret != -ERESTARTSYS) |
728 | printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); | 723 | printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); |
729 | spin_lock(&glob->lru_lock); | 724 | ttm_bo_mem_put(bo, &evict_mem); |
730 | if (evict_mem.mm_node) { | ||
731 | drm_mm_put_block(evict_mem.mm_node); | ||
732 | evict_mem.mm_node = NULL; | ||
733 | } | ||
734 | spin_unlock(&glob->lru_lock); | ||
735 | goto out; | 725 | goto out; |
736 | } | 726 | } |
737 | bo->evicted = true; | 727 | bo->evicted = true; |
@@ -792,41 +782,14 @@ retry: | |||
792 | return ret; | 782 | return ret; |
793 | } | 783 | } |
794 | 784 | ||
795 | static int ttm_bo_man_get_node(struct ttm_buffer_object *bo, | 785 | void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) |
796 | struct ttm_mem_type_manager *man, | ||
797 | struct ttm_placement *placement, | ||
798 | struct ttm_mem_reg *mem, | ||
799 | struct drm_mm_node **node) | ||
800 | { | 786 | { |
801 | struct ttm_bo_global *glob = bo->glob; | 787 | struct ttm_mem_type_manager *man = &bo->bdev->man[mem->mem_type]; |
802 | unsigned long lpfn; | ||
803 | int ret; | ||
804 | 788 | ||
805 | lpfn = placement->lpfn; | 789 | if (mem->mm_node) |
806 | if (!lpfn) | 790 | (*man->func->put_node)(man, mem); |
807 | lpfn = man->size; | ||
808 | *node = NULL; | ||
809 | do { | ||
810 | ret = drm_mm_pre_get(&man->manager); | ||
811 | if (unlikely(ret)) | ||
812 | return ret; | ||
813 | |||
814 | spin_lock(&glob->lru_lock); | ||
815 | *node = drm_mm_search_free_in_range(&man->manager, | ||
816 | mem->num_pages, mem->page_alignment, | ||
817 | placement->fpfn, lpfn, 1); | ||
818 | if (unlikely(*node == NULL)) { | ||
819 | spin_unlock(&glob->lru_lock); | ||
820 | return 0; | ||
821 | } | ||
822 | *node = drm_mm_get_block_atomic_range(*node, mem->num_pages, | ||
823 | mem->page_alignment, | ||
824 | placement->fpfn, | ||
825 | lpfn); | ||
826 | spin_unlock(&glob->lru_lock); | ||
827 | } while (*node == NULL); | ||
828 | return 0; | ||
829 | } | 791 | } |
792 | EXPORT_SYMBOL(ttm_bo_mem_put); | ||
830 | 793 | ||
831 | /** | 794 | /** |
832 | * Repeatedly evict memory from the LRU for @mem_type until we create enough | 795 | * Repeatedly evict memory from the LRU for @mem_type until we create enough |
@@ -843,14 +806,13 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, | |||
843 | struct ttm_bo_device *bdev = bo->bdev; | 806 | struct ttm_bo_device *bdev = bo->bdev; |
844 | struct ttm_bo_global *glob = bdev->glob; | 807 | struct ttm_bo_global *glob = bdev->glob; |
845 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | 808 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; |
846 | struct drm_mm_node *node; | ||
847 | int ret; | 809 | int ret; |
848 | 810 | ||
849 | do { | 811 | do { |
850 | ret = ttm_bo_man_get_node(bo, man, placement, mem, &node); | 812 | ret = (*man->func->get_node)(man, bo, placement, mem); |
851 | if (unlikely(ret != 0)) | 813 | if (unlikely(ret != 0)) |
852 | return ret; | 814 | return ret; |
853 | if (node) | 815 | if (mem->mm_node) |
854 | break; | 816 | break; |
855 | spin_lock(&glob->lru_lock); | 817 | spin_lock(&glob->lru_lock); |
856 | if (list_empty(&man->lru)) { | 818 | if (list_empty(&man->lru)) { |
@@ -863,9 +825,8 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, | |||
863 | if (unlikely(ret != 0)) | 825 | if (unlikely(ret != 0)) |
864 | return ret; | 826 | return ret; |
865 | } while (1); | 827 | } while (1); |
866 | if (node == NULL) | 828 | if (mem->mm_node == NULL) |
867 | return -ENOMEM; | 829 | return -ENOMEM; |
868 | mem->mm_node = node; | ||
869 | mem->mem_type = mem_type; | 830 | mem->mem_type = mem_type; |
870 | return 0; | 831 | return 0; |
871 | } | 832 | } |
@@ -939,7 +900,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, | |||
939 | bool type_found = false; | 900 | bool type_found = false; |
940 | bool type_ok = false; | 901 | bool type_ok = false; |
941 | bool has_erestartsys = false; | 902 | bool has_erestartsys = false; |
942 | struct drm_mm_node *node = NULL; | ||
943 | int i, ret; | 903 | int i, ret; |
944 | 904 | ||
945 | mem->mm_node = NULL; | 905 | mem->mm_node = NULL; |
@@ -973,17 +933,15 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, | |||
973 | 933 | ||
974 | if (man->has_type && man->use_type) { | 934 | if (man->has_type && man->use_type) { |
975 | type_found = true; | 935 | type_found = true; |
976 | ret = ttm_bo_man_get_node(bo, man, placement, mem, | 936 | ret = (*man->func->get_node)(man, bo, placement, mem); |
977 | &node); | ||
978 | if (unlikely(ret)) | 937 | if (unlikely(ret)) |
979 | return ret; | 938 | return ret; |
980 | } | 939 | } |
981 | if (node) | 940 | if (mem->mm_node) |
982 | break; | 941 | break; |
983 | } | 942 | } |
984 | 943 | ||
985 | if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || node) { | 944 | if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || mem->mm_node) { |
986 | mem->mm_node = node; | ||
987 | mem->mem_type = mem_type; | 945 | mem->mem_type = mem_type; |
988 | mem->placement = cur_flags; | 946 | mem->placement = cur_flags; |
989 | return 0; | 947 | return 0; |
@@ -1053,7 +1011,6 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, | |||
1053 | bool interruptible, bool no_wait_reserve, | 1011 | bool interruptible, bool no_wait_reserve, |
1054 | bool no_wait_gpu) | 1012 | bool no_wait_gpu) |
1055 | { | 1013 | { |
1056 | struct ttm_bo_global *glob = bo->glob; | ||
1057 | int ret = 0; | 1014 | int ret = 0; |
1058 | struct ttm_mem_reg mem; | 1015 | struct ttm_mem_reg mem; |
1059 | 1016 | ||
@@ -1081,11 +1038,8 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, | |||
1081 | goto out_unlock; | 1038 | goto out_unlock; |
1082 | ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait_reserve, no_wait_gpu); | 1039 | ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait_reserve, no_wait_gpu); |
1083 | out_unlock: | 1040 | out_unlock: |
1084 | if (ret && mem.mm_node) { | 1041 | if (ret && mem.mm_node) |
1085 | spin_lock(&glob->lru_lock); | 1042 | ttm_bo_mem_put(bo, &mem); |
1086 | drm_mm_put_block(mem.mm_node); | ||
1087 | spin_unlock(&glob->lru_lock); | ||
1088 | } | ||
1089 | return ret; | 1043 | return ret; |
1090 | } | 1044 | } |
1091 | 1045 | ||
@@ -1093,11 +1047,10 @@ static int ttm_bo_mem_compat(struct ttm_placement *placement, | |||
1093 | struct ttm_mem_reg *mem) | 1047 | struct ttm_mem_reg *mem) |
1094 | { | 1048 | { |
1095 | int i; | 1049 | int i; |
1096 | struct drm_mm_node *node = mem->mm_node; | ||
1097 | 1050 | ||
1098 | if (node && placement->lpfn != 0 && | 1051 | if (mem->mm_node && placement->lpfn != 0 && |
1099 | (node->start < placement->fpfn || | 1052 | (mem->start < placement->fpfn || |
1100 | node->start + node->size > placement->lpfn)) | 1053 | mem->start + mem->num_pages > placement->lpfn)) |
1101 | return -1; | 1054 | return -1; |
1102 | 1055 | ||
1103 | for (i = 0; i < placement->num_placement; i++) { | 1056 | for (i = 0; i < placement->num_placement; i++) { |
@@ -1341,7 +1294,6 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, | |||
1341 | 1294 | ||
1342 | int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) | 1295 | int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) |
1343 | { | 1296 | { |
1344 | struct ttm_bo_global *glob = bdev->glob; | ||
1345 | struct ttm_mem_type_manager *man; | 1297 | struct ttm_mem_type_manager *man; |
1346 | int ret = -EINVAL; | 1298 | int ret = -EINVAL; |
1347 | 1299 | ||
@@ -1364,13 +1316,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) | |||
1364 | if (mem_type > 0) { | 1316 | if (mem_type > 0) { |
1365 | ttm_bo_force_list_clean(bdev, mem_type, false); | 1317 | ttm_bo_force_list_clean(bdev, mem_type, false); |
1366 | 1318 | ||
1367 | spin_lock(&glob->lru_lock); | 1319 | ret = (*man->func->takedown)(man); |
1368 | if (drm_mm_clean(&man->manager)) | ||
1369 | drm_mm_takedown(&man->manager); | ||
1370 | else | ||
1371 | ret = -EBUSY; | ||
1372 | |||
1373 | spin_unlock(&glob->lru_lock); | ||
1374 | } | 1320 | } |
1375 | 1321 | ||
1376 | return ret; | 1322 | return ret; |
@@ -1421,6 +1367,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | |||
1421 | ret = bdev->driver->init_mem_type(bdev, type, man); | 1367 | ret = bdev->driver->init_mem_type(bdev, type, man); |
1422 | if (ret) | 1368 | if (ret) |
1423 | return ret; | 1369 | return ret; |
1370 | man->bdev = bdev; | ||
1424 | 1371 | ||
1425 | ret = 0; | 1372 | ret = 0; |
1426 | if (type != TTM_PL_SYSTEM) { | 1373 | if (type != TTM_PL_SYSTEM) { |
@@ -1430,7 +1377,8 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | |||
1430 | type); | 1377 | type); |
1431 | return ret; | 1378 | return ret; |
1432 | } | 1379 | } |
1433 | ret = drm_mm_init(&man->manager, 0, p_size); | 1380 | |
1381 | ret = (*man->func->init)(man, p_size); | ||
1434 | if (ret) | 1382 | if (ret) |
1435 | return ret; | 1383 | return ret; |
1436 | } | 1384 | } |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c new file mode 100644 index 000000000000..7410c190c891 --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /************************************************************************** | ||
2 | * | ||
3 | * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the | ||
8 | * "Software"), to deal in the Software without restriction, including | ||
9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
11 | * permit persons to whom the Software is furnished to do so, subject to | ||
12 | * the following conditions: | ||
13 | * | ||
14 | * The above copyright notice and this permission notice (including the | ||
15 | * next paragraph) shall be included in all copies or substantial portions | ||
16 | * of the Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
25 | * | ||
26 | **************************************************************************/ | ||
27 | /* | ||
28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
29 | */ | ||
30 | |||
31 | #include "ttm/ttm_module.h" | ||
32 | #include "ttm/ttm_bo_driver.h" | ||
33 | #include "ttm/ttm_placement.h" | ||
34 | #include <linux/jiffies.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/sched.h> | ||
37 | #include <linux/mm.h> | ||
38 | #include <linux/file.h> | ||
39 | #include <linux/module.h> | ||
40 | |||
41 | static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, | ||
42 | struct ttm_buffer_object *bo, | ||
43 | struct ttm_placement *placement, | ||
44 | struct ttm_mem_reg *mem) | ||
45 | { | ||
46 | struct ttm_bo_global *glob = man->bdev->glob; | ||
47 | struct drm_mm *mm = man->priv; | ||
48 | struct drm_mm_node *node = NULL; | ||
49 | unsigned long lpfn; | ||
50 | int ret; | ||
51 | |||
52 | lpfn = placement->lpfn; | ||
53 | if (!lpfn) | ||
54 | lpfn = man->size; | ||
55 | do { | ||
56 | ret = drm_mm_pre_get(mm); | ||
57 | if (unlikely(ret)) | ||
58 | return ret; | ||
59 | |||
60 | spin_lock(&glob->lru_lock); | ||
61 | node = drm_mm_search_free_in_range(mm, | ||
62 | mem->num_pages, mem->page_alignment, | ||
63 | placement->fpfn, lpfn, 1); | ||
64 | if (unlikely(node == NULL)) { | ||
65 | spin_unlock(&glob->lru_lock); | ||
66 | return 0; | ||
67 | } | ||
68 | node = drm_mm_get_block_atomic_range(node, mem->num_pages, | ||
69 | mem->page_alignment, | ||
70 | placement->fpfn, | ||
71 | lpfn); | ||
72 | spin_unlock(&glob->lru_lock); | ||
73 | } while (node == NULL); | ||
74 | |||
75 | mem->mm_node = node; | ||
76 | mem->start = node->start; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, | ||
81 | struct ttm_mem_reg *mem) | ||
82 | { | ||
83 | struct ttm_bo_global *glob = man->bdev->glob; | ||
84 | |||
85 | if (mem->mm_node) { | ||
86 | spin_lock(&glob->lru_lock); | ||
87 | drm_mm_put_block(mem->mm_node); | ||
88 | spin_unlock(&glob->lru_lock); | ||
89 | mem->mm_node = NULL; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static int ttm_bo_man_init(struct ttm_mem_type_manager *man, | ||
94 | unsigned long p_size) | ||
95 | { | ||
96 | struct drm_mm *mm; | ||
97 | int ret; | ||
98 | |||
99 | mm = kzalloc(sizeof(*mm), GFP_KERNEL); | ||
100 | if (!mm) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | ret = drm_mm_init(mm, 0, p_size); | ||
104 | if (ret) { | ||
105 | kfree(mm); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | man->priv = mm; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) | ||
114 | { | ||
115 | struct ttm_bo_global *glob = man->bdev->glob; | ||
116 | struct drm_mm *mm = man->priv; | ||
117 | int ret = 0; | ||
118 | |||
119 | spin_lock(&glob->lru_lock); | ||
120 | if (drm_mm_clean(mm)) { | ||
121 | drm_mm_takedown(mm); | ||
122 | kfree(mm); | ||
123 | man->priv = NULL; | ||
124 | } else | ||
125 | ret = -EBUSY; | ||
126 | spin_unlock(&glob->lru_lock); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, | ||
131 | const char *prefix) | ||
132 | { | ||
133 | struct ttm_bo_global *glob = man->bdev->glob; | ||
134 | struct drm_mm *mm = man->priv; | ||
135 | |||
136 | spin_lock(&glob->lru_lock); | ||
137 | drm_mm_debug_table(mm, prefix); | ||
138 | spin_unlock(&glob->lru_lock); | ||
139 | } | ||
140 | |||
141 | const struct ttm_mem_type_manager_func ttm_bo_manager_func = { | ||
142 | ttm_bo_man_init, | ||
143 | ttm_bo_man_takedown, | ||
144 | ttm_bo_man_get_node, | ||
145 | ttm_bo_man_put_node, | ||
146 | ttm_bo_man_debug | ||
147 | }; | ||
148 | EXPORT_SYMBOL(ttm_bo_manager_func); | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 3451a82adba7..ff358ad45aa3 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -39,14 +39,7 @@ | |||
39 | 39 | ||
40 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) | 40 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) |
41 | { | 41 | { |
42 | struct ttm_mem_reg *old_mem = &bo->mem; | 42 | ttm_bo_mem_put(bo, &bo->mem); |
43 | |||
44 | if (old_mem->mm_node) { | ||
45 | spin_lock(&bo->glob->lru_lock); | ||
46 | drm_mm_put_block(old_mem->mm_node); | ||
47 | spin_unlock(&bo->glob->lru_lock); | ||
48 | } | ||
49 | old_mem->mm_node = NULL; | ||
50 | } | 43 | } |
51 | 44 | ||
52 | int ttm_bo_move_ttm(struct ttm_buffer_object *bo, | 45 | int ttm_bo_move_ttm(struct ttm_buffer_object *bo, |
@@ -263,8 +256,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
263 | dir = 1; | 256 | dir = 1; |
264 | 257 | ||
265 | if ((old_mem->mem_type == new_mem->mem_type) && | 258 | if ((old_mem->mem_type == new_mem->mem_type) && |
266 | (new_mem->mm_node->start < | 259 | (new_mem->start < old_mem->start + old_mem->size)) { |
267 | old_mem->mm_node->start + old_mem->mm_node->size)) { | ||
268 | dir = -1; | 260 | dir = -1; |
269 | add = new_mem->num_pages - 1; | 261 | add = new_mem->num_pages - 1; |
270 | } | 262 | } |
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 7a1b210401e0..02f733db61c1 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c | |||
@@ -51,8 +51,6 @@ static struct drm_driver driver = { | |||
51 | .reclaim_buffers_locked = NULL, | 51 | .reclaim_buffers_locked = NULL, |
52 | .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, | 52 | .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, |
53 | .lastclose = via_lastclose, | 53 | .lastclose = via_lastclose, |
54 | .get_map_ofs = drm_core_get_map_ofs, | ||
55 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
56 | .ioctls = via_ioctls, | 54 | .ioctls = via_ioctls, |
57 | .fops = { | 55 | .fops = { |
58 | .owner = THIS_MODULE, | 56 | .owner = THIS_MODULE, |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index c4f5114aee7c..1b3bd8c6c67e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | |||
@@ -147,6 +147,7 @@ int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
147 | break; | 147 | break; |
148 | case TTM_PL_VRAM: | 148 | case TTM_PL_VRAM: |
149 | /* "On-card" video ram */ | 149 | /* "On-card" video ram */ |
150 | man->func = &ttm_bo_manager_func; | ||
150 | man->gpu_offset = 0; | 151 | man->gpu_offset = 0; |
151 | man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; | 152 | man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; |
152 | man->available_caching = TTM_PL_MASK_CACHING; | 153 | man->available_caching = TTM_PL_MASK_CACHING; |
@@ -203,7 +204,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg | |||
203 | /* System memory */ | 204 | /* System memory */ |
204 | return 0; | 205 | return 0; |
205 | case TTM_PL_VRAM: | 206 | case TTM_PL_VRAM: |
206 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; | 207 | mem->bus.offset = mem->start << PAGE_SHIFT; |
207 | mem->bus.base = dev_priv->vram_start; | 208 | mem->bus.base = dev_priv->vram_start; |
208 | mem->bus.is_iomem = true; | 209 | mem->bus.is_iomem = true; |
209 | break; | 210 | break; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index a96ed6d9d010..f2942b3c59c0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -597,6 +597,8 @@ static void vmw_lastclose(struct drm_device *dev) | |||
597 | static void vmw_master_init(struct vmw_master *vmaster) | 597 | static void vmw_master_init(struct vmw_master *vmaster) |
598 | { | 598 | { |
599 | ttm_lock_init(&vmaster->lock); | 599 | ttm_lock_init(&vmaster->lock); |
600 | INIT_LIST_HEAD(&vmaster->fb_surf); | ||
601 | mutex_init(&vmaster->fb_surf_mutex); | ||
600 | } | 602 | } |
601 | 603 | ||
602 | static int vmw_master_create(struct drm_device *dev, | 604 | static int vmw_master_create(struct drm_device *dev, |
@@ -608,7 +610,7 @@ static int vmw_master_create(struct drm_device *dev, | |||
608 | if (unlikely(vmaster == NULL)) | 610 | if (unlikely(vmaster == NULL)) |
609 | return -ENOMEM; | 611 | return -ENOMEM; |
610 | 612 | ||
611 | ttm_lock_init(&vmaster->lock); | 613 | vmw_master_init(vmaster); |
612 | ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); | 614 | ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); |
613 | master->driver_priv = vmaster; | 615 | master->driver_priv = vmaster; |
614 | 616 | ||
@@ -699,6 +701,7 @@ static void vmw_master_drop(struct drm_device *dev, | |||
699 | 701 | ||
700 | vmw_fp->locked_master = drm_master_get(file_priv->master); | 702 | vmw_fp->locked_master = drm_master_get(file_priv->master); |
701 | ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); | 703 | ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); |
704 | vmw_kms_idle_workqueues(vmaster); | ||
702 | 705 | ||
703 | if (unlikely((ret != 0))) { | 706 | if (unlikely((ret != 0))) { |
704 | DRM_ERROR("Unable to lock TTM at VT switch.\n"); | 707 | DRM_ERROR("Unable to lock TTM at VT switch.\n"); |
@@ -751,15 +754,16 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | |||
751 | * Buffer contents is moved to swappable memory. | 754 | * Buffer contents is moved to swappable memory. |
752 | */ | 755 | */ |
753 | ttm_bo_swapout_all(&dev_priv->bdev); | 756 | ttm_bo_swapout_all(&dev_priv->bdev); |
757 | |||
754 | break; | 758 | break; |
755 | case PM_POST_HIBERNATION: | 759 | case PM_POST_HIBERNATION: |
756 | case PM_POST_SUSPEND: | 760 | case PM_POST_SUSPEND: |
761 | case PM_POST_RESTORE: | ||
757 | ttm_suspend_unlock(&vmaster->lock); | 762 | ttm_suspend_unlock(&vmaster->lock); |
763 | |||
758 | break; | 764 | break; |
759 | case PM_RESTORE_PREPARE: | 765 | case PM_RESTORE_PREPARE: |
760 | break; | 766 | break; |
761 | case PM_POST_RESTORE: | ||
762 | break; | ||
763 | default: | 767 | default: |
764 | break; | 768 | break; |
765 | } | 769 | } |
@@ -770,21 +774,98 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | |||
770 | * These might not be needed with the virtual SVGA device. | 774 | * These might not be needed with the virtual SVGA device. |
771 | */ | 775 | */ |
772 | 776 | ||
773 | int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 777 | static int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
774 | { | 778 | { |
779 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
780 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
781 | |||
782 | if (dev_priv->num_3d_resources != 0) { | ||
783 | DRM_INFO("Can't suspend or hibernate " | ||
784 | "while 3D resources are active.\n"); | ||
785 | return -EBUSY; | ||
786 | } | ||
787 | |||
775 | pci_save_state(pdev); | 788 | pci_save_state(pdev); |
776 | pci_disable_device(pdev); | 789 | pci_disable_device(pdev); |
777 | pci_set_power_state(pdev, PCI_D3hot); | 790 | pci_set_power_state(pdev, PCI_D3hot); |
778 | return 0; | 791 | return 0; |
779 | } | 792 | } |
780 | 793 | ||
781 | int vmw_pci_resume(struct pci_dev *pdev) | 794 | static int vmw_pci_resume(struct pci_dev *pdev) |
782 | { | 795 | { |
783 | pci_set_power_state(pdev, PCI_D0); | 796 | pci_set_power_state(pdev, PCI_D0); |
784 | pci_restore_state(pdev); | 797 | pci_restore_state(pdev); |
785 | return pci_enable_device(pdev); | 798 | return pci_enable_device(pdev); |
786 | } | 799 | } |
787 | 800 | ||
801 | static int vmw_pm_suspend(struct device *kdev) | ||
802 | { | ||
803 | struct pci_dev *pdev = to_pci_dev(kdev); | ||
804 | struct pm_message dummy; | ||
805 | |||
806 | dummy.event = 0; | ||
807 | |||
808 | return vmw_pci_suspend(pdev, dummy); | ||
809 | } | ||
810 | |||
811 | static int vmw_pm_resume(struct device *kdev) | ||
812 | { | ||
813 | struct pci_dev *pdev = to_pci_dev(kdev); | ||
814 | |||
815 | return vmw_pci_resume(pdev); | ||
816 | } | ||
817 | |||
818 | static int vmw_pm_prepare(struct device *kdev) | ||
819 | { | ||
820 | struct pci_dev *pdev = to_pci_dev(kdev); | ||
821 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
822 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
823 | |||
824 | /** | ||
825 | * Release 3d reference held by fbdev and potentially | ||
826 | * stop fifo. | ||
827 | */ | ||
828 | dev_priv->suspended = true; | ||
829 | if (dev_priv->enable_fb) | ||
830 | vmw_3d_resource_dec(dev_priv); | ||
831 | |||
832 | if (dev_priv->num_3d_resources != 0) { | ||
833 | |||
834 | DRM_INFO("Can't suspend or hibernate " | ||
835 | "while 3D resources are active.\n"); | ||
836 | |||
837 | if (dev_priv->enable_fb) | ||
838 | vmw_3d_resource_inc(dev_priv); | ||
839 | dev_priv->suspended = false; | ||
840 | return -EBUSY; | ||
841 | } | ||
842 | |||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | static void vmw_pm_complete(struct device *kdev) | ||
847 | { | ||
848 | struct pci_dev *pdev = to_pci_dev(kdev); | ||
849 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
850 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
851 | |||
852 | /** | ||
853 | * Reclaim 3d reference held by fbdev and potentially | ||
854 | * start fifo. | ||
855 | */ | ||
856 | if (dev_priv->enable_fb) | ||
857 | vmw_3d_resource_inc(dev_priv); | ||
858 | |||
859 | dev_priv->suspended = false; | ||
860 | } | ||
861 | |||
862 | static const struct dev_pm_ops vmw_pm_ops = { | ||
863 | .prepare = vmw_pm_prepare, | ||
864 | .complete = vmw_pm_complete, | ||
865 | .suspend = vmw_pm_suspend, | ||
866 | .resume = vmw_pm_resume, | ||
867 | }; | ||
868 | |||
788 | static struct drm_driver driver = { | 869 | static struct drm_driver driver = { |
789 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 870 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
790 | DRIVER_MODESET, | 871 | DRIVER_MODESET, |
@@ -798,8 +879,6 @@ static struct drm_driver driver = { | |||
798 | .irq_handler = vmw_irq_handler, | 879 | .irq_handler = vmw_irq_handler, |
799 | .get_vblank_counter = vmw_get_vblank_counter, | 880 | .get_vblank_counter = vmw_get_vblank_counter, |
800 | .reclaim_buffers_locked = NULL, | 881 | .reclaim_buffers_locked = NULL, |
801 | .get_map_ofs = drm_core_get_map_ofs, | ||
802 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
803 | .ioctls = vmw_ioctls, | 882 | .ioctls = vmw_ioctls, |
804 | .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), | 883 | .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), |
805 | .dma_quiescent = NULL, /*vmw_dma_quiescent, */ | 884 | .dma_quiescent = NULL, /*vmw_dma_quiescent, */ |
@@ -820,15 +899,16 @@ static struct drm_driver driver = { | |||
820 | #if defined(CONFIG_COMPAT) | 899 | #if defined(CONFIG_COMPAT) |
821 | .compat_ioctl = drm_compat_ioctl, | 900 | .compat_ioctl = drm_compat_ioctl, |
822 | #endif | 901 | #endif |
823 | }, | 902 | }, |
824 | .pci_driver = { | 903 | .pci_driver = { |
825 | .name = VMWGFX_DRIVER_NAME, | 904 | .name = VMWGFX_DRIVER_NAME, |
826 | .id_table = vmw_pci_id_list, | 905 | .id_table = vmw_pci_id_list, |
827 | .probe = vmw_probe, | 906 | .probe = vmw_probe, |
828 | .remove = vmw_remove, | 907 | .remove = vmw_remove, |
829 | .suspend = vmw_pci_suspend, | 908 | .driver = { |
830 | .resume = vmw_pci_resume | 909 | .pm = &vmw_pm_ops |
831 | }, | 910 | } |
911 | }, | ||
832 | .name = VMWGFX_DRIVER_NAME, | 912 | .name = VMWGFX_DRIVER_NAME, |
833 | .desc = VMWGFX_DRIVER_DESC, | 913 | .desc = VMWGFX_DRIVER_DESC, |
834 | .date = VMWGFX_DRIVER_DATE, | 914 | .date = VMWGFX_DRIVER_DATE, |
@@ -862,3 +942,7 @@ module_exit(vmwgfx_exit); | |||
862 | MODULE_AUTHOR("VMware Inc. and others"); | 942 | MODULE_AUTHOR("VMware Inc. and others"); |
863 | MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device"); | 943 | MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device"); |
864 | MODULE_LICENSE("GPL and additional rights"); | 944 | MODULE_LICENSE("GPL and additional rights"); |
945 | MODULE_VERSION(__stringify(VMWGFX_DRIVER_MAJOR) "." | ||
946 | __stringify(VMWGFX_DRIVER_MINOR) "." | ||
947 | __stringify(VMWGFX_DRIVER_PATCHLEVEL) "." | ||
948 | "0"); | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 58de6393f611..9d55fa8cd0fe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -39,9 +39,9 @@ | |||
39 | #include "ttm/ttm_execbuf_util.h" | 39 | #include "ttm/ttm_execbuf_util.h" |
40 | #include "ttm/ttm_module.h" | 40 | #include "ttm/ttm_module.h" |
41 | 41 | ||
42 | #define VMWGFX_DRIVER_DATE "20100209" | 42 | #define VMWGFX_DRIVER_DATE "20100927" |
43 | #define VMWGFX_DRIVER_MAJOR 1 | 43 | #define VMWGFX_DRIVER_MAJOR 1 |
44 | #define VMWGFX_DRIVER_MINOR 2 | 44 | #define VMWGFX_DRIVER_MINOR 4 |
45 | #define VMWGFX_DRIVER_PATCHLEVEL 0 | 45 | #define VMWGFX_DRIVER_PATCHLEVEL 0 |
46 | #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 | 46 | #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 |
47 | #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) | 47 | #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) |
@@ -151,6 +151,8 @@ struct vmw_overlay; | |||
151 | 151 | ||
152 | struct vmw_master { | 152 | struct vmw_master { |
153 | struct ttm_lock lock; | 153 | struct ttm_lock lock; |
154 | struct mutex fb_surf_mutex; | ||
155 | struct list_head fb_surf; | ||
154 | }; | 156 | }; |
155 | 157 | ||
156 | struct vmw_vga_topology_state { | 158 | struct vmw_vga_topology_state { |
@@ -286,6 +288,7 @@ struct vmw_private { | |||
286 | struct vmw_master *active_master; | 288 | struct vmw_master *active_master; |
287 | struct vmw_master fbdev_master; | 289 | struct vmw_master fbdev_master; |
288 | struct notifier_block pm_nb; | 290 | struct notifier_block pm_nb; |
291 | bool suspended; | ||
289 | 292 | ||
290 | struct mutex release_mutex; | 293 | struct mutex release_mutex; |
291 | uint32_t num_3d_resources; | 294 | uint32_t num_3d_resources; |
@@ -518,6 +521,10 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv, | |||
518 | unsigned bbp, unsigned depth); | 521 | unsigned bbp, unsigned depth); |
519 | int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, | 522 | int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, |
520 | struct drm_file *file_priv); | 523 | struct drm_file *file_priv); |
524 | void vmw_kms_idle_workqueues(struct vmw_master *vmaster); | ||
525 | bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, | ||
526 | uint32_t pitch, | ||
527 | uint32_t height); | ||
521 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); | 528 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); |
522 | 529 | ||
523 | /** | 530 | /** |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 409e172f4abf..e7304188a784 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | |||
@@ -144,6 +144,13 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var, | |||
144 | return -EINVAL; | 144 | return -EINVAL; |
145 | } | 145 | } |
146 | 146 | ||
147 | if (!vmw_kms_validate_mode_vram(vmw_priv, | ||
148 | info->fix.line_length, | ||
149 | var->yoffset + var->yres)) { | ||
150 | DRM_ERROR("Requested geom can not fit in framebuffer\n"); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
147 | return 0; | 154 | return 0; |
148 | } | 155 | } |
149 | 156 | ||
@@ -205,6 +212,9 @@ static void vmw_fb_dirty_flush(struct vmw_fb_par *par) | |||
205 | SVGAFifoCmdUpdate body; | 212 | SVGAFifoCmdUpdate body; |
206 | } *cmd; | 213 | } *cmd; |
207 | 214 | ||
215 | if (vmw_priv->suspended) | ||
216 | return; | ||
217 | |||
208 | spin_lock_irqsave(&par->dirty.lock, flags); | 218 | spin_lock_irqsave(&par->dirty.lock, flags); |
209 | if (!par->dirty.active) { | 219 | if (!par->dirty.active) { |
210 | spin_unlock_irqrestore(&par->dirty.lock, flags); | 220 | spin_unlock_irqrestore(&par->dirty.lock, flags); |
@@ -602,6 +612,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, | |||
602 | { | 612 | { |
603 | struct ttm_buffer_object *bo = &vmw_bo->base; | 613 | struct ttm_buffer_object *bo = &vmw_bo->base; |
604 | struct ttm_placement ne_placement = vmw_vram_ne_placement; | 614 | struct ttm_placement ne_placement = vmw_vram_ne_placement; |
615 | struct drm_mm_node *mm_node; | ||
605 | int ret = 0; | 616 | int ret = 0; |
606 | 617 | ||
607 | ne_placement.lpfn = bo->num_pages; | 618 | ne_placement.lpfn = bo->num_pages; |
@@ -615,8 +626,9 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, | |||
615 | if (unlikely(ret != 0)) | 626 | if (unlikely(ret != 0)) |
616 | goto err_unlock; | 627 | goto err_unlock; |
617 | 628 | ||
629 | mm_node = bo->mem.mm_node; | ||
618 | if (bo->mem.mem_type == TTM_PL_VRAM && | 630 | if (bo->mem.mem_type == TTM_PL_VRAM && |
619 | bo->mem.mm_node->start < bo->num_pages) | 631 | mm_node->start < bo->num_pages) |
620 | (void) ttm_bo_validate(bo, &vmw_sys_placement, false, | 632 | (void) ttm_bo_validate(bo, &vmw_sys_placement, false, |
621 | false, false); | 633 | false, false); |
622 | 634 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 1c7a316454d8..570d57775a58 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | |||
@@ -54,6 +54,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, | |||
54 | case DRM_VMW_PARAM_FIFO_CAPS: | 54 | case DRM_VMW_PARAM_FIFO_CAPS: |
55 | param->value = dev_priv->fifo.capabilities; | 55 | param->value = dev_priv->fifo.capabilities; |
56 | break; | 56 | break; |
57 | case DRM_VMW_PARAM_MAX_FB_SIZE: | ||
58 | param->value = dev_priv->vram_size; | ||
59 | break; | ||
57 | default: | 60 | default: |
58 | DRM_ERROR("Illegal vmwgfx get param request: %d\n", | 61 | DRM_ERROR("Illegal vmwgfx get param request: %d\n", |
59 | param->param); | 62 | param->param); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e882ba099f0c..87c6e6156d7d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -332,18 +332,55 @@ struct vmw_framebuffer_surface { | |||
332 | struct delayed_work d_work; | 332 | struct delayed_work d_work; |
333 | struct mutex work_lock; | 333 | struct mutex work_lock; |
334 | bool present_fs; | 334 | bool present_fs; |
335 | struct list_head head; | ||
336 | struct drm_master *master; | ||
335 | }; | 337 | }; |
336 | 338 | ||
339 | /** | ||
340 | * vmw_kms_idle_workqueues - Flush workqueues on this master | ||
341 | * | ||
342 | * @vmaster - Pointer identifying the master, for the surfaces of which | ||
343 | * we idle the dirty work queues. | ||
344 | * | ||
345 | * This function should be called with the ttm lock held in exclusive mode | ||
346 | * to idle all dirty work queues before the fifo is taken down. | ||
347 | * | ||
348 | * The work task may actually requeue itself, but after the flush returns we're | ||
349 | * sure that there's nothing to present, since the ttm lock is held in | ||
350 | * exclusive mode, so the fifo will never get used. | ||
351 | */ | ||
352 | |||
353 | void vmw_kms_idle_workqueues(struct vmw_master *vmaster) | ||
354 | { | ||
355 | struct vmw_framebuffer_surface *entry; | ||
356 | |||
357 | mutex_lock(&vmaster->fb_surf_mutex); | ||
358 | list_for_each_entry(entry, &vmaster->fb_surf, head) { | ||
359 | if (cancel_delayed_work_sync(&entry->d_work)) | ||
360 | (void) entry->d_work.work.func(&entry->d_work.work); | ||
361 | |||
362 | (void) cancel_delayed_work_sync(&entry->d_work); | ||
363 | } | ||
364 | mutex_unlock(&vmaster->fb_surf_mutex); | ||
365 | } | ||
366 | |||
337 | void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer) | 367 | void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer) |
338 | { | 368 | { |
339 | struct vmw_framebuffer_surface *vfb = | 369 | struct vmw_framebuffer_surface *vfbs = |
340 | vmw_framebuffer_to_vfbs(framebuffer); | 370 | vmw_framebuffer_to_vfbs(framebuffer); |
371 | struct vmw_master *vmaster = vmw_master(vfbs->master); | ||
372 | |||
341 | 373 | ||
342 | cancel_delayed_work_sync(&vfb->d_work); | 374 | mutex_lock(&vmaster->fb_surf_mutex); |
375 | list_del(&vfbs->head); | ||
376 | mutex_unlock(&vmaster->fb_surf_mutex); | ||
377 | |||
378 | cancel_delayed_work_sync(&vfbs->d_work); | ||
379 | drm_master_put(&vfbs->master); | ||
343 | drm_framebuffer_cleanup(framebuffer); | 380 | drm_framebuffer_cleanup(framebuffer); |
344 | vmw_surface_unreference(&vfb->surface); | 381 | vmw_surface_unreference(&vfbs->surface); |
345 | 382 | ||
346 | kfree(framebuffer); | 383 | kfree(vfbs); |
347 | } | 384 | } |
348 | 385 | ||
349 | static void vmw_framebuffer_present_fs_callback(struct work_struct *work) | 386 | static void vmw_framebuffer_present_fs_callback(struct work_struct *work) |
@@ -362,6 +399,12 @@ static void vmw_framebuffer_present_fs_callback(struct work_struct *work) | |||
362 | SVGA3dCopyRect cr; | 399 | SVGA3dCopyRect cr; |
363 | } *cmd; | 400 | } *cmd; |
364 | 401 | ||
402 | /** | ||
403 | * Strictly we should take the ttm_lock in read mode before accessing | ||
404 | * the fifo, to make sure the fifo is present and up. However, | ||
405 | * instead we flush all workqueues under the ttm lock in exclusive mode | ||
406 | * before taking down the fifo. | ||
407 | */ | ||
365 | mutex_lock(&vfbs->work_lock); | 408 | mutex_lock(&vfbs->work_lock); |
366 | if (!vfbs->present_fs) | 409 | if (!vfbs->present_fs) |
367 | goto out_unlock; | 410 | goto out_unlock; |
@@ -392,17 +435,20 @@ out_unlock: | |||
392 | 435 | ||
393 | 436 | ||
394 | int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, | 437 | int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, |
438 | struct drm_file *file_priv, | ||
395 | unsigned flags, unsigned color, | 439 | unsigned flags, unsigned color, |
396 | struct drm_clip_rect *clips, | 440 | struct drm_clip_rect *clips, |
397 | unsigned num_clips) | 441 | unsigned num_clips) |
398 | { | 442 | { |
399 | struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); | 443 | struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); |
444 | struct vmw_master *vmaster = vmw_master(file_priv->master); | ||
400 | struct vmw_framebuffer_surface *vfbs = | 445 | struct vmw_framebuffer_surface *vfbs = |
401 | vmw_framebuffer_to_vfbs(framebuffer); | 446 | vmw_framebuffer_to_vfbs(framebuffer); |
402 | struct vmw_surface *surf = vfbs->surface; | 447 | struct vmw_surface *surf = vfbs->surface; |
403 | struct drm_clip_rect norect; | 448 | struct drm_clip_rect norect; |
404 | SVGA3dCopyRect *cr; | 449 | SVGA3dCopyRect *cr; |
405 | int i, inc = 1; | 450 | int i, inc = 1; |
451 | int ret; | ||
406 | 452 | ||
407 | struct { | 453 | struct { |
408 | SVGA3dCmdHeader header; | 454 | SVGA3dCmdHeader header; |
@@ -410,6 +456,13 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, | |||
410 | SVGA3dCopyRect cr; | 456 | SVGA3dCopyRect cr; |
411 | } *cmd; | 457 | } *cmd; |
412 | 458 | ||
459 | if (unlikely(vfbs->master != file_priv->master)) | ||
460 | return -EINVAL; | ||
461 | |||
462 | ret = ttm_read_lock(&vmaster->lock, true); | ||
463 | if (unlikely(ret != 0)) | ||
464 | return ret; | ||
465 | |||
413 | if (!num_clips || | 466 | if (!num_clips || |
414 | !(dev_priv->fifo.capabilities & | 467 | !(dev_priv->fifo.capabilities & |
415 | SVGA_FIFO_CAP_SCREEN_OBJECT)) { | 468 | SVGA_FIFO_CAP_SCREEN_OBJECT)) { |
@@ -425,6 +478,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, | |||
425 | */ | 478 | */ |
426 | vmw_framebuffer_present_fs_callback(&vfbs->d_work.work); | 479 | vmw_framebuffer_present_fs_callback(&vfbs->d_work.work); |
427 | } | 480 | } |
481 | ttm_read_unlock(&vmaster->lock); | ||
428 | return 0; | 482 | return 0; |
429 | } | 483 | } |
430 | 484 | ||
@@ -442,6 +496,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, | |||
442 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr)); | 496 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr)); |
443 | if (unlikely(cmd == NULL)) { | 497 | if (unlikely(cmd == NULL)) { |
444 | DRM_ERROR("Fifo reserve failed.\n"); | 498 | DRM_ERROR("Fifo reserve failed.\n"); |
499 | ttm_read_unlock(&vmaster->lock); | ||
445 | return -ENOMEM; | 500 | return -ENOMEM; |
446 | } | 501 | } |
447 | 502 | ||
@@ -461,7 +516,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, | |||
461 | } | 516 | } |
462 | 517 | ||
463 | vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr)); | 518 | vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr)); |
464 | 519 | ttm_read_unlock(&vmaster->lock); | |
465 | return 0; | 520 | return 0; |
466 | } | 521 | } |
467 | 522 | ||
@@ -471,16 +526,57 @@ static struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = { | |||
471 | .create_handle = vmw_framebuffer_create_handle, | 526 | .create_handle = vmw_framebuffer_create_handle, |
472 | }; | 527 | }; |
473 | 528 | ||
474 | int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, | 529 | static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, |
475 | struct vmw_surface *surface, | 530 | struct drm_file *file_priv, |
476 | struct vmw_framebuffer **out, | 531 | struct vmw_surface *surface, |
477 | unsigned width, unsigned height) | 532 | struct vmw_framebuffer **out, |
533 | const struct drm_mode_fb_cmd | ||
534 | *mode_cmd) | ||
478 | 535 | ||
479 | { | 536 | { |
480 | struct drm_device *dev = dev_priv->dev; | 537 | struct drm_device *dev = dev_priv->dev; |
481 | struct vmw_framebuffer_surface *vfbs; | 538 | struct vmw_framebuffer_surface *vfbs; |
539 | enum SVGA3dSurfaceFormat format; | ||
540 | struct vmw_master *vmaster = vmw_master(file_priv->master); | ||
482 | int ret; | 541 | int ret; |
483 | 542 | ||
543 | /* | ||
544 | * Sanity checks. | ||
545 | */ | ||
546 | |||
547 | if (unlikely(surface->mip_levels[0] != 1 || | ||
548 | surface->num_sizes != 1 || | ||
549 | surface->sizes[0].width < mode_cmd->width || | ||
550 | surface->sizes[0].height < mode_cmd->height || | ||
551 | surface->sizes[0].depth != 1)) { | ||
552 | DRM_ERROR("Incompatible surface dimensions " | ||
553 | "for requested mode.\n"); | ||
554 | return -EINVAL; | ||
555 | } | ||
556 | |||
557 | switch (mode_cmd->depth) { | ||
558 | case 32: | ||
559 | format = SVGA3D_A8R8G8B8; | ||
560 | break; | ||
561 | case 24: | ||
562 | format = SVGA3D_X8R8G8B8; | ||
563 | break; | ||
564 | case 16: | ||
565 | format = SVGA3D_R5G6B5; | ||
566 | break; | ||
567 | case 15: | ||
568 | format = SVGA3D_A1R5G5B5; | ||
569 | break; | ||
570 | default: | ||
571 | DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | |||
575 | if (unlikely(format != surface->format)) { | ||
576 | DRM_ERROR("Invalid surface format for requested mode.\n"); | ||
577 | return -EINVAL; | ||
578 | } | ||
579 | |||
484 | vfbs = kzalloc(sizeof(*vfbs), GFP_KERNEL); | 580 | vfbs = kzalloc(sizeof(*vfbs), GFP_KERNEL); |
485 | if (!vfbs) { | 581 | if (!vfbs) { |
486 | ret = -ENOMEM; | 582 | ret = -ENOMEM; |
@@ -498,16 +594,22 @@ int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, | |||
498 | } | 594 | } |
499 | 595 | ||
500 | /* XXX get the first 3 from the surface info */ | 596 | /* XXX get the first 3 from the surface info */ |
501 | vfbs->base.base.bits_per_pixel = 32; | 597 | vfbs->base.base.bits_per_pixel = mode_cmd->bpp; |
502 | vfbs->base.base.pitch = width * 32 / 4; | 598 | vfbs->base.base.pitch = mode_cmd->pitch; |
503 | vfbs->base.base.depth = 24; | 599 | vfbs->base.base.depth = mode_cmd->depth; |
504 | vfbs->base.base.width = width; | 600 | vfbs->base.base.width = mode_cmd->width; |
505 | vfbs->base.base.height = height; | 601 | vfbs->base.base.height = mode_cmd->height; |
506 | vfbs->base.pin = &vmw_surface_dmabuf_pin; | 602 | vfbs->base.pin = &vmw_surface_dmabuf_pin; |
507 | vfbs->base.unpin = &vmw_surface_dmabuf_unpin; | 603 | vfbs->base.unpin = &vmw_surface_dmabuf_unpin; |
508 | vfbs->surface = surface; | 604 | vfbs->surface = surface; |
605 | vfbs->master = drm_master_get(file_priv->master); | ||
509 | mutex_init(&vfbs->work_lock); | 606 | mutex_init(&vfbs->work_lock); |
607 | |||
608 | mutex_lock(&vmaster->fb_surf_mutex); | ||
510 | INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback); | 609 | INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback); |
610 | list_add_tail(&vfbs->head, &vmaster->fb_surf); | ||
611 | mutex_unlock(&vmaster->fb_surf_mutex); | ||
612 | |||
511 | *out = &vfbs->base; | 613 | *out = &vfbs->base; |
512 | 614 | ||
513 | return 0; | 615 | return 0; |
@@ -544,18 +646,25 @@ void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer) | |||
544 | } | 646 | } |
545 | 647 | ||
546 | int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | 648 | int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, |
649 | struct drm_file *file_priv, | ||
547 | unsigned flags, unsigned color, | 650 | unsigned flags, unsigned color, |
548 | struct drm_clip_rect *clips, | 651 | struct drm_clip_rect *clips, |
549 | unsigned num_clips) | 652 | unsigned num_clips) |
550 | { | 653 | { |
551 | struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); | 654 | struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); |
655 | struct vmw_master *vmaster = vmw_master(file_priv->master); | ||
552 | struct drm_clip_rect norect; | 656 | struct drm_clip_rect norect; |
657 | int ret; | ||
553 | struct { | 658 | struct { |
554 | uint32_t header; | 659 | uint32_t header; |
555 | SVGAFifoCmdUpdate body; | 660 | SVGAFifoCmdUpdate body; |
556 | } *cmd; | 661 | } *cmd; |
557 | int i, increment = 1; | 662 | int i, increment = 1; |
558 | 663 | ||
664 | ret = ttm_read_lock(&vmaster->lock, true); | ||
665 | if (unlikely(ret != 0)) | ||
666 | return ret; | ||
667 | |||
559 | if (!num_clips) { | 668 | if (!num_clips) { |
560 | num_clips = 1; | 669 | num_clips = 1; |
561 | clips = &norect; | 670 | clips = &norect; |
@@ -570,6 +679,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | |||
570 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips); | 679 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips); |
571 | if (unlikely(cmd == NULL)) { | 680 | if (unlikely(cmd == NULL)) { |
572 | DRM_ERROR("Fifo reserve failed.\n"); | 681 | DRM_ERROR("Fifo reserve failed.\n"); |
682 | ttm_read_unlock(&vmaster->lock); | ||
573 | return -ENOMEM; | 683 | return -ENOMEM; |
574 | } | 684 | } |
575 | 685 | ||
@@ -582,6 +692,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | |||
582 | } | 692 | } |
583 | 693 | ||
584 | vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips); | 694 | vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips); |
695 | ttm_read_unlock(&vmaster->lock); | ||
585 | 696 | ||
586 | return 0; | 697 | return 0; |
587 | } | 698 | } |
@@ -659,16 +770,25 @@ static int vmw_framebuffer_dmabuf_unpin(struct vmw_framebuffer *vfb) | |||
659 | return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer); | 770 | return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer); |
660 | } | 771 | } |
661 | 772 | ||
662 | int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, | 773 | static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, |
663 | struct vmw_dma_buffer *dmabuf, | 774 | struct vmw_dma_buffer *dmabuf, |
664 | struct vmw_framebuffer **out, | 775 | struct vmw_framebuffer **out, |
665 | unsigned width, unsigned height) | 776 | const struct drm_mode_fb_cmd |
777 | *mode_cmd) | ||
666 | 778 | ||
667 | { | 779 | { |
668 | struct drm_device *dev = dev_priv->dev; | 780 | struct drm_device *dev = dev_priv->dev; |
669 | struct vmw_framebuffer_dmabuf *vfbd; | 781 | struct vmw_framebuffer_dmabuf *vfbd; |
782 | unsigned int requested_size; | ||
670 | int ret; | 783 | int ret; |
671 | 784 | ||
785 | requested_size = mode_cmd->height * mode_cmd->pitch; | ||
786 | if (unlikely(requested_size > dmabuf->base.num_pages * PAGE_SIZE)) { | ||
787 | DRM_ERROR("Screen buffer object size is too small " | ||
788 | "for requested mode.\n"); | ||
789 | return -EINVAL; | ||
790 | } | ||
791 | |||
672 | vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL); | 792 | vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL); |
673 | if (!vfbd) { | 793 | if (!vfbd) { |
674 | ret = -ENOMEM; | 794 | ret = -ENOMEM; |
@@ -685,12 +805,11 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, | |||
685 | goto out_err3; | 805 | goto out_err3; |
686 | } | 806 | } |
687 | 807 | ||
688 | /* XXX get the first 3 from the surface info */ | 808 | vfbd->base.base.bits_per_pixel = mode_cmd->bpp; |
689 | vfbd->base.base.bits_per_pixel = 32; | 809 | vfbd->base.base.pitch = mode_cmd->pitch; |
690 | vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8; | 810 | vfbd->base.base.depth = mode_cmd->depth; |
691 | vfbd->base.base.depth = 24; | 811 | vfbd->base.base.width = mode_cmd->width; |
692 | vfbd->base.base.width = width; | 812 | vfbd->base.base.height = mode_cmd->height; |
693 | vfbd->base.base.height = height; | ||
694 | vfbd->base.pin = vmw_framebuffer_dmabuf_pin; | 813 | vfbd->base.pin = vmw_framebuffer_dmabuf_pin; |
695 | vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin; | 814 | vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin; |
696 | vfbd->buffer = dmabuf; | 815 | vfbd->buffer = dmabuf; |
@@ -719,8 +838,25 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
719 | struct vmw_framebuffer *vfb = NULL; | 838 | struct vmw_framebuffer *vfb = NULL; |
720 | struct vmw_surface *surface = NULL; | 839 | struct vmw_surface *surface = NULL; |
721 | struct vmw_dma_buffer *bo = NULL; | 840 | struct vmw_dma_buffer *bo = NULL; |
841 | u64 required_size; | ||
722 | int ret; | 842 | int ret; |
723 | 843 | ||
844 | /** | ||
845 | * This code should be conditioned on Screen Objects not being used. | ||
846 | * If screen objects are used, we can allocate a GMR to hold the | ||
847 | * requested framebuffer. | ||
848 | */ | ||
849 | |||
850 | required_size = mode_cmd->pitch * mode_cmd->height; | ||
851 | if (unlikely(required_size > (u64) dev_priv->vram_size)) { | ||
852 | DRM_ERROR("VRAM size is too small for requested mode.\n"); | ||
853 | return NULL; | ||
854 | } | ||
855 | |||
856 | /** | ||
857 | * End conditioned code. | ||
858 | */ | ||
859 | |||
724 | ret = vmw_user_surface_lookup_handle(dev_priv, tfile, | 860 | ret = vmw_user_surface_lookup_handle(dev_priv, tfile, |
725 | mode_cmd->handle, &surface); | 861 | mode_cmd->handle, &surface); |
726 | if (ret) | 862 | if (ret) |
@@ -729,8 +865,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
729 | if (!surface->scanout) | 865 | if (!surface->scanout) |
730 | goto err_not_scanout; | 866 | goto err_not_scanout; |
731 | 867 | ||
732 | ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, | 868 | ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface, |
733 | mode_cmd->width, mode_cmd->height); | 869 | &vfb, mode_cmd); |
734 | 870 | ||
735 | /* vmw_user_surface_lookup takes one ref so does new_fb */ | 871 | /* vmw_user_surface_lookup takes one ref so does new_fb */ |
736 | vmw_surface_unreference(&surface); | 872 | vmw_surface_unreference(&surface); |
@@ -751,7 +887,7 @@ try_dmabuf: | |||
751 | } | 887 | } |
752 | 888 | ||
753 | ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, | 889 | ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, |
754 | mode_cmd->width, mode_cmd->height); | 890 | mode_cmd); |
755 | 891 | ||
756 | /* vmw_user_dmabuf_lookup takes one ref so does new_fb */ | 892 | /* vmw_user_dmabuf_lookup takes one ref so does new_fb */ |
757 | vmw_dmabuf_unreference(&bo); | 893 | vmw_dmabuf_unreference(&bo); |
@@ -889,6 +1025,9 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv) | |||
889 | vmw_priv->num_displays = vmw_read(vmw_priv, | 1025 | vmw_priv->num_displays = vmw_read(vmw_priv, |
890 | SVGA_REG_NUM_GUEST_DISPLAYS); | 1026 | SVGA_REG_NUM_GUEST_DISPLAYS); |
891 | 1027 | ||
1028 | if (vmw_priv->num_displays == 0) | ||
1029 | vmw_priv->num_displays = 1; | ||
1030 | |||
892 | for (i = 0; i < vmw_priv->num_displays; ++i) { | 1031 | for (i = 0; i < vmw_priv->num_displays; ++i) { |
893 | save = &vmw_priv->vga_save[i]; | 1032 | save = &vmw_priv->vga_save[i]; |
894 | vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i); | 1033 | vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i); |
@@ -997,6 +1136,13 @@ out_unlock: | |||
997 | return ret; | 1136 | return ret; |
998 | } | 1137 | } |
999 | 1138 | ||
1139 | bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, | ||
1140 | uint32_t pitch, | ||
1141 | uint32_t height) | ||
1142 | { | ||
1143 | return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size; | ||
1144 | } | ||
1145 | |||
1000 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) | 1146 | u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) |
1001 | { | 1147 | { |
1002 | return 0; | 1148 | return 0; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 11cb39e3accb..a01c47ddb5bc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -427,7 +427,9 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | |||
427 | { | 427 | { |
428 | struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector); | 428 | struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector); |
429 | struct drm_device *dev = connector->dev; | 429 | struct drm_device *dev = connector->dev; |
430 | struct vmw_private *dev_priv = vmw_priv(dev); | ||
430 | struct drm_display_mode *mode = NULL; | 431 | struct drm_display_mode *mode = NULL; |
432 | struct drm_display_mode *bmode; | ||
431 | struct drm_display_mode prefmode = { DRM_MODE("preferred", | 433 | struct drm_display_mode prefmode = { DRM_MODE("preferred", |
432 | DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, | 434 | DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, |
433 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 435 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -443,22 +445,30 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | |||
443 | mode->hdisplay = ldu->pref_width; | 445 | mode->hdisplay = ldu->pref_width; |
444 | mode->vdisplay = ldu->pref_height; | 446 | mode->vdisplay = ldu->pref_height; |
445 | mode->vrefresh = drm_mode_vrefresh(mode); | 447 | mode->vrefresh = drm_mode_vrefresh(mode); |
446 | drm_mode_probed_add(connector, mode); | 448 | if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, |
449 | mode->vdisplay)) { | ||
450 | drm_mode_probed_add(connector, mode); | ||
447 | 451 | ||
448 | if (ldu->pref_mode) { | 452 | if (ldu->pref_mode) { |
449 | list_del_init(&ldu->pref_mode->head); | 453 | list_del_init(&ldu->pref_mode->head); |
450 | drm_mode_destroy(dev, ldu->pref_mode); | 454 | drm_mode_destroy(dev, ldu->pref_mode); |
451 | } | 455 | } |
452 | 456 | ||
453 | ldu->pref_mode = mode; | 457 | ldu->pref_mode = mode; |
458 | } | ||
454 | } | 459 | } |
455 | 460 | ||
456 | for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { | 461 | for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { |
457 | if (vmw_ldu_connector_builtin[i].hdisplay > max_width || | 462 | bmode = &vmw_ldu_connector_builtin[i]; |
458 | vmw_ldu_connector_builtin[i].vdisplay > max_height) | 463 | if (bmode->hdisplay > max_width || |
464 | bmode->vdisplay > max_height) | ||
465 | continue; | ||
466 | |||
467 | if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2, | ||
468 | bmode->vdisplay)) | ||
459 | continue; | 469 | continue; |
460 | 470 | ||
461 | mode = drm_mode_duplicate(dev, &vmw_ldu_connector_builtin[i]); | 471 | mode = drm_mode_duplicate(dev, bmode); |
462 | if (!mode) | 472 | if (!mode) |
463 | return 0; | 473 | return 0; |
464 | mode->vrefresh = drm_mode_vrefresh(mode); | 474 | mode->vrefresh = drm_mode_vrefresh(mode); |