aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/gpu/drm
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_dp_i2c_helper.c208
-rw-r--r--drivers/gpu/drm/drm_sman.c350
-rw-r--r--drivers/gpu/drm/i915/i915_mem.c387
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c484
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c197
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c490
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1613
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fb.h49
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_grctx.h133
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.c323
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.h53
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.c178
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.h66
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_notifier.c204
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c1036
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ramht.c309
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ramht.h55
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c1218
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_temp.c314
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_util.c78
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_util.h49
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.c435
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h115
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fb.c21
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fifo.c543
-rw-r--r--drivers/gpu/drm/nouveau/nv04_graph.c1353
-rw-r--r--drivers/gpu/drm/nouveau/nv04_instmem.c192
-rw-r--r--drivers/gpu/drm/nouveau/nv04_mc.c24
-rw-r--r--drivers/gpu/drm/nouveau/nv04_timer.c51
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fb.c144
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fifo.c246
-rw-r--r--drivers/gpu/drm/nouveau/nv10_gpio.c92
-rw-r--r--drivers/gpu/drm/nouveau/nv10_graph.c1194
-rw-r--r--drivers/gpu/drm/nouveau/nv20_graph.c842
-rw-r--r--drivers/gpu/drm/nouveau/nv30_fb.c116
-rw-r--r--drivers/gpu/drm/nouveau/nv40_fb.c118
-rw-r--r--drivers/gpu/drm/nouveau/nv40_fifo.c307
-rw-r--r--drivers/gpu/drm/nouveau/nv40_graph.c490
-rw-r--r--drivers/gpu/drm/nouveau/nv40_grctx.c662
-rw-r--r--drivers/gpu/drm/nouveau/nv40_mc.c28
-rw-r--r--drivers/gpu/drm/nouveau/nv40_mpeg.c311
-rw-r--r--drivers/gpu/drm/nouveau/nv50_calc.c97
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c796
-rw-r--r--drivers/gpu/drm/nouveau/nv50_cursor.c157
-rw-r--r--drivers/gpu/drm/nouveau/nv50_dac.c319
-rw-r--r--drivers/gpu/drm/nouveau/nv50_evo.c425
-rw-r--r--drivers/gpu/drm/nouveau/nv50_evo.h119
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fb.c294
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fifo.c504
-rw-r--r--drivers/gpu/drm/nouveau/nv50_gpio.c302
-rw-r--r--drivers/gpu/drm/nouveau/nv50_graph.c1123
-rw-r--r--drivers/gpu/drm/nouveau/nv50_grctx.c3322
-rw-r--r--drivers/gpu/drm/nouveau/nv50_instmem.c428
-rw-r--r--drivers/gpu/drm/nouveau/nv50_mc.c40
-rw-r--r--drivers/gpu/drm/nouveau/nv50_mpeg.c256
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c343
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vm.c182
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vram.c220
-rw-r--r--drivers/gpu/drm/nouveau/nv84_crypt.c193
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.c226
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.fuc870
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.fuc.h534
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_copy.c243
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_copy.fuc.h527
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fb.c102
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c508
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.c908
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.fuc400
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.h95
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grctx.c2807
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grgpc.fuc474
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h483
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grhub.fuc808
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h838
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_instmem.c223
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vm.c134
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vram.c117
77 files changed, 34495 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_dp_i2c_helper.c b/drivers/gpu/drm/drm_dp_i2c_helper.c
new file mode 100644
index 00000000000..f7eba0a0973
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_i2c_helper.c
@@ -0,0 +1,208 @@
1/*
2 * Copyright © 2009 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/delay.h>
26#include <linux/init.h>
27#include <linux/errno.h>
28#include <linux/sched.h>
29#include <linux/i2c.h>
30#include "drm_dp_helper.h"
31#include "drmP.h"
32
33/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
34static int
35i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
36 uint8_t write_byte, uint8_t *read_byte)
37{
38 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
39 int ret;
40
41 ret = (*algo_data->aux_ch)(adapter, mode,
42 write_byte, read_byte);
43 return ret;
44}
45
46/*
47 * I2C over AUX CH
48 */
49
50/*
51 * Send the address. If the I2C link is running, this 'restarts'
52 * the connection with the new address, this is used for doing
53 * a write followed by a read (as needed for DDC)
54 */
55static int
56i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
57{
58 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
59 int mode = MODE_I2C_START;
60 int ret;
61
62 if (reading)
63 mode |= MODE_I2C_READ;
64 else
65 mode |= MODE_I2C_WRITE;
66 algo_data->address = address;
67 algo_data->running = true;
68 ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
69 return ret;
70}
71
72/*
73 * Stop the I2C transaction. This closes out the link, sending
74 * a bare address packet with the MOT bit turned off
75 */
76static void
77i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
78{
79 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
80 int mode = MODE_I2C_STOP;
81
82 if (reading)
83 mode |= MODE_I2C_READ;
84 else
85 mode |= MODE_I2C_WRITE;
86 if (algo_data->running) {
87 (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
88 algo_data->running = false;
89 }
90}
91
92/*
93 * Write a single byte to the current I2C address, the
94 * the I2C link must be running or this returns -EIO
95 */
96static int
97i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
98{
99 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
100 int ret;
101
102 if (!algo_data->running)
103 return -EIO;
104
105 ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
106 return ret;
107}
108
109/*
110 * Read a single byte from the current I2C address, the
111 * I2C link must be running or this returns -EIO
112 */
113static int
114i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
115{
116 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
117 int ret;
118
119 if (!algo_data->running)
120 return -EIO;
121
122 ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
123 return ret;
124}
125
126static int
127i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
128 struct i2c_msg *msgs,
129 int num)
130{
131 int ret = 0;
132 bool reading = false;
133 int m;
134 int b;
135
136 for (m = 0; m < num; m++) {
137 u16 len = msgs[m].len;
138 u8 *buf = msgs[m].buf;
139 reading = (msgs[m].flags & I2C_M_RD) != 0;
140 ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
141 if (ret < 0)
142 break;
143 if (reading) {
144 for (b = 0; b < len; b++) {
145 ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
146 if (ret < 0)
147 break;
148 }
149 } else {
150 for (b = 0; b < len; b++) {
151 ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
152 if (ret < 0)
153 break;
154 }
155 }
156 if (ret < 0)
157 break;
158 }
159 if (ret >= 0)
160 ret = num;
161 i2c_algo_dp_aux_stop(adapter, reading);
162 DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
163 return ret;
164}
165
166static u32
167i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
168{
169 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
170 I2C_FUNC_SMBUS_READ_BLOCK_DATA |
171 I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
172 I2C_FUNC_10BIT_ADDR;
173}
174
175static const struct i2c_algorithm i2c_dp_aux_algo = {
176 .master_xfer = i2c_algo_dp_aux_xfer,
177 .functionality = i2c_algo_dp_aux_functionality,
178};
179
180static void
181i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
182{
183 (void) i2c_algo_dp_aux_address(adapter, 0, false);
184 (void) i2c_algo_dp_aux_stop(adapter, false);
185
186}
187
188static int
189i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
190{
191 adapter->algo = &i2c_dp_aux_algo;
192 adapter->retries = 3;
193 i2c_dp_aux_reset_bus(adapter);
194 return 0;
195}
196
197int
198i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
199{
200 int error;
201
202 error = i2c_dp_aux_prepare_bus(adapter);
203 if (error)
204 return error;
205 error = i2c_add_adapter(adapter);
206 return error;
207}
208EXPORT_SYMBOL(i2c_dp_aux_add_bus);
diff --git a/drivers/gpu/drm/drm_sman.c b/drivers/gpu/drm/drm_sman.c
new file mode 100644
index 00000000000..34664587a74
--- /dev/null
+++ b/drivers/gpu/drm/drm_sman.c
@@ -0,0 +1,350 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 *
27 **************************************************************************/
28/*
29 * Simple memory manager interface that keeps track on allocate regions on a
30 * per "owner" basis. All regions associated with an "owner" can be released
31 * with a simple call. Typically if the "owner" exists. The owner is any
32 * "unsigned long" identifier. Can typically be a pointer to a file private
33 * struct or a context identifier.
34 *
35 * Authors:
36 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
37 */
38
39#include "drm_sman.h"
40
41struct drm_owner_item {
42 struct drm_hash_item owner_hash;
43 struct list_head sman_list;
44 struct list_head mem_blocks;
45};
46
47void drm_sman_takedown(struct drm_sman * sman)
48{
49 drm_ht_remove(&sman->user_hash_tab);
50 drm_ht_remove(&sman->owner_hash_tab);
51 kfree(sman->mm);
52}
53
54EXPORT_SYMBOL(drm_sman_takedown);
55
56int
57drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
58 unsigned int user_order, unsigned int owner_order)
59{
60 int ret = 0;
61
62 sman->mm = kcalloc(num_managers, sizeof(*sman->mm), GFP_KERNEL);
63 if (!sman->mm) {
64 ret = -ENOMEM;
65 goto out;
66 }
67 sman->num_managers = num_managers;
68 INIT_LIST_HEAD(&sman->owner_items);
69 ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
70 if (ret)
71 goto out1;
72 ret = drm_ht_create(&sman->user_hash_tab, user_order);
73 if (!ret)
74 goto out;
75
76 drm_ht_remove(&sman->owner_hash_tab);
77out1:
78 kfree(sman->mm);
79out:
80 return ret;
81}
82
83EXPORT_SYMBOL(drm_sman_init);
84
85static void *drm_sman_mm_allocate(void *private, unsigned long size,
86 unsigned alignment)
87{
88 struct drm_mm *mm = (struct drm_mm *) private;
89 struct drm_mm_node *tmp;
90
91 tmp = drm_mm_search_free(mm, size, alignment, 1);
92 if (!tmp) {
93 return NULL;
94 }
95 tmp = drm_mm_get_block(tmp, size, alignment);
96 return tmp;
97}
98
99static void drm_sman_mm_free(void *private, void *ref)
100{
101 struct drm_mm_node *node = (struct drm_mm_node *) ref;
102
103 drm_mm_put_block(node);
104}
105
106static void drm_sman_mm_destroy(void *private)
107{
108 struct drm_mm *mm = (struct drm_mm *) private;
109 drm_mm_takedown(mm);
110 kfree(mm);
111}
112
113static unsigned long drm_sman_mm_offset(void *private, void *ref)
114{
115 struct drm_mm_node *node = (struct drm_mm_node *) ref;
116 return node->start;
117}
118
119int
120drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
121 unsigned long start, unsigned long size)
122{
123 struct drm_sman_mm *sman_mm;
124 struct drm_mm *mm;
125 int ret;
126
127 BUG_ON(manager >= sman->num_managers);
128
129 sman_mm = &sman->mm[manager];
130 mm = kzalloc(sizeof(*mm), GFP_KERNEL);
131 if (!mm) {
132 return -ENOMEM;
133 }
134 sman_mm->private = mm;
135 ret = drm_mm_init(mm, start, size);
136
137 if (ret) {
138 kfree(mm);
139 return ret;
140 }
141
142 sman_mm->allocate = drm_sman_mm_allocate;
143 sman_mm->free = drm_sman_mm_free;
144 sman_mm->destroy = drm_sman_mm_destroy;
145 sman_mm->offset = drm_sman_mm_offset;
146
147 return 0;
148}
149
150EXPORT_SYMBOL(drm_sman_set_range);
151
152int
153drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
154 struct drm_sman_mm * allocator)
155{
156 BUG_ON(manager >= sman->num_managers);
157 sman->mm[manager] = *allocator;
158
159 return 0;
160}
161EXPORT_SYMBOL(drm_sman_set_manager);
162
163static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
164 unsigned long owner)
165{
166 int ret;
167 struct drm_hash_item *owner_hash_item;
168 struct drm_owner_item *owner_item;
169
170 ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
171 if (!ret) {
172 return drm_hash_entry(owner_hash_item, struct drm_owner_item,
173 owner_hash);
174 }
175
176 owner_item = kzalloc(sizeof(*owner_item), GFP_KERNEL);
177 if (!owner_item)
178 goto out;
179
180 INIT_LIST_HEAD(&owner_item->mem_blocks);
181 owner_item->owner_hash.key = owner;
182 if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
183 goto out1;
184
185 list_add_tail(&owner_item->sman_list, &sman->owner_items);
186 return owner_item;
187
188out1:
189 kfree(owner_item);
190out:
191 return NULL;
192}
193
194struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
195 unsigned long size, unsigned alignment,
196 unsigned long owner)
197{
198 void *tmp;
199 struct drm_sman_mm *sman_mm;
200 struct drm_owner_item *owner_item;
201 struct drm_memblock_item *memblock;
202
203 BUG_ON(manager >= sman->num_managers);
204
205 sman_mm = &sman->mm[manager];
206 tmp = sman_mm->allocate(sman_mm->private, size, alignment);
207
208 if (!tmp) {
209 return NULL;
210 }
211
212 memblock = kzalloc(sizeof(*memblock), GFP_KERNEL);
213
214 if (!memblock)
215 goto out;
216
217 memblock->mm_info = tmp;
218 memblock->mm = sman_mm;
219 memblock->sman = sman;
220
221 if (drm_ht_just_insert_please
222 (&sman->user_hash_tab, &memblock->user_hash,
223 (unsigned long)memblock, 32, 0, 0))
224 goto out1;
225
226 owner_item = drm_sman_get_owner_item(sman, owner);
227 if (!owner_item)
228 goto out2;
229
230 list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
231
232 return memblock;
233
234out2:
235 drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
236out1:
237 kfree(memblock);
238out:
239 sman_mm->free(sman_mm->private, tmp);
240
241 return NULL;
242}
243
244EXPORT_SYMBOL(drm_sman_alloc);
245
246static void drm_sman_free(struct drm_memblock_item *item)
247{
248 struct drm_sman *sman = item->sman;
249
250 list_del(&item->owner_list);
251 drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
252 item->mm->free(item->mm->private, item->mm_info);
253 kfree(item);
254}
255
256int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
257{
258 struct drm_hash_item *hash_item;
259 struct drm_memblock_item *memblock_item;
260
261 if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
262 return -EINVAL;
263
264 memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
265 user_hash);
266 drm_sman_free(memblock_item);
267 return 0;
268}
269
270EXPORT_SYMBOL(drm_sman_free_key);
271
272static void drm_sman_remove_owner(struct drm_sman *sman,
273 struct drm_owner_item *owner_item)
274{
275 list_del(&owner_item->sman_list);
276 drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
277 kfree(owner_item);
278}
279
280int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
281{
282
283 struct drm_hash_item *hash_item;
284 struct drm_owner_item *owner_item;
285
286 if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
287 return -1;
288 }
289
290 owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
291 if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
292 drm_sman_remove_owner(sman, owner_item);
293 return -1;
294 }
295
296 return 0;
297}
298
299EXPORT_SYMBOL(drm_sman_owner_clean);
300
301static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
302 struct drm_owner_item *owner_item)
303{
304 struct drm_memblock_item *entry, *next;
305
306 list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
307 owner_list) {
308 drm_sman_free(entry);
309 }
310 drm_sman_remove_owner(sman, owner_item);
311}
312
313void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
314{
315
316 struct drm_hash_item *hash_item;
317 struct drm_owner_item *owner_item;
318
319 if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
320
321 return;
322 }
323
324 owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
325 drm_sman_do_owner_cleanup(sman, owner_item);
326}
327
328EXPORT_SYMBOL(drm_sman_owner_cleanup);
329
330void drm_sman_cleanup(struct drm_sman *sman)
331{
332 struct drm_owner_item *entry, *next;
333 unsigned int i;
334 struct drm_sman_mm *sman_mm;
335
336 list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
337 drm_sman_do_owner_cleanup(sman, entry);
338 }
339 if (sman->mm) {
340 for (i = 0; i < sman->num_managers; ++i) {
341 sman_mm = &sman->mm[i];
342 if (sman_mm->private) {
343 sman_mm->destroy(sman_mm->private);
344 sman_mm->private = NULL;
345 }
346 }
347 }
348}
349
350EXPORT_SYMBOL(drm_sman_cleanup);
diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c
new file mode 100644
index 00000000000..83b7b81bb2b
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_mem.c
@@ -0,0 +1,387 @@
1/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
2 */
3/*
4 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 */
28
29#include "drmP.h"
30#include "drm.h"
31#include "i915_drm.h"
32#include "i915_drv.h"
33
34/* This memory manager is integrated into the global/local lru
35 * mechanisms used by the clients. Specifically, it operates by
36 * setting the 'in_use' fields of the global LRU to indicate whether
37 * this region is privately allocated to a client.
38 *
39 * This does require the client to actually respect that field.
40 *
41 * Currently no effort is made to allocate 'private' memory in any
42 * clever way - the LRU information isn't used to determine which
43 * block to allocate, and the ring is drained prior to allocations --
44 * in other words allocation is expensive.
45 */
46static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
47{
48 drm_i915_private_t *dev_priv = dev->dev_private;
49 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
50 drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv;
51 struct drm_tex_region *list;
52 unsigned shift, nr;
53 unsigned start;
54 unsigned end;
55 unsigned i;
56 int age;
57
58 shift = dev_priv->tex_lru_log_granularity;
59 nr = I915_NR_TEX_REGIONS;
60
61 start = p->start >> shift;
62 end = (p->start + p->size - 1) >> shift;
63
64 age = ++sarea_priv->texAge;
65 list = sarea_priv->texList;
66
67 /* Mark the regions with the new flag and update their age. Move
68 * them to head of list to preserve LRU semantics.
69 */
70 for (i = start; i <= end; i++) {
71 list[i].in_use = in_use;
72 list[i].age = age;
73
74 /* remove_from_list(i)
75 */
76 list[(unsigned)list[i].next].prev = list[i].prev;
77 list[(unsigned)list[i].prev].next = list[i].next;
78
79 /* insert_at_head(list, i)
80 */
81 list[i].prev = nr;
82 list[i].next = list[nr].next;
83 list[(unsigned)list[nr].next].prev = i;
84 list[nr].next = i;
85 }
86}
87
88/* Very simple allocator for agp memory, working on a static range
89 * already mapped into each client's address space.
90 */
91
92static struct mem_block *split_block(struct mem_block *p, int start, int size,
93 struct drm_file *file_priv)
94{
95 /* Maybe cut off the start of an existing block */
96 if (start > p->start) {
97 struct mem_block *newblock = kmalloc(sizeof(*newblock),
98 GFP_KERNEL);
99 if (!newblock)
100 goto out;
101 newblock->start = start;
102 newblock->size = p->size - (start - p->start);
103 newblock->file_priv = NULL;
104 newblock->next = p->next;
105 newblock->prev = p;
106 p->next->prev = newblock;
107 p->next = newblock;
108 p->size -= newblock->size;
109 p = newblock;
110 }
111
112 /* Maybe cut off the end of an existing block */
113 if (size < p->size) {
114 struct mem_block *newblock = kmalloc(sizeof(*newblock),
115 GFP_KERNEL);
116 if (!newblock)
117 goto out;
118 newblock->start = start + size;
119 newblock->size = p->size - size;
120 newblock->file_priv = NULL;
121 newblock->next = p->next;
122 newblock->prev = p;
123 p->next->prev = newblock;
124 p->next = newblock;
125 p->size = size;
126 }
127
128 out:
129 /* Our block is in the middle */
130 p->file_priv = file_priv;
131 return p;
132}
133
134static struct mem_block *alloc_block(struct mem_block *heap, int size,
135 int align2, struct drm_file *file_priv)
136{
137 struct mem_block *p;
138 int mask = (1 << align2) - 1;
139
140 for (p = heap->next; p != heap; p = p->next) {
141 int start = (p->start + mask) & ~mask;
142 if (p->file_priv == NULL && start + size <= p->start + p->size)
143 return split_block(p, start, size, file_priv);
144 }
145
146 return NULL;
147}
148
149static struct mem_block *find_block(struct mem_block *heap, int start)
150{
151 struct mem_block *p;
152
153 for (p = heap->next; p != heap; p = p->next)
154 if (p->start == start)
155 return p;
156
157 return NULL;
158}
159
160static void free_block(struct mem_block *p)
161{
162 p->file_priv = NULL;
163
164 /* Assumes a single contiguous range. Needs a special file_priv in
165 * 'heap' to stop it being subsumed.
166 */
167 if (p->next->file_priv == NULL) {
168 struct mem_block *q = p->next;
169 p->size += q->size;
170 p->next = q->next;
171 p->next->prev = p;
172 kfree(q);
173 }
174
175 if (p->prev->file_priv == NULL) {
176 struct mem_block *q = p->prev;
177 q->size += p->size;
178 q->next = p->next;
179 q->next->prev = q;
180 kfree(p);
181 }
182}
183
184/* Initialize. How to check for an uninitialized heap?
185 */
186static int init_heap(struct mem_block **heap, int start, int size)
187{
188 struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
189
190 if (!blocks)
191 return -ENOMEM;
192
193 *heap = kmalloc(sizeof(**heap), GFP_KERNEL);
194 if (!*heap) {
195 kfree(blocks);
196 return -ENOMEM;
197 }
198
199 blocks->start = start;
200 blocks->size = size;
201 blocks->file_priv = NULL;
202 blocks->next = blocks->prev = *heap;
203
204 memset(*heap, 0, sizeof(**heap));
205 (*heap)->file_priv = (struct drm_file *) - 1;
206 (*heap)->next = (*heap)->prev = blocks;
207 return 0;
208}
209
210/* Free all blocks associated with the releasing file.
211 */
212void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv,
213 struct mem_block *heap)
214{
215 struct mem_block *p;
216
217 if (!heap || !heap->next)
218 return;
219
220 for (p = heap->next; p != heap; p = p->next) {
221 if (p->file_priv == file_priv) {
222 p->file_priv = NULL;
223 mark_block(dev, p, 0);
224 }
225 }
226
227 /* Assumes a single contiguous range. Needs a special file_priv in
228 * 'heap' to stop it being subsumed.
229 */
230 for (p = heap->next; p != heap; p = p->next) {
231 while (p->file_priv == NULL && p->next->file_priv == NULL) {
232 struct mem_block *q = p->next;
233 p->size += q->size;
234 p->next = q->next;
235 p->next->prev = p;
236 kfree(q);
237 }
238 }
239}
240
241/* Shutdown.
242 */
243void i915_mem_takedown(struct mem_block **heap)
244{
245 struct mem_block *p;
246
247 if (!*heap)
248 return;
249
250 for (p = (*heap)->next; p != *heap;) {
251 struct mem_block *q = p;
252 p = p->next;
253 kfree(q);
254 }
255
256 kfree(*heap);
257 *heap = NULL;
258}
259
260static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
261{
262 switch (region) {
263 case I915_MEM_REGION_AGP:
264 return &dev_priv->agp_heap;
265 default:
266 return NULL;
267 }
268}
269
270/* IOCTL HANDLERS */
271
272int i915_mem_alloc(struct drm_device *dev, void *data,
273 struct drm_file *file_priv)
274{
275 drm_i915_private_t *dev_priv = dev->dev_private;
276 drm_i915_mem_alloc_t *alloc = data;
277 struct mem_block *block, **heap;
278
279 if (!dev_priv) {
280 DRM_ERROR("called with no initialization\n");
281 return -EINVAL;
282 }
283
284 heap = get_heap(dev_priv, alloc->region);
285 if (!heap || !*heap)
286 return -EFAULT;
287
288 /* Make things easier on ourselves: all allocations at least
289 * 4k aligned.
290 */
291 if (alloc->alignment < 12)
292 alloc->alignment = 12;
293
294 block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
295
296 if (!block)
297 return -ENOMEM;
298
299 mark_block(dev, block, 1);
300
301 if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
302 sizeof(int))) {
303 DRM_ERROR("copy_to_user\n");
304 return -EFAULT;
305 }
306
307 return 0;
308}
309
310int i915_mem_free(struct drm_device *dev, void *data,
311 struct drm_file *file_priv)
312{
313 drm_i915_private_t *dev_priv = dev->dev_private;
314 drm_i915_mem_free_t *memfree = data;
315 struct mem_block *block, **heap;
316
317 if (!dev_priv) {
318 DRM_ERROR("called with no initialization\n");
319 return -EINVAL;
320 }
321
322 heap = get_heap(dev_priv, memfree->region);
323 if (!heap || !*heap)
324 return -EFAULT;
325
326 block = find_block(*heap, memfree->region_offset);
327 if (!block)
328 return -EFAULT;
329
330 if (block->file_priv != file_priv)
331 return -EPERM;
332
333 mark_block(dev, block, 0);
334 free_block(block);
335 return 0;
336}
337
338int i915_mem_init_heap(struct drm_device *dev, void *data,
339 struct drm_file *file_priv)
340{
341 drm_i915_private_t *dev_priv = dev->dev_private;
342 drm_i915_mem_init_heap_t *initheap = data;
343 struct mem_block **heap;
344
345 if (!dev_priv) {
346 DRM_ERROR("called with no initialization\n");
347 return -EINVAL;
348 }
349
350 heap = get_heap(dev_priv, initheap->region);
351 if (!heap)
352 return -EFAULT;
353
354 if (*heap) {
355 DRM_ERROR("heap already initialized?");
356 return -EFAULT;
357 }
358
359 return init_heap(heap, initheap->start, initheap->size);
360}
361
362int i915_mem_destroy_heap( struct drm_device *dev, void *data,
363 struct drm_file *file_priv )
364{
365 drm_i915_private_t *dev_priv = dev->dev_private;
366 drm_i915_mem_destroy_heap_t *destroyheap = data;
367 struct mem_block **heap;
368
369 if ( !dev_priv ) {
370 DRM_ERROR( "called with no initialization\n" );
371 return -EINVAL;
372 }
373
374 heap = get_heap( dev_priv, destroyheap->region );
375 if (!heap) {
376 DRM_ERROR("get_heap failed");
377 return -EFAULT;
378 }
379
380 if (!*heap) {
381 DRM_ERROR("heap not initialized?");
382 return -EFAULT;
383 }
384
385 i915_mem_takedown( heap );
386 return 0;
387}
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
new file mode 100644
index 00000000000..0e3241c39b8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -0,0 +1,484 @@
1/*
2 * Copyright 2005-2006 Stephane Marchesin
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include "drmP.h"
26#include "drm.h"
27#include "nouveau_drv.h"
28#include "nouveau_drm.h"
29#include "nouveau_dma.h"
30#include "nouveau_ramht.h"
31
32static int
33nouveau_channel_pushbuf_init(struct nouveau_channel *chan)
34{
35 u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT;
36 struct drm_device *dev = chan->dev;
37 struct drm_nouveau_private *dev_priv = dev->dev_private;
38 int ret;
39
40 /* allocate buffer object */
41 ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo);
42 if (ret)
43 goto out;
44
45 ret = nouveau_bo_pin(chan->pushbuf_bo, mem);
46 if (ret)
47 goto out;
48
49 ret = nouveau_bo_map(chan->pushbuf_bo);
50 if (ret)
51 goto out;
52
53 /* create DMA object covering the entire memtype where the push
54 * buffer resides, userspace can submit its own push buffers from
55 * anywhere within the same memtype.
56 */
57 chan->pushbuf_base = chan->pushbuf_bo->bo.offset;
58 if (dev_priv->card_type >= NV_50) {
59 ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm,
60 &chan->pushbuf_vma);
61 if (ret)
62 goto out;
63
64 if (dev_priv->card_type < NV_C0) {
65 ret = nouveau_gpuobj_dma_new(chan,
66 NV_CLASS_DMA_IN_MEMORY, 0,
67 (1ULL << 40),
68 NV_MEM_ACCESS_RO,
69 NV_MEM_TARGET_VM,
70 &chan->pushbuf);
71 }
72 chan->pushbuf_base = chan->pushbuf_vma.offset;
73 } else
74 if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) {
75 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
76 dev_priv->gart_info.aper_size,
77 NV_MEM_ACCESS_RO,
78 NV_MEM_TARGET_GART,
79 &chan->pushbuf);
80 } else
81 if (dev_priv->card_type != NV_04) {
82 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
83 dev_priv->fb_available_size,
84 NV_MEM_ACCESS_RO,
85 NV_MEM_TARGET_VRAM,
86 &chan->pushbuf);
87 } else {
88 /* NV04 cmdbuf hack, from original ddx.. not sure of it's
89 * exact reason for existing :) PCI access to cmdbuf in
90 * VRAM.
91 */
92 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
93 pci_resource_start(dev->pdev, 1),
94 dev_priv->fb_available_size,
95 NV_MEM_ACCESS_RO,
96 NV_MEM_TARGET_PCI,
97 &chan->pushbuf);
98 }
99
100out:
101 if (ret) {
102 NV_ERROR(dev, "error initialising pushbuf: %d\n", ret);
103 nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
104 nouveau_gpuobj_ref(NULL, &chan->pushbuf);
105 if (chan->pushbuf_bo) {
106 nouveau_bo_unmap(chan->pushbuf_bo);
107 nouveau_bo_ref(NULL, &chan->pushbuf_bo);
108 }
109 }
110
111 return 0;
112}
113
114/* allocates and initializes a fifo for user space consumption */
115int
116nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
117 struct drm_file *file_priv,
118 uint32_t vram_handle, uint32_t gart_handle)
119{
120 struct drm_nouveau_private *dev_priv = dev->dev_private;
121 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
122 struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
123 struct nouveau_channel *chan;
124 unsigned long flags;
125 int ret;
126
127 /* allocate and lock channel structure */
128 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
129 if (!chan)
130 return -ENOMEM;
131 chan->dev = dev;
132 chan->file_priv = file_priv;
133 chan->vram_handle = vram_handle;
134 chan->gart_handle = gart_handle;
135
136 kref_init(&chan->ref);
137 atomic_set(&chan->users, 1);
138 mutex_init(&chan->mutex);
139 mutex_lock(&chan->mutex);
140
141 /* allocate hw channel id */
142 spin_lock_irqsave(&dev_priv->channels.lock, flags);
143 for (chan->id = 0; chan->id < pfifo->channels; chan->id++) {
144 if (!dev_priv->channels.ptr[chan->id]) {
145 nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]);
146 break;
147 }
148 }
149 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
150
151 if (chan->id == pfifo->channels) {
152 mutex_unlock(&chan->mutex);
153 kfree(chan);
154 return -ENODEV;
155 }
156
157 NV_DEBUG(dev, "initialising channel %d\n", chan->id);
158 INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
159 INIT_LIST_HEAD(&chan->nvsw.flip);
160 INIT_LIST_HEAD(&chan->fence.pending);
161 spin_lock_init(&chan->fence.lock);
162
163 /* setup channel's memory and vm */
164 ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
165 if (ret) {
166 NV_ERROR(dev, "gpuobj %d\n", ret);
167 nouveau_channel_put(&chan);
168 return ret;
169 }
170
171 /* Allocate space for per-channel fixed notifier memory */
172 ret = nouveau_notifier_init_channel(chan);
173 if (ret) {
174 NV_ERROR(dev, "ntfy %d\n", ret);
175 nouveau_channel_put(&chan);
176 return ret;
177 }
178
179 /* Allocate DMA push buffer */
180 ret = nouveau_channel_pushbuf_init(chan);
181 if (ret) {
182 NV_ERROR(dev, "pushbuf %d\n", ret);
183 nouveau_channel_put(&chan);
184 return ret;
185 }
186
187 nouveau_dma_pre_init(chan);
188 chan->user_put = 0x40;
189 chan->user_get = 0x44;
190
191 /* disable the fifo caches */
192 pfifo->reassign(dev, false);
193
194 /* Construct initial RAMFC for new channel */
195 ret = pfifo->create_context(chan);
196 if (ret) {
197 nouveau_channel_put(&chan);
198 return ret;
199 }
200
201 pfifo->reassign(dev, true);
202
203 ret = nouveau_dma_init(chan);
204 if (!ret)
205 ret = nouveau_fence_channel_init(chan);
206 if (ret) {
207 nouveau_channel_put(&chan);
208 return ret;
209 }
210
211 nouveau_debugfs_channel_init(chan);
212
213 NV_DEBUG(dev, "channel %d initialised\n", chan->id);
214 if (fpriv) {
215 spin_lock(&fpriv->lock);
216 list_add(&chan->list, &fpriv->channels);
217 spin_unlock(&fpriv->lock);
218 }
219 *chan_ret = chan;
220 return 0;
221}
222
223struct nouveau_channel *
224nouveau_channel_get_unlocked(struct nouveau_channel *ref)
225{
226 struct nouveau_channel *chan = NULL;
227
228 if (likely(ref && atomic_inc_not_zero(&ref->users)))
229 nouveau_channel_ref(ref, &chan);
230
231 return chan;
232}
233
234struct nouveau_channel *
235nouveau_channel_get(struct drm_file *file_priv, int id)
236{
237 struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
238 struct nouveau_channel *chan;
239
240 spin_lock(&fpriv->lock);
241 list_for_each_entry(chan, &fpriv->channels, list) {
242 if (chan->id == id) {
243 chan = nouveau_channel_get_unlocked(chan);
244 spin_unlock(&fpriv->lock);
245 mutex_lock(&chan->mutex);
246 return chan;
247 }
248 }
249 spin_unlock(&fpriv->lock);
250
251 return ERR_PTR(-EINVAL);
252}
253
254void
255nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
256{
257 struct nouveau_channel *chan = *pchan;
258 struct drm_device *dev = chan->dev;
259 struct drm_nouveau_private *dev_priv = dev->dev_private;
260 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
261 unsigned long flags;
262 int i;
263
264 /* decrement the refcount, and we're done if there's still refs */
265 if (likely(!atomic_dec_and_test(&chan->users))) {
266 nouveau_channel_ref(NULL, pchan);
267 return;
268 }
269
270 /* no one wants the channel anymore */
271 NV_DEBUG(dev, "freeing channel %d\n", chan->id);
272 nouveau_debugfs_channel_fini(chan);
273
274 /* give it chance to idle */
275 nouveau_channel_idle(chan);
276
277 /* ensure all outstanding fences are signaled. they should be if the
278 * above attempts at idling were OK, but if we failed this'll tell TTM
279 * we're done with the buffers.
280 */
281 nouveau_fence_channel_fini(chan);
282
283 /* boot it off the hardware */
284 pfifo->reassign(dev, false);
285
286 /* destroy the engine specific contexts */
287 pfifo->destroy_context(chan);
288 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
289 if (chan->engctx[i])
290 dev_priv->eng[i]->context_del(chan, i);
291 }
292
293 pfifo->reassign(dev, true);
294
295 /* aside from its resources, the channel should now be dead,
296 * remove it from the channel list
297 */
298 spin_lock_irqsave(&dev_priv->channels.lock, flags);
299 nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]);
300 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
301
302 /* destroy any resources the channel owned */
303 nouveau_gpuobj_ref(NULL, &chan->pushbuf);
304 if (chan->pushbuf_bo) {
305 nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
306 nouveau_bo_unmap(chan->pushbuf_bo);
307 nouveau_bo_unpin(chan->pushbuf_bo);
308 nouveau_bo_ref(NULL, &chan->pushbuf_bo);
309 }
310 nouveau_ramht_ref(NULL, &chan->ramht, chan);
311 nouveau_notifier_takedown_channel(chan);
312 nouveau_gpuobj_channel_takedown(chan);
313
314 nouveau_channel_ref(NULL, pchan);
315}
316
317void
318nouveau_channel_put(struct nouveau_channel **pchan)
319{
320 mutex_unlock(&(*pchan)->mutex);
321 nouveau_channel_put_unlocked(pchan);
322}
323
324static void
325nouveau_channel_del(struct kref *ref)
326{
327 struct nouveau_channel *chan =
328 container_of(ref, struct nouveau_channel, ref);
329
330 kfree(chan);
331}
332
333void
334nouveau_channel_ref(struct nouveau_channel *chan,
335 struct nouveau_channel **pchan)
336{
337 if (chan)
338 kref_get(&chan->ref);
339
340 if (*pchan)
341 kref_put(&(*pchan)->ref, nouveau_channel_del);
342
343 *pchan = chan;
344}
345
346void
347nouveau_channel_idle(struct nouveau_channel *chan)
348{
349 struct drm_device *dev = chan->dev;
350 struct nouveau_fence *fence = NULL;
351 int ret;
352
353 nouveau_fence_update(chan);
354
355 if (chan->fence.sequence != chan->fence.sequence_ack) {
356 ret = nouveau_fence_new(chan, &fence, true);
357 if (!ret) {
358 ret = nouveau_fence_wait(fence, false, false);
359 nouveau_fence_unref(&fence);
360 }
361
362 if (ret)
363 NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
364 }
365}
366
367/* cleans up all the fifos from file_priv */
368void
369nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
370{
371 struct drm_nouveau_private *dev_priv = dev->dev_private;
372 struct nouveau_engine *engine = &dev_priv->engine;
373 struct nouveau_channel *chan;
374 int i;
375
376 NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
377 for (i = 0; i < engine->fifo.channels; i++) {
378 chan = nouveau_channel_get(file_priv, i);
379 if (IS_ERR(chan))
380 continue;
381
382 list_del(&chan->list);
383 atomic_dec(&chan->users);
384 nouveau_channel_put(&chan);
385 }
386}
387
388
389/***********************************
390 * ioctls wrapping the functions
391 ***********************************/
392
393static int
394nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
395 struct drm_file *file_priv)
396{
397 struct drm_nouveau_private *dev_priv = dev->dev_private;
398 struct drm_nouveau_channel_alloc *init = data;
399 struct nouveau_channel *chan;
400 int ret;
401
402 if (!dev_priv->eng[NVOBJ_ENGINE_GR])
403 return -ENODEV;
404
405 if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
406 return -EINVAL;
407
408 ret = nouveau_channel_alloc(dev, &chan, file_priv,
409 init->fb_ctxdma_handle,
410 init->tt_ctxdma_handle);
411 if (ret)
412 return ret;
413 init->channel = chan->id;
414
415 if (chan->dma.ib_max)
416 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
417 NOUVEAU_GEM_DOMAIN_GART;
418 else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
419 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
420 else
421 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
422
423 if (dev_priv->card_type < NV_C0) {
424 init->subchan[0].handle = NvM2MF;
425 if (dev_priv->card_type < NV_50)
426 init->subchan[0].grclass = 0x0039;
427 else
428 init->subchan[0].grclass = 0x5039;
429 init->subchan[1].handle = NvSw;
430 init->subchan[1].grclass = NV_SW;
431 init->nr_subchan = 2;
432 } else {
433 init->subchan[0].handle = 0x9039;
434 init->subchan[0].grclass = 0x9039;
435 init->nr_subchan = 1;
436 }
437
438 /* Named memory object area */
439 ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
440 &init->notifier_handle);
441
442 if (ret == 0)
443 atomic_inc(&chan->users); /* userspace reference */
444 nouveau_channel_put(&chan);
445 return ret;
446}
447
448static int
449nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
450 struct drm_file *file_priv)
451{
452 struct drm_nouveau_channel_free *req = data;
453 struct nouveau_channel *chan;
454
455 chan = nouveau_channel_get(file_priv, req->channel);
456 if (IS_ERR(chan))
457 return PTR_ERR(chan);
458
459 list_del(&chan->list);
460 atomic_dec(&chan->users);
461 nouveau_channel_put(&chan);
462 return 0;
463}
464
465/***********************************
466 * finally, the ioctl table
467 ***********************************/
468
469struct drm_ioctl_desc nouveau_ioctls[] = {
470 DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
471 DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
472 DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH),
473 DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH),
474 DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH),
475 DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH),
476 DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH),
477 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH),
478 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH),
479 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
480 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
481 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH),
482};
483
484int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
new file mode 100644
index 00000000000..8e1592368cc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -0,0 +1,197 @@
1/*
2 * Copyright (C) 2009 Red Hat <bskeggs@redhat.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26/*
27 * Authors:
28 * Ben Skeggs <bskeggs@redhat.com>
29 */
30
31#include <linux/debugfs.h>
32
33#include "drmP.h"
34#include "nouveau_drv.h"
35
36#include <ttm/ttm_page_alloc.h>
37
38static int
39nouveau_debugfs_channel_info(struct seq_file *m, void *data)
40{
41 struct drm_info_node *node = (struct drm_info_node *) m->private;
42 struct nouveau_channel *chan = node->info_ent->data;
43
44 seq_printf(m, "channel id : %d\n", chan->id);
45
46 seq_printf(m, "cpu fifo state:\n");
47 seq_printf(m, " base: 0x%08x\n", chan->pushbuf_base);
48 seq_printf(m, " max: 0x%08x\n", chan->dma.max << 2);
49 seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2);
50 seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2);
51 seq_printf(m, " free: 0x%08x\n", chan->dma.free << 2);
52 if (chan->dma.ib_max) {
53 seq_printf(m, " ib max: 0x%08x\n", chan->dma.ib_max);
54 seq_printf(m, " ib put: 0x%08x\n", chan->dma.ib_put);
55 seq_printf(m, " ib free: 0x%08x\n", chan->dma.ib_free);
56 }
57
58 seq_printf(m, "gpu fifo state:\n");
59 seq_printf(m, " get: 0x%08x\n",
60 nvchan_rd32(chan, chan->user_get));
61 seq_printf(m, " put: 0x%08x\n",
62 nvchan_rd32(chan, chan->user_put));
63 if (chan->dma.ib_max) {
64 seq_printf(m, " ib get: 0x%08x\n",
65 nvchan_rd32(chan, 0x88));
66 seq_printf(m, " ib put: 0x%08x\n",
67 nvchan_rd32(chan, 0x8c));
68 }
69
70 seq_printf(m, "last fence : %d\n", chan->fence.sequence);
71 seq_printf(m, "last signalled: %d\n", chan->fence.sequence_ack);
72 return 0;
73}
74
75int
76nouveau_debugfs_channel_init(struct nouveau_channel *chan)
77{
78 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
79 struct drm_minor *minor = chan->dev->primary;
80 int ret;
81
82 if (!dev_priv->debugfs.channel_root) {
83 dev_priv->debugfs.channel_root =
84 debugfs_create_dir("channel", minor->debugfs_root);
85 if (!dev_priv->debugfs.channel_root)
86 return -ENOENT;
87 }
88
89 snprintf(chan->debugfs.name, 32, "%d", chan->id);
90 chan->debugfs.info.name = chan->debugfs.name;
91 chan->debugfs.info.show = nouveau_debugfs_channel_info;
92 chan->debugfs.info.driver_features = 0;
93 chan->debugfs.info.data = chan;
94
95 ret = drm_debugfs_create_files(&chan->debugfs.info, 1,
96 dev_priv->debugfs.channel_root,
97 chan->dev->primary);
98 if (ret == 0)
99 chan->debugfs.active = true;
100 return ret;
101}
102
103void
104nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
105{
106 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
107
108 if (!chan->debugfs.active)
109 return;
110
111 drm_debugfs_remove_files(&chan->debugfs.info, 1, chan->dev->primary);
112 chan->debugfs.active = false;
113
114 if (chan == dev_priv->channel) {
115 debugfs_remove(dev_priv->debugfs.channel_root);
116 dev_priv->debugfs.channel_root = NULL;
117 }
118}
119
120static int
121nouveau_debugfs_chipset_info(struct seq_file *m, void *data)
122{
123 struct drm_info_node *node = (struct drm_info_node *) m->private;
124 struct drm_minor *minor = node->minor;
125 struct drm_device *dev = minor->dev;
126 struct drm_nouveau_private *dev_priv = dev->dev_private;
127 uint32_t ppci_0;
128
129 ppci_0 = nv_rd32(dev, dev_priv->chipset >= 0x40 ? 0x88000 : 0x1800);
130
131 seq_printf(m, "PMC_BOOT_0: 0x%08x\n", nv_rd32(dev, NV03_PMC_BOOT_0));
132 seq_printf(m, "PCI ID : 0x%04x:0x%04x\n",
133 ppci_0 & 0xffff, ppci_0 >> 16);
134 return 0;
135}
136
137static int
138nouveau_debugfs_memory_info(struct seq_file *m, void *data)
139{
140 struct drm_info_node *node = (struct drm_info_node *) m->private;
141 struct drm_minor *minor = node->minor;
142 struct drm_nouveau_private *dev_priv = minor->dev->dev_private;
143
144 seq_printf(m, "VRAM total: %dKiB\n", (int)(dev_priv->vram_size >> 10));
145 return 0;
146}
147
148static int
149nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
150{
151 struct drm_info_node *node = (struct drm_info_node *) m->private;
152 struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private;
153 int i;
154
155 for (i = 0; i < dev_priv->vbios.length; i++)
156 seq_printf(m, "%c", dev_priv->vbios.data[i]);
157 return 0;
158}
159
160static int
161nouveau_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
175static struct drm_info_list nouveau_debugfs_list[] = {
176 { "evict_vram", nouveau_debugfs_evict_vram, 0, NULL },
177 { "chipset", nouveau_debugfs_chipset_info, 0, NULL },
178 { "memory", nouveau_debugfs_memory_info, 0, NULL },
179 { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
180 { "ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL },
181};
182#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
183
184int
185nouveau_debugfs_init(struct drm_minor *minor)
186{
187 drm_debugfs_create_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
188 minor->debugfs_root, minor);
189 return 0;
190}
191
192void
193nouveau_debugfs_takedown(struct drm_minor *minor)
194{
195 drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
196 minor);
197}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
new file mode 100644
index 00000000000..b30ddd8d2e2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -0,0 +1,490 @@
1/*
2 * Copyright 2005 Stephane Marchesin.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <linux/console.h>
26
27#include "drmP.h"
28#include "drm.h"
29#include "drm_crtc_helper.h"
30#include "nouveau_drv.h"
31#include "nouveau_hw.h"
32#include "nouveau_fb.h"
33#include "nouveau_fbcon.h"
34#include "nouveau_pm.h"
35#include "nv50_display.h"
36
37#include "drm_pciids.h"
38
39MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)");
40int nouveau_agpmode = -1;
41module_param_named(agpmode, nouveau_agpmode, int, 0400);
42
43MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
44static int nouveau_modeset = -1; /* kms */
45module_param_named(modeset, nouveau_modeset, int, 0400);
46
47MODULE_PARM_DESC(vbios, "Override default VBIOS location");
48char *nouveau_vbios;
49module_param_named(vbios, nouveau_vbios, charp, 0400);
50
51MODULE_PARM_DESC(vram_pushbuf, "Force DMA push buffers to be in VRAM");
52int nouveau_vram_pushbuf;
53module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
54
55MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
56int nouveau_vram_notify = 0;
57module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
58
59MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
60int nouveau_duallink = 1;
61module_param_named(duallink, nouveau_duallink, int, 0400);
62
63MODULE_PARM_DESC(uscript_lvds, "LVDS output script table ID (>=GeForce 8)");
64int nouveau_uscript_lvds = -1;
65module_param_named(uscript_lvds, nouveau_uscript_lvds, int, 0400);
66
67MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)");
68int nouveau_uscript_tmds = -1;
69module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400);
70
71MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
72int nouveau_ignorelid = 0;
73module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
74
75MODULE_PARM_DESC(noaccel, "Disable all acceleration");
76int nouveau_noaccel = -1;
77module_param_named(noaccel, nouveau_noaccel, int, 0400);
78
79MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
80int nouveau_nofbaccel = 0;
81module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
82
83MODULE_PARM_DESC(force_post, "Force POST");
84int nouveau_force_post = 0;
85module_param_named(force_post, nouveau_force_post, int, 0400);
86
87MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type");
88int nouveau_override_conntype = 0;
89module_param_named(override_conntype, nouveau_override_conntype, int, 0400);
90
91MODULE_PARM_DESC(tv_disable, "Disable TV-out detection\n");
92int nouveau_tv_disable = 0;
93module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
94
95MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
96 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
97 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
98 "\t\tDefault: PAL\n"
99 "\t\t*NOTE* Ignored for cards with external TV encoders.");
100char *nouveau_tv_norm;
101module_param_named(tv_norm, nouveau_tv_norm, charp, 0400);
102
103MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n"
104 "\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n"
105 "\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n"
106 "\t\t0x100 vgaattr, 0x200 EVO (G80+). ");
107int nouveau_reg_debug;
108module_param_named(reg_debug, nouveau_reg_debug, int, 0600);
109
110MODULE_PARM_DESC(perflvl, "Performance level (default: boot)\n");
111char *nouveau_perflvl;
112module_param_named(perflvl, nouveau_perflvl, charp, 0400);
113
114MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n");
115int nouveau_perflvl_wr;
116module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
117
118MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n");
119int nouveau_msi;
120module_param_named(msi, nouveau_msi, int, 0400);
121
122MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
123int nouveau_ctxfw;
124module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
125
126int nouveau_fbpercrtc;
127#if 0
128module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
129#endif
130
131static struct pci_device_id pciidlist[] = {
132 {
133 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
134 .class = PCI_BASE_CLASS_DISPLAY << 16,
135 .class_mask = 0xff << 16,
136 },
137 {
138 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID),
139 .class = PCI_BASE_CLASS_DISPLAY << 16,
140 .class_mask = 0xff << 16,
141 },
142 {}
143};
144
145MODULE_DEVICE_TABLE(pci, pciidlist);
146
147static struct drm_driver driver;
148
149static int __devinit
150nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
151{
152 return drm_get_pci_dev(pdev, ent, &driver);
153}
154
155static void
156nouveau_pci_remove(struct pci_dev *pdev)
157{
158 struct drm_device *dev = pci_get_drvdata(pdev);
159
160 drm_put_dev(dev);
161}
162
163int
164nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
165{
166 struct drm_device *dev = pci_get_drvdata(pdev);
167 struct drm_nouveau_private *dev_priv = dev->dev_private;
168 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
169 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
170 struct nouveau_channel *chan;
171 struct drm_crtc *crtc;
172 int ret, i, e;
173
174 if (pm_state.event == PM_EVENT_PRETHAW)
175 return 0;
176
177 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
178 return 0;
179
180 NV_INFO(dev, "Disabling fbcon acceleration...\n");
181 nouveau_fbcon_save_disable_accel(dev);
182
183 NV_INFO(dev, "Unpinning framebuffer(s)...\n");
184 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
185 struct nouveau_framebuffer *nouveau_fb;
186
187 nouveau_fb = nouveau_framebuffer(crtc->fb);
188 if (!nouveau_fb || !nouveau_fb->nvbo)
189 continue;
190
191 nouveau_bo_unpin(nouveau_fb->nvbo);
192 }
193
194 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
195 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
196
197 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
198 nouveau_bo_unpin(nv_crtc->cursor.nvbo);
199 }
200
201 NV_INFO(dev, "Evicting buffers...\n");
202 ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
203
204 NV_INFO(dev, "Idling channels...\n");
205 for (i = 0; i < pfifo->channels; i++) {
206 chan = dev_priv->channels.ptr[i];
207
208 if (chan && chan->pushbuf_bo)
209 nouveau_channel_idle(chan);
210 }
211
212 pfifo->reassign(dev, false);
213 pfifo->disable(dev);
214 pfifo->unload_context(dev);
215
216 for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
217 if (!dev_priv->eng[e])
218 continue;
219
220 ret = dev_priv->eng[e]->fini(dev, e, true);
221 if (ret) {
222 NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
223 goto out_abort;
224 }
225 }
226
227 ret = pinstmem->suspend(dev);
228 if (ret) {
229 NV_ERROR(dev, "... failed: %d\n", ret);
230 goto out_abort;
231 }
232
233 NV_INFO(dev, "Suspending GPU objects...\n");
234 ret = nouveau_gpuobj_suspend(dev);
235 if (ret) {
236 NV_ERROR(dev, "... failed: %d\n", ret);
237 pinstmem->resume(dev);
238 goto out_abort;
239 }
240
241 NV_INFO(dev, "And we're gone!\n");
242 pci_save_state(pdev);
243 if (pm_state.event == PM_EVENT_SUSPEND) {
244 pci_disable_device(pdev);
245 pci_set_power_state(pdev, PCI_D3hot);
246 }
247
248 console_lock();
249 nouveau_fbcon_set_suspend(dev, 1);
250 console_unlock();
251 nouveau_fbcon_restore_accel(dev);
252 return 0;
253
254out_abort:
255 NV_INFO(dev, "Re-enabling acceleration..\n");
256 for (e = e + 1; e < NVOBJ_ENGINE_NR; e++) {
257 if (dev_priv->eng[e])
258 dev_priv->eng[e]->init(dev, e);
259 }
260 pfifo->enable(dev);
261 pfifo->reassign(dev, true);
262 return ret;
263}
264
265int
266nouveau_pci_resume(struct pci_dev *pdev)
267{
268 struct drm_device *dev = pci_get_drvdata(pdev);
269 struct drm_nouveau_private *dev_priv = dev->dev_private;
270 struct nouveau_engine *engine = &dev_priv->engine;
271 struct drm_crtc *crtc;
272 int ret, i;
273
274 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
275 return 0;
276
277 nouveau_fbcon_save_disable_accel(dev);
278
279 NV_INFO(dev, "We're back, enabling device...\n");
280 pci_set_power_state(pdev, PCI_D0);
281 pci_restore_state(pdev);
282 if (pci_enable_device(pdev))
283 return -1;
284 pci_set_master(dev->pdev);
285
286 /* Make sure the AGP controller is in a consistent state */
287 if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
288 nouveau_mem_reset_agp(dev);
289
290 /* Make the CRTCs accessible */
291 engine->display.early_init(dev);
292
293 NV_INFO(dev, "POSTing device...\n");
294 ret = nouveau_run_vbios_init(dev);
295 if (ret)
296 return ret;
297
298 nouveau_pm_resume(dev);
299
300 if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
301 ret = nouveau_mem_init_agp(dev);
302 if (ret) {
303 NV_ERROR(dev, "error reinitialising AGP: %d\n", ret);
304 return ret;
305 }
306 }
307
308 NV_INFO(dev, "Restoring GPU objects...\n");
309 nouveau_gpuobj_resume(dev);
310
311 NV_INFO(dev, "Reinitialising engines...\n");
312 engine->instmem.resume(dev);
313 engine->mc.init(dev);
314 engine->timer.init(dev);
315 engine->fb.init(dev);
316 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
317 if (dev_priv->eng[i])
318 dev_priv->eng[i]->init(dev, i);
319 }
320 engine->fifo.init(dev);
321
322 nouveau_irq_postinstall(dev);
323
324 /* Re-write SKIPS, they'll have been lost over the suspend */
325 if (nouveau_vram_pushbuf) {
326 struct nouveau_channel *chan;
327 int j;
328
329 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
330 chan = dev_priv->channels.ptr[i];
331 if (!chan || !chan->pushbuf_bo)
332 continue;
333
334 for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
335 nouveau_bo_wr32(chan->pushbuf_bo, i, 0);
336 }
337 }
338
339 NV_INFO(dev, "Restoring mode...\n");
340 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
341 struct nouveau_framebuffer *nouveau_fb;
342
343 nouveau_fb = nouveau_framebuffer(crtc->fb);
344 if (!nouveau_fb || !nouveau_fb->nvbo)
345 continue;
346
347 nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
348 }
349
350 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
351 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
352
353 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
354 if (!ret)
355 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
356 if (ret)
357 NV_ERROR(dev, "Could not pin/map cursor.\n");
358 }
359
360 engine->display.init(dev);
361
362 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
363 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
364 u32 offset = nv_crtc->cursor.nvbo->bo.offset;
365
366 nv_crtc->cursor.set_offset(nv_crtc, offset);
367 nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
368 nv_crtc->cursor_saved_y);
369 }
370
371 /* Force CLUT to get re-loaded during modeset */
372 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
373 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
374
375 nv_crtc->lut.depth = 0;
376 }
377
378 console_lock();
379 nouveau_fbcon_set_suspend(dev, 0);
380 console_unlock();
381
382 nouveau_fbcon_zfill_all(dev);
383
384 drm_helper_resume_force_mode(dev);
385
386 nouveau_fbcon_restore_accel(dev);
387 return 0;
388}
389
390static struct drm_driver driver = {
391 .driver_features =
392 DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
393 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
394 DRIVER_MODESET,
395 .load = nouveau_load,
396 .firstopen = nouveau_firstopen,
397 .lastclose = nouveau_lastclose,
398 .unload = nouveau_unload,
399 .open = nouveau_open,
400 .preclose = nouveau_preclose,
401 .postclose = nouveau_postclose,
402#if defined(CONFIG_DRM_NOUVEAU_DEBUG)
403 .debugfs_init = nouveau_debugfs_init,
404 .debugfs_cleanup = nouveau_debugfs_takedown,
405#endif
406 .irq_preinstall = nouveau_irq_preinstall,
407 .irq_postinstall = nouveau_irq_postinstall,
408 .irq_uninstall = nouveau_irq_uninstall,
409 .irq_handler = nouveau_irq_handler,
410 .get_vblank_counter = drm_vblank_count,
411 .enable_vblank = nouveau_vblank_enable,
412 .disable_vblank = nouveau_vblank_disable,
413 .reclaim_buffers = drm_core_reclaim_buffers,
414 .ioctls = nouveau_ioctls,
415 .fops = {
416 .owner = THIS_MODULE,
417 .open = drm_open,
418 .release = drm_release,
419 .unlocked_ioctl = drm_ioctl,
420 .mmap = nouveau_ttm_mmap,
421 .poll = drm_poll,
422 .fasync = drm_fasync,
423 .read = drm_read,
424#if defined(CONFIG_COMPAT)
425 .compat_ioctl = nouveau_compat_ioctl,
426#endif
427 .llseek = noop_llseek,
428 },
429
430 .gem_init_object = nouveau_gem_object_new,
431 .gem_free_object = nouveau_gem_object_del,
432 .gem_open_object = nouveau_gem_object_open,
433 .gem_close_object = nouveau_gem_object_close,
434
435 .name = DRIVER_NAME,
436 .desc = DRIVER_DESC,
437#ifdef GIT_REVISION
438 .date = GIT_REVISION,
439#else
440 .date = DRIVER_DATE,
441#endif
442 .major = DRIVER_MAJOR,
443 .minor = DRIVER_MINOR,
444 .patchlevel = DRIVER_PATCHLEVEL,
445};
446
447static struct pci_driver nouveau_pci_driver = {
448 .name = DRIVER_NAME,
449 .id_table = pciidlist,
450 .probe = nouveau_pci_probe,
451 .remove = nouveau_pci_remove,
452 .suspend = nouveau_pci_suspend,
453 .resume = nouveau_pci_resume
454};
455
456static int __init nouveau_init(void)
457{
458 driver.num_ioctls = nouveau_max_ioctl;
459
460 if (nouveau_modeset == -1) {
461#ifdef CONFIG_VGA_CONSOLE
462 if (vgacon_text_force())
463 nouveau_modeset = 0;
464 else
465#endif
466 nouveau_modeset = 1;
467 }
468
469 if (!nouveau_modeset)
470 return 0;
471
472 nouveau_register_dsm_handler();
473 return drm_pci_init(&driver, &nouveau_pci_driver);
474}
475
476static void __exit nouveau_exit(void)
477{
478 if (!nouveau_modeset)
479 return;
480
481 drm_pci_exit(&driver, &nouveau_pci_driver);
482 nouveau_unregister_dsm_handler();
483}
484
485module_init(nouveau_init);
486module_exit(nouveau_exit);
487
488MODULE_AUTHOR(DRIVER_AUTHOR);
489MODULE_DESCRIPTION(DRIVER_DESC);
490MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
new file mode 100644
index 00000000000..d7d51deb34b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -0,0 +1,1613 @@
1/*
2 * Copyright 2005 Stephane Marchesin.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef __NOUVEAU_DRV_H__
26#define __NOUVEAU_DRV_H__
27
28#define DRIVER_AUTHOR "Stephane Marchesin"
29#define DRIVER_EMAIL "dri-devel@lists.sourceforge.net"
30
31#define DRIVER_NAME "nouveau"
32#define DRIVER_DESC "nVidia Riva/TNT/GeForce"
33#define DRIVER_DATE "20090420"
34
35#define DRIVER_MAJOR 0
36#define DRIVER_MINOR 0
37#define DRIVER_PATCHLEVEL 16
38
39#define NOUVEAU_FAMILY 0x0000FFFF
40#define NOUVEAU_FLAGS 0xFFFF0000
41
42#include "ttm/ttm_bo_api.h"
43#include "ttm/ttm_bo_driver.h"
44#include "ttm/ttm_placement.h"
45#include "ttm/ttm_memory.h"
46#include "ttm/ttm_module.h"
47
48struct nouveau_fpriv {
49 spinlock_t lock;
50 struct list_head channels;
51 struct nouveau_vm *vm;
52};
53
54static inline struct nouveau_fpriv *
55nouveau_fpriv(struct drm_file *file_priv)
56{
57 return file_priv ? file_priv->driver_priv : NULL;
58}
59
60#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
61
62#include "nouveau_drm.h"
63#include "nouveau_reg.h"
64#include "nouveau_bios.h"
65#include "nouveau_util.h"
66
67struct nouveau_grctx;
68struct nouveau_mem;
69#include "nouveau_vm.h"
70
71#define MAX_NUM_DCB_ENTRIES 16
72
73#define NOUVEAU_MAX_CHANNEL_NR 128
74#define NOUVEAU_MAX_TILE_NR 15
75
76struct nouveau_mem {
77 struct drm_device *dev;
78
79 struct nouveau_vma bar_vma;
80 struct nouveau_vma vma[2];
81 u8 page_shift;
82
83 struct drm_mm_node *tag;
84 struct list_head regions;
85 dma_addr_t *pages;
86 u32 memtype;
87 u64 offset;
88 u64 size;
89};
90
91struct nouveau_tile_reg {
92 bool used;
93 uint32_t addr;
94 uint32_t limit;
95 uint32_t pitch;
96 uint32_t zcomp;
97 struct drm_mm_node *tag_mem;
98 struct nouveau_fence *fence;
99};
100
101struct nouveau_bo {
102 struct ttm_buffer_object bo;
103 struct ttm_placement placement;
104 u32 valid_domains;
105 u32 placements[3];
106 u32 busy_placements[3];
107 struct ttm_bo_kmap_obj kmap;
108 struct list_head head;
109
110 /* protected by ttm_bo_reserve() */
111 struct drm_file *reserved_by;
112 struct list_head entry;
113 int pbbo_index;
114 bool validate_mapped;
115
116 struct nouveau_channel *channel;
117
118 struct list_head vma_list;
119 unsigned page_shift;
120
121 uint32_t tile_mode;
122 uint32_t tile_flags;
123 struct nouveau_tile_reg *tile;
124
125 struct drm_gem_object *gem;
126 int pin_refcnt;
127};
128
129#define nouveau_bo_tile_layout(nvbo) \
130 ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)
131
132static inline struct nouveau_bo *
133nouveau_bo(struct ttm_buffer_object *bo)
134{
135 return container_of(bo, struct nouveau_bo, bo);
136}
137
138static inline struct nouveau_bo *
139nouveau_gem_object(struct drm_gem_object *gem)
140{
141 return gem ? gem->driver_private : NULL;
142}
143
144/* TODO: submit equivalent to TTM generic API upstream? */
145static inline void __iomem *
146nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo)
147{
148 bool is_iomem;
149 void __iomem *ioptr = (void __force __iomem *)ttm_kmap_obj_virtual(
150 &nvbo->kmap, &is_iomem);
151 WARN_ON_ONCE(ioptr && !is_iomem);
152 return ioptr;
153}
154
155enum nouveau_flags {
156 NV_NFORCE = 0x10000000,
157 NV_NFORCE2 = 0x20000000
158};
159
160#define NVOBJ_ENGINE_SW 0
161#define NVOBJ_ENGINE_GR 1
162#define NVOBJ_ENGINE_CRYPT 2
163#define NVOBJ_ENGINE_COPY0 3
164#define NVOBJ_ENGINE_COPY1 4
165#define NVOBJ_ENGINE_MPEG 5
166#define NVOBJ_ENGINE_DISPLAY 15
167#define NVOBJ_ENGINE_NR 16
168
169#define NVOBJ_FLAG_DONT_MAP (1 << 0)
170#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1)
171#define NVOBJ_FLAG_ZERO_FREE (1 << 2)
172#define NVOBJ_FLAG_VM (1 << 3)
173#define NVOBJ_FLAG_VM_USER (1 << 4)
174
175#define NVOBJ_CINST_GLOBAL 0xdeadbeef
176
177struct nouveau_gpuobj {
178 struct drm_device *dev;
179 struct kref refcount;
180 struct list_head list;
181
182 void *node;
183 u32 *suspend;
184
185 uint32_t flags;
186
187 u32 size;
188 u32 pinst; /* PRAMIN BAR offset */
189 u32 cinst; /* Channel offset */
190 u64 vinst; /* VRAM address */
191 u64 linst; /* VM address */
192
193 uint32_t engine;
194 uint32_t class;
195
196 void (*dtor)(struct drm_device *, struct nouveau_gpuobj *);
197 void *priv;
198};
199
200struct nouveau_page_flip_state {
201 struct list_head head;
202 struct drm_pending_vblank_event *event;
203 int crtc, bpp, pitch, x, y;
204 uint64_t offset;
205};
206
207enum nouveau_channel_mutex_class {
208 NOUVEAU_UCHANNEL_MUTEX,
209 NOUVEAU_KCHANNEL_MUTEX
210};
211
212struct nouveau_channel {
213 struct drm_device *dev;
214 struct list_head list;
215 int id;
216
217 /* references to the channel data structure */
218 struct kref ref;
219 /* users of the hardware channel resources, the hardware
220 * context will be kicked off when it reaches zero. */
221 atomic_t users;
222 struct mutex mutex;
223
224 /* owner of this fifo */
225 struct drm_file *file_priv;
226 /* mapping of the fifo itself */
227 struct drm_local_map *map;
228
229 /* mapping of the regs controlling the fifo */
230 void __iomem *user;
231 uint32_t user_get;
232 uint32_t user_put;
233
234 /* Fencing */
235 struct {
236 /* lock protects the pending list only */
237 spinlock_t lock;
238 struct list_head pending;
239 uint32_t sequence;
240 uint32_t sequence_ack;
241 atomic_t last_sequence_irq;
242 struct nouveau_vma vma;
243 } fence;
244
245 /* DMA push buffer */
246 struct nouveau_gpuobj *pushbuf;
247 struct nouveau_bo *pushbuf_bo;
248 struct nouveau_vma pushbuf_vma;
249 uint32_t pushbuf_base;
250
251 /* Notifier memory */
252 struct nouveau_bo *notifier_bo;
253 struct nouveau_vma notifier_vma;
254 struct drm_mm notifier_heap;
255
256 /* PFIFO context */
257 struct nouveau_gpuobj *ramfc;
258 struct nouveau_gpuobj *cache;
259 void *fifo_priv;
260
261 /* Execution engine contexts */
262 void *engctx[NVOBJ_ENGINE_NR];
263
264 /* NV50 VM */
265 struct nouveau_vm *vm;
266 struct nouveau_gpuobj *vm_pd;
267
268 /* Objects */
269 struct nouveau_gpuobj *ramin; /* Private instmem */
270 struct drm_mm ramin_heap; /* Private PRAMIN heap */
271 struct nouveau_ramht *ramht; /* Hash table */
272
273 /* GPU object info for stuff used in-kernel (mm_enabled) */
274 uint32_t m2mf_ntfy;
275 uint32_t vram_handle;
276 uint32_t gart_handle;
277 bool accel_done;
278
279 /* Push buffer state (only for drm's channel on !mm_enabled) */
280 struct {
281 int max;
282 int free;
283 int cur;
284 int put;
285 /* access via pushbuf_bo */
286
287 int ib_base;
288 int ib_max;
289 int ib_free;
290 int ib_put;
291 } dma;
292
293 uint32_t sw_subchannel[8];
294
295 struct nouveau_vma dispc_vma[2];
296 struct {
297 struct nouveau_gpuobj *vblsem;
298 uint32_t vblsem_head;
299 uint32_t vblsem_offset;
300 uint32_t vblsem_rval;
301 struct list_head vbl_wait;
302 struct list_head flip;
303 } nvsw;
304
305 struct {
306 bool active;
307 char name[32];
308 struct drm_info_list info;
309 } debugfs;
310};
311
312struct nouveau_exec_engine {
313 void (*destroy)(struct drm_device *, int engine);
314 int (*init)(struct drm_device *, int engine);
315 int (*fini)(struct drm_device *, int engine, bool suspend);
316 int (*context_new)(struct nouveau_channel *, int engine);
317 void (*context_del)(struct nouveau_channel *, int engine);
318 int (*object_new)(struct nouveau_channel *, int engine,
319 u32 handle, u16 class);
320 void (*set_tile_region)(struct drm_device *dev, int i);
321 void (*tlb_flush)(struct drm_device *, int engine);
322};
323
324struct nouveau_instmem_engine {
325 void *priv;
326
327 int (*init)(struct drm_device *dev);
328 void (*takedown)(struct drm_device *dev);
329 int (*suspend)(struct drm_device *dev);
330 void (*resume)(struct drm_device *dev);
331
332 int (*get)(struct nouveau_gpuobj *, struct nouveau_channel *,
333 u32 size, u32 align);
334 void (*put)(struct nouveau_gpuobj *);
335 int (*map)(struct nouveau_gpuobj *);
336 void (*unmap)(struct nouveau_gpuobj *);
337
338 void (*flush)(struct drm_device *);
339};
340
341struct nouveau_mc_engine {
342 int (*init)(struct drm_device *dev);
343 void (*takedown)(struct drm_device *dev);
344};
345
346struct nouveau_timer_engine {
347 int (*init)(struct drm_device *dev);
348 void (*takedown)(struct drm_device *dev);
349 uint64_t (*read)(struct drm_device *dev);
350};
351
352struct nouveau_fb_engine {
353 int num_tiles;
354 struct drm_mm tag_heap;
355 void *priv;
356
357 int (*init)(struct drm_device *dev);
358 void (*takedown)(struct drm_device *dev);
359
360 void (*init_tile_region)(struct drm_device *dev, int i,
361 uint32_t addr, uint32_t size,
362 uint32_t pitch, uint32_t flags);
363 void (*set_tile_region)(struct drm_device *dev, int i);
364 void (*free_tile_region)(struct drm_device *dev, int i);
365};
366
367struct nouveau_fifo_engine {
368 void *priv;
369 int channels;
370
371 struct nouveau_gpuobj *playlist[2];
372 int cur_playlist;
373
374 int (*init)(struct drm_device *);
375 void (*takedown)(struct drm_device *);
376
377 void (*disable)(struct drm_device *);
378 void (*enable)(struct drm_device *);
379 bool (*reassign)(struct drm_device *, bool enable);
380 bool (*cache_pull)(struct drm_device *dev, bool enable);
381
382 int (*channel_id)(struct drm_device *);
383
384 int (*create_context)(struct nouveau_channel *);
385 void (*destroy_context)(struct nouveau_channel *);
386 int (*load_context)(struct nouveau_channel *);
387 int (*unload_context)(struct drm_device *);
388 void (*tlb_flush)(struct drm_device *dev);
389};
390
391struct nouveau_display_engine {
392 void *priv;
393 int (*early_init)(struct drm_device *);
394 void (*late_takedown)(struct drm_device *);
395 int (*create)(struct drm_device *);
396 int (*init)(struct drm_device *);
397 void (*destroy)(struct drm_device *);
398};
399
400struct nouveau_gpio_engine {
401 void *priv;
402
403 int (*init)(struct drm_device *);
404 void (*takedown)(struct drm_device *);
405
406 int (*get)(struct drm_device *, enum dcb_gpio_tag);
407 int (*set)(struct drm_device *, enum dcb_gpio_tag, int state);
408
409 int (*irq_register)(struct drm_device *, enum dcb_gpio_tag,
410 void (*)(void *, int), void *);
411 void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag,
412 void (*)(void *, int), void *);
413 bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on);
414};
415
416struct nouveau_pm_voltage_level {
417 u8 voltage;
418 u8 vid;
419};
420
421struct nouveau_pm_voltage {
422 bool supported;
423 u8 vid_mask;
424
425 struct nouveau_pm_voltage_level *level;
426 int nr_level;
427};
428
429struct nouveau_pm_memtiming {
430 int id;
431 u32 reg_100220;
432 u32 reg_100224;
433 u32 reg_100228;
434 u32 reg_10022c;
435 u32 reg_100230;
436 u32 reg_100234;
437 u32 reg_100238;
438 u32 reg_10023c;
439 u32 reg_100240;
440};
441
442#define NOUVEAU_PM_MAX_LEVEL 8
443struct nouveau_pm_level {
444 struct device_attribute dev_attr;
445 char name[32];
446 int id;
447
448 u32 core;
449 u32 memory;
450 u32 shader;
451 u32 unk05;
452 u32 unk0a;
453
454 u8 voltage;
455 u8 fanspeed;
456
457 u16 memscript;
458 struct nouveau_pm_memtiming *timing;
459};
460
461struct nouveau_pm_temp_sensor_constants {
462 u16 offset_constant;
463 s16 offset_mult;
464 s16 offset_div;
465 s16 slope_mult;
466 s16 slope_div;
467};
468
469struct nouveau_pm_threshold_temp {
470 s16 critical;
471 s16 down_clock;
472 s16 fan_boost;
473};
474
475struct nouveau_pm_memtimings {
476 bool supported;
477 struct nouveau_pm_memtiming *timing;
478 int nr_timing;
479};
480
481struct nouveau_pm_engine {
482 struct nouveau_pm_voltage voltage;
483 struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL];
484 int nr_perflvl;
485 struct nouveau_pm_memtimings memtimings;
486 struct nouveau_pm_temp_sensor_constants sensor_constants;
487 struct nouveau_pm_threshold_temp threshold_temp;
488
489 struct nouveau_pm_level boot;
490 struct nouveau_pm_level *cur;
491
492 struct device *hwmon;
493 struct notifier_block acpi_nb;
494
495 int (*clock_get)(struct drm_device *, u32 id);
496 void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *,
497 u32 id, int khz);
498 void (*clock_set)(struct drm_device *, void *);
499 int (*voltage_get)(struct drm_device *);
500 int (*voltage_set)(struct drm_device *, int voltage);
501 int (*fanspeed_get)(struct drm_device *);
502 int (*fanspeed_set)(struct drm_device *, int fanspeed);
503 int (*temp_get)(struct drm_device *);
504};
505
506struct nouveau_vram_engine {
507 struct nouveau_mm *mm;
508
509 int (*init)(struct drm_device *);
510 void (*takedown)(struct drm_device *dev);
511 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
512 u32 type, struct nouveau_mem **);
513 void (*put)(struct drm_device *, struct nouveau_mem **);
514
515 bool (*flags_valid)(struct drm_device *, u32 tile_flags);
516};
517
518struct nouveau_engine {
519 struct nouveau_instmem_engine instmem;
520 struct nouveau_mc_engine mc;
521 struct nouveau_timer_engine timer;
522 struct nouveau_fb_engine fb;
523 struct nouveau_fifo_engine fifo;
524 struct nouveau_display_engine display;
525 struct nouveau_gpio_engine gpio;
526 struct nouveau_pm_engine pm;
527 struct nouveau_vram_engine vram;
528};
529
530struct nouveau_pll_vals {
531 union {
532 struct {
533#ifdef __BIG_ENDIAN
534 uint8_t N1, M1, N2, M2;
535#else
536 uint8_t M1, N1, M2, N2;
537#endif
538 };
539 struct {
540 uint16_t NM1, NM2;
541 } __attribute__((packed));
542 };
543 int log2P;
544
545 int refclk;
546};
547
548enum nv04_fp_display_regs {
549 FP_DISPLAY_END,
550 FP_TOTAL,
551 FP_CRTC,
552 FP_SYNC_START,
553 FP_SYNC_END,
554 FP_VALID_START,
555 FP_VALID_END
556};
557
558struct nv04_crtc_reg {
559 unsigned char MiscOutReg;
560 uint8_t CRTC[0xa0];
561 uint8_t CR58[0x10];
562 uint8_t Sequencer[5];
563 uint8_t Graphics[9];
564 uint8_t Attribute[21];
565 unsigned char DAC[768];
566
567 /* PCRTC regs */
568 uint32_t fb_start;
569 uint32_t crtc_cfg;
570 uint32_t cursor_cfg;
571 uint32_t gpio_ext;
572 uint32_t crtc_830;
573 uint32_t crtc_834;
574 uint32_t crtc_850;
575 uint32_t crtc_eng_ctrl;
576
577 /* PRAMDAC regs */
578 uint32_t nv10_cursync;
579 struct nouveau_pll_vals pllvals;
580 uint32_t ramdac_gen_ctrl;
581 uint32_t ramdac_630;
582 uint32_t ramdac_634;
583 uint32_t tv_setup;
584 uint32_t tv_vtotal;
585 uint32_t tv_vskew;
586 uint32_t tv_vsync_delay;
587 uint32_t tv_htotal;
588 uint32_t tv_hskew;
589 uint32_t tv_hsync_delay;
590 uint32_t tv_hsync_delay2;
591 uint32_t fp_horiz_regs[7];
592 uint32_t fp_vert_regs[7];
593 uint32_t dither;
594 uint32_t fp_control;
595 uint32_t dither_regs[6];
596 uint32_t fp_debug_0;
597 uint32_t fp_debug_1;
598 uint32_t fp_debug_2;
599 uint32_t fp_margin_color;
600 uint32_t ramdac_8c0;
601 uint32_t ramdac_a20;
602 uint32_t ramdac_a24;
603 uint32_t ramdac_a34;
604 uint32_t ctv_regs[38];
605};
606
607struct nv04_output_reg {
608 uint32_t output;
609 int head;
610};
611
612struct nv04_mode_state {
613 struct nv04_crtc_reg crtc_reg[2];
614 uint32_t pllsel;
615 uint32_t sel_clk;
616};
617
618enum nouveau_card_type {
619 NV_04 = 0x00,
620 NV_10 = 0x10,
621 NV_20 = 0x20,
622 NV_30 = 0x30,
623 NV_40 = 0x40,
624 NV_50 = 0x50,
625 NV_C0 = 0xc0,
626};
627
628struct drm_nouveau_private {
629 struct drm_device *dev;
630 bool noaccel;
631
632 /* the card type, takes NV_* as values */
633 enum nouveau_card_type card_type;
634 /* exact chipset, derived from NV_PMC_BOOT_0 */
635 int chipset;
636 int stepping;
637 int flags;
638
639 void __iomem *mmio;
640
641 spinlock_t ramin_lock;
642 void __iomem *ramin;
643 u32 ramin_size;
644 u32 ramin_base;
645 bool ramin_available;
646 struct drm_mm ramin_heap;
647 struct nouveau_exec_engine *eng[NVOBJ_ENGINE_NR];
648 struct list_head gpuobj_list;
649 struct list_head classes;
650
651 struct nouveau_bo *vga_ram;
652
653 /* interrupt handling */
654 void (*irq_handler[32])(struct drm_device *);
655 bool msi_enabled;
656
657 struct list_head vbl_waiting;
658
659 struct {
660 struct drm_global_reference mem_global_ref;
661 struct ttm_bo_global_ref bo_global_ref;
662 struct ttm_bo_device bdev;
663 atomic_t validate_sequence;
664 } ttm;
665
666 struct {
667 spinlock_t lock;
668 struct drm_mm heap;
669 struct nouveau_bo *bo;
670 } fence;
671
672 struct {
673 spinlock_t lock;
674 struct nouveau_channel *ptr[NOUVEAU_MAX_CHANNEL_NR];
675 } channels;
676
677 struct nouveau_engine engine;
678 struct nouveau_channel *channel;
679
680 /* For PFIFO and PGRAPH. */
681 spinlock_t context_switch_lock;
682
683 /* VM/PRAMIN flush, legacy PRAMIN aperture */
684 spinlock_t vm_lock;
685
686 /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
687 struct nouveau_ramht *ramht;
688 struct nouveau_gpuobj *ramfc;
689 struct nouveau_gpuobj *ramro;
690
691 uint32_t ramin_rsvd_vram;
692
693 struct {
694 enum {
695 NOUVEAU_GART_NONE = 0,
696 NOUVEAU_GART_AGP, /* AGP */
697 NOUVEAU_GART_PDMA, /* paged dma object */
698 NOUVEAU_GART_HW /* on-chip gart/vm */
699 } type;
700 uint64_t aper_base;
701 uint64_t aper_size;
702 uint64_t aper_free;
703
704 struct ttm_backend_func *func;
705
706 struct {
707 struct page *page;
708 dma_addr_t addr;
709 } dummy;
710
711 struct nouveau_gpuobj *sg_ctxdma;
712 } gart_info;
713
714 /* nv10-nv40 tiling regions */
715 struct {
716 struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR];
717 spinlock_t lock;
718 } tile;
719
720 /* VRAM/fb configuration */
721 uint64_t vram_size;
722 uint64_t vram_sys_base;
723
724 uint64_t fb_phys;
725 uint64_t fb_available_size;
726 uint64_t fb_mappable_pages;
727 uint64_t fb_aper_free;
728 int fb_mtrr;
729
730 /* BAR control (NV50-) */
731 struct nouveau_vm *bar1_vm;
732 struct nouveau_vm *bar3_vm;
733
734 /* G8x/G9x virtual address space */
735 struct nouveau_vm *chan_vm;
736
737 struct nvbios vbios;
738
739 struct nv04_mode_state mode_reg;
740 struct nv04_mode_state saved_reg;
741 uint32_t saved_vga_font[4][16384];
742 uint32_t crtc_owner;
743 uint32_t dac_users[4];
744
745 struct backlight_device *backlight;
746
747 struct {
748 struct dentry *channel_root;
749 } debugfs;
750
751 struct nouveau_fbdev *nfbdev;
752 struct apertures_struct *apertures;
753};
754
755static inline struct drm_nouveau_private *
756nouveau_private(struct drm_device *dev)
757{
758 return dev->dev_private;
759}
760
761static inline struct drm_nouveau_private *
762nouveau_bdev(struct ttm_bo_device *bd)
763{
764 return container_of(bd, struct drm_nouveau_private, ttm.bdev);
765}
766
767static inline int
768nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
769{
770 struct nouveau_bo *prev;
771
772 if (!pnvbo)
773 return -EINVAL;
774 prev = *pnvbo;
775
776 *pnvbo = ref ? nouveau_bo(ttm_bo_reference(&ref->bo)) : NULL;
777 if (prev) {
778 struct ttm_buffer_object *bo = &prev->bo;
779
780 ttm_bo_unref(&bo);
781 }
782
783 return 0;
784}
785
786/* nouveau_drv.c */
787extern int nouveau_agpmode;
788extern int nouveau_duallink;
789extern int nouveau_uscript_lvds;
790extern int nouveau_uscript_tmds;
791extern int nouveau_vram_pushbuf;
792extern int nouveau_vram_notify;
793extern int nouveau_fbpercrtc;
794extern int nouveau_tv_disable;
795extern char *nouveau_tv_norm;
796extern int nouveau_reg_debug;
797extern char *nouveau_vbios;
798extern int nouveau_ignorelid;
799extern int nouveau_nofbaccel;
800extern int nouveau_noaccel;
801extern int nouveau_force_post;
802extern int nouveau_override_conntype;
803extern char *nouveau_perflvl;
804extern int nouveau_perflvl_wr;
805extern int nouveau_msi;
806extern int nouveau_ctxfw;
807
808extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
809extern int nouveau_pci_resume(struct pci_dev *pdev);
810
811/* nouveau_state.c */
812extern int nouveau_open(struct drm_device *, struct drm_file *);
813extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
814extern void nouveau_postclose(struct drm_device *, struct drm_file *);
815extern int nouveau_load(struct drm_device *, unsigned long flags);
816extern int nouveau_firstopen(struct drm_device *);
817extern void nouveau_lastclose(struct drm_device *);
818extern int nouveau_unload(struct drm_device *);
819extern int nouveau_ioctl_getparam(struct drm_device *, void *data,
820 struct drm_file *);
821extern int nouveau_ioctl_setparam(struct drm_device *, void *data,
822 struct drm_file *);
823extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout,
824 uint32_t reg, uint32_t mask, uint32_t val);
825extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
826 uint32_t reg, uint32_t mask, uint32_t val);
827extern bool nouveau_wait_for_idle(struct drm_device *);
828extern int nouveau_card_init(struct drm_device *);
829
830/* nouveau_mem.c */
831extern int nouveau_mem_vram_init(struct drm_device *);
832extern void nouveau_mem_vram_fini(struct drm_device *);
833extern int nouveau_mem_gart_init(struct drm_device *);
834extern void nouveau_mem_gart_fini(struct drm_device *);
835extern int nouveau_mem_init_agp(struct drm_device *);
836extern int nouveau_mem_reset_agp(struct drm_device *);
837extern void nouveau_mem_close(struct drm_device *);
838extern int nouveau_mem_detect(struct drm_device *);
839extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
840extern struct nouveau_tile_reg *nv10_mem_set_tiling(
841 struct drm_device *dev, uint32_t addr, uint32_t size,
842 uint32_t pitch, uint32_t flags);
843extern void nv10_mem_put_tile_region(struct drm_device *dev,
844 struct nouveau_tile_reg *tile,
845 struct nouveau_fence *fence);
846extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
847extern const struct ttm_mem_type_manager_func nouveau_gart_manager;
848
849/* nouveau_notifier.c */
850extern int nouveau_notifier_init_channel(struct nouveau_channel *);
851extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
852extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
853 int cout, uint32_t start, uint32_t end,
854 uint32_t *offset);
855extern int nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *);
856extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data,
857 struct drm_file *);
858extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data,
859 struct drm_file *);
860
861/* nouveau_channel.c */
862extern struct drm_ioctl_desc nouveau_ioctls[];
863extern int nouveau_max_ioctl;
864extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *);
865extern int nouveau_channel_alloc(struct drm_device *dev,
866 struct nouveau_channel **chan,
867 struct drm_file *file_priv,
868 uint32_t fb_ctxdma, uint32_t tt_ctxdma);
869extern struct nouveau_channel *
870nouveau_channel_get_unlocked(struct nouveau_channel *);
871extern struct nouveau_channel *
872nouveau_channel_get(struct drm_file *, int id);
873extern void nouveau_channel_put_unlocked(struct nouveau_channel **);
874extern void nouveau_channel_put(struct nouveau_channel **);
875extern void nouveau_channel_ref(struct nouveau_channel *chan,
876 struct nouveau_channel **pchan);
877extern void nouveau_channel_idle(struct nouveau_channel *chan);
878
879/* nouveau_object.c */
880#define NVOBJ_ENGINE_ADD(d, e, p) do { \
881 struct drm_nouveau_private *dev_priv = (d)->dev_private; \
882 dev_priv->eng[NVOBJ_ENGINE_##e] = (p); \
883} while (0)
884
885#define NVOBJ_ENGINE_DEL(d, e) do { \
886 struct drm_nouveau_private *dev_priv = (d)->dev_private; \
887 dev_priv->eng[NVOBJ_ENGINE_##e] = NULL; \
888} while (0)
889
890#define NVOBJ_CLASS(d, c, e) do { \
891 int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \
892 if (ret) \
893 return ret; \
894} while (0)
895
896#define NVOBJ_MTHD(d, c, m, e) do { \
897 int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \
898 if (ret) \
899 return ret; \
900} while (0)
901
902extern int nouveau_gpuobj_early_init(struct drm_device *);
903extern int nouveau_gpuobj_init(struct drm_device *);
904extern void nouveau_gpuobj_takedown(struct drm_device *);
905extern int nouveau_gpuobj_suspend(struct drm_device *dev);
906extern void nouveau_gpuobj_resume(struct drm_device *dev);
907extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng);
908extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
909 int (*exec)(struct nouveau_channel *,
910 u32 class, u32 mthd, u32 data));
911extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32);
912extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32);
913extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
914 uint32_t vram_h, uint32_t tt_h);
915extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
916extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *,
917 uint32_t size, int align, uint32_t flags,
918 struct nouveau_gpuobj **);
919extern void nouveau_gpuobj_ref(struct nouveau_gpuobj *,
920 struct nouveau_gpuobj **);
921extern int nouveau_gpuobj_new_fake(struct drm_device *, u32 pinst, u64 vinst,
922 u32 size, u32 flags,
923 struct nouveau_gpuobj **);
924extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class,
925 uint64_t offset, uint64_t size, int access,
926 int target, struct nouveau_gpuobj **);
927extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, u32 handle, int class);
928extern int nv50_gpuobj_dma_new(struct nouveau_channel *, int class, u64 base,
929 u64 size, int target, int access, u32 type,
930 u32 comp, struct nouveau_gpuobj **pobj);
931extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset,
932 int class, u64 base, u64 size, int target,
933 int access, u32 type, u32 comp);
934extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
935 struct drm_file *);
936extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
937 struct drm_file *);
938
939/* nouveau_irq.c */
940extern int nouveau_irq_init(struct drm_device *);
941extern void nouveau_irq_fini(struct drm_device *);
942extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
943extern void nouveau_irq_register(struct drm_device *, int status_bit,
944 void (*)(struct drm_device *));
945extern void nouveau_irq_unregister(struct drm_device *, int status_bit);
946extern void nouveau_irq_preinstall(struct drm_device *);
947extern int nouveau_irq_postinstall(struct drm_device *);
948extern void nouveau_irq_uninstall(struct drm_device *);
949
950/* nouveau_sgdma.c */
951extern int nouveau_sgdma_init(struct drm_device *);
952extern void nouveau_sgdma_takedown(struct drm_device *);
953extern uint32_t nouveau_sgdma_get_physical(struct drm_device *,
954 uint32_t offset);
955extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
956
957/* nouveau_debugfs.c */
958#if defined(CONFIG_DRM_NOUVEAU_DEBUG)
959extern int nouveau_debugfs_init(struct drm_minor *);
960extern void nouveau_debugfs_takedown(struct drm_minor *);
961extern int nouveau_debugfs_channel_init(struct nouveau_channel *);
962extern void nouveau_debugfs_channel_fini(struct nouveau_channel *);
963#else
964static inline int
965nouveau_debugfs_init(struct drm_minor *minor)
966{
967 return 0;
968}
969
970static inline void nouveau_debugfs_takedown(struct drm_minor *minor)
971{
972}
973
974static inline int
975nouveau_debugfs_channel_init(struct nouveau_channel *chan)
976{
977 return 0;
978}
979
980static inline void
981nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
982{
983}
984#endif
985
986/* nouveau_dma.c */
987extern void nouveau_dma_pre_init(struct nouveau_channel *);
988extern int nouveau_dma_init(struct nouveau_channel *);
989extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
990
991/* nouveau_acpi.c */
992#define ROM_BIOS_PAGE 4096
993#if defined(CONFIG_ACPI)
994void nouveau_register_dsm_handler(void);
995void nouveau_unregister_dsm_handler(void);
996int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
997bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
998int nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
999#else
1000static inline void nouveau_register_dsm_handler(void) {}
1001static inline void nouveau_unregister_dsm_handler(void) {}
1002static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
1003static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
1004static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; }
1005#endif
1006
1007/* nouveau_backlight.c */
1008#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
1009extern int nouveau_backlight_init(struct drm_connector *);
1010extern void nouveau_backlight_exit(struct drm_connector *);
1011#else
1012static inline int nouveau_backlight_init(struct drm_connector *dev)
1013{
1014 return 0;
1015}
1016
1017static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
1018#endif
1019
1020/* nouveau_bios.c */
1021extern int nouveau_bios_init(struct drm_device *);
1022extern void nouveau_bios_takedown(struct drm_device *dev);
1023extern int nouveau_run_vbios_init(struct drm_device *);
1024extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table,
1025 struct dcb_entry *);
1026extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *,
1027 enum dcb_gpio_tag);
1028extern struct dcb_connector_table_entry *
1029nouveau_bios_connector_entry(struct drm_device *, int index);
1030extern u32 get_pll_register(struct drm_device *, enum pll_types);
1031extern int get_pll_limits(struct drm_device *, uint32_t limit_match,
1032 struct pll_lims *);
1033extern int nouveau_bios_run_display_table(struct drm_device *,
1034 struct dcb_entry *,
1035 uint32_t script, int pxclk);
1036extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *,
1037 int *length);
1038extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
1039extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *);
1040extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk,
1041 bool *dl, bool *if_is_24bit);
1042extern int run_tmds_table(struct drm_device *, struct dcb_entry *,
1043 int head, int pxclk);
1044extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head,
1045 enum LVDS_script, int pxclk);
1046
1047/* nouveau_ttm.c */
1048int nouveau_ttm_global_init(struct drm_nouveau_private *);
1049void nouveau_ttm_global_release(struct drm_nouveau_private *);
1050int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
1051
1052/* nouveau_dp.c */
1053int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
1054 uint8_t *data, int data_nr);
1055bool nouveau_dp_detect(struct drm_encoder *);
1056bool nouveau_dp_link_train(struct drm_encoder *);
1057
1058/* nv04_fb.c */
1059extern int nv04_fb_init(struct drm_device *);
1060extern void nv04_fb_takedown(struct drm_device *);
1061
1062/* nv10_fb.c */
1063extern int nv10_fb_init(struct drm_device *);
1064extern void nv10_fb_takedown(struct drm_device *);
1065extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
1066 uint32_t addr, uint32_t size,
1067 uint32_t pitch, uint32_t flags);
1068extern void nv10_fb_set_tile_region(struct drm_device *dev, int i);
1069extern void nv10_fb_free_tile_region(struct drm_device *dev, int i);
1070
1071/* nv30_fb.c */
1072extern int nv30_fb_init(struct drm_device *);
1073extern void nv30_fb_takedown(struct drm_device *);
1074extern void nv30_fb_init_tile_region(struct drm_device *dev, int i,
1075 uint32_t addr, uint32_t size,
1076 uint32_t pitch, uint32_t flags);
1077extern void nv30_fb_free_tile_region(struct drm_device *dev, int i);
1078
1079/* nv40_fb.c */
1080extern int nv40_fb_init(struct drm_device *);
1081extern void nv40_fb_takedown(struct drm_device *);
1082extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
1083
1084/* nv50_fb.c */
1085extern int nv50_fb_init(struct drm_device *);
1086extern void nv50_fb_takedown(struct drm_device *);
1087extern void nv50_fb_vm_trap(struct drm_device *, int display);
1088
1089/* nvc0_fb.c */
1090extern int nvc0_fb_init(struct drm_device *);
1091extern void nvc0_fb_takedown(struct drm_device *);
1092
1093/* nv04_fifo.c */
1094extern int nv04_fifo_init(struct drm_device *);
1095extern void nv04_fifo_fini(struct drm_device *);
1096extern void nv04_fifo_disable(struct drm_device *);
1097extern void nv04_fifo_enable(struct drm_device *);
1098extern bool nv04_fifo_reassign(struct drm_device *, bool);
1099extern bool nv04_fifo_cache_pull(struct drm_device *, bool);
1100extern int nv04_fifo_channel_id(struct drm_device *);
1101extern int nv04_fifo_create_context(struct nouveau_channel *);
1102extern void nv04_fifo_destroy_context(struct nouveau_channel *);
1103extern int nv04_fifo_load_context(struct nouveau_channel *);
1104extern int nv04_fifo_unload_context(struct drm_device *);
1105extern void nv04_fifo_isr(struct drm_device *);
1106
1107/* nv10_fifo.c */
1108extern int nv10_fifo_init(struct drm_device *);
1109extern int nv10_fifo_channel_id(struct drm_device *);
1110extern int nv10_fifo_create_context(struct nouveau_channel *);
1111extern int nv10_fifo_load_context(struct nouveau_channel *);
1112extern int nv10_fifo_unload_context(struct drm_device *);
1113
1114/* nv40_fifo.c */
1115extern int nv40_fifo_init(struct drm_device *);
1116extern int nv40_fifo_create_context(struct nouveau_channel *);
1117extern int nv40_fifo_load_context(struct nouveau_channel *);
1118extern int nv40_fifo_unload_context(struct drm_device *);
1119
1120/* nv50_fifo.c */
1121extern int nv50_fifo_init(struct drm_device *);
1122extern void nv50_fifo_takedown(struct drm_device *);
1123extern int nv50_fifo_channel_id(struct drm_device *);
1124extern int nv50_fifo_create_context(struct nouveau_channel *);
1125extern void nv50_fifo_destroy_context(struct nouveau_channel *);
1126extern int nv50_fifo_load_context(struct nouveau_channel *);
1127extern int nv50_fifo_unload_context(struct drm_device *);
1128extern void nv50_fifo_tlb_flush(struct drm_device *dev);
1129
1130/* nvc0_fifo.c */
1131extern int nvc0_fifo_init(struct drm_device *);
1132extern void nvc0_fifo_takedown(struct drm_device *);
1133extern void nvc0_fifo_disable(struct drm_device *);
1134extern void nvc0_fifo_enable(struct drm_device *);
1135extern bool nvc0_fifo_reassign(struct drm_device *, bool);
1136extern bool nvc0_fifo_cache_pull(struct drm_device *, bool);
1137extern int nvc0_fifo_channel_id(struct drm_device *);
1138extern int nvc0_fifo_create_context(struct nouveau_channel *);
1139extern void nvc0_fifo_destroy_context(struct nouveau_channel *);
1140extern int nvc0_fifo_load_context(struct nouveau_channel *);
1141extern int nvc0_fifo_unload_context(struct drm_device *);
1142
1143/* nv04_graph.c */
1144extern int nv04_graph_create(struct drm_device *);
1145extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
1146extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
1147 u32 class, u32 mthd, u32 data);
1148extern struct nouveau_bitfield nv04_graph_nsource[];
1149
1150/* nv10_graph.c */
1151extern int nv10_graph_create(struct drm_device *);
1152extern struct nouveau_channel *nv10_graph_channel(struct drm_device *);
1153extern struct nouveau_bitfield nv10_graph_intr[];
1154extern struct nouveau_bitfield nv10_graph_nstatus[];
1155
1156/* nv20_graph.c */
1157extern int nv20_graph_create(struct drm_device *);
1158
1159/* nv40_graph.c */
1160extern int nv40_graph_create(struct drm_device *);
1161extern void nv40_grctx_init(struct nouveau_grctx *);
1162
1163/* nv50_graph.c */
1164extern int nv50_graph_create(struct drm_device *);
1165extern int nv50_grctx_init(struct nouveau_grctx *);
1166extern struct nouveau_enum nv50_data_error_names[];
1167extern int nv50_graph_isr_chid(struct drm_device *dev, u64 inst);
1168
1169/* nvc0_graph.c */
1170extern int nvc0_graph_create(struct drm_device *);
1171extern int nvc0_graph_isr_chid(struct drm_device *dev, u64 inst);
1172
1173/* nv84_crypt.c */
1174extern int nv84_crypt_create(struct drm_device *);
1175
1176/* nva3_copy.c */
1177extern int nva3_copy_create(struct drm_device *dev);
1178
1179/* nvc0_copy.c */
1180extern int nvc0_copy_create(struct drm_device *dev, int engine);
1181
1182/* nv40_mpeg.c */
1183extern int nv40_mpeg_create(struct drm_device *dev);
1184
1185/* nv50_mpeg.c */
1186extern int nv50_mpeg_create(struct drm_device *dev);
1187
1188/* nv04_instmem.c */
1189extern int nv04_instmem_init(struct drm_device *);
1190extern void nv04_instmem_takedown(struct drm_device *);
1191extern int nv04_instmem_suspend(struct drm_device *);
1192extern void nv04_instmem_resume(struct drm_device *);
1193extern int nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
1194 u32 size, u32 align);
1195extern void nv04_instmem_put(struct nouveau_gpuobj *);
1196extern int nv04_instmem_map(struct nouveau_gpuobj *);
1197extern void nv04_instmem_unmap(struct nouveau_gpuobj *);
1198extern void nv04_instmem_flush(struct drm_device *);
1199
1200/* nv50_instmem.c */
1201extern int nv50_instmem_init(struct drm_device *);
1202extern void nv50_instmem_takedown(struct drm_device *);
1203extern int nv50_instmem_suspend(struct drm_device *);
1204extern void nv50_instmem_resume(struct drm_device *);
1205extern int nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
1206 u32 size, u32 align);
1207extern void nv50_instmem_put(struct nouveau_gpuobj *);
1208extern int nv50_instmem_map(struct nouveau_gpuobj *);
1209extern void nv50_instmem_unmap(struct nouveau_gpuobj *);
1210extern void nv50_instmem_flush(struct drm_device *);
1211extern void nv84_instmem_flush(struct drm_device *);
1212
1213/* nvc0_instmem.c */
1214extern int nvc0_instmem_init(struct drm_device *);
1215extern void nvc0_instmem_takedown(struct drm_device *);
1216extern int nvc0_instmem_suspend(struct drm_device *);
1217extern void nvc0_instmem_resume(struct drm_device *);
1218
1219/* nv04_mc.c */
1220extern int nv04_mc_init(struct drm_device *);
1221extern void nv04_mc_takedown(struct drm_device *);
1222
1223/* nv40_mc.c */
1224extern int nv40_mc_init(struct drm_device *);
1225extern void nv40_mc_takedown(struct drm_device *);
1226
1227/* nv50_mc.c */
1228extern int nv50_mc_init(struct drm_device *);
1229extern void nv50_mc_takedown(struct drm_device *);
1230
1231/* nv04_timer.c */
1232extern int nv04_timer_init(struct drm_device *);
1233extern uint64_t nv04_timer_read(struct drm_device *);
1234extern void nv04_timer_takedown(struct drm_device *);
1235
1236extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
1237 unsigned long arg);
1238
1239/* nv04_dac.c */
1240extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
1241extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
1242extern int nv04_dac_output_offset(struct drm_encoder *encoder);
1243extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
1244extern bool nv04_dac_in_use(struct drm_encoder *encoder);
1245
1246/* nv04_dfp.c */
1247extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
1248extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
1249extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
1250 int head, bool dl);
1251extern void nv04_dfp_disable(struct drm_device *dev, int head);
1252extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);
1253
1254/* nv04_tv.c */
1255extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
1256extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *);
1257
1258/* nv17_tv.c */
1259extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *);
1260
1261/* nv04_display.c */
1262extern int nv04_display_early_init(struct drm_device *);
1263extern void nv04_display_late_takedown(struct drm_device *);
1264extern int nv04_display_create(struct drm_device *);
1265extern int nv04_display_init(struct drm_device *);
1266extern void nv04_display_destroy(struct drm_device *);
1267
1268/* nv04_crtc.c */
1269extern int nv04_crtc_create(struct drm_device *, int index);
1270
1271/* nouveau_bo.c */
1272extern struct ttm_bo_driver nouveau_bo_driver;
1273extern int nouveau_bo_new(struct drm_device *, int size, int align,
1274 uint32_t flags, uint32_t tile_mode,
1275 uint32_t tile_flags, struct nouveau_bo **);
1276extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
1277extern int nouveau_bo_unpin(struct nouveau_bo *);
1278extern int nouveau_bo_map(struct nouveau_bo *);
1279extern void nouveau_bo_unmap(struct nouveau_bo *);
1280extern void nouveau_bo_placement_set(struct nouveau_bo *, uint32_t type,
1281 uint32_t busy);
1282extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
1283extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
1284extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
1285extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
1286extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *);
1287extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
1288 bool no_wait_reserve, bool no_wait_gpu);
1289
1290extern struct nouveau_vma *
1291nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *);
1292extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
1293 struct nouveau_vma *);
1294extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);
1295
1296/* nouveau_fence.c */
1297struct nouveau_fence;
1298extern int nouveau_fence_init(struct drm_device *);
1299extern void nouveau_fence_fini(struct drm_device *);
1300extern int nouveau_fence_channel_init(struct nouveau_channel *);
1301extern void nouveau_fence_channel_fini(struct nouveau_channel *);
1302extern void nouveau_fence_update(struct nouveau_channel *);
1303extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **,
1304 bool emit);
1305extern int nouveau_fence_emit(struct nouveau_fence *);
1306extern void nouveau_fence_work(struct nouveau_fence *fence,
1307 void (*work)(void *priv, bool signalled),
1308 void *priv);
1309struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *);
1310
1311extern bool __nouveau_fence_signalled(void *obj, void *arg);
1312extern int __nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
1313extern int __nouveau_fence_flush(void *obj, void *arg);
1314extern void __nouveau_fence_unref(void **obj);
1315extern void *__nouveau_fence_ref(void *obj);
1316
1317static inline bool nouveau_fence_signalled(struct nouveau_fence *obj)
1318{
1319 return __nouveau_fence_signalled(obj, NULL);
1320}
1321static inline int
1322nouveau_fence_wait(struct nouveau_fence *obj, bool lazy, bool intr)
1323{
1324 return __nouveau_fence_wait(obj, NULL, lazy, intr);
1325}
1326extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *);
1327static inline int nouveau_fence_flush(struct nouveau_fence *obj)
1328{
1329 return __nouveau_fence_flush(obj, NULL);
1330}
1331static inline void nouveau_fence_unref(struct nouveau_fence **obj)
1332{
1333 __nouveau_fence_unref((void **)obj);
1334}
1335static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj)
1336{
1337 return __nouveau_fence_ref(obj);
1338}
1339
1340/* nouveau_gem.c */
1341extern int nouveau_gem_new(struct drm_device *, int size, int align,
1342 uint32_t domain, uint32_t tile_mode,
1343 uint32_t tile_flags, struct nouveau_bo **);
1344extern int nouveau_gem_object_new(struct drm_gem_object *);
1345extern void nouveau_gem_object_del(struct drm_gem_object *);
1346extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *);
1347extern void nouveau_gem_object_close(struct drm_gem_object *,
1348 struct drm_file *);
1349extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
1350 struct drm_file *);
1351extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
1352 struct drm_file *);
1353extern int nouveau_gem_ioctl_cpu_prep(struct drm_device *, void *,
1354 struct drm_file *);
1355extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
1356 struct drm_file *);
1357extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
1358 struct drm_file *);
1359
1360/* nouveau_display.c */
1361int nouveau_vblank_enable(struct drm_device *dev, int crtc);
1362void nouveau_vblank_disable(struct drm_device *dev, int crtc);
1363int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
1364 struct drm_pending_vblank_event *event);
1365int nouveau_finish_page_flip(struct nouveau_channel *,
1366 struct nouveau_page_flip_state *);
1367
1368/* nv10_gpio.c */
1369int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
1370int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
1371
1372/* nv50_gpio.c */
1373int nv50_gpio_init(struct drm_device *dev);
1374void nv50_gpio_fini(struct drm_device *dev);
1375int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
1376int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
1377int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag,
1378 void (*)(void *, int), void *);
1379void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag,
1380 void (*)(void *, int), void *);
1381bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
1382
1383/* nv50_calc. */
1384int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
1385 int *N1, int *M1, int *N2, int *M2, int *P);
1386int nva3_calc_pll(struct drm_device *, struct pll_lims *,
1387 int clk, int *N, int *fN, int *M, int *P);
1388
1389#ifndef ioread32_native
1390#ifdef __BIG_ENDIAN
1391#define ioread16_native ioread16be
1392#define iowrite16_native iowrite16be
1393#define ioread32_native ioread32be
1394#define iowrite32_native iowrite32be
1395#else /* def __BIG_ENDIAN */
1396#define ioread16_native ioread16
1397#define iowrite16_native iowrite16
1398#define ioread32_native ioread32
1399#define iowrite32_native iowrite32
1400#endif /* def __BIG_ENDIAN else */
1401#endif /* !ioread32_native */
1402
1403/* channel control reg access */
1404static inline u32 nvchan_rd32(struct nouveau_channel *chan, unsigned reg)
1405{
1406 return ioread32_native(chan->user + reg);
1407}
1408
1409static inline void nvchan_wr32(struct nouveau_channel *chan,
1410 unsigned reg, u32 val)
1411{
1412 iowrite32_native(val, chan->user + reg);
1413}
1414
1415/* register access */
1416static inline u32 nv_rd32(struct drm_device *dev, unsigned reg)
1417{
1418 struct drm_nouveau_private *dev_priv = dev->dev_private;
1419 return ioread32_native(dev_priv->mmio + reg);
1420}
1421
1422static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
1423{
1424 struct drm_nouveau_private *dev_priv = dev->dev_private;
1425 iowrite32_native(val, dev_priv->mmio + reg);
1426}
1427
1428static inline u32 nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val)
1429{
1430 u32 tmp = nv_rd32(dev, reg);
1431 nv_wr32(dev, reg, (tmp & ~mask) | val);
1432 return tmp;
1433}
1434
1435static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
1436{
1437 struct drm_nouveau_private *dev_priv = dev->dev_private;
1438 return ioread8(dev_priv->mmio + reg);
1439}
1440
1441static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val)
1442{
1443 struct drm_nouveau_private *dev_priv = dev->dev_private;
1444 iowrite8(val, dev_priv->mmio + reg);
1445}
1446
1447#define nv_wait(dev, reg, mask, val) \
1448 nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))
1449#define nv_wait_ne(dev, reg, mask, val) \
1450 nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val))
1451
1452/* PRAMIN access */
1453static inline u32 nv_ri32(struct drm_device *dev, unsigned offset)
1454{
1455 struct drm_nouveau_private *dev_priv = dev->dev_private;
1456 return ioread32_native(dev_priv->ramin + offset);
1457}
1458
1459static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val)
1460{
1461 struct drm_nouveau_private *dev_priv = dev->dev_private;
1462 iowrite32_native(val, dev_priv->ramin + offset);
1463}
1464
1465/* object access */
1466extern u32 nv_ro32(struct nouveau_gpuobj *, u32 offset);
1467extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val);
1468
1469/*
1470 * Logging
1471 * Argument d is (struct drm_device *).
1472 */
1473#define NV_PRINTK(level, d, fmt, arg...) \
1474 printk(level "[" DRM_NAME "] " DRIVER_NAME " %s: " fmt, \
1475 pci_name(d->pdev), ##arg)
1476#ifndef NV_DEBUG_NOTRACE
1477#define NV_DEBUG(d, fmt, arg...) do { \
1478 if (drm_debug & DRM_UT_DRIVER) { \
1479 NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \
1480 __LINE__, ##arg); \
1481 } \
1482} while (0)
1483#define NV_DEBUG_KMS(d, fmt, arg...) do { \
1484 if (drm_debug & DRM_UT_KMS) { \
1485 NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \
1486 __LINE__, ##arg); \
1487 } \
1488} while (0)
1489#else
1490#define NV_DEBUG(d, fmt, arg...) do { \
1491 if (drm_debug & DRM_UT_DRIVER) \
1492 NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \
1493} while (0)
1494#define NV_DEBUG_KMS(d, fmt, arg...) do { \
1495 if (drm_debug & DRM_UT_KMS) \
1496 NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \
1497} while (0)
1498#endif
1499#define NV_ERROR(d, fmt, arg...) NV_PRINTK(KERN_ERR, d, fmt, ##arg)
1500#define NV_INFO(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg)
1501#define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg)
1502#define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg)
1503#define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg)
1504
1505/* nouveau_reg_debug bitmask */
1506enum {
1507 NOUVEAU_REG_DEBUG_MC = 0x1,
1508 NOUVEAU_REG_DEBUG_VIDEO = 0x2,
1509 NOUVEAU_REG_DEBUG_FB = 0x4,
1510 NOUVEAU_REG_DEBUG_EXTDEV = 0x8,
1511 NOUVEAU_REG_DEBUG_CRTC = 0x10,
1512 NOUVEAU_REG_DEBUG_RAMDAC = 0x20,
1513 NOUVEAU_REG_DEBUG_VGACRTC = 0x40,
1514 NOUVEAU_REG_DEBUG_RMVIO = 0x80,
1515 NOUVEAU_REG_DEBUG_VGAATTR = 0x100,
1516 NOUVEAU_REG_DEBUG_EVO = 0x200,
1517};
1518
1519#define NV_REG_DEBUG(type, dev, fmt, arg...) do { \
1520 if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_##type) \
1521 NV_PRINTK(KERN_DEBUG, dev, "%s: " fmt, __func__, ##arg); \
1522} while (0)
1523
1524static inline bool
1525nv_two_heads(struct drm_device *dev)
1526{
1527 struct drm_nouveau_private *dev_priv = dev->dev_private;
1528 const int impl = dev->pci_device & 0x0ff0;
1529
1530 if (dev_priv->card_type >= NV_10 && impl != 0x0100 &&
1531 impl != 0x0150 && impl != 0x01a0 && impl != 0x0200)
1532 return true;
1533
1534 return false;
1535}
1536
1537static inline bool
1538nv_gf4_disp_arch(struct drm_device *dev)
1539{
1540 return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110;
1541}
1542
1543static inline bool
1544nv_two_reg_pll(struct drm_device *dev)
1545{
1546 struct drm_nouveau_private *dev_priv = dev->dev_private;
1547 const int impl = dev->pci_device & 0x0ff0;
1548
1549 if (impl == 0x0310 || impl == 0x0340 || dev_priv->card_type >= NV_40)
1550 return true;
1551 return false;
1552}
1553
1554static inline bool
1555nv_match_device(struct drm_device *dev, unsigned device,
1556 unsigned sub_vendor, unsigned sub_device)
1557{
1558 return dev->pdev->device == device &&
1559 dev->pdev->subsystem_vendor == sub_vendor &&
1560 dev->pdev->subsystem_device == sub_device;
1561}
1562
1563static inline void *
1564nv_engine(struct drm_device *dev, int engine)
1565{
1566 struct drm_nouveau_private *dev_priv = dev->dev_private;
1567 return (void *)dev_priv->eng[engine];
1568}
1569
1570/* returns 1 if device is one of the nv4x using the 0x4497 object class,
1571 * helpful to determine a number of other hardware features
1572 */
1573static inline int
1574nv44_graph_class(struct drm_device *dev)
1575{
1576 struct drm_nouveau_private *dev_priv = dev->dev_private;
1577
1578 if ((dev_priv->chipset & 0xf0) == 0x60)
1579 return 1;
1580
1581 return !(0x0baf & (1 << (dev_priv->chipset & 0x0f)));
1582}
1583
1584/* memory type/access flags, do not match hardware values */
1585#define NV_MEM_ACCESS_RO 1
1586#define NV_MEM_ACCESS_WO 2
1587#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO)
1588#define NV_MEM_ACCESS_SYS 4
1589#define NV_MEM_ACCESS_VM 8
1590
1591#define NV_MEM_TARGET_VRAM 0
1592#define NV_MEM_TARGET_PCI 1
1593#define NV_MEM_TARGET_PCI_NOSNOOP 2
1594#define NV_MEM_TARGET_VM 3
1595#define NV_MEM_TARGET_GART 4
1596
1597#define NV_MEM_TYPE_VM 0x7f
1598#define NV_MEM_COMP_VM 0x03
1599
1600/* NV_SW object class */
1601#define NV_SW 0x0000506e
1602#define NV_SW_DMA_SEMAPHORE 0x00000060
1603#define NV_SW_SEMAPHORE_OFFSET 0x00000064
1604#define NV_SW_SEMAPHORE_ACQUIRE 0x00000068
1605#define NV_SW_SEMAPHORE_RELEASE 0x0000006c
1606#define NV_SW_YIELD 0x00000080
1607#define NV_SW_DMA_VBLSEM 0x0000018c
1608#define NV_SW_VBLSEM_OFFSET 0x00000400
1609#define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404
1610#define NV_SW_VBLSEM_RELEASE 0x00000408
1611#define NV_SW_PAGE_FLIP 0x00000500
1612
1613#endif /* __NOUVEAU_DRV_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
new file mode 100644
index 00000000000..95c843e684b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#ifndef __NOUVEAU_FB_H__
28#define __NOUVEAU_FB_H__
29
30struct nouveau_framebuffer {
31 struct drm_framebuffer base;
32 struct nouveau_bo *nvbo;
33 struct nouveau_vma vma;
34 u32 r_dma;
35 u32 r_format;
36 u32 r_pitch;
37};
38
39static inline struct nouveau_framebuffer *
40nouveau_framebuffer(struct drm_framebuffer *fb)
41{
42 return container_of(fb, struct nouveau_framebuffer, base);
43}
44
45extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
46
47int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
48 struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo);
49#endif /* __NOUVEAU_FB_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h
new file mode 100644
index 00000000000..86c2e374e93
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h
@@ -0,0 +1,133 @@
1#ifndef __NOUVEAU_GRCTX_H__
2#define __NOUVEAU_GRCTX_H__
3
4struct nouveau_grctx {
5 struct drm_device *dev;
6
7 enum {
8 NOUVEAU_GRCTX_PROG,
9 NOUVEAU_GRCTX_VALS
10 } mode;
11 void *data;
12
13 uint32_t ctxprog_max;
14 uint32_t ctxprog_len;
15 uint32_t ctxprog_reg;
16 int ctxprog_label[32];
17 uint32_t ctxvals_pos;
18 uint32_t ctxvals_base;
19};
20
21#ifdef CP_CTX
22static inline void
23cp_out(struct nouveau_grctx *ctx, uint32_t inst)
24{
25 uint32_t *ctxprog = ctx->data;
26
27 if (ctx->mode != NOUVEAU_GRCTX_PROG)
28 return;
29
30 BUG_ON(ctx->ctxprog_len == ctx->ctxprog_max);
31 ctxprog[ctx->ctxprog_len++] = inst;
32}
33
34static inline void
35cp_lsr(struct nouveau_grctx *ctx, uint32_t val)
36{
37 cp_out(ctx, CP_LOAD_SR | val);
38}
39
40static inline void
41cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length)
42{
43 ctx->ctxprog_reg = (reg - 0x00400000) >> 2;
44
45 ctx->ctxvals_base = ctx->ctxvals_pos;
46 ctx->ctxvals_pos = ctx->ctxvals_base + length;
47
48 if (length > (CP_CTX_COUNT >> CP_CTX_COUNT_SHIFT)) {
49 cp_lsr(ctx, length);
50 length = 0;
51 }
52
53 cp_out(ctx, CP_CTX | (length << CP_CTX_COUNT_SHIFT) | ctx->ctxprog_reg);
54}
55
56static inline void
57cp_name(struct nouveau_grctx *ctx, int name)
58{
59 uint32_t *ctxprog = ctx->data;
60 int i;
61
62 if (ctx->mode != NOUVEAU_GRCTX_PROG)
63 return;
64
65 ctx->ctxprog_label[name] = ctx->ctxprog_len;
66 for (i = 0; i < ctx->ctxprog_len; i++) {
67 if ((ctxprog[i] & 0xfff00000) != 0xff400000)
68 continue;
69 if ((ctxprog[i] & CP_BRA_IP) != ((name) << CP_BRA_IP_SHIFT))
70 continue;
71 ctxprog[i] = (ctxprog[i] & 0x00ff00ff) |
72 (ctx->ctxprog_len << CP_BRA_IP_SHIFT);
73 }
74}
75
76static inline void
77_cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name)
78{
79 int ip = 0;
80
81 if (mod != 2) {
82 ip = ctx->ctxprog_label[name] << CP_BRA_IP_SHIFT;
83 if (ip == 0)
84 ip = 0xff000000 | (name << CP_BRA_IP_SHIFT);
85 }
86
87 cp_out(ctx, CP_BRA | (mod << 18) | ip | flag |
88 (state ? 0 : CP_BRA_IF_CLEAR));
89}
90#define cp_bra(c, f, s, n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
91#ifdef CP_BRA_MOD
92#define cp_cal(c, f, s, n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
93#define cp_ret(c, f, s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0)
94#endif
95
96static inline void
97_cp_wait(struct nouveau_grctx *ctx, int flag, int state)
98{
99 cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0));
100}
101#define cp_wait(c, f, s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
102
103static inline void
104_cp_set(struct nouveau_grctx *ctx, int flag, int state)
105{
106 cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0));
107}
108#define cp_set(c, f, s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
109
110static inline void
111cp_pos(struct nouveau_grctx *ctx, int offset)
112{
113 ctx->ctxvals_pos = offset;
114 ctx->ctxvals_base = ctx->ctxvals_pos;
115
116 cp_lsr(ctx, ctx->ctxvals_pos);
117 cp_out(ctx, CP_SET_CONTEXT_POINTER);
118}
119
120static inline void
121gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val)
122{
123 if (ctx->mode != NOUVEAU_GRCTX_VALS)
124 return;
125
126 reg = (reg - 0x00400000) / 4;
127 reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base;
128
129 nv_wo32(ctx->data, reg * 4, val);
130}
131#endif
132
133#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
new file mode 100644
index 00000000000..cb389d01432
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -0,0 +1,323 @@
1/*
2 * Copyright 2009 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_i2c.h"
28#include "nouveau_hw.h"
29
30static void
31nv04_i2c_setscl(void *data, int state)
32{
33 struct nouveau_i2c_chan *i2c = data;
34 struct drm_device *dev = i2c->dev;
35 uint8_t val;
36
37 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
38 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
39}
40
41static void
42nv04_i2c_setsda(void *data, int state)
43{
44 struct nouveau_i2c_chan *i2c = data;
45 struct drm_device *dev = i2c->dev;
46 uint8_t val;
47
48 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
49 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
50}
51
52static int
53nv04_i2c_getscl(void *data)
54{
55 struct nouveau_i2c_chan *i2c = data;
56 struct drm_device *dev = i2c->dev;
57
58 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4);
59}
60
61static int
62nv04_i2c_getsda(void *data)
63{
64 struct nouveau_i2c_chan *i2c = data;
65 struct drm_device *dev = i2c->dev;
66
67 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8);
68}
69
70static void
71nv4e_i2c_setscl(void *data, int state)
72{
73 struct nouveau_i2c_chan *i2c = data;
74 struct drm_device *dev = i2c->dev;
75 uint8_t val;
76
77 val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
78 nv_wr32(dev, i2c->wr, val | 0x01);
79}
80
81static void
82nv4e_i2c_setsda(void *data, int state)
83{
84 struct nouveau_i2c_chan *i2c = data;
85 struct drm_device *dev = i2c->dev;
86 uint8_t val;
87
88 val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
89 nv_wr32(dev, i2c->wr, val | 0x01);
90}
91
92static int
93nv4e_i2c_getscl(void *data)
94{
95 struct nouveau_i2c_chan *i2c = data;
96 struct drm_device *dev = i2c->dev;
97
98 return !!((nv_rd32(dev, i2c->rd) >> 16) & 4);
99}
100
101static int
102nv4e_i2c_getsda(void *data)
103{
104 struct nouveau_i2c_chan *i2c = data;
105 struct drm_device *dev = i2c->dev;
106
107 return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
108}
109
110static int
111nv50_i2c_getscl(void *data)
112{
113 struct nouveau_i2c_chan *i2c = data;
114 struct drm_device *dev = i2c->dev;
115
116 return !!(nv_rd32(dev, i2c->rd) & 1);
117}
118
119
120static int
121nv50_i2c_getsda(void *data)
122{
123 struct nouveau_i2c_chan *i2c = data;
124 struct drm_device *dev = i2c->dev;
125
126 return !!(nv_rd32(dev, i2c->rd) & 2);
127}
128
129static void
130nv50_i2c_setscl(void *data, int state)
131{
132 struct nouveau_i2c_chan *i2c = data;
133 struct drm_device *dev = i2c->dev;
134
135 nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
136}
137
138static void
139nv50_i2c_setsda(void *data, int state)
140{
141 struct nouveau_i2c_chan *i2c = data;
142 struct drm_device *dev = i2c->dev;
143
144 nv_wr32(dev, i2c->wr,
145 (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0));
146 i2c->data = state;
147}
148
149static const uint32_t nv50_i2c_port[] = {
150 0x00e138, 0x00e150, 0x00e168, 0x00e180,
151 0x00e254, 0x00e274, 0x00e764, 0x00e780,
152 0x00e79c, 0x00e7b8
153};
154#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
155
156int
157nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
158{
159 struct drm_nouveau_private *dev_priv = dev->dev_private;
160 struct nouveau_i2c_chan *i2c;
161 int ret;
162
163 if (entry->chan)
164 return -EEXIST;
165
166 if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
167 NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
168 return -EINVAL;
169 }
170
171 i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
172 if (i2c == NULL)
173 return -ENOMEM;
174
175 switch (entry->port_type) {
176 case 0:
177 i2c->bit.setsda = nv04_i2c_setsda;
178 i2c->bit.setscl = nv04_i2c_setscl;
179 i2c->bit.getsda = nv04_i2c_getsda;
180 i2c->bit.getscl = nv04_i2c_getscl;
181 i2c->rd = entry->read;
182 i2c->wr = entry->write;
183 break;
184 case 4:
185 i2c->bit.setsda = nv4e_i2c_setsda;
186 i2c->bit.setscl = nv4e_i2c_setscl;
187 i2c->bit.getsda = nv4e_i2c_getsda;
188 i2c->bit.getscl = nv4e_i2c_getscl;
189 i2c->rd = 0x600800 + entry->read;
190 i2c->wr = 0x600800 + entry->write;
191 break;
192 case 5:
193 i2c->bit.setsda = nv50_i2c_setsda;
194 i2c->bit.setscl = nv50_i2c_setscl;
195 i2c->bit.getsda = nv50_i2c_getsda;
196 i2c->bit.getscl = nv50_i2c_getscl;
197 i2c->rd = nv50_i2c_port[entry->read];
198 i2c->wr = i2c->rd;
199 break;
200 case 6:
201 i2c->rd = entry->read;
202 i2c->wr = entry->write;
203 break;
204 default:
205 NV_ERROR(dev, "DCB I2C port type %d unknown\n",
206 entry->port_type);
207 kfree(i2c);
208 return -EINVAL;
209 }
210
211 snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
212 "nouveau-%s-%d", pci_name(dev->pdev), index);
213 i2c->adapter.owner = THIS_MODULE;
214 i2c->adapter.dev.parent = &dev->pdev->dev;
215 i2c->dev = dev;
216 i2c_set_adapdata(&i2c->adapter, i2c);
217
218 if (entry->port_type < 6) {
219 i2c->adapter.algo_data = &i2c->bit;
220 i2c->bit.udelay = 40;
221 i2c->bit.timeout = usecs_to_jiffies(5000);
222 i2c->bit.data = i2c;
223 ret = i2c_bit_add_bus(&i2c->adapter);
224 } else {
225 i2c->adapter.algo = &nouveau_dp_i2c_algo;
226 ret = i2c_add_adapter(&i2c->adapter);
227 }
228
229 if (ret) {
230 NV_ERROR(dev, "Failed to register i2c %d\n", index);
231 kfree(i2c);
232 return ret;
233 }
234
235 entry->chan = i2c;
236 return 0;
237}
238
239void
240nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry)
241{
242 if (!entry->chan)
243 return;
244
245 i2c_del_adapter(&entry->chan->adapter);
246 kfree(entry->chan);
247 entry->chan = NULL;
248}
249
250struct nouveau_i2c_chan *
251nouveau_i2c_find(struct drm_device *dev, int index)
252{
253 struct drm_nouveau_private *dev_priv = dev->dev_private;
254 struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index];
255
256 if (index >= DCB_MAX_NUM_I2C_ENTRIES)
257 return NULL;
258
259 if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) {
260 uint32_t reg = 0xe500, val;
261
262 if (i2c->port_type == 6) {
263 reg += i2c->read * 0x50;
264 val = 0x2002;
265 } else {
266 reg += ((i2c->entry & 0x1e00) >> 9) * 0x50;
267 val = 0xe001;
268 }
269
270 nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val);
271 }
272
273 if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
274 return NULL;
275 return i2c->chan;
276}
277
278bool
279nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
280{
281 uint8_t buf[] = { 0 };
282 struct i2c_msg msgs[] = {
283 {
284 .addr = addr,
285 .flags = 0,
286 .len = 1,
287 .buf = buf,
288 },
289 {
290 .addr = addr,
291 .flags = I2C_M_RD,
292 .len = 1,
293 .buf = buf,
294 }
295 };
296
297 return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
298}
299
300int
301nouveau_i2c_identify(struct drm_device *dev, const char *what,
302 struct i2c_board_info *info,
303 bool (*match)(struct nouveau_i2c_chan *,
304 struct i2c_board_info *),
305 int index)
306{
307 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
308 int i;
309
310 NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
311
312 for (i = 0; info[i].addr; i++) {
313 if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
314 (!match || match(i2c, &info[i]))) {
315 NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
316 return i;
317 }
318 }
319
320 NV_DEBUG(dev, "No devices found.\n");
321
322 return -ENODEV;
323}
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h
new file mode 100644
index 00000000000..422b62fd827
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h
@@ -0,0 +1,53 @@
1/*
2 * Copyright 2009 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
23#ifndef __NOUVEAU_I2C_H__
24#define __NOUVEAU_I2C_H__
25
26#include <linux/i2c.h>
27#include <linux/i2c-algo-bit.h>
28#include "drm_dp_helper.h"
29
30struct dcb_i2c_entry;
31
32struct nouveau_i2c_chan {
33 struct i2c_adapter adapter;
34 struct drm_device *dev;
35 struct i2c_algo_bit_data bit;
36 unsigned rd;
37 unsigned wr;
38 unsigned data;
39};
40
41int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
42void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
43struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
44bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
45int nouveau_i2c_identify(struct drm_device *dev, const char *what,
46 struct i2c_board_info *info,
47 bool (*match)(struct nouveau_i2c_chan *,
48 struct i2c_board_info *),
49 int index);
50
51extern const struct i2c_algorithm nouveau_dp_i2c_algo;
52
53#endif /* __NOUVEAU_I2C_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c
new file mode 100644
index 00000000000..1640dec3b82
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.c
@@ -0,0 +1,178 @@
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_mm.h"
28
29static inline void
30region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
31{
32 list_del(&a->nl_entry);
33 list_del(&a->fl_entry);
34 kfree(a);
35}
36
37static struct nouveau_mm_node *
38region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
39{
40 struct nouveau_mm_node *b;
41
42 if (a->length == size)
43 return a;
44
45 b = kmalloc(sizeof(*b), GFP_KERNEL);
46 if (unlikely(b == NULL))
47 return NULL;
48
49 b->offset = a->offset;
50 b->length = size;
51 b->type = a->type;
52 a->offset += size;
53 a->length -= size;
54 list_add_tail(&b->nl_entry, &a->nl_entry);
55 if (b->type == 0)
56 list_add_tail(&b->fl_entry, &a->fl_entry);
57 return b;
58}
59
60#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \
61 list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry)
62
63void
64nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this)
65{
66 struct nouveau_mm_node *prev = node(this, prev);
67 struct nouveau_mm_node *next = node(this, next);
68
69 list_add(&this->fl_entry, &rmm->free);
70 this->type = 0;
71
72 if (prev && prev->type == 0) {
73 prev->length += this->length;
74 region_put(rmm, this);
75 this = prev;
76 }
77
78 if (next && next->type == 0) {
79 next->offset = this->offset;
80 next->length += this->length;
81 region_put(rmm, this);
82 }
83}
84
85int
86nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
87 u32 align, struct nouveau_mm_node **pnode)
88{
89 struct nouveau_mm_node *prev, *this, *next;
90 u32 min = size_nc ? size_nc : size;
91 u32 align_mask = align - 1;
92 u32 splitoff;
93 u32 s, e;
94
95 list_for_each_entry(this, &rmm->free, fl_entry) {
96 e = this->offset + this->length;
97 s = this->offset;
98
99 prev = node(this, prev);
100 if (prev && prev->type != type)
101 s = roundup(s, rmm->block_size);
102
103 next = node(this, next);
104 if (next && next->type != type)
105 e = rounddown(e, rmm->block_size);
106
107 s = (s + align_mask) & ~align_mask;
108 e &= ~align_mask;
109 if (s > e || e - s < min)
110 continue;
111
112 splitoff = s - this->offset;
113 if (splitoff && !region_split(rmm, this, splitoff))
114 return -ENOMEM;
115
116 this = region_split(rmm, this, min(size, e - s));
117 if (!this)
118 return -ENOMEM;
119
120 this->type = type;
121 list_del(&this->fl_entry);
122 *pnode = this;
123 return 0;
124 }
125
126 return -ENOSPC;
127}
128
129int
130nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
131{
132 struct nouveau_mm *rmm;
133 struct nouveau_mm_node *heap;
134
135 heap = kzalloc(sizeof(*heap), GFP_KERNEL);
136 if (!heap)
137 return -ENOMEM;
138 heap->offset = roundup(offset, block);
139 heap->length = rounddown(offset + length, block) - heap->offset;
140
141 rmm = kzalloc(sizeof(*rmm), GFP_KERNEL);
142 if (!rmm) {
143 kfree(heap);
144 return -ENOMEM;
145 }
146 rmm->block_size = block;
147 mutex_init(&rmm->mutex);
148 INIT_LIST_HEAD(&rmm->nodes);
149 INIT_LIST_HEAD(&rmm->free);
150 list_add(&heap->nl_entry, &rmm->nodes);
151 list_add(&heap->fl_entry, &rmm->free);
152
153 *prmm = rmm;
154 return 0;
155}
156
157int
158nouveau_mm_fini(struct nouveau_mm **prmm)
159{
160 struct nouveau_mm *rmm = *prmm;
161 struct nouveau_mm_node *node, *heap =
162 list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
163
164 if (!list_is_singular(&rmm->nodes)) {
165 printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
166 list_for_each_entry(node, &rmm->nodes, nl_entry) {
167 printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
168 node->type, node->offset, node->length);
169 }
170 WARN_ON(1);
171 return -EBUSY;
172 }
173
174 kfree(heap);
175 kfree(rmm);
176 *prmm = NULL;
177 return 0;
178}
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
new file mode 100644
index 00000000000..b9c016d2155
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -0,0 +1,66 @@
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_REGION_H__
26#define __NOUVEAU_REGION_H__
27
28struct nouveau_mm_node {
29 struct list_head nl_entry;
30 struct list_head fl_entry;
31 struct list_head rl_entry;
32
33 u8 type;
34 u32 offset;
35 u32 length;
36};
37
38struct nouveau_mm {
39 struct list_head nodes;
40 struct list_head free;
41
42 struct mutex mutex;
43
44 u32 block_size;
45};
46
47int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block);
48int nouveau_mm_fini(struct nouveau_mm **);
49int nouveau_mm_pre(struct nouveau_mm *);
50int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
51 u32 align, struct nouveau_mm_node **);
52void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
53
54int nv50_vram_init(struct drm_device *);
55void nv50_vram_fini(struct drm_device *);
56int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
57 u32 memtype, struct nouveau_mem **);
58void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
59bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);
60
61int nvc0_vram_init(struct drm_device *);
62int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin,
63 u32 memtype, struct nouveau_mem **);
64bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags);
65
66#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c
new file mode 100644
index 00000000000..6abdbe6530a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c
@@ -0,0 +1,204 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#include "drmP.h"
29#include "drm.h"
30#include "nouveau_drv.h"
31#include "nouveau_ramht.h"
32
33int
34nouveau_notifier_init_channel(struct nouveau_channel *chan)
35{
36 struct drm_device *dev = chan->dev;
37 struct drm_nouveau_private *dev_priv = dev->dev_private;
38 struct nouveau_bo *ntfy = NULL;
39 uint32_t flags, ttmpl;
40 int ret;
41
42 if (nouveau_vram_notify) {
43 flags = NOUVEAU_GEM_DOMAIN_VRAM;
44 ttmpl = TTM_PL_FLAG_VRAM;
45 } else {
46 flags = NOUVEAU_GEM_DOMAIN_GART;
47 ttmpl = TTM_PL_FLAG_TT;
48 }
49
50 ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
51 if (ret)
52 return ret;
53
54 ret = nouveau_bo_pin(ntfy, ttmpl);
55 if (ret)
56 goto out_err;
57
58 ret = nouveau_bo_map(ntfy);
59 if (ret)
60 goto out_err;
61
62 if (dev_priv->card_type >= NV_50) {
63 ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma);
64 if (ret)
65 goto out_err;
66 }
67
68 ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
69 if (ret)
70 goto out_err;
71
72 chan->notifier_bo = ntfy;
73out_err:
74 if (ret) {
75 nouveau_bo_vma_del(ntfy, &chan->notifier_vma);
76 drm_gem_object_unreference_unlocked(ntfy->gem);
77 }
78
79 return ret;
80}
81
82void
83nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
84{
85 struct drm_device *dev = chan->dev;
86
87 if (!chan->notifier_bo)
88 return;
89
90 nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma);
91 nouveau_bo_unmap(chan->notifier_bo);
92 mutex_lock(&dev->struct_mutex);
93 nouveau_bo_unpin(chan->notifier_bo);
94 mutex_unlock(&dev->struct_mutex);
95 drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
96 drm_mm_takedown(&chan->notifier_heap);
97}
98
99static void
100nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
101 struct nouveau_gpuobj *gpuobj)
102{
103 NV_DEBUG(dev, "\n");
104
105 if (gpuobj->priv)
106 drm_mm_put_block(gpuobj->priv);
107}
108
109int
110nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
111 int size, uint32_t start, uint32_t end,
112 uint32_t *b_offset)
113{
114 struct drm_device *dev = chan->dev;
115 struct drm_nouveau_private *dev_priv = dev->dev_private;
116 struct nouveau_gpuobj *nobj = NULL;
117 struct drm_mm_node *mem;
118 uint32_t offset;
119 int target, ret;
120
121 mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0,
122 start, end, 0);
123 if (mem)
124 mem = drm_mm_get_block_range(mem, size, 0, start, end);
125 if (!mem) {
126 NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
127 return -ENOMEM;
128 }
129
130 if (dev_priv->card_type < NV_50) {
131 if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM)
132 target = NV_MEM_TARGET_VRAM;
133 else
134 target = NV_MEM_TARGET_GART;
135 offset = chan->notifier_bo->bo.offset;
136 } else {
137 target = NV_MEM_TARGET_VM;
138 offset = chan->notifier_vma.offset;
139 }
140 offset += mem->start;
141
142 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset,
143 mem->size, NV_MEM_ACCESS_RW, target,
144 &nobj);
145 if (ret) {
146 drm_mm_put_block(mem);
147 NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret);
148 return ret;
149 }
150 nobj->dtor = nouveau_notifier_gpuobj_dtor;
151 nobj->priv = mem;
152
153 ret = nouveau_ramht_insert(chan, handle, nobj);
154 nouveau_gpuobj_ref(NULL, &nobj);
155 if (ret) {
156 drm_mm_put_block(mem);
157 NV_ERROR(dev, "Error adding notifier to ramht: %d\n", ret);
158 return ret;
159 }
160
161 *b_offset = mem->start;
162 return 0;
163}
164
165int
166nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset)
167{
168 if (!nobj || nobj->dtor != nouveau_notifier_gpuobj_dtor)
169 return -EINVAL;
170
171 if (poffset) {
172 struct drm_mm_node *mem = nobj->priv;
173
174 if (*poffset >= mem->size)
175 return false;
176
177 *poffset += mem->start;
178 }
179
180 return 0;
181}
182
183int
184nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
185 struct drm_file *file_priv)
186{
187 struct drm_nouveau_private *dev_priv = dev->dev_private;
188 struct drm_nouveau_notifierobj_alloc *na = data;
189 struct nouveau_channel *chan;
190 int ret;
191
192 /* completely unnecessary for these chipsets... */
193 if (unlikely(dev_priv->card_type >= NV_C0))
194 return -EINVAL;
195
196 chan = nouveau_channel_get(file_priv, na->channel);
197 if (IS_ERR(chan))
198 return PTR_ERR(chan);
199
200 ret = nouveau_notifier_alloc(chan, na->handle, na->size, 0, 0x1000,
201 &na->offset);
202 nouveau_channel_put(&chan);
203 return ret;
204}
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
new file mode 100644
index 00000000000..159b7c437d3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -0,0 +1,1036 @@
1/*
2 * Copyright (C) 2006 Ben Skeggs.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28/*
29 * Authors:
30 * Ben Skeggs <darktama@iinet.net.au>
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "nouveau_drv.h"
36#include "nouveau_drm.h"
37#include "nouveau_ramht.h"
38#include "nouveau_vm.h"
39#include "nv50_display.h"
40
41struct nouveau_gpuobj_method {
42 struct list_head head;
43 u32 mthd;
44 int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data);
45};
46
47struct nouveau_gpuobj_class {
48 struct list_head head;
49 struct list_head methods;
50 u32 id;
51 u32 engine;
52};
53
54int
55nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine)
56{
57 struct drm_nouveau_private *dev_priv = dev->dev_private;
58 struct nouveau_gpuobj_class *oc;
59
60 oc = kzalloc(sizeof(*oc), GFP_KERNEL);
61 if (!oc)
62 return -ENOMEM;
63
64 INIT_LIST_HEAD(&oc->methods);
65 oc->id = class;
66 oc->engine = engine;
67 list_add(&oc->head, &dev_priv->classes);
68 return 0;
69}
70
71int
72nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd,
73 int (*exec)(struct nouveau_channel *, u32, u32, u32))
74{
75 struct drm_nouveau_private *dev_priv = dev->dev_private;
76 struct nouveau_gpuobj_method *om;
77 struct nouveau_gpuobj_class *oc;
78
79 list_for_each_entry(oc, &dev_priv->classes, head) {
80 if (oc->id == class)
81 goto found;
82 }
83
84 return -EINVAL;
85
86found:
87 om = kzalloc(sizeof(*om), GFP_KERNEL);
88 if (!om)
89 return -ENOMEM;
90
91 om->mthd = mthd;
92 om->exec = exec;
93 list_add(&om->head, &oc->methods);
94 return 0;
95}
96
97int
98nouveau_gpuobj_mthd_call(struct nouveau_channel *chan,
99 u32 class, u32 mthd, u32 data)
100{
101 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
102 struct nouveau_gpuobj_method *om;
103 struct nouveau_gpuobj_class *oc;
104
105 list_for_each_entry(oc, &dev_priv->classes, head) {
106 if (oc->id != class)
107 continue;
108
109 list_for_each_entry(om, &oc->methods, head) {
110 if (om->mthd == mthd)
111 return om->exec(chan, class, mthd, data);
112 }
113 }
114
115 return -ENOENT;
116}
117
118int
119nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
120 u32 class, u32 mthd, u32 data)
121{
122 struct drm_nouveau_private *dev_priv = dev->dev_private;
123 struct nouveau_channel *chan = NULL;
124 unsigned long flags;
125 int ret = -EINVAL;
126
127 spin_lock_irqsave(&dev_priv->channels.lock, flags);
128 if (chid >= 0 && chid < dev_priv->engine.fifo.channels)
129 chan = dev_priv->channels.ptr[chid];
130 if (chan)
131 ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
132 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
133 return ret;
134}
135
136/* NVidia uses context objects to drive drawing operations.
137
138 Context objects can be selected into 8 subchannels in the FIFO,
139 and then used via DMA command buffers.
140
141 A context object is referenced by a user defined handle (CARD32). The HW
142 looks up graphics objects in a hash table in the instance RAM.
143
144 An entry in the hash table consists of 2 CARD32. The first CARD32 contains
145 the handle, the second one a bitfield, that contains the address of the
146 object in instance RAM.
147
148 The format of the second CARD32 seems to be:
149
150 NV4 to NV30:
151
152 15: 0 instance_addr >> 4
153 17:16 engine (here uses 1 = graphics)
154 28:24 channel id (here uses 0)
155 31 valid (use 1)
156
157 NV40:
158
159 15: 0 instance_addr >> 4 (maybe 19-0)
160 21:20 engine (here uses 1 = graphics)
161 I'm unsure about the other bits, but using 0 seems to work.
162
163 The key into the hash table depends on the object handle and channel id and
164 is given as:
165*/
166
167int
168nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
169 uint32_t size, int align, uint32_t flags,
170 struct nouveau_gpuobj **gpuobj_ret)
171{
172 struct drm_nouveau_private *dev_priv = dev->dev_private;
173 struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
174 struct nouveau_gpuobj *gpuobj;
175 struct drm_mm_node *ramin = NULL;
176 int ret, i;
177
178 NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
179 chan ? chan->id : -1, size, align, flags);
180
181 gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
182 if (!gpuobj)
183 return -ENOMEM;
184 NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
185 gpuobj->dev = dev;
186 gpuobj->flags = flags;
187 kref_init(&gpuobj->refcount);
188 gpuobj->size = size;
189
190 spin_lock(&dev_priv->ramin_lock);
191 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
192 spin_unlock(&dev_priv->ramin_lock);
193
194 if (!(flags & NVOBJ_FLAG_VM) && chan) {
195 ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
196 if (ramin)
197 ramin = drm_mm_get_block(ramin, size, align);
198 if (!ramin) {
199 nouveau_gpuobj_ref(NULL, &gpuobj);
200 return -ENOMEM;
201 }
202
203 gpuobj->pinst = chan->ramin->pinst;
204 if (gpuobj->pinst != ~0)
205 gpuobj->pinst += ramin->start;
206
207 gpuobj->cinst = ramin->start;
208 gpuobj->vinst = ramin->start + chan->ramin->vinst;
209 gpuobj->node = ramin;
210 } else {
211 ret = instmem->get(gpuobj, chan, size, align);
212 if (ret) {
213 nouveau_gpuobj_ref(NULL, &gpuobj);
214 return ret;
215 }
216
217 ret = -ENOSYS;
218 if (!(flags & NVOBJ_FLAG_DONT_MAP))
219 ret = instmem->map(gpuobj);
220 if (ret)
221 gpuobj->pinst = ~0;
222
223 gpuobj->cinst = NVOBJ_CINST_GLOBAL;
224 }
225
226 if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
227 for (i = 0; i < gpuobj->size; i += 4)
228 nv_wo32(gpuobj, i, 0);
229 instmem->flush(dev);
230 }
231
232
233 *gpuobj_ret = gpuobj;
234 return 0;
235}
236
237int
238nouveau_gpuobj_init(struct drm_device *dev)
239{
240 struct drm_nouveau_private *dev_priv = dev->dev_private;
241
242 NV_DEBUG(dev, "\n");
243
244 INIT_LIST_HEAD(&dev_priv->gpuobj_list);
245 INIT_LIST_HEAD(&dev_priv->classes);
246 spin_lock_init(&dev_priv->ramin_lock);
247 dev_priv->ramin_base = ~0;
248
249 return 0;
250}
251
252void
253nouveau_gpuobj_takedown(struct drm_device *dev)
254{
255 struct drm_nouveau_private *dev_priv = dev->dev_private;
256 struct nouveau_gpuobj_method *om, *tm;
257 struct nouveau_gpuobj_class *oc, *tc;
258
259 NV_DEBUG(dev, "\n");
260
261 list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) {
262 list_for_each_entry_safe(om, tm, &oc->methods, head) {
263 list_del(&om->head);
264 kfree(om);
265 }
266 list_del(&oc->head);
267 kfree(oc);
268 }
269
270 BUG_ON(!list_empty(&dev_priv->gpuobj_list));
271}
272
273
274static void
275nouveau_gpuobj_del(struct kref *ref)
276{
277 struct nouveau_gpuobj *gpuobj =
278 container_of(ref, struct nouveau_gpuobj, refcount);
279 struct drm_device *dev = gpuobj->dev;
280 struct drm_nouveau_private *dev_priv = dev->dev_private;
281 struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
282 int i;
283
284 NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
285
286 if (gpuobj->node && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
287 for (i = 0; i < gpuobj->size; i += 4)
288 nv_wo32(gpuobj, i, 0);
289 instmem->flush(dev);
290 }
291
292 if (gpuobj->dtor)
293 gpuobj->dtor(dev, gpuobj);
294
295 if (gpuobj->cinst == NVOBJ_CINST_GLOBAL) {
296 if (gpuobj->node) {
297 instmem->unmap(gpuobj);
298 instmem->put(gpuobj);
299 }
300 } else {
301 if (gpuobj->node) {
302 spin_lock(&dev_priv->ramin_lock);
303 drm_mm_put_block(gpuobj->node);
304 spin_unlock(&dev_priv->ramin_lock);
305 }
306 }
307
308 spin_lock(&dev_priv->ramin_lock);
309 list_del(&gpuobj->list);
310 spin_unlock(&dev_priv->ramin_lock);
311
312 kfree(gpuobj);
313}
314
315void
316nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
317{
318 if (ref)
319 kref_get(&ref->refcount);
320
321 if (*ptr)
322 kref_put(&(*ptr)->refcount, nouveau_gpuobj_del);
323
324 *ptr = ref;
325}
326
327int
328nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
329 u32 size, u32 flags, struct nouveau_gpuobj **pgpuobj)
330{
331 struct drm_nouveau_private *dev_priv = dev->dev_private;
332 struct nouveau_gpuobj *gpuobj = NULL;
333 int i;
334
335 NV_DEBUG(dev,
336 "pinst=0x%08x vinst=0x%010llx size=0x%08x flags=0x%08x\n",
337 pinst, vinst, size, flags);
338
339 gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
340 if (!gpuobj)
341 return -ENOMEM;
342 NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
343 gpuobj->dev = dev;
344 gpuobj->flags = flags;
345 kref_init(&gpuobj->refcount);
346 gpuobj->size = size;
347 gpuobj->pinst = pinst;
348 gpuobj->cinst = NVOBJ_CINST_GLOBAL;
349 gpuobj->vinst = vinst;
350
351 if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
352 for (i = 0; i < gpuobj->size; i += 4)
353 nv_wo32(gpuobj, i, 0);
354 dev_priv->engine.instmem.flush(dev);
355 }
356
357 spin_lock(&dev_priv->ramin_lock);
358 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
359 spin_unlock(&dev_priv->ramin_lock);
360 *pgpuobj = gpuobj;
361 return 0;
362}
363
364/*
365 DMA objects are used to reference a piece of memory in the
366 framebuffer, PCI or AGP address space. Each object is 16 bytes big
367 and looks as follows:
368
369 entry[0]
370 11:0 class (seems like I can always use 0 here)
371 12 page table present?
372 13 page entry linear?
373 15:14 access: 0 rw, 1 ro, 2 wo
374 17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP
375 31:20 dma adjust (bits 0-11 of the address)
376 entry[1]
377 dma limit (size of transfer)
378 entry[X]
379 1 0 readonly, 1 readwrite
380 31:12 dma frame address of the page (bits 12-31 of the address)
381 entry[N]
382 page table terminator, same value as the first pte, as does nvidia
383 rivatv uses 0xffffffff
384
385 Non linear page tables need a list of frame addresses afterwards,
386 the rivatv project has some info on this.
387
388 The method below creates a DMA object in instance RAM and returns a handle
389 to it that can be used to set up context objects.
390*/
391
392void
393nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class,
394 u64 base, u64 size, int target, int access,
395 u32 type, u32 comp)
396{
397 struct drm_nouveau_private *dev_priv = obj->dev->dev_private;
398 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
399 u32 flags0;
400
401 flags0 = (comp << 29) | (type << 22) | class;
402 flags0 |= 0x00100000;
403
404 switch (access) {
405 case NV_MEM_ACCESS_RO: flags0 |= 0x00040000; break;
406 case NV_MEM_ACCESS_RW:
407 case NV_MEM_ACCESS_WO: flags0 |= 0x00080000; break;
408 default:
409 break;
410 }
411
412 switch (target) {
413 case NV_MEM_TARGET_VRAM:
414 flags0 |= 0x00010000;
415 break;
416 case NV_MEM_TARGET_PCI:
417 flags0 |= 0x00020000;
418 break;
419 case NV_MEM_TARGET_PCI_NOSNOOP:
420 flags0 |= 0x00030000;
421 break;
422 case NV_MEM_TARGET_GART:
423 base += dev_priv->gart_info.aper_base;
424 default:
425 flags0 &= ~0x00100000;
426 break;
427 }
428
429 /* convert to base + limit */
430 size = (base + size) - 1;
431
432 nv_wo32(obj, offset + 0x00, flags0);
433 nv_wo32(obj, offset + 0x04, lower_32_bits(size));
434 nv_wo32(obj, offset + 0x08, lower_32_bits(base));
435 nv_wo32(obj, offset + 0x0c, upper_32_bits(size) << 24 |
436 upper_32_bits(base));
437 nv_wo32(obj, offset + 0x10, 0x00000000);
438 nv_wo32(obj, offset + 0x14, 0x00000000);
439
440 pinstmem->flush(obj->dev);
441}
442
443int
444nv50_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, u64 size,
445 int target, int access, u32 type, u32 comp,
446 struct nouveau_gpuobj **pobj)
447{
448 struct drm_device *dev = chan->dev;
449 int ret;
450
451 ret = nouveau_gpuobj_new(dev, chan, 24, 16, NVOBJ_FLAG_ZERO_FREE, pobj);
452 if (ret)
453 return ret;
454
455 nv50_gpuobj_dma_init(*pobj, 0, class, base, size, target,
456 access, type, comp);
457 return 0;
458}
459
460int
461nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base,
462 u64 size, int access, int target,
463 struct nouveau_gpuobj **pobj)
464{
465 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
466 struct drm_device *dev = chan->dev;
467 struct nouveau_gpuobj *obj;
468 u32 flags0, flags2;
469 int ret;
470
471 if (dev_priv->card_type >= NV_50) {
472 u32 comp = (target == NV_MEM_TARGET_VM) ? NV_MEM_COMP_VM : 0;
473 u32 type = (target == NV_MEM_TARGET_VM) ? NV_MEM_TYPE_VM : 0;
474
475 return nv50_gpuobj_dma_new(chan, class, base, size,
476 target, access, type, comp, pobj);
477 }
478
479 if (target == NV_MEM_TARGET_GART) {
480 struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
481
482 if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) {
483 if (base == 0) {
484 nouveau_gpuobj_ref(gart, pobj);
485 return 0;
486 }
487
488 base = nouveau_sgdma_get_physical(dev, base);
489 target = NV_MEM_TARGET_PCI;
490 } else {
491 base += dev_priv->gart_info.aper_base;
492 if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
493 target = NV_MEM_TARGET_PCI_NOSNOOP;
494 else
495 target = NV_MEM_TARGET_PCI;
496 }
497 }
498
499 flags0 = class;
500 flags0 |= 0x00003000; /* PT present, PT linear */
501 flags2 = 0;
502
503 switch (target) {
504 case NV_MEM_TARGET_PCI:
505 flags0 |= 0x00020000;
506 break;
507 case NV_MEM_TARGET_PCI_NOSNOOP:
508 flags0 |= 0x00030000;
509 break;
510 default:
511 break;
512 }
513
514 switch (access) {
515 case NV_MEM_ACCESS_RO:
516 flags0 |= 0x00004000;
517 break;
518 case NV_MEM_ACCESS_WO:
519 flags0 |= 0x00008000;
520 default:
521 flags2 |= 0x00000002;
522 break;
523 }
524
525 flags0 |= (base & 0x00000fff) << 20;
526 flags2 |= (base & 0xfffff000);
527
528 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
529 if (ret)
530 return ret;
531
532 nv_wo32(obj, 0x00, flags0);
533 nv_wo32(obj, 0x04, size - 1);
534 nv_wo32(obj, 0x08, flags2);
535 nv_wo32(obj, 0x0c, flags2);
536
537 obj->engine = NVOBJ_ENGINE_SW;
538 obj->class = class;
539 *pobj = obj;
540 return 0;
541}
542
543/* Context objects in the instance RAM have the following structure.
544 * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes.
545
546 NV4 - NV30:
547
548 entry[0]
549 11:0 class
550 12 chroma key enable
551 13 user clip enable
552 14 swizzle enable
553 17:15 patch config:
554 scrcopy_and, rop_and, blend_and, scrcopy, srccopy_pre, blend_pre
555 18 synchronize enable
556 19 endian: 1 big, 0 little
557 21:20 dither mode
558 23 single step enable
559 24 patch status: 0 invalid, 1 valid
560 25 context_surface 0: 1 valid
561 26 context surface 1: 1 valid
562 27 context pattern: 1 valid
563 28 context rop: 1 valid
564 29,30 context beta, beta4
565 entry[1]
566 7:0 mono format
567 15:8 color format
568 31:16 notify instance address
569 entry[2]
570 15:0 dma 0 instance address
571 31:16 dma 1 instance address
572 entry[3]
573 dma method traps
574
575 NV40:
576 No idea what the exact format is. Here's what can be deducted:
577
578 entry[0]:
579 11:0 class (maybe uses more bits here?)
580 17 user clip enable
581 21:19 patch config
582 25 patch status valid ?
583 entry[1]:
584 15:0 DMA notifier (maybe 20:0)
585 entry[2]:
586 15:0 DMA 0 instance (maybe 20:0)
587 24 big endian
588 entry[3]:
589 15:0 DMA 1 instance (maybe 20:0)
590 entry[4]:
591 entry[5]:
592 set to 0?
593*/
594static int
595nouveau_gpuobj_sw_new(struct nouveau_channel *chan, u32 handle, u16 class)
596{
597 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
598 struct nouveau_gpuobj *gpuobj;
599 int ret;
600
601 gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
602 if (!gpuobj)
603 return -ENOMEM;
604 gpuobj->dev = chan->dev;
605 gpuobj->engine = NVOBJ_ENGINE_SW;
606 gpuobj->class = class;
607 kref_init(&gpuobj->refcount);
608 gpuobj->cinst = 0x40;
609
610 spin_lock(&dev_priv->ramin_lock);
611 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
612 spin_unlock(&dev_priv->ramin_lock);
613
614 ret = nouveau_ramht_insert(chan, handle, gpuobj);
615 nouveau_gpuobj_ref(NULL, &gpuobj);
616 return ret;
617}
618
619int
620nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
621{
622 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
623 struct drm_device *dev = chan->dev;
624 struct nouveau_gpuobj_class *oc;
625 int ret;
626
627 NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
628
629 list_for_each_entry(oc, &dev_priv->classes, head) {
630 struct nouveau_exec_engine *eng = dev_priv->eng[oc->engine];
631
632 if (oc->id != class)
633 continue;
634
635 if (oc->engine == NVOBJ_ENGINE_SW)
636 return nouveau_gpuobj_sw_new(chan, handle, class);
637
638 if (!chan->engctx[oc->engine]) {
639 ret = eng->context_new(chan, oc->engine);
640 if (ret)
641 return ret;
642 }
643
644 return eng->object_new(chan, oc->engine, handle, class);
645 }
646
647 NV_ERROR(dev, "illegal object class: 0x%x\n", class);
648 return -EINVAL;
649}
650
651static int
652nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
653{
654 struct drm_device *dev = chan->dev;
655 struct drm_nouveau_private *dev_priv = dev->dev_private;
656 uint32_t size;
657 uint32_t base;
658 int ret;
659
660 NV_DEBUG(dev, "ch%d\n", chan->id);
661
662 /* Base amount for object storage (4KiB enough?) */
663 size = 0x2000;
664 base = 0;
665
666 if (dev_priv->card_type == NV_50) {
667 /* Various fixed table thingos */
668 size += 0x1400; /* mostly unknown stuff */
669 size += 0x4000; /* vm pd */
670 base = 0x6000;
671 /* RAMHT, not sure about setting size yet, 32KiB to be safe */
672 size += 0x8000;
673 /* RAMFC */
674 size += 0x1000;
675 }
676
677 ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
678 if (ret) {
679 NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret);
680 return ret;
681 }
682
683 ret = drm_mm_init(&chan->ramin_heap, base, size);
684 if (ret) {
685 NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
686 nouveau_gpuobj_ref(NULL, &chan->ramin);
687 return ret;
688 }
689
690 return 0;
691}
692
693static int
694nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
695{
696 struct drm_device *dev = chan->dev;
697 struct nouveau_gpuobj *pgd = NULL;
698 struct nouveau_vm_pgd *vpgd;
699 int ret, i;
700
701 ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin);
702 if (ret)
703 return ret;
704
705 /* create page directory for this vm if none currently exists,
706 * will be destroyed automagically when last reference to the
707 * vm is removed
708 */
709 if (list_empty(&vm->pgd_list)) {
710 ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd);
711 if (ret)
712 return ret;
713 }
714 nouveau_vm_ref(vm, &chan->vm, pgd);
715 nouveau_gpuobj_ref(NULL, &pgd);
716
717 /* point channel at vm's page directory */
718 vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
719 nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
720 nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
721 nv_wo32(chan->ramin, 0x0208, 0xffffffff);
722 nv_wo32(chan->ramin, 0x020c, 0x000000ff);
723
724 /* map display semaphore buffers into channel's vm */
725 for (i = 0; i < 2; i++) {
726 struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
727
728 ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
729 &chan->dispc_vma[i]);
730 if (ret)
731 return ret;
732 }
733
734 return 0;
735}
736
737int
738nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
739 uint32_t vram_h, uint32_t tt_h)
740{
741 struct drm_device *dev = chan->dev;
742 struct drm_nouveau_private *dev_priv = dev->dev_private;
743 struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
744 struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
745 struct nouveau_gpuobj *vram = NULL, *tt = NULL;
746 int ret, i;
747
748 NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
749 if (dev_priv->card_type == NV_C0)
750 return nvc0_gpuobj_channel_init(chan, vm);
751
752 /* Allocate a chunk of memory for per-channel object storage */
753 ret = nouveau_gpuobj_channel_init_pramin(chan);
754 if (ret) {
755 NV_ERROR(dev, "init pramin\n");
756 return ret;
757 }
758
759 /* NV50 VM
760 * - Allocate per-channel page-directory
761 * - Link with shared channel VM
762 */
763 if (vm) {
764 u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
765 u64 vm_vinst = chan->ramin->vinst + pgd_offs;
766 u32 vm_pinst = chan->ramin->pinst;
767
768 if (vm_pinst != ~0)
769 vm_pinst += pgd_offs;
770
771 ret = nouveau_gpuobj_new_fake(dev, vm_pinst, vm_vinst, 0x4000,
772 0, &chan->vm_pd);
773 if (ret)
774 return ret;
775
776 nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
777 }
778
779 /* RAMHT */
780 if (dev_priv->card_type < NV_50) {
781 nouveau_ramht_ref(dev_priv->ramht, &chan->ramht, NULL);
782 } else {
783 struct nouveau_gpuobj *ramht = NULL;
784
785 ret = nouveau_gpuobj_new(dev, chan, 0x8000, 16,
786 NVOBJ_FLAG_ZERO_ALLOC, &ramht);
787 if (ret)
788 return ret;
789
790 ret = nouveau_ramht_new(dev, ramht, &chan->ramht);
791 nouveau_gpuobj_ref(NULL, &ramht);
792 if (ret)
793 return ret;
794
795 /* dma objects for display sync channel semaphore blocks */
796 for (i = 0; i < 2; i++) {
797 struct nouveau_gpuobj *sem = NULL;
798 struct nv50_display_crtc *dispc =
799 &nv50_display(dev)->crtc[i];
800 u64 offset = dispc->sem.bo->bo.offset;
801
802 ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff,
803 NV_MEM_ACCESS_RW,
804 NV_MEM_TARGET_VRAM, &sem);
805 if (ret)
806 return ret;
807
808 ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem);
809 nouveau_gpuobj_ref(NULL, &sem);
810 if (ret)
811 return ret;
812 }
813 }
814
815 /* VRAM ctxdma */
816 if (dev_priv->card_type >= NV_50) {
817 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
818 0, (1ULL << 40), NV_MEM_ACCESS_RW,
819 NV_MEM_TARGET_VM, &vram);
820 if (ret) {
821 NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
822 return ret;
823 }
824 } else {
825 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
826 0, dev_priv->fb_available_size,
827 NV_MEM_ACCESS_RW,
828 NV_MEM_TARGET_VRAM, &vram);
829 if (ret) {
830 NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
831 return ret;
832 }
833 }
834
835 ret = nouveau_ramht_insert(chan, vram_h, vram);
836 nouveau_gpuobj_ref(NULL, &vram);
837 if (ret) {
838 NV_ERROR(dev, "Error adding VRAM ctxdma to RAMHT: %d\n", ret);
839 return ret;
840 }
841
842 /* TT memory ctxdma */
843 if (dev_priv->card_type >= NV_50) {
844 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
845 0, (1ULL << 40), NV_MEM_ACCESS_RW,
846 NV_MEM_TARGET_VM, &tt);
847 } else {
848 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
849 0, dev_priv->gart_info.aper_size,
850 NV_MEM_ACCESS_RW,
851 NV_MEM_TARGET_GART, &tt);
852 }
853
854 if (ret) {
855 NV_ERROR(dev, "Error creating TT ctxdma: %d\n", ret);
856 return ret;
857 }
858
859 ret = nouveau_ramht_insert(chan, tt_h, tt);
860 nouveau_gpuobj_ref(NULL, &tt);
861 if (ret) {
862 NV_ERROR(dev, "Error adding TT ctxdma to RAMHT: %d\n", ret);
863 return ret;
864 }
865
866 return 0;
867}
868
869void
870nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
871{
872 struct drm_device *dev = chan->dev;
873 struct drm_nouveau_private *dev_priv = dev->dev_private;
874 int i;
875
876 NV_DEBUG(dev, "ch%d\n", chan->id);
877
878 if (dev_priv->card_type >= NV_50) {
879 struct nv50_display *disp = nv50_display(dev);
880
881 for (i = 0; i < 2; i++) {
882 struct nv50_display_crtc *dispc = &disp->crtc[i];
883 nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
884 }
885
886 nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
887 nouveau_gpuobj_ref(NULL, &chan->vm_pd);
888 }
889
890 if (drm_mm_initialized(&chan->ramin_heap))
891 drm_mm_takedown(&chan->ramin_heap);
892 nouveau_gpuobj_ref(NULL, &chan->ramin);
893}
894
895int
896nouveau_gpuobj_suspend(struct drm_device *dev)
897{
898 struct drm_nouveau_private *dev_priv = dev->dev_private;
899 struct nouveau_gpuobj *gpuobj;
900 int i;
901
902 list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
903 if (gpuobj->cinst != NVOBJ_CINST_GLOBAL)
904 continue;
905
906 gpuobj->suspend = vmalloc(gpuobj->size);
907 if (!gpuobj->suspend) {
908 nouveau_gpuobj_resume(dev);
909 return -ENOMEM;
910 }
911
912 for (i = 0; i < gpuobj->size; i += 4)
913 gpuobj->suspend[i/4] = nv_ro32(gpuobj, i);
914 }
915
916 return 0;
917}
918
919void
920nouveau_gpuobj_resume(struct drm_device *dev)
921{
922 struct drm_nouveau_private *dev_priv = dev->dev_private;
923 struct nouveau_gpuobj *gpuobj;
924 int i;
925
926 list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
927 if (!gpuobj->suspend)
928 continue;
929
930 for (i = 0; i < gpuobj->size; i += 4)
931 nv_wo32(gpuobj, i, gpuobj->suspend[i/4]);
932
933 vfree(gpuobj->suspend);
934 gpuobj->suspend = NULL;
935 }
936
937 dev_priv->engine.instmem.flush(dev);
938}
939
940int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
941 struct drm_file *file_priv)
942{
943 struct drm_nouveau_grobj_alloc *init = data;
944 struct nouveau_channel *chan;
945 int ret;
946
947 if (init->handle == ~0)
948 return -EINVAL;
949
950 chan = nouveau_channel_get(file_priv, init->channel);
951 if (IS_ERR(chan))
952 return PTR_ERR(chan);
953
954 if (nouveau_ramht_find(chan, init->handle)) {
955 ret = -EEXIST;
956 goto out;
957 }
958
959 ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class);
960 if (ret) {
961 NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n",
962 ret, init->channel, init->handle);
963 }
964
965out:
966 nouveau_channel_put(&chan);
967 return ret;
968}
969
970int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
971 struct drm_file *file_priv)
972{
973 struct drm_nouveau_gpuobj_free *objfree = data;
974 struct nouveau_channel *chan;
975 int ret;
976
977 chan = nouveau_channel_get(file_priv, objfree->channel);
978 if (IS_ERR(chan))
979 return PTR_ERR(chan);
980
981 /* Synchronize with the user channel */
982 nouveau_channel_idle(chan);
983
984 ret = nouveau_ramht_remove(chan, objfree->handle);
985 nouveau_channel_put(&chan);
986 return ret;
987}
988
989u32
990nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset)
991{
992 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
993 struct drm_device *dev = gpuobj->dev;
994 unsigned long flags;
995
996 if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
997 u64 ptr = gpuobj->vinst + offset;
998 u32 base = ptr >> 16;
999 u32 val;
1000
1001 spin_lock_irqsave(&dev_priv->vm_lock, flags);
1002 if (dev_priv->ramin_base != base) {
1003 dev_priv->ramin_base = base;
1004 nv_wr32(dev, 0x001700, dev_priv->ramin_base);
1005 }
1006 val = nv_rd32(dev, 0x700000 + (ptr & 0xffff));
1007 spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
1008 return val;
1009 }
1010
1011 return nv_ri32(dev, gpuobj->pinst + offset);
1012}
1013
1014void
1015nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val)
1016{
1017 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
1018 struct drm_device *dev = gpuobj->dev;
1019 unsigned long flags;
1020
1021 if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
1022 u64 ptr = gpuobj->vinst + offset;
1023 u32 base = ptr >> 16;
1024
1025 spin_lock_irqsave(&dev_priv->vm_lock, flags);
1026 if (dev_priv->ramin_base != base) {
1027 dev_priv->ramin_base = base;
1028 nv_wr32(dev, 0x001700, dev_priv->ramin_base);
1029 }
1030 nv_wr32(dev, 0x700000 + (ptr & 0xffff), val);
1031 spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
1032 return;
1033 }
1034
1035 nv_wi32(dev, gpuobj->pinst + offset, val);
1036}
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c
new file mode 100644
index 00000000000..a24a81f5a89
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c
@@ -0,0 +1,309 @@
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
30static u32
31nouveau_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
54static int
55nouveau_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
66static int
67nouveau_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
83int
84nouveau_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->pinst >> 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->pinst >> 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) |
118 (chan->id << 28) |
119 chan->id; /* HASH_TAG */
120 } else {
121 ctx = (gpuobj->cinst >> 4) |
122 ((gpuobj->engine <<
123 NV40_RAMHT_CONTEXT_ENGINE_SHIFT));
124 }
125 }
126
127 spin_lock_irqsave(&chan->ramht->lock, flags);
128 list_add(&entry->head, &chan->ramht->entries);
129
130 co = ho = nouveau_ramht_hash_handle(chan, handle);
131 do {
132 if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
133 NV_DEBUG(dev,
134 "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
135 chan->id, co, handle, ctx);
136 nv_wo32(ramht, co + 0, handle);
137 nv_wo32(ramht, co + 4, ctx);
138
139 spin_unlock_irqrestore(&chan->ramht->lock, flags);
140 instmem->flush(dev);
141 return 0;
142 }
143 NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
144 chan->id, co, nv_ro32(ramht, co));
145
146 co += 8;
147 if (co >= ramht->size)
148 co = 0;
149 } while (co != ho);
150
151 NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
152 list_del(&entry->head);
153 spin_unlock_irqrestore(&chan->ramht->lock, flags);
154 kfree(entry);
155 return -ENOMEM;
156}
157
158static struct nouveau_ramht_entry *
159nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle)
160{
161 struct nouveau_ramht *ramht = chan ? chan->ramht : NULL;
162 struct nouveau_ramht_entry *entry;
163 unsigned long flags;
164
165 if (!ramht)
166 return NULL;
167
168 spin_lock_irqsave(&ramht->lock, flags);
169 list_for_each_entry(entry, &ramht->entries, head) {
170 if (entry->channel == chan &&
171 (!handle || entry->handle == handle)) {
172 list_del(&entry->head);
173 spin_unlock_irqrestore(&ramht->lock, flags);
174
175 return entry;
176 }
177 }
178 spin_unlock_irqrestore(&ramht->lock, flags);
179
180 return NULL;
181}
182
183static void
184nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle)
185{
186 struct drm_device *dev = chan->dev;
187 struct drm_nouveau_private *dev_priv = dev->dev_private;
188 struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
189 struct nouveau_gpuobj *ramht = chan->ramht->gpuobj;
190 unsigned long flags;
191 u32 co, ho;
192
193 spin_lock_irqsave(&chan->ramht->lock, flags);
194 co = ho = nouveau_ramht_hash_handle(chan, handle);
195 do {
196 if (nouveau_ramht_entry_valid(dev, ramht, co) &&
197 nouveau_ramht_entry_same_channel(chan, ramht, co) &&
198 (handle == nv_ro32(ramht, co))) {
199 NV_DEBUG(dev,
200 "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
201 chan->id, co, handle, nv_ro32(ramht, co + 4));
202 nv_wo32(ramht, co + 0, 0x00000000);
203 nv_wo32(ramht, co + 4, 0x00000000);
204 instmem->flush(dev);
205 goto out;
206 }
207
208 co += 8;
209 if (co >= ramht->size)
210 co = 0;
211 } while (co != ho);
212
213 NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
214 chan->id, handle);
215out:
216 spin_unlock_irqrestore(&chan->ramht->lock, flags);
217}
218
219int
220nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle)
221{
222 struct nouveau_ramht_entry *entry;
223
224 entry = nouveau_ramht_remove_entry(chan, handle);
225 if (!entry)
226 return -ENOENT;
227
228 nouveau_ramht_remove_hash(chan, entry->handle);
229 nouveau_gpuobj_ref(NULL, &entry->gpuobj);
230 kfree(entry);
231 return 0;
232}
233
234struct nouveau_gpuobj *
235nouveau_ramht_find(struct nouveau_channel *chan, u32 handle)
236{
237 struct nouveau_ramht *ramht = chan->ramht;
238 struct nouveau_ramht_entry *entry;
239 struct nouveau_gpuobj *gpuobj = NULL;
240 unsigned long flags;
241
242 if (unlikely(!chan->ramht))
243 return NULL;
244
245 spin_lock_irqsave(&ramht->lock, flags);
246 list_for_each_entry(entry, &chan->ramht->entries, head) {
247 if (entry->channel == chan && entry->handle == handle) {
248 gpuobj = entry->gpuobj;
249 break;
250 }
251 }
252 spin_unlock_irqrestore(&ramht->lock, flags);
253
254 return gpuobj;
255}
256
257int
258nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
259 struct nouveau_ramht **pramht)
260{
261 struct nouveau_ramht *ramht;
262
263 ramht = kzalloc(sizeof(*ramht), GFP_KERNEL);
264 if (!ramht)
265 return -ENOMEM;
266
267 ramht->dev = dev;
268 kref_init(&ramht->refcount);
269 ramht->bits = drm_order(gpuobj->size / 8);
270 INIT_LIST_HEAD(&ramht->entries);
271 spin_lock_init(&ramht->lock);
272 nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj);
273
274 *pramht = ramht;
275 return 0;
276}
277
278static void
279nouveau_ramht_del(struct kref *ref)
280{
281 struct nouveau_ramht *ramht =
282 container_of(ref, struct nouveau_ramht, refcount);
283
284 nouveau_gpuobj_ref(NULL, &ramht->gpuobj);
285 kfree(ramht);
286}
287
288void
289nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr,
290 struct nouveau_channel *chan)
291{
292 struct nouveau_ramht_entry *entry;
293 struct nouveau_ramht *ramht;
294
295 if (ref)
296 kref_get(&ref->refcount);
297
298 ramht = *ptr;
299 if (ramht) {
300 while ((entry = nouveau_ramht_remove_entry(chan, 0))) {
301 nouveau_ramht_remove_hash(chan, entry->handle);
302 nouveau_gpuobj_ref(NULL, &entry->gpuobj);
303 kfree(entry);
304 }
305
306 kref_put(&ramht->refcount, nouveau_ramht_del);
307 }
308 *ptr = ref;
309}
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.h b/drivers/gpu/drm/nouveau/nouveau_ramht.h
new file mode 100644
index 00000000000..c82de98fee0
--- /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
28struct nouveau_ramht_entry {
29 struct list_head head;
30 struct nouveau_channel *channel;
31 struct nouveau_gpuobj *gpuobj;
32 u32 handle;
33};
34
35struct 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
44extern int nouveau_ramht_new(struct drm_device *, struct nouveau_gpuobj *,
45 struct nouveau_ramht **);
46extern void nouveau_ramht_ref(struct nouveau_ramht *, struct nouveau_ramht **,
47 struct nouveau_channel *unref_channel);
48
49extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle,
50 struct nouveau_gpuobj *);
51extern int nouveau_ramht_remove(struct nouveau_channel *, u32 handle);
52extern struct nouveau_gpuobj *
53nouveau_ramht_find(struct nouveau_channel *chan, u32 handle);
54
55#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
new file mode 100644
index 00000000000..10656e430b4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -0,0 +1,1218 @@
1/*
2 * Copyright 2005 Stephane Marchesin
3 * Copyright 2008 Stuart Bennett
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 "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26#include <linux/swab.h>
27#include <linux/slab.h>
28#include "drmP.h"
29#include "drm.h"
30#include "drm_sarea.h"
31#include "drm_crtc_helper.h"
32#include <linux/vgaarb.h>
33#include <linux/vga_switcheroo.h>
34
35#include "nouveau_drv.h"
36#include "nouveau_drm.h"
37#include "nouveau_fbcon.h"
38#include "nouveau_ramht.h"
39#include "nouveau_pm.h"
40#include "nv50_display.h"
41
42static void nouveau_stub_takedown(struct drm_device *dev) {}
43static int nouveau_stub_init(struct drm_device *dev) { return 0; }
44
45static int nouveau_init_engine_ptrs(struct drm_device *dev)
46{
47 struct drm_nouveau_private *dev_priv = dev->dev_private;
48 struct nouveau_engine *engine = &dev_priv->engine;
49
50 switch (dev_priv->chipset & 0xf0) {
51 case 0x00:
52 engine->instmem.init = nv04_instmem_init;
53 engine->instmem.takedown = nv04_instmem_takedown;
54 engine->instmem.suspend = nv04_instmem_suspend;
55 engine->instmem.resume = nv04_instmem_resume;
56 engine->instmem.get = nv04_instmem_get;
57 engine->instmem.put = nv04_instmem_put;
58 engine->instmem.map = nv04_instmem_map;
59 engine->instmem.unmap = nv04_instmem_unmap;
60 engine->instmem.flush = nv04_instmem_flush;
61 engine->mc.init = nv04_mc_init;
62 engine->mc.takedown = nv04_mc_takedown;
63 engine->timer.init = nv04_timer_init;
64 engine->timer.read = nv04_timer_read;
65 engine->timer.takedown = nv04_timer_takedown;
66 engine->fb.init = nv04_fb_init;
67 engine->fb.takedown = nv04_fb_takedown;
68 engine->fifo.channels = 16;
69 engine->fifo.init = nv04_fifo_init;
70 engine->fifo.takedown = nv04_fifo_fini;
71 engine->fifo.disable = nv04_fifo_disable;
72 engine->fifo.enable = nv04_fifo_enable;
73 engine->fifo.reassign = nv04_fifo_reassign;
74 engine->fifo.cache_pull = nv04_fifo_cache_pull;
75 engine->fifo.channel_id = nv04_fifo_channel_id;
76 engine->fifo.create_context = nv04_fifo_create_context;
77 engine->fifo.destroy_context = nv04_fifo_destroy_context;
78 engine->fifo.load_context = nv04_fifo_load_context;
79 engine->fifo.unload_context = nv04_fifo_unload_context;
80 engine->display.early_init = nv04_display_early_init;
81 engine->display.late_takedown = nv04_display_late_takedown;
82 engine->display.create = nv04_display_create;
83 engine->display.init = nv04_display_init;
84 engine->display.destroy = nv04_display_destroy;
85 engine->gpio.init = nouveau_stub_init;
86 engine->gpio.takedown = nouveau_stub_takedown;
87 engine->gpio.get = NULL;
88 engine->gpio.set = NULL;
89 engine->gpio.irq_enable = NULL;
90 engine->pm.clock_get = nv04_pm_clock_get;
91 engine->pm.clock_pre = nv04_pm_clock_pre;
92 engine->pm.clock_set = nv04_pm_clock_set;
93 engine->vram.init = nouveau_mem_detect;
94 engine->vram.takedown = nouveau_stub_takedown;
95 engine->vram.flags_valid = nouveau_mem_flags_valid;
96 break;
97 case 0x10:
98 engine->instmem.init = nv04_instmem_init;
99 engine->instmem.takedown = nv04_instmem_takedown;
100 engine->instmem.suspend = nv04_instmem_suspend;
101 engine->instmem.resume = nv04_instmem_resume;
102 engine->instmem.get = nv04_instmem_get;
103 engine->instmem.put = nv04_instmem_put;
104 engine->instmem.map = nv04_instmem_map;
105 engine->instmem.unmap = nv04_instmem_unmap;
106 engine->instmem.flush = nv04_instmem_flush;
107 engine->mc.init = nv04_mc_init;
108 engine->mc.takedown = nv04_mc_takedown;
109 engine->timer.init = nv04_timer_init;
110 engine->timer.read = nv04_timer_read;
111 engine->timer.takedown = nv04_timer_takedown;
112 engine->fb.init = nv10_fb_init;
113 engine->fb.takedown = nv10_fb_takedown;
114 engine->fb.init_tile_region = nv10_fb_init_tile_region;
115 engine->fb.set_tile_region = nv10_fb_set_tile_region;
116 engine->fb.free_tile_region = nv10_fb_free_tile_region;
117 engine->fifo.channels = 32;
118 engine->fifo.init = nv10_fifo_init;
119 engine->fifo.takedown = nv04_fifo_fini;
120 engine->fifo.disable = nv04_fifo_disable;
121 engine->fifo.enable = nv04_fifo_enable;
122 engine->fifo.reassign = nv04_fifo_reassign;
123 engine->fifo.cache_pull = nv04_fifo_cache_pull;
124 engine->fifo.channel_id = nv10_fifo_channel_id;
125 engine->fifo.create_context = nv10_fifo_create_context;
126 engine->fifo.destroy_context = nv04_fifo_destroy_context;
127 engine->fifo.load_context = nv10_fifo_load_context;
128 engine->fifo.unload_context = nv10_fifo_unload_context;
129 engine->display.early_init = nv04_display_early_init;
130 engine->display.late_takedown = nv04_display_late_takedown;
131 engine->display.create = nv04_display_create;
132 engine->display.init = nv04_display_init;
133 engine->display.destroy = nv04_display_destroy;
134 engine->gpio.init = nouveau_stub_init;
135 engine->gpio.takedown = nouveau_stub_takedown;
136 engine->gpio.get = nv10_gpio_get;
137 engine->gpio.set = nv10_gpio_set;
138 engine->gpio.irq_enable = NULL;
139 engine->pm.clock_get = nv04_pm_clock_get;
140 engine->pm.clock_pre = nv04_pm_clock_pre;
141 engine->pm.clock_set = nv04_pm_clock_set;
142 engine->vram.init = nouveau_mem_detect;
143 engine->vram.takedown = nouveau_stub_takedown;
144 engine->vram.flags_valid = nouveau_mem_flags_valid;
145 break;
146 case 0x20:
147 engine->instmem.init = nv04_instmem_init;
148 engine->instmem.takedown = nv04_instmem_takedown;
149 engine->instmem.suspend = nv04_instmem_suspend;
150 engine->instmem.resume = nv04_instmem_resume;
151 engine->instmem.get = nv04_instmem_get;
152 engine->instmem.put = nv04_instmem_put;
153 engine->instmem.map = nv04_instmem_map;
154 engine->instmem.unmap = nv04_instmem_unmap;
155 engine->instmem.flush = nv04_instmem_flush;
156 engine->mc.init = nv04_mc_init;
157 engine->mc.takedown = nv04_mc_takedown;
158 engine->timer.init = nv04_timer_init;
159 engine->timer.read = nv04_timer_read;
160 engine->timer.takedown = nv04_timer_takedown;
161 engine->fb.init = nv10_fb_init;
162 engine->fb.takedown = nv10_fb_takedown;
163 engine->fb.init_tile_region = nv10_fb_init_tile_region;
164 engine->fb.set_tile_region = nv10_fb_set_tile_region;
165 engine->fb.free_tile_region = nv10_fb_free_tile_region;
166 engine->fifo.channels = 32;
167 engine->fifo.init = nv10_fifo_init;
168 engine->fifo.takedown = nv04_fifo_fini;
169 engine->fifo.disable = nv04_fifo_disable;
170 engine->fifo.enable = nv04_fifo_enable;
171 engine->fifo.reassign = nv04_fifo_reassign;
172 engine->fifo.cache_pull = nv04_fifo_cache_pull;
173 engine->fifo.channel_id = nv10_fifo_channel_id;
174 engine->fifo.create_context = nv10_fifo_create_context;
175 engine->fifo.destroy_context = nv04_fifo_destroy_context;
176 engine->fifo.load_context = nv10_fifo_load_context;
177 engine->fifo.unload_context = nv10_fifo_unload_context;
178 engine->display.early_init = nv04_display_early_init;
179 engine->display.late_takedown = nv04_display_late_takedown;
180 engine->display.create = nv04_display_create;
181 engine->display.init = nv04_display_init;
182 engine->display.destroy = nv04_display_destroy;
183 engine->gpio.init = nouveau_stub_init;
184 engine->gpio.takedown = nouveau_stub_takedown;
185 engine->gpio.get = nv10_gpio_get;
186 engine->gpio.set = nv10_gpio_set;
187 engine->gpio.irq_enable = NULL;
188 engine->pm.clock_get = nv04_pm_clock_get;
189 engine->pm.clock_pre = nv04_pm_clock_pre;
190 engine->pm.clock_set = nv04_pm_clock_set;
191 engine->vram.init = nouveau_mem_detect;
192 engine->vram.takedown = nouveau_stub_takedown;
193 engine->vram.flags_valid = nouveau_mem_flags_valid;
194 break;
195 case 0x30:
196 engine->instmem.init = nv04_instmem_init;
197 engine->instmem.takedown = nv04_instmem_takedown;
198 engine->instmem.suspend = nv04_instmem_suspend;
199 engine->instmem.resume = nv04_instmem_resume;
200 engine->instmem.get = nv04_instmem_get;
201 engine->instmem.put = nv04_instmem_put;
202 engine->instmem.map = nv04_instmem_map;
203 engine->instmem.unmap = nv04_instmem_unmap;
204 engine->instmem.flush = nv04_instmem_flush;
205 engine->mc.init = nv04_mc_init;
206 engine->mc.takedown = nv04_mc_takedown;
207 engine->timer.init = nv04_timer_init;
208 engine->timer.read = nv04_timer_read;
209 engine->timer.takedown = nv04_timer_takedown;
210 engine->fb.init = nv30_fb_init;
211 engine->fb.takedown = nv30_fb_takedown;
212 engine->fb.init_tile_region = nv30_fb_init_tile_region;
213 engine->fb.set_tile_region = nv10_fb_set_tile_region;
214 engine->fb.free_tile_region = nv30_fb_free_tile_region;
215 engine->fifo.channels = 32;
216 engine->fifo.init = nv10_fifo_init;
217 engine->fifo.takedown = nv04_fifo_fini;
218 engine->fifo.disable = nv04_fifo_disable;
219 engine->fifo.enable = nv04_fifo_enable;
220 engine->fifo.reassign = nv04_fifo_reassign;
221 engine->fifo.cache_pull = nv04_fifo_cache_pull;
222 engine->fifo.channel_id = nv10_fifo_channel_id;
223 engine->fifo.create_context = nv10_fifo_create_context;
224 engine->fifo.destroy_context = nv04_fifo_destroy_context;
225 engine->fifo.load_context = nv10_fifo_load_context;
226 engine->fifo.unload_context = nv10_fifo_unload_context;
227 engine->display.early_init = nv04_display_early_init;
228 engine->display.late_takedown = nv04_display_late_takedown;
229 engine->display.create = nv04_display_create;
230 engine->display.init = nv04_display_init;
231 engine->display.destroy = nv04_display_destroy;
232 engine->gpio.init = nouveau_stub_init;
233 engine->gpio.takedown = nouveau_stub_takedown;
234 engine->gpio.get = nv10_gpio_get;
235 engine->gpio.set = nv10_gpio_set;
236 engine->gpio.irq_enable = NULL;
237 engine->pm.clock_get = nv04_pm_clock_get;
238 engine->pm.clock_pre = nv04_pm_clock_pre;
239 engine->pm.clock_set = nv04_pm_clock_set;
240 engine->pm.voltage_get = nouveau_voltage_gpio_get;
241 engine->pm.voltage_set = nouveau_voltage_gpio_set;
242 engine->vram.init = nouveau_mem_detect;
243 engine->vram.takedown = nouveau_stub_takedown;
244 engine->vram.flags_valid = nouveau_mem_flags_valid;
245 break;
246 case 0x40:
247 case 0x60:
248 engine->instmem.init = nv04_instmem_init;
249 engine->instmem.takedown = nv04_instmem_takedown;
250 engine->instmem.suspend = nv04_instmem_suspend;
251 engine->instmem.resume = nv04_instmem_resume;
252 engine->instmem.get = nv04_instmem_get;
253 engine->instmem.put = nv04_instmem_put;
254 engine->instmem.map = nv04_instmem_map;
255 engine->instmem.unmap = nv04_instmem_unmap;
256 engine->instmem.flush = nv04_instmem_flush;
257 engine->mc.init = nv40_mc_init;
258 engine->mc.takedown = nv40_mc_takedown;
259 engine->timer.init = nv04_timer_init;
260 engine->timer.read = nv04_timer_read;
261 engine->timer.takedown = nv04_timer_takedown;
262 engine->fb.init = nv40_fb_init;
263 engine->fb.takedown = nv40_fb_takedown;
264 engine->fb.init_tile_region = nv30_fb_init_tile_region;
265 engine->fb.set_tile_region = nv40_fb_set_tile_region;
266 engine->fb.free_tile_region = nv30_fb_free_tile_region;
267 engine->fifo.channels = 32;
268 engine->fifo.init = nv40_fifo_init;
269 engine->fifo.takedown = nv04_fifo_fini;
270 engine->fifo.disable = nv04_fifo_disable;
271 engine->fifo.enable = nv04_fifo_enable;
272 engine->fifo.reassign = nv04_fifo_reassign;
273 engine->fifo.cache_pull = nv04_fifo_cache_pull;
274 engine->fifo.channel_id = nv10_fifo_channel_id;
275 engine->fifo.create_context = nv40_fifo_create_context;
276 engine->fifo.destroy_context = nv04_fifo_destroy_context;
277 engine->fifo.load_context = nv40_fifo_load_context;
278 engine->fifo.unload_context = nv40_fifo_unload_context;
279 engine->display.early_init = nv04_display_early_init;
280 engine->display.late_takedown = nv04_display_late_takedown;
281 engine->display.create = nv04_display_create;
282 engine->display.init = nv04_display_init;
283 engine->display.destroy = nv04_display_destroy;
284 engine->gpio.init = nouveau_stub_init;
285 engine->gpio.takedown = nouveau_stub_takedown;
286 engine->gpio.get = nv10_gpio_get;
287 engine->gpio.set = nv10_gpio_set;
288 engine->gpio.irq_enable = NULL;
289 engine->pm.clock_get = nv04_pm_clock_get;
290 engine->pm.clock_pre = nv04_pm_clock_pre;
291 engine->pm.clock_set = nv04_pm_clock_set;
292 engine->pm.voltage_get = nouveau_voltage_gpio_get;
293 engine->pm.voltage_set = nouveau_voltage_gpio_set;
294 engine->pm.temp_get = nv40_temp_get;
295 engine->vram.init = nouveau_mem_detect;
296 engine->vram.takedown = nouveau_stub_takedown;
297 engine->vram.flags_valid = nouveau_mem_flags_valid;
298 break;
299 case 0x50:
300 case 0x80: /* gotta love NVIDIA's consistency.. */
301 case 0x90:
302 case 0xA0:
303 engine->instmem.init = nv50_instmem_init;
304 engine->instmem.takedown = nv50_instmem_takedown;
305 engine->instmem.suspend = nv50_instmem_suspend;
306 engine->instmem.resume = nv50_instmem_resume;
307 engine->instmem.get = nv50_instmem_get;
308 engine->instmem.put = nv50_instmem_put;
309 engine->instmem.map = nv50_instmem_map;
310 engine->instmem.unmap = nv50_instmem_unmap;
311 if (dev_priv->chipset == 0x50)
312 engine->instmem.flush = nv50_instmem_flush;
313 else
314 engine->instmem.flush = nv84_instmem_flush;
315 engine->mc.init = nv50_mc_init;
316 engine->mc.takedown = nv50_mc_takedown;
317 engine->timer.init = nv04_timer_init;
318 engine->timer.read = nv04_timer_read;
319 engine->timer.takedown = nv04_timer_takedown;
320 engine->fb.init = nv50_fb_init;
321 engine->fb.takedown = nv50_fb_takedown;
322 engine->fifo.channels = 128;
323 engine->fifo.init = nv50_fifo_init;
324 engine->fifo.takedown = nv50_fifo_takedown;
325 engine->fifo.disable = nv04_fifo_disable;
326 engine->fifo.enable = nv04_fifo_enable;
327 engine->fifo.reassign = nv04_fifo_reassign;
328 engine->fifo.channel_id = nv50_fifo_channel_id;
329 engine->fifo.create_context = nv50_fifo_create_context;
330 engine->fifo.destroy_context = nv50_fifo_destroy_context;
331 engine->fifo.load_context = nv50_fifo_load_context;
332 engine->fifo.unload_context = nv50_fifo_unload_context;
333 engine->fifo.tlb_flush = nv50_fifo_tlb_flush;
334 engine->display.early_init = nv50_display_early_init;
335 engine->display.late_takedown = nv50_display_late_takedown;
336 engine->display.create = nv50_display_create;
337 engine->display.init = nv50_display_init;
338 engine->display.destroy = nv50_display_destroy;
339 engine->gpio.init = nv50_gpio_init;
340 engine->gpio.takedown = nv50_gpio_fini;
341 engine->gpio.get = nv50_gpio_get;
342 engine->gpio.set = nv50_gpio_set;
343 engine->gpio.irq_register = nv50_gpio_irq_register;
344 engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
345 engine->gpio.irq_enable = nv50_gpio_irq_enable;
346 switch (dev_priv->chipset) {
347 case 0x84:
348 case 0x86:
349 case 0x92:
350 case 0x94:
351 case 0x96:
352 case 0x98:
353 case 0xa0:
354 case 0xaa:
355 case 0xac:
356 case 0x50:
357 engine->pm.clock_get = nv50_pm_clock_get;
358 engine->pm.clock_pre = nv50_pm_clock_pre;
359 engine->pm.clock_set = nv50_pm_clock_set;
360 break;
361 default:
362 engine->pm.clock_get = nva3_pm_clock_get;
363 engine->pm.clock_pre = nva3_pm_clock_pre;
364 engine->pm.clock_set = nva3_pm_clock_set;
365 break;
366 }
367 engine->pm.voltage_get = nouveau_voltage_gpio_get;
368 engine->pm.voltage_set = nouveau_voltage_gpio_set;
369 if (dev_priv->chipset >= 0x84)
370 engine->pm.temp_get = nv84_temp_get;
371 else
372 engine->pm.temp_get = nv40_temp_get;
373 engine->vram.init = nv50_vram_init;
374 engine->vram.takedown = nv50_vram_fini;
375 engine->vram.get = nv50_vram_new;
376 engine->vram.put = nv50_vram_del;
377 engine->vram.flags_valid = nv50_vram_flags_valid;
378 break;
379 case 0xC0:
380 engine->instmem.init = nvc0_instmem_init;
381 engine->instmem.takedown = nvc0_instmem_takedown;
382 engine->instmem.suspend = nvc0_instmem_suspend;
383 engine->instmem.resume = nvc0_instmem_resume;
384 engine->instmem.get = nv50_instmem_get;
385 engine->instmem.put = nv50_instmem_put;
386 engine->instmem.map = nv50_instmem_map;
387 engine->instmem.unmap = nv50_instmem_unmap;
388 engine->instmem.flush = nv84_instmem_flush;
389 engine->mc.init = nv50_mc_init;
390 engine->mc.takedown = nv50_mc_takedown;
391 engine->timer.init = nv04_timer_init;
392 engine->timer.read = nv04_timer_read;
393 engine->timer.takedown = nv04_timer_takedown;
394 engine->fb.init = nvc0_fb_init;
395 engine->fb.takedown = nvc0_fb_takedown;
396 engine->fifo.channels = 128;
397 engine->fifo.init = nvc0_fifo_init;
398 engine->fifo.takedown = nvc0_fifo_takedown;
399 engine->fifo.disable = nvc0_fifo_disable;
400 engine->fifo.enable = nvc0_fifo_enable;
401 engine->fifo.reassign = nvc0_fifo_reassign;
402 engine->fifo.channel_id = nvc0_fifo_channel_id;
403 engine->fifo.create_context = nvc0_fifo_create_context;
404 engine->fifo.destroy_context = nvc0_fifo_destroy_context;
405 engine->fifo.load_context = nvc0_fifo_load_context;
406 engine->fifo.unload_context = nvc0_fifo_unload_context;
407 engine->display.early_init = nv50_display_early_init;
408 engine->display.late_takedown = nv50_display_late_takedown;
409 engine->display.create = nv50_display_create;
410 engine->display.init = nv50_display_init;
411 engine->display.destroy = nv50_display_destroy;
412 engine->gpio.init = nv50_gpio_init;
413 engine->gpio.takedown = nouveau_stub_takedown;
414 engine->gpio.get = nv50_gpio_get;
415 engine->gpio.set = nv50_gpio_set;
416 engine->gpio.irq_register = nv50_gpio_irq_register;
417 engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
418 engine->gpio.irq_enable = nv50_gpio_irq_enable;
419 engine->vram.init = nvc0_vram_init;
420 engine->vram.takedown = nv50_vram_fini;
421 engine->vram.get = nvc0_vram_new;
422 engine->vram.put = nv50_vram_del;
423 engine->vram.flags_valid = nvc0_vram_flags_valid;
424 engine->pm.temp_get = nv84_temp_get;
425 break;
426 default:
427 NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
428 return 1;
429 }
430
431 return 0;
432}
433
434static unsigned int
435nouveau_vga_set_decode(void *priv, bool state)
436{
437 struct drm_device *dev = priv;
438 struct drm_nouveau_private *dev_priv = dev->dev_private;
439
440 if (dev_priv->chipset >= 0x40)
441 nv_wr32(dev, 0x88054, state);
442 else
443 nv_wr32(dev, 0x1854, state);
444
445 if (state)
446 return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
447 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
448 else
449 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
450}
451
452static int
453nouveau_card_init_channel(struct drm_device *dev)
454{
455 struct drm_nouveau_private *dev_priv = dev->dev_private;
456 int ret;
457
458 ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
459 NvDmaFB, NvDmaTT);
460 if (ret)
461 return ret;
462
463 mutex_unlock(&dev_priv->channel->mutex);
464 return 0;
465}
466
467static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
468 enum vga_switcheroo_state state)
469{
470 struct drm_device *dev = pci_get_drvdata(pdev);
471 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
472 if (state == VGA_SWITCHEROO_ON) {
473 printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
474 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
475 nouveau_pci_resume(pdev);
476 drm_kms_helper_poll_enable(dev);
477 dev->switch_power_state = DRM_SWITCH_POWER_ON;
478 } else {
479 printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
480 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
481 drm_kms_helper_poll_disable(dev);
482 nouveau_pci_suspend(pdev, pmm);
483 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
484 }
485}
486
487static void nouveau_switcheroo_reprobe(struct pci_dev *pdev)
488{
489 struct drm_device *dev = pci_get_drvdata(pdev);
490 nouveau_fbcon_output_poll_changed(dev);
491}
492
493static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev)
494{
495 struct drm_device *dev = pci_get_drvdata(pdev);
496 bool can_switch;
497
498 spin_lock(&dev->count_lock);
499 can_switch = (dev->open_count == 0);
500 spin_unlock(&dev->count_lock);
501 return can_switch;
502}
503
504int
505nouveau_card_init(struct drm_device *dev)
506{
507 struct drm_nouveau_private *dev_priv = dev->dev_private;
508 struct nouveau_engine *engine;
509 int ret, e = 0;
510
511 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
512 vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
513 nouveau_switcheroo_reprobe,
514 nouveau_switcheroo_can_switch);
515
516 /* Initialise internal driver API hooks */
517 ret = nouveau_init_engine_ptrs(dev);
518 if (ret)
519 goto out;
520 engine = &dev_priv->engine;
521 spin_lock_init(&dev_priv->channels.lock);
522 spin_lock_init(&dev_priv->tile.lock);
523 spin_lock_init(&dev_priv->context_switch_lock);
524 spin_lock_init(&dev_priv->vm_lock);
525
526 /* Make the CRTCs and I2C buses accessible */
527 ret = engine->display.early_init(dev);
528 if (ret)
529 goto out;
530
531 /* Parse BIOS tables / Run init tables if card not POSTed */
532 ret = nouveau_bios_init(dev);
533 if (ret)
534 goto out_display_early;
535
536 nouveau_pm_init(dev);
537
538 ret = engine->vram.init(dev);
539 if (ret)
540 goto out_bios;
541
542 ret = nouveau_gpuobj_init(dev);
543 if (ret)
544 goto out_vram;
545
546 ret = engine->instmem.init(dev);
547 if (ret)
548 goto out_gpuobj;
549
550 ret = nouveau_mem_vram_init(dev);
551 if (ret)
552 goto out_instmem;
553
554 ret = nouveau_mem_gart_init(dev);
555 if (ret)
556 goto out_ttmvram;
557
558 /* PMC */
559 ret = engine->mc.init(dev);
560 if (ret)
561 goto out_gart;
562
563 /* PGPIO */
564 ret = engine->gpio.init(dev);
565 if (ret)
566 goto out_mc;
567
568 /* PTIMER */
569 ret = engine->timer.init(dev);
570 if (ret)
571 goto out_gpio;
572
573 /* PFB */
574 ret = engine->fb.init(dev);
575 if (ret)
576 goto out_timer;
577
578 if (!dev_priv->noaccel) {
579 switch (dev_priv->card_type) {
580 case NV_04:
581 nv04_graph_create(dev);
582 break;
583 case NV_10:
584 nv10_graph_create(dev);
585 break;
586 case NV_20:
587 case NV_30:
588 nv20_graph_create(dev);
589 break;
590 case NV_40:
591 nv40_graph_create(dev);
592 break;
593 case NV_50:
594 nv50_graph_create(dev);
595 break;
596 case NV_C0:
597 nvc0_graph_create(dev);
598 break;
599 default:
600 break;
601 }
602
603 switch (dev_priv->chipset) {
604 case 0x84:
605 case 0x86:
606 case 0x92:
607 case 0x94:
608 case 0x96:
609 case 0xa0:
610 nv84_crypt_create(dev);
611 break;
612 }
613
614 switch (dev_priv->card_type) {
615 case NV_50:
616 switch (dev_priv->chipset) {
617 case 0xa3:
618 case 0xa5:
619 case 0xa8:
620 case 0xaf:
621 nva3_copy_create(dev);
622 break;
623 }
624 break;
625 case NV_C0:
626 nvc0_copy_create(dev, 0);
627 nvc0_copy_create(dev, 1);
628 break;
629 default:
630 break;
631 }
632
633 if (dev_priv->card_type == NV_40)
634 nv40_mpeg_create(dev);
635 else
636 if (dev_priv->card_type == NV_50 &&
637 (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
638 nv50_mpeg_create(dev);
639
640 for (e = 0; e < NVOBJ_ENGINE_NR; e++) {
641 if (dev_priv->eng[e]) {
642 ret = dev_priv->eng[e]->init(dev, e);
643 if (ret)
644 goto out_engine;
645 }
646 }
647
648 /* PFIFO */
649 ret = engine->fifo.init(dev);
650 if (ret)
651 goto out_engine;
652 }
653
654 ret = engine->display.create(dev);
655 if (ret)
656 goto out_fifo;
657
658 ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
659 if (ret)
660 goto out_vblank;
661
662 ret = nouveau_irq_init(dev);
663 if (ret)
664 goto out_vblank;
665
666 /* what about PVIDEO/PCRTC/PRAMDAC etc? */
667
668 if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
669 ret = nouveau_fence_init(dev);
670 if (ret)
671 goto out_irq;
672
673 ret = nouveau_card_init_channel(dev);
674 if (ret)
675 goto out_fence;
676 }
677
678 nouveau_fbcon_init(dev);
679 drm_kms_helper_poll_init(dev);
680 return 0;
681
682out_fence:
683 nouveau_fence_fini(dev);
684out_irq:
685 nouveau_irq_fini(dev);
686out_vblank:
687 drm_vblank_cleanup(dev);
688 engine->display.destroy(dev);
689out_fifo:
690 if (!dev_priv->noaccel)
691 engine->fifo.takedown(dev);
692out_engine:
693 if (!dev_priv->noaccel) {
694 for (e = e - 1; e >= 0; e--) {
695 if (!dev_priv->eng[e])
696 continue;
697 dev_priv->eng[e]->fini(dev, e, false);
698 dev_priv->eng[e]->destroy(dev,e );
699 }
700 }
701
702 engine->fb.takedown(dev);
703out_timer:
704 engine->timer.takedown(dev);
705out_gpio:
706 engine->gpio.takedown(dev);
707out_mc:
708 engine->mc.takedown(dev);
709out_gart:
710 nouveau_mem_gart_fini(dev);
711out_ttmvram:
712 nouveau_mem_vram_fini(dev);
713out_instmem:
714 engine->instmem.takedown(dev);
715out_gpuobj:
716 nouveau_gpuobj_takedown(dev);
717out_vram:
718 engine->vram.takedown(dev);
719out_bios:
720 nouveau_pm_fini(dev);
721 nouveau_bios_takedown(dev);
722out_display_early:
723 engine->display.late_takedown(dev);
724out:
725 vga_client_register(dev->pdev, NULL, NULL, NULL);
726 return ret;
727}
728
729static void nouveau_card_takedown(struct drm_device *dev)
730{
731 struct drm_nouveau_private *dev_priv = dev->dev_private;
732 struct nouveau_engine *engine = &dev_priv->engine;
733 int e;
734
735 drm_kms_helper_poll_fini(dev);
736 nouveau_fbcon_fini(dev);
737
738 if (dev_priv->channel) {
739 nouveau_channel_put_unlocked(&dev_priv->channel);
740 nouveau_fence_fini(dev);
741 }
742
743 engine->display.destroy(dev);
744
745 if (!dev_priv->noaccel) {
746 engine->fifo.takedown(dev);
747 for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
748 if (dev_priv->eng[e]) {
749 dev_priv->eng[e]->fini(dev, e, false);
750 dev_priv->eng[e]->destroy(dev,e );
751 }
752 }
753 }
754 engine->fb.takedown(dev);
755 engine->timer.takedown(dev);
756 engine->gpio.takedown(dev);
757 engine->mc.takedown(dev);
758 engine->display.late_takedown(dev);
759
760 if (dev_priv->vga_ram) {
761 nouveau_bo_unpin(dev_priv->vga_ram);
762 nouveau_bo_ref(NULL, &dev_priv->vga_ram);
763 }
764
765 mutex_lock(&dev->struct_mutex);
766 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
767 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
768 mutex_unlock(&dev->struct_mutex);
769 nouveau_mem_gart_fini(dev);
770 nouveau_mem_vram_fini(dev);
771
772 engine->instmem.takedown(dev);
773 nouveau_gpuobj_takedown(dev);
774 engine->vram.takedown(dev);
775
776 nouveau_irq_fini(dev);
777 drm_vblank_cleanup(dev);
778
779 nouveau_pm_fini(dev);
780 nouveau_bios_takedown(dev);
781
782 vga_client_register(dev->pdev, NULL, NULL, NULL);
783}
784
785int
786nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
787{
788 struct drm_nouveau_private *dev_priv = dev->dev_private;
789 struct nouveau_fpriv *fpriv;
790 int ret;
791
792 fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
793 if (unlikely(!fpriv))
794 return -ENOMEM;
795
796 spin_lock_init(&fpriv->lock);
797 INIT_LIST_HEAD(&fpriv->channels);
798
799 if (dev_priv->card_type == NV_50) {
800 ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
801 &fpriv->vm);
802 if (ret) {
803 kfree(fpriv);
804 return ret;
805 }
806 } else
807 if (dev_priv->card_type >= NV_C0) {
808 ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
809 &fpriv->vm);
810 if (ret) {
811 kfree(fpriv);
812 return ret;
813 }
814 }
815
816 file_priv->driver_priv = fpriv;
817 return 0;
818}
819
820/* here a client dies, release the stuff that was allocated for its
821 * file_priv */
822void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
823{
824 nouveau_channel_cleanup(dev, file_priv);
825}
826
827void
828nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
829{
830 struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
831 nouveau_vm_ref(NULL, &fpriv->vm, NULL);
832 kfree(fpriv);
833}
834
835/* first module load, setup the mmio/fb mapping */
836/* KMS: we need mmio at load time, not when the first drm client opens. */
837int nouveau_firstopen(struct drm_device *dev)
838{
839 return 0;
840}
841
842/* if we have an OF card, copy vbios to RAMIN */
843static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev)
844{
845#if defined(__powerpc__)
846 int size, i;
847 const uint32_t *bios;
848 struct device_node *dn = pci_device_to_OF_node(dev->pdev);
849 if (!dn) {
850 NV_INFO(dev, "Unable to get the OF node\n");
851 return;
852 }
853
854 bios = of_get_property(dn, "NVDA,BMP", &size);
855 if (bios) {
856 for (i = 0; i < size; i += 4)
857 nv_wi32(dev, i, bios[i/4]);
858 NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size);
859 } else {
860 NV_INFO(dev, "Unable to get the OF bios\n");
861 }
862#endif
863}
864
865static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev)
866{
867 struct pci_dev *pdev = dev->pdev;
868 struct apertures_struct *aper = alloc_apertures(3);
869 if (!aper)
870 return NULL;
871
872 aper->ranges[0].base = pci_resource_start(pdev, 1);
873 aper->ranges[0].size = pci_resource_len(pdev, 1);
874 aper->count = 1;
875
876 if (pci_resource_len(pdev, 2)) {
877 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
878 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
879 aper->count++;
880 }
881
882 if (pci_resource_len(pdev, 3)) {
883 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
884 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
885 aper->count++;
886 }
887
888 return aper;
889}
890
891static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
892{
893 struct drm_nouveau_private *dev_priv = dev->dev_private;
894 bool primary = false;
895 dev_priv->apertures = nouveau_get_apertures(dev);
896 if (!dev_priv->apertures)
897 return -ENOMEM;
898
899#ifdef CONFIG_X86
900 primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
901#endif
902
903 remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary);
904 return 0;
905}
906
907int nouveau_load(struct drm_device *dev, unsigned long flags)
908{
909 struct drm_nouveau_private *dev_priv;
910 uint32_t reg0;
911 resource_size_t mmio_start_offs;
912 int ret;
913
914 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
915 if (!dev_priv) {
916 ret = -ENOMEM;
917 goto err_out;
918 }
919 dev->dev_private = dev_priv;
920 dev_priv->dev = dev;
921
922 dev_priv->flags = flags & NOUVEAU_FLAGS;
923
924 NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
925 dev->pci_vendor, dev->pci_device, dev->pdev->class);
926
927 /* resource 0 is mmio regs */
928 /* resource 1 is linear FB */
929 /* resource 2 is RAMIN (mmio regs + 0x1000000) */
930 /* resource 6 is bios */
931
932 /* map the mmio regs */
933 mmio_start_offs = pci_resource_start(dev->pdev, 0);
934 dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000);
935 if (!dev_priv->mmio) {
936 NV_ERROR(dev, "Unable to initialize the mmio mapping. "
937 "Please report your setup to " DRIVER_EMAIL "\n");
938 ret = -EINVAL;
939 goto err_priv;
940 }
941 NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
942 (unsigned long long)mmio_start_offs);
943
944#ifdef __BIG_ENDIAN
945 /* Put the card in BE mode if it's not */
946 if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001)
947 nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);
948
949 DRM_MEMORYBARRIER();
950#endif
951
952 /* Time to determine the card architecture */
953 reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
954 dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */
955
956 /* We're dealing with >=NV10 */
957 if ((reg0 & 0x0f000000) > 0) {
958 /* Bit 27-20 contain the architecture in hex */
959 dev_priv->chipset = (reg0 & 0xff00000) >> 20;
960 dev_priv->stepping = (reg0 & 0xff);
961 /* NV04 or NV05 */
962 } else if ((reg0 & 0xff00fff0) == 0x20004000) {
963 if (reg0 & 0x00f00000)
964 dev_priv->chipset = 0x05;
965 else
966 dev_priv->chipset = 0x04;
967 } else
968 dev_priv->chipset = 0xff;
969
970 switch (dev_priv->chipset & 0xf0) {
971 case 0x00:
972 case 0x10:
973 case 0x20:
974 case 0x30:
975 dev_priv->card_type = dev_priv->chipset & 0xf0;
976 break;
977 case 0x40:
978 case 0x60:
979 dev_priv->card_type = NV_40;
980 break;
981 case 0x50:
982 case 0x80:
983 case 0x90:
984 case 0xa0:
985 dev_priv->card_type = NV_50;
986 break;
987 case 0xc0:
988 dev_priv->card_type = NV_C0;
989 break;
990 default:
991 NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0);
992 ret = -EINVAL;
993 goto err_mmio;
994 }
995
996 NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
997 dev_priv->card_type, reg0);
998
999 /* Determine whether we'll attempt acceleration or not, some
1000 * cards are disabled by default here due to them being known
1001 * non-functional, or never been tested due to lack of hw.
1002 */
1003 dev_priv->noaccel = !!nouveau_noaccel;
1004 if (nouveau_noaccel == -1) {
1005 switch (dev_priv->chipset) {
1006 case 0xc1: /* known broken */
1007 case 0xc8: /* never tested */
1008 NV_INFO(dev, "acceleration disabled by default, pass "
1009 "noaccel=0 to force enable\n");
1010 dev_priv->noaccel = true;
1011 break;
1012 default:
1013 dev_priv->noaccel = false;
1014 break;
1015 }
1016 }
1017
1018 ret = nouveau_remove_conflicting_drivers(dev);
1019 if (ret)
1020 goto err_mmio;
1021
1022 /* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */
1023 if (dev_priv->card_type >= NV_40) {
1024 int ramin_bar = 2;
1025 if (pci_resource_len(dev->pdev, ramin_bar) == 0)
1026 ramin_bar = 3;
1027
1028 dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar);
1029 dev_priv->ramin =
1030 ioremap(pci_resource_start(dev->pdev, ramin_bar),
1031 dev_priv->ramin_size);
1032 if (!dev_priv->ramin) {
1033 NV_ERROR(dev, "Failed to PRAMIN BAR");
1034 ret = -ENOMEM;
1035 goto err_mmio;
1036 }
1037 } else {
1038 dev_priv->ramin_size = 1 * 1024 * 1024;
1039 dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN,
1040 dev_priv->ramin_size);
1041 if (!dev_priv->ramin) {
1042 NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n");
1043 ret = -ENOMEM;
1044 goto err_mmio;
1045 }
1046 }
1047
1048 nouveau_OF_copy_vbios_to_ramin(dev);
1049
1050 /* Special flags */
1051 if (dev->pci_device == 0x01a0)
1052 dev_priv->flags |= NV_NFORCE;
1053 else if (dev->pci_device == 0x01f0)
1054 dev_priv->flags |= NV_NFORCE2;
1055
1056 /* For kernel modesetting, init card now and bring up fbcon */
1057 ret = nouveau_card_init(dev);
1058 if (ret)
1059 goto err_ramin;
1060
1061 return 0;
1062
1063err_ramin:
1064 iounmap(dev_priv->ramin);
1065err_mmio:
1066 iounmap(dev_priv->mmio);
1067err_priv:
1068 kfree(dev_priv);
1069 dev->dev_private = NULL;
1070err_out:
1071 return ret;
1072}
1073
1074void nouveau_lastclose(struct drm_device *dev)
1075{
1076 vga_switcheroo_process_delayed_switch();
1077}
1078
1079int nouveau_unload(struct drm_device *dev)
1080{
1081 struct drm_nouveau_private *dev_priv = dev->dev_private;
1082
1083 nouveau_card_takedown(dev);
1084
1085 iounmap(dev_priv->mmio);
1086 iounmap(dev_priv->ramin);
1087
1088 kfree(dev_priv);
1089 dev->dev_private = NULL;
1090 return 0;
1091}
1092
1093int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
1094 struct drm_file *file_priv)
1095{
1096 struct drm_nouveau_private *dev_priv = dev->dev_private;
1097 struct drm_nouveau_getparam *getparam = data;
1098
1099 switch (getparam->param) {
1100 case NOUVEAU_GETPARAM_CHIPSET_ID:
1101 getparam->value = dev_priv->chipset;
1102 break;
1103 case NOUVEAU_GETPARAM_PCI_VENDOR:
1104 getparam->value = dev->pci_vendor;
1105 break;
1106 case NOUVEAU_GETPARAM_PCI_DEVICE:
1107 getparam->value = dev->pci_device;
1108 break;
1109 case NOUVEAU_GETPARAM_BUS_TYPE:
1110 if (drm_pci_device_is_agp(dev))
1111 getparam->value = NV_AGP;
1112 else if (pci_is_pcie(dev->pdev))
1113 getparam->value = NV_PCIE;
1114 else
1115 getparam->value = NV_PCI;
1116 break;
1117 case NOUVEAU_GETPARAM_FB_SIZE:
1118 getparam->value = dev_priv->fb_available_size;
1119 break;
1120 case NOUVEAU_GETPARAM_AGP_SIZE:
1121 getparam->value = dev_priv->gart_info.aper_size;
1122 break;
1123 case NOUVEAU_GETPARAM_VM_VRAM_BASE:
1124 getparam->value = 0; /* deprecated */
1125 break;
1126 case NOUVEAU_GETPARAM_PTIMER_TIME:
1127 getparam->value = dev_priv->engine.timer.read(dev);
1128 break;
1129 case NOUVEAU_GETPARAM_HAS_BO_USAGE:
1130 getparam->value = 1;
1131 break;
1132 case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
1133 getparam->value = 1;
1134 break;
1135 case NOUVEAU_GETPARAM_GRAPH_UNITS:
1136 /* NV40 and NV50 versions are quite different, but register
1137 * address is the same. User is supposed to know the card
1138 * family anyway... */
1139 if (dev_priv->chipset >= 0x40) {
1140 getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS);
1141 break;
1142 }
1143 /* FALLTHRU */
1144 default:
1145 NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param);
1146 return -EINVAL;
1147 }
1148
1149 return 0;
1150}
1151
1152int
1153nouveau_ioctl_setparam(struct drm_device *dev, void *data,
1154 struct drm_file *file_priv)
1155{
1156 struct drm_nouveau_setparam *setparam = data;
1157
1158 switch (setparam->param) {
1159 default:
1160 NV_DEBUG(dev, "unknown parameter %lld\n", setparam->param);
1161 return -EINVAL;
1162 }
1163
1164 return 0;
1165}
1166
1167/* Wait until (value(reg) & mask) == val, up until timeout has hit */
1168bool
1169nouveau_wait_eq(struct drm_device *dev, uint64_t timeout,
1170 uint32_t reg, uint32_t mask, uint32_t val)
1171{
1172 struct drm_nouveau_private *dev_priv = dev->dev_private;
1173 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
1174 uint64_t start = ptimer->read(dev);
1175
1176 do {
1177 if ((nv_rd32(dev, reg) & mask) == val)
1178 return true;
1179 } while (ptimer->read(dev) - start < timeout);
1180
1181 return false;
1182}
1183
1184/* Wait until (value(reg) & mask) != val, up until timeout has hit */
1185bool
1186nouveau_wait_ne(struct drm_device *dev, uint64_t timeout,
1187 uint32_t reg, uint32_t mask, uint32_t val)
1188{
1189 struct drm_nouveau_private *dev_priv = dev->dev_private;
1190 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
1191 uint64_t start = ptimer->read(dev);
1192
1193 do {
1194 if ((nv_rd32(dev, reg) & mask) != val)
1195 return true;
1196 } while (ptimer->read(dev) - start < timeout);
1197
1198 return false;
1199}
1200
1201/* Waits for PGRAPH to go completely idle */
1202bool nouveau_wait_for_idle(struct drm_device *dev)
1203{
1204 struct drm_nouveau_private *dev_priv = dev->dev_private;
1205 uint32_t mask = ~0;
1206
1207 if (dev_priv->card_type == NV_40)
1208 mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL;
1209
1210 if (!nv_wait(dev, NV04_PGRAPH_STATUS, mask, 0)) {
1211 NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n",
1212 nv_rd32(dev, NV04_PGRAPH_STATUS));
1213 return false;
1214 }
1215
1216 return true;
1217}
1218
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c
new file mode 100644
index 00000000000..081ca7b03e8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_temp.c
@@ -0,0 +1,314 @@
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
30static void
31nouveau_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 = 0;
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 case 0x67:
104 sensor->offset_mult = -26149;
105 sensor->offset_div = 100;
106 sensor->slope_mult = 484;
107 sensor->slope_div = 10000;
108 break;
109 }
110 }
111
112 headerlen = temp[1];
113 recordlen = temp[2];
114 entries = temp[3];
115 temp = temp + headerlen;
116
117 /* Read the entries from the table */
118 for (i = 0; i < entries; i++) {
119 s16 value = ROM16(temp[1]);
120
121 switch (temp[0]) {
122 case 0x01:
123 if ((value & 0x8f) == 0)
124 sensor->offset_constant = (value >> 9) & 0x7f;
125 break;
126
127 case 0x04:
128 if ((value & 0xf00f) == 0xa000) /* core */
129 temps->critical = (value&0x0ff0) >> 4;
130 break;
131
132 case 0x07:
133 if ((value & 0xf00f) == 0xa000) /* core */
134 temps->down_clock = (value&0x0ff0) >> 4;
135 break;
136
137 case 0x08:
138 if ((value & 0xf00f) == 0xa000) /* core */
139 temps->fan_boost = (value&0x0ff0) >> 4;
140 break;
141
142 case 0x10:
143 sensor->offset_mult = value;
144 break;
145
146 case 0x11:
147 sensor->offset_div = value;
148 break;
149
150 case 0x12:
151 sensor->slope_mult = value;
152 break;
153
154 case 0x13:
155 sensor->slope_div = value;
156 break;
157 }
158 temp += recordlen;
159 }
160
161 nouveau_temp_safety_checks(dev);
162}
163
164static int
165nv40_sensor_setup(struct drm_device *dev)
166{
167 struct drm_nouveau_private *dev_priv = dev->dev_private;
168 struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
169 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
170 s32 offset = sensor->offset_mult / sensor->offset_div;
171 s32 sensor_calibration;
172
173 /* set up the sensors */
174 sensor_calibration = 120 - offset - sensor->offset_constant;
175 sensor_calibration = sensor_calibration * sensor->slope_div /
176 sensor->slope_mult;
177
178 if (dev_priv->chipset >= 0x46)
179 sensor_calibration |= 0x80000000;
180 else
181 sensor_calibration |= 0x10000000;
182
183 nv_wr32(dev, 0x0015b0, sensor_calibration);
184
185 /* Wait for the sensor to update */
186 msleep(5);
187
188 /* read */
189 return nv_rd32(dev, 0x0015b4) & 0x1fff;
190}
191
192int
193nv40_temp_get(struct drm_device *dev)
194{
195 struct drm_nouveau_private *dev_priv = dev->dev_private;
196 struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
197 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
198 int offset = sensor->offset_mult / sensor->offset_div;
199 int core_temp;
200
201 if (dev_priv->card_type >= NV_50) {
202 core_temp = nv_rd32(dev, 0x20008);
203 } else {
204 core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff;
205 /* Setup the sensor if the temperature is 0 */
206 if (core_temp == 0)
207 core_temp = nv40_sensor_setup(dev);
208 }
209
210 core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
211 core_temp = core_temp + offset + sensor->offset_constant;
212
213 return core_temp;
214}
215
216int
217nv84_temp_get(struct drm_device *dev)
218{
219 return nv_rd32(dev, 0x20400);
220}
221
222void
223nouveau_temp_safety_checks(struct drm_device *dev)
224{
225 struct drm_nouveau_private *dev_priv = dev->dev_private;
226 struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
227 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
228
229 if (temps->critical > 120)
230 temps->critical = 120;
231 else if (temps->critical < 80)
232 temps->critical = 80;
233
234 if (temps->down_clock > 110)
235 temps->down_clock = 110;
236 else if (temps->down_clock < 60)
237 temps->down_clock = 60;
238
239 if (temps->fan_boost > 100)
240 temps->fan_boost = 100;
241 else if (temps->fan_boost < 40)
242 temps->fan_boost = 40;
243}
244
245static bool
246probe_monitoring_device(struct nouveau_i2c_chan *i2c,
247 struct i2c_board_info *info)
248{
249 struct i2c_client *client;
250
251 request_module("%s%s", I2C_MODULE_PREFIX, info->type);
252
253 client = i2c_new_device(&i2c->adapter, info);
254 if (!client)
255 return false;
256
257 if (!client->driver || client->driver->detect(client, info)) {
258 i2c_unregister_device(client);
259 return false;
260 }
261
262 return true;
263}
264
265static void
266nouveau_temp_probe_i2c(struct drm_device *dev)
267{
268 struct drm_nouveau_private *dev_priv = dev->dev_private;
269 struct dcb_table *dcb = &dev_priv->vbios.dcb;
270 struct i2c_board_info info[] = {
271 { I2C_BOARD_INFO("w83l785ts", 0x2d) },
272 { I2C_BOARD_INFO("w83781d", 0x2d) },
273 { I2C_BOARD_INFO("adt7473", 0x2e) },
274 { I2C_BOARD_INFO("f75375", 0x2e) },
275 { I2C_BOARD_INFO("lm99", 0x4c) },
276 { }
277 };
278 int idx = (dcb->version >= 0x40 ?
279 dcb->i2c_default_indices & 0xf : 2);
280
281 nouveau_i2c_identify(dev, "monitoring device", info,
282 probe_monitoring_device, idx);
283}
284
285void
286nouveau_temp_init(struct drm_device *dev)
287{
288 struct drm_nouveau_private *dev_priv = dev->dev_private;
289 struct nvbios *bios = &dev_priv->vbios;
290 struct bit_entry P;
291 u8 *temp = NULL;
292
293 if (bios->type == NVBIOS_BIT) {
294 if (bit_table(dev, 'P', &P))
295 return;
296
297 if (P.version == 1)
298 temp = ROMPTR(bios, P.data[12]);
299 else if (P.version == 2)
300 temp = ROMPTR(bios, P.data[16]);
301 else
302 NV_WARN(dev, "unknown temp for BIT P %d\n", P.version);
303
304 nouveau_temp_vbios_parse(dev, temp);
305 }
306
307 nouveau_temp_probe_i2c(dev);
308}
309
310void
311nouveau_temp_fini(struct drm_device *dev)
312{
313
314}
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c
new file mode 100644
index 00000000000..e51b51503ba
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_util.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (C) 2010 Nouveau Project
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#include <linux/ratelimit.h>
29
30#include "nouveau_util.h"
31
32static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
33
34void
35nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
36{
37 while (bf->name) {
38 if (value & bf->mask) {
39 printk(" %s", bf->name);
40 value &= ~bf->mask;
41 }
42
43 bf++;
44 }
45
46 if (value)
47 printk(" (unknown bits 0x%08x)", value);
48}
49
50const struct nouveau_enum *
51nouveau_enum_find(const struct nouveau_enum *en, u32 value)
52{
53 while (en->name) {
54 if (en->value == value)
55 return en;
56 en++;
57 }
58
59 return NULL;
60}
61
62void
63nouveau_enum_print(const struct nouveau_enum *en, u32 value)
64{
65 en = nouveau_enum_find(en, value);
66 if (en) {
67 printk("%s", en->name);
68 return;
69 }
70
71 printk("(unknown enum 0x%08x)", value);
72}
73
74int
75nouveau_ratelimit(void)
76{
77 return __ratelimit(&nouveau_ratelimit_state);
78}
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h
new file mode 100644
index 00000000000..b97719fbb73
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_util.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2010 Nouveau Project
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#ifndef __NOUVEAU_UTIL_H__
29#define __NOUVEAU_UTIL_H__
30
31struct nouveau_bitfield {
32 u32 mask;
33 const char *name;
34};
35
36struct nouveau_enum {
37 u32 value;
38 const char *name;
39 void *data;
40};
41
42void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value);
43void nouveau_enum_print(const struct nouveau_enum *, u32 value);
44const struct nouveau_enum *
45nouveau_enum_find(const struct nouveau_enum *, u32 value);
46
47int nouveau_ratelimit(void);
48
49#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
new file mode 100644
index 00000000000..244fd38fdb8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -0,0 +1,435 @@
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_mm.h"
28#include "nouveau_vm.h"
29
30void
31nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
32{
33 struct nouveau_vm *vm = vma->vm;
34 struct nouveau_mm_node *r;
35 int big = vma->node->type != vm->spg_shift;
36 u32 offset = vma->node->offset + (delta >> 12);
37 u32 bits = vma->node->type - 12;
38 u32 pde = (offset >> vm->pgt_bits) - vm->fpde;
39 u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
40 u32 max = 1 << (vm->pgt_bits - bits);
41 u32 end, len;
42
43 delta = 0;
44 list_for_each_entry(r, &node->regions, rl_entry) {
45 u64 phys = (u64)r->offset << 12;
46 u32 num = r->length >> bits;
47
48 while (num) {
49 struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
50
51 end = (pte + num);
52 if (unlikely(end >= max))
53 end = max;
54 len = end - pte;
55
56 vm->map(vma, pgt, node, pte, len, phys, delta);
57
58 num -= len;
59 pte += len;
60 if (unlikely(end >= max)) {
61 phys += len << (bits + 12);
62 pde++;
63 pte = 0;
64 }
65
66 delta += (u64)len << vma->node->type;
67 }
68 }
69
70 vm->flush(vm);
71}
72
73void
74nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
75{
76 nouveau_vm_map_at(vma, 0, node);
77}
78
79void
80nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
81 struct nouveau_mem *mem, dma_addr_t *list)
82{
83 struct nouveau_vm *vm = vma->vm;
84 int big = vma->node->type != vm->spg_shift;
85 u32 offset = vma->node->offset + (delta >> 12);
86 u32 bits = vma->node->type - 12;
87 u32 num = length >> vma->node->type;
88 u32 pde = (offset >> vm->pgt_bits) - vm->fpde;
89 u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
90 u32 max = 1 << (vm->pgt_bits - bits);
91 u32 end, len;
92
93 while (num) {
94 struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
95
96 end = (pte + num);
97 if (unlikely(end >= max))
98 end = max;
99 len = end - pte;
100
101 vm->map_sg(vma, pgt, mem, pte, len, list);
102
103 num -= len;
104 pte += len;
105 list += len;
106 if (unlikely(end >= max)) {
107 pde++;
108 pte = 0;
109 }
110 }
111
112 vm->flush(vm);
113}
114
115void
116nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
117{
118 struct nouveau_vm *vm = vma->vm;
119 int big = vma->node->type != vm->spg_shift;
120 u32 offset = vma->node->offset + (delta >> 12);
121 u32 bits = vma->node->type - 12;
122 u32 num = length >> vma->node->type;
123 u32 pde = (offset >> vm->pgt_bits) - vm->fpde;
124 u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
125 u32 max = 1 << (vm->pgt_bits - bits);
126 u32 end, len;
127
128 while (num) {
129 struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
130
131 end = (pte + num);
132 if (unlikely(end >= max))
133 end = max;
134 len = end - pte;
135
136 vm->unmap(pgt, pte, len);
137
138 num -= len;
139 pte += len;
140 if (unlikely(end >= max)) {
141 pde++;
142 pte = 0;
143 }
144 }
145
146 vm->flush(vm);
147}
148
149void
150nouveau_vm_unmap(struct nouveau_vma *vma)
151{
152 nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12);
153}
154
155static void
156nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde)
157{
158 struct nouveau_vm_pgd *vpgd;
159 struct nouveau_vm_pgt *vpgt;
160 struct nouveau_gpuobj *pgt;
161 u32 pde;
162
163 for (pde = fpde; pde <= lpde; pde++) {
164 vpgt = &vm->pgt[pde - vm->fpde];
165 if (--vpgt->refcount[big])
166 continue;
167
168 pgt = vpgt->obj[big];
169 vpgt->obj[big] = NULL;
170
171 list_for_each_entry(vpgd, &vm->pgd_list, head) {
172 vm->map_pgt(vpgd->obj, pde, vpgt->obj);
173 }
174
175 mutex_unlock(&vm->mm->mutex);
176 nouveau_gpuobj_ref(NULL, &pgt);
177 mutex_lock(&vm->mm->mutex);
178 }
179}
180
181static int
182nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type)
183{
184 struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
185 struct nouveau_vm_pgd *vpgd;
186 struct nouveau_gpuobj *pgt;
187 int big = (type != vm->spg_shift);
188 u32 pgt_size;
189 int ret;
190
191 pgt_size = (1 << (vm->pgt_bits + 12)) >> type;
192 pgt_size *= 8;
193
194 mutex_unlock(&vm->mm->mutex);
195 ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000,
196 NVOBJ_FLAG_ZERO_ALLOC, &pgt);
197 mutex_lock(&vm->mm->mutex);
198 if (unlikely(ret))
199 return ret;
200
201 /* someone beat us to filling the PDE while we didn't have the lock */
202 if (unlikely(vpgt->refcount[big]++)) {
203 mutex_unlock(&vm->mm->mutex);
204 nouveau_gpuobj_ref(NULL, &pgt);
205 mutex_lock(&vm->mm->mutex);
206 return 0;
207 }
208
209 vpgt->obj[big] = pgt;
210 list_for_each_entry(vpgd, &vm->pgd_list, head) {
211 vm->map_pgt(vpgd->obj, pde, vpgt->obj);
212 }
213
214 return 0;
215}
216
217int
218nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
219 u32 access, struct nouveau_vma *vma)
220{
221 u32 align = (1 << page_shift) >> 12;
222 u32 msize = size >> 12;
223 u32 fpde, lpde, pde;
224 int ret;
225
226 mutex_lock(&vm->mm->mutex);
227 ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node);
228 if (unlikely(ret != 0)) {
229 mutex_unlock(&vm->mm->mutex);
230 return ret;
231 }
232
233 fpde = (vma->node->offset >> vm->pgt_bits);
234 lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
235 for (pde = fpde; pde <= lpde; pde++) {
236 struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde];
237 int big = (vma->node->type != vm->spg_shift);
238
239 if (likely(vpgt->refcount[big])) {
240 vpgt->refcount[big]++;
241 continue;
242 }
243
244 ret = nouveau_vm_map_pgt(vm, pde, vma->node->type);
245 if (ret) {
246 if (pde != fpde)
247 nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1);
248 nouveau_mm_put(vm->mm, vma->node);
249 mutex_unlock(&vm->mm->mutex);
250 vma->node = NULL;
251 return ret;
252 }
253 }
254 mutex_unlock(&vm->mm->mutex);
255
256 vma->vm = vm;
257 vma->offset = (u64)vma->node->offset << 12;
258 vma->access = access;
259 return 0;
260}
261
262void
263nouveau_vm_put(struct nouveau_vma *vma)
264{
265 struct nouveau_vm *vm = vma->vm;
266 u32 fpde, lpde;
267
268 if (unlikely(vma->node == NULL))
269 return;
270 fpde = (vma->node->offset >> vm->pgt_bits);
271 lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;
272
273 mutex_lock(&vm->mm->mutex);
274 nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde);
275 nouveau_mm_put(vm->mm, vma->node);
276 vma->node = NULL;
277 mutex_unlock(&vm->mm->mutex);
278}
279
280int
281nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
282 struct nouveau_vm **pvm)
283{
284 struct drm_nouveau_private *dev_priv = dev->dev_private;
285 struct nouveau_vm *vm;
286 u64 mm_length = (offset + length) - mm_offset;
287 u32 block, pgt_bits;
288 int ret;
289
290 vm = kzalloc(sizeof(*vm), GFP_KERNEL);
291 if (!vm)
292 return -ENOMEM;
293
294 if (dev_priv->card_type == NV_50) {
295 vm->map_pgt = nv50_vm_map_pgt;
296 vm->map = nv50_vm_map;
297 vm->map_sg = nv50_vm_map_sg;
298 vm->unmap = nv50_vm_unmap;
299 vm->flush = nv50_vm_flush;
300 vm->spg_shift = 12;
301 vm->lpg_shift = 16;
302
303 pgt_bits = 29;
304 block = (1 << pgt_bits);
305 if (length < block)
306 block = length;
307
308 } else
309 if (dev_priv->card_type == NV_C0) {
310 vm->map_pgt = nvc0_vm_map_pgt;
311 vm->map = nvc0_vm_map;
312 vm->map_sg = nvc0_vm_map_sg;
313 vm->unmap = nvc0_vm_unmap;
314 vm->flush = nvc0_vm_flush;
315 vm->spg_shift = 12;
316 vm->lpg_shift = 17;
317 pgt_bits = 27;
318 block = 4096;
319 } else {
320 kfree(vm);
321 return -ENOSYS;
322 }
323
324 vm->fpde = offset >> pgt_bits;
325 vm->lpde = (offset + length - 1) >> pgt_bits;
326 vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL);
327 if (!vm->pgt) {
328 kfree(vm);
329 return -ENOMEM;
330 }
331
332 INIT_LIST_HEAD(&vm->pgd_list);
333 vm->dev = dev;
334 vm->refcount = 1;
335 vm->pgt_bits = pgt_bits - 12;
336
337 ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12,
338 block >> 12);
339 if (ret) {
340 kfree(vm);
341 return ret;
342 }
343
344 *pvm = vm;
345 return 0;
346}
347
348static int
349nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
350{
351 struct nouveau_vm_pgd *vpgd;
352 int i;
353
354 if (!pgd)
355 return 0;
356
357 vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL);
358 if (!vpgd)
359 return -ENOMEM;
360
361 nouveau_gpuobj_ref(pgd, &vpgd->obj);
362
363 mutex_lock(&vm->mm->mutex);
364 for (i = vm->fpde; i <= vm->lpde; i++)
365 vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
366 list_add(&vpgd->head, &vm->pgd_list);
367 mutex_unlock(&vm->mm->mutex);
368 return 0;
369}
370
371static void
372nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
373{
374 struct nouveau_vm_pgd *vpgd, *tmp;
375 struct nouveau_gpuobj *pgd = NULL;
376
377 if (!mpgd)
378 return;
379
380 mutex_lock(&vm->mm->mutex);
381 list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
382 if (vpgd->obj == mpgd) {
383 pgd = vpgd->obj;
384 list_del(&vpgd->head);
385 kfree(vpgd);
386 break;
387 }
388 }
389 mutex_unlock(&vm->mm->mutex);
390
391 nouveau_gpuobj_ref(NULL, &pgd);
392}
393
394static void
395nouveau_vm_del(struct nouveau_vm *vm)
396{
397 struct nouveau_vm_pgd *vpgd, *tmp;
398
399 list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
400 nouveau_vm_unlink(vm, vpgd->obj);
401 }
402
403 nouveau_mm_fini(&vm->mm);
404 kfree(vm->pgt);
405 kfree(vm);
406}
407
408int
409nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr,
410 struct nouveau_gpuobj *pgd)
411{
412 struct nouveau_vm *vm;
413 int ret;
414
415 vm = ref;
416 if (vm) {
417 ret = nouveau_vm_link(vm, pgd);
418 if (ret)
419 return ret;
420
421 vm->refcount++;
422 }
423
424 vm = *ptr;
425 *ptr = ref;
426
427 if (vm) {
428 nouveau_vm_unlink(vm, pgd);
429
430 if (--vm->refcount == 0)
431 nouveau_vm_del(vm);
432 }
433
434 return 0;
435}
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
new file mode 100644
index 00000000000..579ca8cc223
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -0,0 +1,115 @@
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_VM_H__
26#define __NOUVEAU_VM_H__
27
28#include "drmP.h"
29
30#include "nouveau_drv.h"
31#include "nouveau_mm.h"
32
33struct nouveau_vm_pgt {
34 struct nouveau_gpuobj *obj[2];
35 u32 refcount[2];
36};
37
38struct nouveau_vm_pgd {
39 struct list_head head;
40 struct nouveau_gpuobj *obj;
41};
42
43struct nouveau_vma {
44 struct list_head head;
45 int refcount;
46 struct nouveau_vm *vm;
47 struct nouveau_mm_node *node;
48 u64 offset;
49 u32 access;
50};
51
52struct nouveau_vm {
53 struct drm_device *dev;
54 struct nouveau_mm *mm;
55 int refcount;
56
57 struct list_head pgd_list;
58 atomic_t engref[16];
59
60 struct nouveau_vm_pgt *pgt;
61 u32 fpde;
62 u32 lpde;
63
64 u32 pgt_bits;
65 u8 spg_shift;
66 u8 lpg_shift;
67
68 void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde,
69 struct nouveau_gpuobj *pgt[2]);
70 void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *,
71 struct nouveau_mem *, u32 pte, u32 cnt,
72 u64 phys, u64 delta);
73 void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
74 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
75 void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt);
76 void (*flush)(struct nouveau_vm *);
77};
78
79/* nouveau_vm.c */
80int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset,
81 struct nouveau_vm **);
82int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **,
83 struct nouveau_gpuobj *pgd);
84int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift,
85 u32 access, struct nouveau_vma *);
86void nouveau_vm_put(struct nouveau_vma *);
87void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);
88void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);
89void nouveau_vm_unmap(struct nouveau_vma *);
90void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
91void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
92 struct nouveau_mem *, dma_addr_t *);
93
94/* nv50_vm.c */
95void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
96 struct nouveau_gpuobj *pgt[2]);
97void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
98 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
99void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
100 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
101void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
102void nv50_vm_flush(struct nouveau_vm *);
103void nv50_vm_flush_engine(struct drm_device *, int engine);
104
105/* nvc0_vm.c */
106void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
107 struct nouveau_gpuobj *pgt[2]);
108void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
109 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
110void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
111 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
112void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
113void nvc0_vm_flush(struct nouveau_vm *);
114
115#endif
diff --git a/drivers/gpu/drm/nouveau/nv04_fb.c b/drivers/gpu/drm/nouveau/nv04_fb.c
new file mode 100644
index 00000000000..638cf601c42
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv04_fb.c
@@ -0,0 +1,21 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6int
7nv04_fb_init(struct drm_device *dev)
8{
9 /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows
10 * nvidia reading PFB_CFG_0, then writing back its original value.
11 * (which was 0x701114 in this case)
12 */
13
14 nv_wr32(dev, NV04_PFB_CFG0, 0x1114);
15 return 0;
16}
17
18void
19nv04_fb_takedown(struct drm_device *dev)
20{
21}
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
new file mode 100644
index 00000000000..db465a3ee1b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
@@ -0,0 +1,543 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30#include "nouveau_ramht.h"
31#include "nouveau_util.h"
32
33#define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE))
34#define NV04_RAMFC__SIZE 32
35#define NV04_RAMFC_DMA_PUT 0x00
36#define NV04_RAMFC_DMA_GET 0x04
37#define NV04_RAMFC_DMA_INSTANCE 0x08
38#define NV04_RAMFC_DMA_STATE 0x0C
39#define NV04_RAMFC_DMA_FETCH 0x10
40#define NV04_RAMFC_ENGINE 0x14
41#define NV04_RAMFC_PULL1_ENGINE 0x18
42
43#define RAMFC_WR(offset, val) nv_wo32(chan->ramfc, NV04_RAMFC_##offset, (val))
44#define RAMFC_RD(offset) nv_ro32(chan->ramfc, NV04_RAMFC_##offset)
45
46void
47nv04_fifo_disable(struct drm_device *dev)
48{
49 uint32_t tmp;
50
51 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH);
52 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, tmp & ~1);
53 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0);
54 tmp = nv_rd32(dev, NV03_PFIFO_CACHE1_PULL1);
55 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, tmp & ~1);
56}
57
58void
59nv04_fifo_enable(struct drm_device *dev)
60{
61 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1);
62 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
63}
64
65bool
66nv04_fifo_reassign(struct drm_device *dev, bool enable)
67{
68 uint32_t reassign = nv_rd32(dev, NV03_PFIFO_CACHES);
69
70 nv_wr32(dev, NV03_PFIFO_CACHES, enable ? 1 : 0);
71 return (reassign == 1);
72}
73
74bool
75nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
76{
77 int pull = nv_mask(dev, NV04_PFIFO_CACHE1_PULL0, 1, enable);
78
79 if (!enable) {
80 /* In some cases the PFIFO puller may be left in an
81 * inconsistent state if you try to stop it when it's
82 * busy translating handles. Sometimes you get a
83 * PFIFO_CACHE_ERROR, sometimes it just fails silently
84 * sending incorrect instance offsets to PGRAPH after
85 * it's started up again. To avoid the latter we
86 * invalidate the most recently calculated instance.
87 */
88 if (!nv_wait(dev, NV04_PFIFO_CACHE1_PULL0,
89 NV04_PFIFO_CACHE1_PULL0_HASH_BUSY, 0))
90 NV_ERROR(dev, "Timeout idling the PFIFO puller.\n");
91
92 if (nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0) &
93 NV04_PFIFO_CACHE1_PULL0_HASH_FAILED)
94 nv_wr32(dev, NV03_PFIFO_INTR_0,
95 NV_PFIFO_INTR_CACHE_ERROR);
96
97 nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
98 }
99
100 return pull & 1;
101}
102
103int
104nv04_fifo_channel_id(struct drm_device *dev)
105{
106 return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) &
107 NV03_PFIFO_CACHE1_PUSH1_CHID_MASK;
108}
109
110#ifdef __BIG_ENDIAN
111#define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN
112#else
113#define DMA_FETCH_ENDIANNESS 0
114#endif
115
116int
117nv04_fifo_create_context(struct nouveau_channel *chan)
118{
119 struct drm_device *dev = chan->dev;
120 struct drm_nouveau_private *dev_priv = dev->dev_private;
121 unsigned long flags;
122 int ret;
123
124 ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0,
125 NV04_RAMFC__SIZE,
126 NVOBJ_FLAG_ZERO_ALLOC |
127 NVOBJ_FLAG_ZERO_FREE,
128 &chan->ramfc);
129 if (ret)
130 return ret;
131
132 chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
133 NV03_USER(chan->id), PAGE_SIZE);
134 if (!chan->user)
135 return -ENOMEM;
136
137 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
138
139 /* Setup initial state */
140 RAMFC_WR(DMA_PUT, chan->pushbuf_base);
141 RAMFC_WR(DMA_GET, chan->pushbuf_base);
142 RAMFC_WR(DMA_INSTANCE, chan->pushbuf->pinst >> 4);
143 RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
144 NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
145 NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
146 DMA_FETCH_ENDIANNESS));
147
148 /* enable the fifo dma operation */
149 nv_wr32(dev, NV04_PFIFO_MODE,
150 nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
151
152 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
153 return 0;
154}
155
156void
157nv04_fifo_destroy_context(struct nouveau_channel *chan)
158{
159 struct drm_device *dev = chan->dev;
160 struct drm_nouveau_private *dev_priv = dev->dev_private;
161 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
162 unsigned long flags;
163
164 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
165 pfifo->reassign(dev, false);
166
167 /* Unload the context if it's the currently active one */
168 if (pfifo->channel_id(dev) == chan->id) {
169 pfifo->disable(dev);
170 pfifo->unload_context(dev);
171 pfifo->enable(dev);
172 }
173
174 /* Keep it from being rescheduled */
175 nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0);
176
177 pfifo->reassign(dev, true);
178 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
179
180 /* Free the channel resources */
181 if (chan->user) {
182 iounmap(chan->user);
183 chan->user = NULL;
184 }
185 nouveau_gpuobj_ref(NULL, &chan->ramfc);
186}
187
188static void
189nv04_fifo_do_load_context(struct drm_device *dev, int chid)
190{
191 struct drm_nouveau_private *dev_priv = dev->dev_private;
192 uint32_t fc = NV04_RAMFC(chid), tmp;
193
194 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
195 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
196 tmp = nv_ri32(dev, fc + 8);
197 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
198 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
199 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 12));
200 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 16));
201 nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
202 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
203
204 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
205 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
206}
207
208int
209nv04_fifo_load_context(struct nouveau_channel *chan)
210{
211 uint32_t tmp;
212
213 nv_wr32(chan->dev, NV03_PFIFO_CACHE1_PUSH1,
214 NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
215 nv04_fifo_do_load_context(chan->dev, chan->id);
216 nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
217
218 /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
219 tmp = nv_rd32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
220 nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
221
222 return 0;
223}
224
225int
226nv04_fifo_unload_context(struct drm_device *dev)
227{
228 struct drm_nouveau_private *dev_priv = dev->dev_private;
229 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
230 struct nouveau_channel *chan = NULL;
231 uint32_t tmp;
232 int chid;
233
234 chid = pfifo->channel_id(dev);
235 if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
236 return 0;
237
238 chan = dev_priv->channels.ptr[chid];
239 if (!chan) {
240 NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
241 return -EINVAL;
242 }
243
244 RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
245 RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
246 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
247 tmp |= nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE);
248 RAMFC_WR(DMA_INSTANCE, tmp);
249 RAMFC_WR(DMA_STATE, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
250 RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
251 RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
252 RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
253
254 nv04_fifo_do_load_context(dev, pfifo->channels - 1);
255 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
256 return 0;
257}
258
259static void
260nv04_fifo_init_reset(struct drm_device *dev)
261{
262 nv_wr32(dev, NV03_PMC_ENABLE,
263 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
264 nv_wr32(dev, NV03_PMC_ENABLE,
265 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO);
266
267 nv_wr32(dev, 0x003224, 0x000f0078);
268 nv_wr32(dev, 0x002044, 0x0101ffff);
269 nv_wr32(dev, 0x002040, 0x000000ff);
270 nv_wr32(dev, 0x002500, 0x00000000);
271 nv_wr32(dev, 0x003000, 0x00000000);
272 nv_wr32(dev, 0x003050, 0x00000000);
273 nv_wr32(dev, 0x003200, 0x00000000);
274 nv_wr32(dev, 0x003250, 0x00000000);
275 nv_wr32(dev, 0x003220, 0x00000000);
276
277 nv_wr32(dev, 0x003250, 0x00000000);
278 nv_wr32(dev, 0x003270, 0x00000000);
279 nv_wr32(dev, 0x003210, 0x00000000);
280}
281
282static void
283nv04_fifo_init_ramxx(struct drm_device *dev)
284{
285 struct drm_nouveau_private *dev_priv = dev->dev_private;
286
287 nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
288 ((dev_priv->ramht->bits - 9) << 16) |
289 (dev_priv->ramht->gpuobj->pinst >> 8));
290 nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8);
291 nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8);
292}
293
294static void
295nv04_fifo_init_intr(struct drm_device *dev)
296{
297 nouveau_irq_register(dev, 8, nv04_fifo_isr);
298 nv_wr32(dev, 0x002100, 0xffffffff);
299 nv_wr32(dev, 0x002140, 0xffffffff);
300}
301
302int
303nv04_fifo_init(struct drm_device *dev)
304{
305 struct drm_nouveau_private *dev_priv = dev->dev_private;
306 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
307 int i;
308
309 nv04_fifo_init_reset(dev);
310 nv04_fifo_init_ramxx(dev);
311
312 nv04_fifo_do_load_context(dev, pfifo->channels - 1);
313 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
314
315 nv04_fifo_init_intr(dev);
316 pfifo->enable(dev);
317 pfifo->reassign(dev, true);
318
319 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
320 if (dev_priv->channels.ptr[i]) {
321 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
322 nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
323 }
324 }
325
326 return 0;
327}
328
329void
330nv04_fifo_fini(struct drm_device *dev)
331{
332 nv_wr32(dev, 0x2140, 0x00000000);
333 nouveau_irq_unregister(dev, 8);
334}
335
336static bool
337nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
338{
339 struct drm_nouveau_private *dev_priv = dev->dev_private;
340 struct nouveau_channel *chan = NULL;
341 struct nouveau_gpuobj *obj;
342 unsigned long flags;
343 const int subc = (addr >> 13) & 0x7;
344 const int mthd = addr & 0x1ffc;
345 bool handled = false;
346 u32 engine;
347
348 spin_lock_irqsave(&dev_priv->channels.lock, flags);
349 if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels))
350 chan = dev_priv->channels.ptr[chid];
351 if (unlikely(!chan))
352 goto out;
353
354 switch (mthd) {
355 case 0x0000: /* bind object to subchannel */
356 obj = nouveau_ramht_find(chan, data);
357 if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW))
358 break;
359
360 chan->sw_subchannel[subc] = obj->class;
361 engine = 0x0000000f << (subc * 4);
362
363 nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000);
364 handled = true;
365 break;
366 default:
367 engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE);
368 if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
369 break;
370
371 if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc],
372 mthd, data))
373 handled = true;
374 break;
375 }
376
377out:
378 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
379 return handled;
380}
381
382static const char *nv_dma_state_err(u32 state)
383{
384 static const char * const desc[] = {
385 "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE",
386 "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK"
387 };
388 return desc[(state >> 29) & 0x7];
389}
390
391void
392nv04_fifo_isr(struct drm_device *dev)
393{
394 struct drm_nouveau_private *dev_priv = dev->dev_private;
395 struct nouveau_engine *engine = &dev_priv->engine;
396 uint32_t status, reassign;
397 int cnt = 0;
398
399 reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
400 while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
401 uint32_t chid, get;
402
403 nv_wr32(dev, NV03_PFIFO_CACHES, 0);
404
405 chid = engine->fifo.channel_id(dev);
406 get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
407
408 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
409 uint32_t mthd, data;
410 int ptr;
411
412 /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
413 * wrapping on my G80 chips, but CACHE1 isn't big
414 * enough for this much data.. Tests show that it
415 * wraps around to the start at GET=0x800.. No clue
416 * as to why..
417 */
418 ptr = (get & 0x7ff) >> 2;
419
420 if (dev_priv->card_type < NV_40) {
421 mthd = nv_rd32(dev,
422 NV04_PFIFO_CACHE1_METHOD(ptr));
423 data = nv_rd32(dev,
424 NV04_PFIFO_CACHE1_DATA(ptr));
425 } else {
426 mthd = nv_rd32(dev,
427 NV40_PFIFO_CACHE1_METHOD(ptr));
428 data = nv_rd32(dev,
429 NV40_PFIFO_CACHE1_DATA(ptr));
430 }
431
432 if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) {
433 NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
434 "Mthd 0x%04x Data 0x%08x\n",
435 chid, (mthd >> 13) & 7, mthd & 0x1ffc,
436 data);
437 }
438
439 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
440 nv_wr32(dev, NV03_PFIFO_INTR_0,
441 NV_PFIFO_INTR_CACHE_ERROR);
442
443 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
444 nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1);
445 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
446 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
447 nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1);
448 nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
449
450 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH,
451 nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
452 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
453
454 status &= ~NV_PFIFO_INTR_CACHE_ERROR;
455 }
456
457 if (status & NV_PFIFO_INTR_DMA_PUSHER) {
458 u32 dma_get = nv_rd32(dev, 0x003244);
459 u32 dma_put = nv_rd32(dev, 0x003240);
460 u32 push = nv_rd32(dev, 0x003220);
461 u32 state = nv_rd32(dev, 0x003228);
462
463 if (dev_priv->card_type == NV_50) {
464 u32 ho_get = nv_rd32(dev, 0x003328);
465 u32 ho_put = nv_rd32(dev, 0x003320);
466 u32 ib_get = nv_rd32(dev, 0x003334);
467 u32 ib_put = nv_rd32(dev, 0x003330);
468
469 if (nouveau_ratelimit())
470 NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
471 "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
472 "State 0x%08x (err: %s) Push 0x%08x\n",
473 chid, ho_get, dma_get, ho_put,
474 dma_put, ib_get, ib_put, state,
475 nv_dma_state_err(state),
476 push);
477
478 /* METHOD_COUNT, in DMA_STATE on earlier chipsets */
479 nv_wr32(dev, 0x003364, 0x00000000);
480 if (dma_get != dma_put || ho_get != ho_put) {
481 nv_wr32(dev, 0x003244, dma_put);
482 nv_wr32(dev, 0x003328, ho_put);
483 } else
484 if (ib_get != ib_put) {
485 nv_wr32(dev, 0x003334, ib_put);
486 }
487 } else {
488 NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
489 "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
490 chid, dma_get, dma_put, state,
491 nv_dma_state_err(state), push);
492
493 if (dma_get != dma_put)
494 nv_wr32(dev, 0x003244, dma_put);
495 }
496
497 nv_wr32(dev, 0x003228, 0x00000000);
498 nv_wr32(dev, 0x003220, 0x00000001);
499 nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
500 status &= ~NV_PFIFO_INTR_DMA_PUSHER;
501 }
502
503 if (status & NV_PFIFO_INTR_SEMAPHORE) {
504 uint32_t sem;
505
506 status &= ~NV_PFIFO_INTR_SEMAPHORE;
507 nv_wr32(dev, NV03_PFIFO_INTR_0,
508 NV_PFIFO_INTR_SEMAPHORE);
509
510 sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
511 nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
512
513 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
514 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
515 }
516
517 if (dev_priv->card_type == NV_50) {
518 if (status & 0x00000010) {
519 nv50_fb_vm_trap(dev, nouveau_ratelimit());
520 status &= ~0x00000010;
521 nv_wr32(dev, 0x002100, 0x00000010);
522 }
523 }
524
525 if (status) {
526 if (nouveau_ratelimit())
527 NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
528 status, chid);
529 nv_wr32(dev, NV03_PFIFO_INTR_0, status);
530 status = 0;
531 }
532
533 nv_wr32(dev, NV03_PFIFO_CACHES, reassign);
534 }
535
536 if (status) {
537 NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt);
538 nv_wr32(dev, 0x2140, 0);
539 nv_wr32(dev, 0x140, 0);
540 }
541
542 nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
543}
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c
new file mode 100644
index 00000000000..dbdea8ed392
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv04_graph.c
@@ -0,0 +1,1353 @@
1/*
2 * Copyright 2007 Stephane Marchesin
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include "drmP.h"
26#include "drm.h"
27#include "nouveau_drm.h"
28#include "nouveau_drv.h"
29#include "nouveau_hw.h"
30#include "nouveau_util.h"
31#include "nouveau_ramht.h"
32
33struct nv04_graph_engine {
34 struct nouveau_exec_engine base;
35};
36
37static uint32_t nv04_graph_ctx_regs[] = {
38 0x0040053c,
39 0x00400544,
40 0x00400540,
41 0x00400548,
42 NV04_PGRAPH_CTX_SWITCH1,
43 NV04_PGRAPH_CTX_SWITCH2,
44 NV04_PGRAPH_CTX_SWITCH3,
45 NV04_PGRAPH_CTX_SWITCH4,
46 NV04_PGRAPH_CTX_CACHE1,
47 NV04_PGRAPH_CTX_CACHE2,
48 NV04_PGRAPH_CTX_CACHE3,
49 NV04_PGRAPH_CTX_CACHE4,
50 0x00400184,
51 0x004001a4,
52 0x004001c4,
53 0x004001e4,
54 0x00400188,
55 0x004001a8,
56 0x004001c8,
57 0x004001e8,
58 0x0040018c,
59 0x004001ac,
60 0x004001cc,
61 0x004001ec,
62 0x00400190,
63 0x004001b0,
64 0x004001d0,
65 0x004001f0,
66 0x00400194,
67 0x004001b4,
68 0x004001d4,
69 0x004001f4,
70 0x00400198,
71 0x004001b8,
72 0x004001d8,
73 0x004001f8,
74 0x0040019c,
75 0x004001bc,
76 0x004001dc,
77 0x004001fc,
78 0x00400174,
79 NV04_PGRAPH_DMA_START_0,
80 NV04_PGRAPH_DMA_START_1,
81 NV04_PGRAPH_DMA_LENGTH,
82 NV04_PGRAPH_DMA_MISC,
83 NV04_PGRAPH_DMA_PITCH,
84 NV04_PGRAPH_BOFFSET0,
85 NV04_PGRAPH_BBASE0,
86 NV04_PGRAPH_BLIMIT0,
87 NV04_PGRAPH_BOFFSET1,
88 NV04_PGRAPH_BBASE1,
89 NV04_PGRAPH_BLIMIT1,
90 NV04_PGRAPH_BOFFSET2,
91 NV04_PGRAPH_BBASE2,
92 NV04_PGRAPH_BLIMIT2,
93 NV04_PGRAPH_BOFFSET3,
94 NV04_PGRAPH_BBASE3,
95 NV04_PGRAPH_BLIMIT3,
96 NV04_PGRAPH_BOFFSET4,
97 NV04_PGRAPH_BBASE4,
98 NV04_PGRAPH_BLIMIT4,
99 NV04_PGRAPH_BOFFSET5,
100 NV04_PGRAPH_BBASE5,
101 NV04_PGRAPH_BLIMIT5,
102 NV04_PGRAPH_BPITCH0,
103 NV04_PGRAPH_BPITCH1,
104 NV04_PGRAPH_BPITCH2,
105 NV04_PGRAPH_BPITCH3,
106 NV04_PGRAPH_BPITCH4,
107 NV04_PGRAPH_SURFACE,
108 NV04_PGRAPH_STATE,
109 NV04_PGRAPH_BSWIZZLE2,
110 NV04_PGRAPH_BSWIZZLE5,
111 NV04_PGRAPH_BPIXEL,
112 NV04_PGRAPH_NOTIFY,
113 NV04_PGRAPH_PATT_COLOR0,
114 NV04_PGRAPH_PATT_COLOR1,
115 NV04_PGRAPH_PATT_COLORRAM+0x00,
116 NV04_PGRAPH_PATT_COLORRAM+0x04,
117 NV04_PGRAPH_PATT_COLORRAM+0x08,
118 NV04_PGRAPH_PATT_COLORRAM+0x0c,
119 NV04_PGRAPH_PATT_COLORRAM+0x10,
120 NV04_PGRAPH_PATT_COLORRAM+0x14,
121 NV04_PGRAPH_PATT_COLORRAM+0x18,
122 NV04_PGRAPH_PATT_COLORRAM+0x1c,
123 NV04_PGRAPH_PATT_COLORRAM+0x20,
124 NV04_PGRAPH_PATT_COLORRAM+0x24,
125 NV04_PGRAPH_PATT_COLORRAM+0x28,
126 NV04_PGRAPH_PATT_COLORRAM+0x2c,
127 NV04_PGRAPH_PATT_COLORRAM+0x30,
128 NV04_PGRAPH_PATT_COLORRAM+0x34,
129 NV04_PGRAPH_PATT_COLORRAM+0x38,
130 NV04_PGRAPH_PATT_COLORRAM+0x3c,
131 NV04_PGRAPH_PATT_COLORRAM+0x40,
132 NV04_PGRAPH_PATT_COLORRAM+0x44,
133 NV04_PGRAPH_PATT_COLORRAM+0x48,
134 NV04_PGRAPH_PATT_COLORRAM+0x4c,
135 NV04_PGRAPH_PATT_COLORRAM+0x50,
136 NV04_PGRAPH_PATT_COLORRAM+0x54,
137 NV04_PGRAPH_PATT_COLORRAM+0x58,
138 NV04_PGRAPH_PATT_COLORRAM+0x5c,
139 NV04_PGRAPH_PATT_COLORRAM+0x60,
140 NV04_PGRAPH_PATT_COLORRAM+0x64,
141 NV04_PGRAPH_PATT_COLORRAM+0x68,
142 NV04_PGRAPH_PATT_COLORRAM+0x6c,
143 NV04_PGRAPH_PATT_COLORRAM+0x70,
144 NV04_PGRAPH_PATT_COLORRAM+0x74,
145 NV04_PGRAPH_PATT_COLORRAM+0x78,
146 NV04_PGRAPH_PATT_COLORRAM+0x7c,
147 NV04_PGRAPH_PATT_COLORRAM+0x80,
148 NV04_PGRAPH_PATT_COLORRAM+0x84,
149 NV04_PGRAPH_PATT_COLORRAM+0x88,
150 NV04_PGRAPH_PATT_COLORRAM+0x8c,
151 NV04_PGRAPH_PATT_COLORRAM+0x90,
152 NV04_PGRAPH_PATT_COLORRAM+0x94,
153 NV04_PGRAPH_PATT_COLORRAM+0x98,
154 NV04_PGRAPH_PATT_COLORRAM+0x9c,
155 NV04_PGRAPH_PATT_COLORRAM+0xa0,
156 NV04_PGRAPH_PATT_COLORRAM+0xa4,
157 NV04_PGRAPH_PATT_COLORRAM+0xa8,
158 NV04_PGRAPH_PATT_COLORRAM+0xac,
159 NV04_PGRAPH_PATT_COLORRAM+0xb0,
160 NV04_PGRAPH_PATT_COLORRAM+0xb4,
161 NV04_PGRAPH_PATT_COLORRAM+0xb8,
162 NV04_PGRAPH_PATT_COLORRAM+0xbc,
163 NV04_PGRAPH_PATT_COLORRAM+0xc0,
164 NV04_PGRAPH_PATT_COLORRAM+0xc4,
165 NV04_PGRAPH_PATT_COLORRAM+0xc8,
166 NV04_PGRAPH_PATT_COLORRAM+0xcc,
167 NV04_PGRAPH_PATT_COLORRAM+0xd0,
168 NV04_PGRAPH_PATT_COLORRAM+0xd4,
169 NV04_PGRAPH_PATT_COLORRAM+0xd8,
170 NV04_PGRAPH_PATT_COLORRAM+0xdc,
171 NV04_PGRAPH_PATT_COLORRAM+0xe0,
172 NV04_PGRAPH_PATT_COLORRAM+0xe4,
173 NV04_PGRAPH_PATT_COLORRAM+0xe8,
174 NV04_PGRAPH_PATT_COLORRAM+0xec,
175 NV04_PGRAPH_PATT_COLORRAM+0xf0,
176 NV04_PGRAPH_PATT_COLORRAM+0xf4,
177 NV04_PGRAPH_PATT_COLORRAM+0xf8,
178 NV04_PGRAPH_PATT_COLORRAM+0xfc,
179 NV04_PGRAPH_PATTERN,
180 0x0040080c,
181 NV04_PGRAPH_PATTERN_SHAPE,
182 0x00400600,
183 NV04_PGRAPH_ROP3,
184 NV04_PGRAPH_CHROMA,
185 NV04_PGRAPH_BETA_AND,
186 NV04_PGRAPH_BETA_PREMULT,
187 NV04_PGRAPH_CONTROL0,
188 NV04_PGRAPH_CONTROL1,
189 NV04_PGRAPH_CONTROL2,
190 NV04_PGRAPH_BLEND,
191 NV04_PGRAPH_STORED_FMT,
192 NV04_PGRAPH_SOURCE_COLOR,
193 0x00400560,
194 0x00400568,
195 0x00400564,
196 0x0040056c,
197 0x00400400,
198 0x00400480,
199 0x00400404,
200 0x00400484,
201 0x00400408,
202 0x00400488,
203 0x0040040c,
204 0x0040048c,
205 0x00400410,
206 0x00400490,
207 0x00400414,
208 0x00400494,
209 0x00400418,
210 0x00400498,
211 0x0040041c,
212 0x0040049c,
213 0x00400420,
214 0x004004a0,
215 0x00400424,
216 0x004004a4,
217 0x00400428,
218 0x004004a8,
219 0x0040042c,
220 0x004004ac,
221 0x00400430,
222 0x004004b0,
223 0x00400434,
224 0x004004b4,
225 0x00400438,
226 0x004004b8,
227 0x0040043c,
228 0x004004bc,
229 0x00400440,
230 0x004004c0,
231 0x00400444,
232 0x004004c4,
233 0x00400448,
234 0x004004c8,
235 0x0040044c,
236 0x004004cc,
237 0x00400450,
238 0x004004d0,
239 0x00400454,
240 0x004004d4,
241 0x00400458,
242 0x004004d8,
243 0x0040045c,
244 0x004004dc,
245 0x00400460,
246 0x004004e0,
247 0x00400464,
248 0x004004e4,
249 0x00400468,
250 0x004004e8,
251 0x0040046c,
252 0x004004ec,
253 0x00400470,
254 0x004004f0,
255 0x00400474,
256 0x004004f4,
257 0x00400478,
258 0x004004f8,
259 0x0040047c,
260 0x004004fc,
261 0x00400534,
262 0x00400538,
263 0x00400514,
264 0x00400518,
265 0x0040051c,
266 0x00400520,
267 0x00400524,
268 0x00400528,
269 0x0040052c,
270 0x00400530,
271 0x00400d00,
272 0x00400d40,
273 0x00400d80,
274 0x00400d04,
275 0x00400d44,
276 0x00400d84,
277 0x00400d08,
278 0x00400d48,
279 0x00400d88,
280 0x00400d0c,
281 0x00400d4c,
282 0x00400d8c,
283 0x00400d10,
284 0x00400d50,
285 0x00400d90,
286 0x00400d14,
287 0x00400d54,
288 0x00400d94,
289 0x00400d18,
290 0x00400d58,
291 0x00400d98,
292 0x00400d1c,
293 0x00400d5c,
294 0x00400d9c,
295 0x00400d20,
296 0x00400d60,
297 0x00400da0,
298 0x00400d24,
299 0x00400d64,
300 0x00400da4,
301 0x00400d28,
302 0x00400d68,
303 0x00400da8,
304 0x00400d2c,
305 0x00400d6c,
306 0x00400dac,
307 0x00400d30,
308 0x00400d70,
309 0x00400db0,
310 0x00400d34,
311 0x00400d74,
312 0x00400db4,
313 0x00400d38,
314 0x00400d78,
315 0x00400db8,
316 0x00400d3c,
317 0x00400d7c,
318 0x00400dbc,
319 0x00400590,
320 0x00400594,
321 0x00400598,
322 0x0040059c,
323 0x004005a8,
324 0x004005ac,
325 0x004005b0,
326 0x004005b4,
327 0x004005c0,
328 0x004005c4,
329 0x004005c8,
330 0x004005cc,
331 0x004005d0,
332 0x004005d4,
333 0x004005d8,
334 0x004005dc,
335 0x004005e0,
336 NV04_PGRAPH_PASSTHRU_0,
337 NV04_PGRAPH_PASSTHRU_1,
338 NV04_PGRAPH_PASSTHRU_2,
339 NV04_PGRAPH_DVD_COLORFMT,
340 NV04_PGRAPH_SCALED_FORMAT,
341 NV04_PGRAPH_MISC24_0,
342 NV04_PGRAPH_MISC24_1,
343 NV04_PGRAPH_MISC24_2,
344 0x00400500,
345 0x00400504,
346 NV04_PGRAPH_VALID1,
347 NV04_PGRAPH_VALID2,
348 NV04_PGRAPH_DEBUG_3
349};
350
351struct graph_state {
352 uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
353};
354
355static struct nouveau_channel *
356nv04_graph_channel(struct drm_device *dev)
357{
358 struct drm_nouveau_private *dev_priv = dev->dev_private;
359 int chid = dev_priv->engine.fifo.channels;
360
361 if (nv_rd32(dev, NV04_PGRAPH_CTX_CONTROL) & 0x00010000)
362 chid = nv_rd32(dev, NV04_PGRAPH_CTX_USER) >> 24;
363
364 if (chid >= dev_priv->engine.fifo.channels)
365 return NULL;
366
367 return dev_priv->channels.ptr[chid];
368}
369
370static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
371{
372 int i;
373
374 for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) {
375 if (nv04_graph_ctx_regs[i] == reg)
376 return &ctx->nv04[i];
377 }
378
379 return NULL;
380}
381
382static int
383nv04_graph_load_context(struct nouveau_channel *chan)
384{
385 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
386 struct drm_device *dev = chan->dev;
387 uint32_t tmp;
388 int i;
389
390 for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
391 nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]);
392
393 nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
394
395 tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
396 nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24);
397
398 tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2);
399 nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff);
400
401 return 0;
402}
403
404static int
405nv04_graph_unload_context(struct drm_device *dev)
406{
407 struct drm_nouveau_private *dev_priv = dev->dev_private;
408 struct nouveau_channel *chan = NULL;
409 struct graph_state *ctx;
410 uint32_t tmp;
411 int i;
412
413 chan = nv04_graph_channel(dev);
414 if (!chan)
415 return 0;
416 ctx = chan->engctx[NVOBJ_ENGINE_GR];
417
418 for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
419 ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]);
420
421 nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10000000);
422 tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
423 tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
424 nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
425 return 0;
426}
427
428static int
429nv04_graph_context_new(struct nouveau_channel *chan, int engine)
430{
431 struct graph_state *pgraph_ctx;
432 NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id);
433
434 pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL);
435 if (pgraph_ctx == NULL)
436 return -ENOMEM;
437
438 *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
439
440 chan->engctx[engine] = pgraph_ctx;
441 return 0;
442}
443
444static void
445nv04_graph_context_del(struct nouveau_channel *chan, int engine)
446{
447 struct drm_device *dev = chan->dev;
448 struct drm_nouveau_private *dev_priv = dev->dev_private;
449 struct graph_state *pgraph_ctx = chan->engctx[engine];
450 unsigned long flags;
451
452 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
453 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
454
455 /* Unload the context if it's the currently active one */
456 if (nv04_graph_channel(dev) == chan)
457 nv04_graph_unload_context(dev);
458
459 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
460 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
461
462 /* Free the context resources */
463 kfree(pgraph_ctx);
464 chan->engctx[engine] = NULL;
465}
466
467int
468nv04_graph_object_new(struct nouveau_channel *chan, int engine,
469 u32 handle, u16 class)
470{
471 struct drm_device *dev = chan->dev;
472 struct nouveau_gpuobj *obj = NULL;
473 int ret;
474
475 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
476 if (ret)
477 return ret;
478 obj->engine = 1;
479 obj->class = class;
480
481#ifdef __BIG_ENDIAN
482 nv_wo32(obj, 0x00, 0x00080000 | class);
483#else
484 nv_wo32(obj, 0x00, class);
485#endif
486 nv_wo32(obj, 0x04, 0x00000000);
487 nv_wo32(obj, 0x08, 0x00000000);
488 nv_wo32(obj, 0x0c, 0x00000000);
489
490 ret = nouveau_ramht_insert(chan, handle, obj);
491 nouveau_gpuobj_ref(NULL, &obj);
492 return ret;
493}
494
495static int
496nv04_graph_init(struct drm_device *dev, int engine)
497{
498 struct drm_nouveau_private *dev_priv = dev->dev_private;
499 uint32_t tmp;
500
501 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
502 ~NV_PMC_ENABLE_PGRAPH);
503 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
504 NV_PMC_ENABLE_PGRAPH);
505
506 /* Enable PGRAPH interrupts */
507 nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
508 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
509
510 nv_wr32(dev, NV04_PGRAPH_VALID1, 0);
511 nv_wr32(dev, NV04_PGRAPH_VALID2, 0);
512 /*nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x000001FF);
513 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
514 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000);
515 /*1231C000 blob, 001 haiku*/
516 /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
517 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100);
518 /*0x72111100 blob , 01 haiku*/
519 /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
520 nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f071);
521 /*haiku same*/
522
523 /*nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
524 nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31);
525 /*haiku and blob 10d4*/
526
527 nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF);
528 nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100);
529 tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
530 tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
531 nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
532
533 /* These don't belong here, they're part of a per-channel context */
534 nv_wr32(dev, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
535 nv_wr32(dev, NV04_PGRAPH_BETA_AND , 0xFFFFFFFF);
536
537 return 0;
538}
539
540static int
541nv04_graph_fini(struct drm_device *dev, int engine, bool suspend)
542{
543 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
544 if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
545 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
546 return -EBUSY;
547 }
548 nv04_graph_unload_context(dev);
549 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
550 return 0;
551}
552
553static int
554nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
555 u32 class, u32 mthd, u32 data)
556{
557 atomic_set(&chan->fence.last_sequence_irq, data);
558 return 0;
559}
560
561int
562nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
563 u32 class, u32 mthd, u32 data)
564{
565 struct drm_device *dev = chan->dev;
566 struct nouveau_page_flip_state s;
567
568 if (!nouveau_finish_page_flip(chan, &s))
569 nv_set_crtc_base(dev, s.crtc,
570 s.offset + s.y * s.pitch + s.x * s.bpp / 8);
571
572 return 0;
573}
574
575/*
576 * Software methods, why they are needed, and how they all work:
577 *
578 * NV04 and NV05 keep most of the state in PGRAPH context itself, but some
579 * 2d engine settings are kept inside the grobjs themselves. The grobjs are
580 * 3 words long on both. grobj format on NV04 is:
581 *
582 * word 0:
583 * - bits 0-7: class
584 * - bit 12: color key active
585 * - bit 13: clip rect active
586 * - bit 14: if set, destination surface is swizzled and taken from buffer 5
587 * [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
588 * from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
589 * NV03_CONTEXT_SURFACE_DST].
590 * - bits 15-17: 2d operation [aka patch config]
591 * - bit 24: patch valid [enables rendering using this object]
592 * - bit 25: surf3d valid [for tex_tri and multitex_tri only]
593 * word 1:
594 * - bits 0-1: mono format
595 * - bits 8-13: color format
596 * - bits 16-31: DMA_NOTIFY instance
597 * word 2:
598 * - bits 0-15: DMA_A instance
599 * - bits 16-31: DMA_B instance
600 *
601 * On NV05 it's:
602 *
603 * word 0:
604 * - bits 0-7: class
605 * - bit 12: color key active
606 * - bit 13: clip rect active
607 * - bit 14: if set, destination surface is swizzled and taken from buffer 5
608 * [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
609 * from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
610 * NV03_CONTEXT_SURFACE_DST].
611 * - bits 15-17: 2d operation [aka patch config]
612 * - bits 20-22: dither mode
613 * - bit 24: patch valid [enables rendering using this object]
614 * - bit 25: surface_dst/surface_color/surf2d/surf3d valid
615 * - bit 26: surface_src/surface_zeta valid
616 * - bit 27: pattern valid
617 * - bit 28: rop valid
618 * - bit 29: beta1 valid
619 * - bit 30: beta4 valid
620 * word 1:
621 * - bits 0-1: mono format
622 * - bits 8-13: color format
623 * - bits 16-31: DMA_NOTIFY instance
624 * word 2:
625 * - bits 0-15: DMA_A instance
626 * - bits 16-31: DMA_B instance
627 *
628 * NV05 will set/unset the relevant valid bits when you poke the relevant
629 * object-binding methods with object of the proper type, or with the NULL
630 * type. It'll only allow rendering using the grobj if all needed objects
631 * are bound. The needed set of objects depends on selected operation: for
632 * example rop object is needed by ROP_AND, but not by SRCCOPY_AND.
633 *
634 * NV04 doesn't have these methods implemented at all, and doesn't have the
635 * relevant bits in grobj. Instead, it'll allow rendering whenever bit 24
636 * is set. So we have to emulate them in software, internally keeping the
637 * same bits as NV05 does. Since grobjs are aligned to 16 bytes on nv04,
638 * but the last word isn't actually used for anything, we abuse it for this
639 * purpose.
640 *
641 * Actually, NV05 can optionally check bit 24 too, but we disable this since
642 * there's no use for it.
643 *
644 * For unknown reasons, NV04 implements surf3d binding in hardware as an
645 * exception. Also for unknown reasons, NV04 doesn't implement the clipping
646 * methods on the surf3d object, so we have to emulate them too.
647 */
648
649static void
650nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value)
651{
652 struct drm_device *dev = chan->dev;
653 u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
654 int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
655 u32 tmp;
656
657 tmp = nv_ri32(dev, instance);
658 tmp &= ~mask;
659 tmp |= value;
660
661 nv_wi32(dev, instance, tmp);
662 nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp);
663 nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp);
664}
665
666static void
667nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value)
668{
669 struct drm_device *dev = chan->dev;
670 u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
671 u32 tmp, ctx1;
672 int class, op, valid = 1;
673
674 ctx1 = nv_ri32(dev, instance);
675 class = ctx1 & 0xff;
676 op = (ctx1 >> 15) & 7;
677 tmp = nv_ri32(dev, instance + 0xc);
678 tmp &= ~mask;
679 tmp |= value;
680 nv_wi32(dev, instance + 0xc, tmp);
681
682 /* check for valid surf2d/surf_dst/surf_color */
683 if (!(tmp & 0x02000000))
684 valid = 0;
685 /* check for valid surf_src/surf_zeta */
686 if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000))
687 valid = 0;
688
689 switch (op) {
690 /* SRCCOPY_AND, SRCCOPY: no extra objects required */
691 case 0:
692 case 3:
693 break;
694 /* ROP_AND: requires pattern and rop */
695 case 1:
696 if (!(tmp & 0x18000000))
697 valid = 0;
698 break;
699 /* BLEND_AND: requires beta1 */
700 case 2:
701 if (!(tmp & 0x20000000))
702 valid = 0;
703 break;
704 /* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */
705 case 4:
706 case 5:
707 if (!(tmp & 0x40000000))
708 valid = 0;
709 break;
710 }
711
712 nv04_graph_set_ctx1(chan, 0x01000000, valid << 24);
713}
714
715static int
716nv04_graph_mthd_set_operation(struct nouveau_channel *chan,
717 u32 class, u32 mthd, u32 data)
718{
719 if (data > 5)
720 return 1;
721 /* Old versions of the objects only accept first three operations. */
722 if (data > 2 && class < 0x40)
723 return 1;
724 nv04_graph_set_ctx1(chan, 0x00038000, data << 15);
725 /* changing operation changes set of objects needed for validation */
726 nv04_graph_set_ctx_val(chan, 0, 0);
727 return 0;
728}
729
730static int
731nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan,
732 u32 class, u32 mthd, u32 data)
733{
734 uint32_t min = data & 0xffff, max;
735 uint32_t w = data >> 16;
736 if (min & 0x8000)
737 /* too large */
738 return 1;
739 if (w & 0x8000)
740 /* yes, it accepts negative for some reason. */
741 w |= 0xffff0000;
742 max = min + w;
743 max &= 0x3ffff;
744 nv_wr32(chan->dev, 0x40053c, min);
745 nv_wr32(chan->dev, 0x400544, max);
746 return 0;
747}
748
749static int
750nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan,
751 u32 class, u32 mthd, u32 data)
752{
753 uint32_t min = data & 0xffff, max;
754 uint32_t w = data >> 16;
755 if (min & 0x8000)
756 /* too large */
757 return 1;
758 if (w & 0x8000)
759 /* yes, it accepts negative for some reason. */
760 w |= 0xffff0000;
761 max = min + w;
762 max &= 0x3ffff;
763 nv_wr32(chan->dev, 0x400540, min);
764 nv_wr32(chan->dev, 0x400548, max);
765 return 0;
766}
767
768static int
769nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan,
770 u32 class, u32 mthd, u32 data)
771{
772 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
773 case 0x30:
774 nv04_graph_set_ctx1(chan, 0x00004000, 0);
775 nv04_graph_set_ctx_val(chan, 0x02000000, 0);
776 return 0;
777 case 0x42:
778 nv04_graph_set_ctx1(chan, 0x00004000, 0);
779 nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
780 return 0;
781 }
782 return 1;
783}
784
785static int
786nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan,
787 u32 class, u32 mthd, u32 data)
788{
789 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
790 case 0x30:
791 nv04_graph_set_ctx1(chan, 0x00004000, 0);
792 nv04_graph_set_ctx_val(chan, 0x02000000, 0);
793 return 0;
794 case 0x42:
795 nv04_graph_set_ctx1(chan, 0x00004000, 0);
796 nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
797 return 0;
798 case 0x52:
799 nv04_graph_set_ctx1(chan, 0x00004000, 0x00004000);
800 nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
801 return 0;
802 }
803 return 1;
804}
805
806static int
807nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan,
808 u32 class, u32 mthd, u32 data)
809{
810 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
811 case 0x30:
812 nv04_graph_set_ctx_val(chan, 0x08000000, 0);
813 return 0;
814 case 0x18:
815 nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000);
816 return 0;
817 }
818 return 1;
819}
820
821static int
822nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan,
823 u32 class, u32 mthd, u32 data)
824{
825 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
826 case 0x30:
827 nv04_graph_set_ctx_val(chan, 0x08000000, 0);
828 return 0;
829 case 0x44:
830 nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000);
831 return 0;
832 }
833 return 1;
834}
835
836static int
837nv04_graph_mthd_bind_rop(struct nouveau_channel *chan,
838 u32 class, u32 mthd, u32 data)
839{
840 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
841 case 0x30:
842 nv04_graph_set_ctx_val(chan, 0x10000000, 0);
843 return 0;
844 case 0x43:
845 nv04_graph_set_ctx_val(chan, 0x10000000, 0x10000000);
846 return 0;
847 }
848 return 1;
849}
850
851static int
852nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan,
853 u32 class, u32 mthd, u32 data)
854{
855 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
856 case 0x30:
857 nv04_graph_set_ctx_val(chan, 0x20000000, 0);
858 return 0;
859 case 0x12:
860 nv04_graph_set_ctx_val(chan, 0x20000000, 0x20000000);
861 return 0;
862 }
863 return 1;
864}
865
866static int
867nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan,
868 u32 class, u32 mthd, u32 data)
869{
870 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
871 case 0x30:
872 nv04_graph_set_ctx_val(chan, 0x40000000, 0);
873 return 0;
874 case 0x72:
875 nv04_graph_set_ctx_val(chan, 0x40000000, 0x40000000);
876 return 0;
877 }
878 return 1;
879}
880
881static int
882nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan,
883 u32 class, u32 mthd, u32 data)
884{
885 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
886 case 0x30:
887 nv04_graph_set_ctx_val(chan, 0x02000000, 0);
888 return 0;
889 case 0x58:
890 nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
891 return 0;
892 }
893 return 1;
894}
895
896static int
897nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan,
898 u32 class, u32 mthd, u32 data)
899{
900 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
901 case 0x30:
902 nv04_graph_set_ctx_val(chan, 0x04000000, 0);
903 return 0;
904 case 0x59:
905 nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000);
906 return 0;
907 }
908 return 1;
909}
910
911static int
912nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan,
913 u32 class, u32 mthd, u32 data)
914{
915 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
916 case 0x30:
917 nv04_graph_set_ctx_val(chan, 0x02000000, 0);
918 return 0;
919 case 0x5a:
920 nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
921 return 0;
922 }
923 return 1;
924}
925
926static int
927nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan,
928 u32 class, u32 mthd, u32 data)
929{
930 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
931 case 0x30:
932 nv04_graph_set_ctx_val(chan, 0x04000000, 0);
933 return 0;
934 case 0x5b:
935 nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000);
936 return 0;
937 }
938 return 1;
939}
940
941static int
942nv04_graph_mthd_bind_clip(struct nouveau_channel *chan,
943 u32 class, u32 mthd, u32 data)
944{
945 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
946 case 0x30:
947 nv04_graph_set_ctx1(chan, 0x2000, 0);
948 return 0;
949 case 0x19:
950 nv04_graph_set_ctx1(chan, 0x2000, 0x2000);
951 return 0;
952 }
953 return 1;
954}
955
956static int
957nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan,
958 u32 class, u32 mthd, u32 data)
959{
960 switch (nv_ri32(chan->dev, data << 4) & 0xff) {
961 case 0x30:
962 nv04_graph_set_ctx1(chan, 0x1000, 0);
963 return 0;
964 /* Yes, for some reason even the old versions of objects
965 * accept 0x57 and not 0x17. Consistency be damned.
966 */
967 case 0x57:
968 nv04_graph_set_ctx1(chan, 0x1000, 0x1000);
969 return 0;
970 }
971 return 1;
972}
973
974static struct nouveau_bitfield nv04_graph_intr[] = {
975 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
976 {}
977};
978
979static struct nouveau_bitfield nv04_graph_nstatus[] = {
980 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
981 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
982 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
983 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
984 {}
985};
986
987struct nouveau_bitfield nv04_graph_nsource[] = {
988 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" },
989 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" },
990 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" },
991 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" },
992 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" },
993 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" },
994 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" },
995 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" },
996 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" },
997 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" },
998 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" },
999 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" },
1000 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" },
1001 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" },
1002 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" },
1003 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" },
1004 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
1005 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" },
1006 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" },
1007 {}
1008};
1009
1010static void
1011nv04_graph_context_switch(struct drm_device *dev)
1012{
1013 struct drm_nouveau_private *dev_priv = dev->dev_private;
1014 struct nouveau_channel *chan = NULL;
1015 int chid;
1016
1017 nouveau_wait_for_idle(dev);
1018
1019 /* If previous context is valid, we need to save it */
1020 nv04_graph_unload_context(dev);
1021
1022 /* Load context for next channel */
1023 chid = dev_priv->engine.fifo.channel_id(dev);
1024 chan = dev_priv->channels.ptr[chid];
1025 if (chan)
1026 nv04_graph_load_context(chan);
1027}
1028
1029static void
1030nv04_graph_isr(struct drm_device *dev)
1031{
1032 u32 stat;
1033
1034 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1035 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
1036 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
1037 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
1038 u32 chid = (addr & 0x0f000000) >> 24;
1039 u32 subc = (addr & 0x0000e000) >> 13;
1040 u32 mthd = (addr & 0x00001ffc);
1041 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
1042 u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff;
1043 u32 show = stat;
1044
1045 if (stat & NV_PGRAPH_INTR_NOTIFY) {
1046 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
1047 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
1048 show &= ~NV_PGRAPH_INTR_NOTIFY;
1049 }
1050 }
1051
1052 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1053 nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1054 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1055 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1056 nv04_graph_context_switch(dev);
1057 }
1058
1059 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
1060 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
1061
1062 if (show && nouveau_ratelimit()) {
1063 NV_INFO(dev, "PGRAPH -");
1064 nouveau_bitfield_print(nv04_graph_intr, show);
1065 printk(" nsource:");
1066 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1067 printk(" nstatus:");
1068 nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
1069 printk("\n");
1070 NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
1071 "mthd 0x%04x data 0x%08x\n",
1072 chid, subc, class, mthd, data);
1073 }
1074 }
1075}
1076
1077static void
1078nv04_graph_destroy(struct drm_device *dev, int engine)
1079{
1080 struct nv04_graph_engine *pgraph = nv_engine(dev, engine);
1081
1082 nouveau_irq_unregister(dev, 12);
1083
1084 NVOBJ_ENGINE_DEL(dev, GR);
1085 kfree(pgraph);
1086}
1087
1088int
1089nv04_graph_create(struct drm_device *dev)
1090{
1091 struct nv04_graph_engine *pgraph;
1092
1093 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
1094 if (!pgraph)
1095 return -ENOMEM;
1096
1097 pgraph->base.destroy = nv04_graph_destroy;
1098 pgraph->base.init = nv04_graph_init;
1099 pgraph->base.fini = nv04_graph_fini;
1100 pgraph->base.context_new = nv04_graph_context_new;
1101 pgraph->base.context_del = nv04_graph_context_del;
1102 pgraph->base.object_new = nv04_graph_object_new;
1103
1104 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
1105 nouveau_irq_register(dev, 12, nv04_graph_isr);
1106
1107 /* dvd subpicture */
1108 NVOBJ_CLASS(dev, 0x0038, GR);
1109
1110 /* m2mf */
1111 NVOBJ_CLASS(dev, 0x0039, GR);
1112
1113 /* nv03 gdirect */
1114 NVOBJ_CLASS(dev, 0x004b, GR);
1115 NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt);
1116 NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop);
1117 NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1);
1118 NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst);
1119 NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation);
1120
1121 /* nv04 gdirect */
1122 NVOBJ_CLASS(dev, 0x004a, GR);
1123 NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt);
1124 NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop);
1125 NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1);
1126 NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4);
1127 NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d);
1128 NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation);
1129
1130 /* nv01 imageblit */
1131 NVOBJ_CLASS(dev, 0x001f, GR);
1132 NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma);
1133 NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip);
1134 NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt);
1135 NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop);
1136 NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1);
1137 NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst);
1138 NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src);
1139 NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation);
1140
1141 /* nv04 imageblit */
1142 NVOBJ_CLASS(dev, 0x005f, GR);
1143 NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma);
1144 NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip);
1145 NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt);
1146 NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop);
1147 NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1);
1148 NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4);
1149 NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d);
1150 NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation);
1151
1152 /* nv04 iifc */
1153 NVOBJ_CLASS(dev, 0x0060, GR);
1154 NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma);
1155 NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip);
1156 NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt);
1157 NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop);
1158 NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1);
1159 NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4);
1160 NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf);
1161 NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation);
1162
1163 /* nv05 iifc */
1164 NVOBJ_CLASS(dev, 0x0064, GR);
1165
1166 /* nv01 ifc */
1167 NVOBJ_CLASS(dev, 0x0021, GR);
1168 NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma);
1169 NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip);
1170 NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt);
1171 NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop);
1172 NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1);
1173 NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst);
1174 NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation);
1175
1176 /* nv04 ifc */
1177 NVOBJ_CLASS(dev, 0x0061, GR);
1178 NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma);
1179 NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip);
1180 NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt);
1181 NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop);
1182 NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1);
1183 NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4);
1184 NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d);
1185 NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation);
1186
1187 /* nv05 ifc */
1188 NVOBJ_CLASS(dev, 0x0065, GR);
1189
1190 /* nv03 sifc */
1191 NVOBJ_CLASS(dev, 0x0036, GR);
1192 NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma);
1193 NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt);
1194 NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop);
1195 NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1);
1196 NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst);
1197 NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation);
1198
1199 /* nv04 sifc */
1200 NVOBJ_CLASS(dev, 0x0076, GR);
1201 NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma);
1202 NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt);
1203 NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop);
1204 NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1);
1205 NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4);
1206 NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d);
1207 NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation);
1208
1209 /* nv05 sifc */
1210 NVOBJ_CLASS(dev, 0x0066, GR);
1211
1212 /* nv03 sifm */
1213 NVOBJ_CLASS(dev, 0x0037, GR);
1214 NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt);
1215 NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop);
1216 NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1);
1217 NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst);
1218 NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation);
1219
1220 /* nv04 sifm */
1221 NVOBJ_CLASS(dev, 0x0077, GR);
1222 NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt);
1223 NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop);
1224 NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1);
1225 NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4);
1226 NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf);
1227 NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation);
1228
1229 /* null */
1230 NVOBJ_CLASS(dev, 0x0030, GR);
1231
1232 /* surf2d */
1233 NVOBJ_CLASS(dev, 0x0042, GR);
1234
1235 /* rop */
1236 NVOBJ_CLASS(dev, 0x0043, GR);
1237
1238 /* beta1 */
1239 NVOBJ_CLASS(dev, 0x0012, GR);
1240
1241 /* beta4 */
1242 NVOBJ_CLASS(dev, 0x0072, GR);
1243
1244 /* cliprect */
1245 NVOBJ_CLASS(dev, 0x0019, GR);
1246
1247 /* nv01 pattern */
1248 NVOBJ_CLASS(dev, 0x0018, GR);
1249
1250 /* nv04 pattern */
1251 NVOBJ_CLASS(dev, 0x0044, GR);
1252
1253 /* swzsurf */
1254 NVOBJ_CLASS(dev, 0x0052, GR);
1255
1256 /* surf3d */
1257 NVOBJ_CLASS(dev, 0x0053, GR);
1258 NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h);
1259 NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v);
1260
1261 /* nv03 tex_tri */
1262 NVOBJ_CLASS(dev, 0x0048, GR);
1263 NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip);
1264 NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color);
1265 NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta);
1266
1267 /* tex_tri */
1268 NVOBJ_CLASS(dev, 0x0054, GR);
1269
1270 /* multitex_tri */
1271 NVOBJ_CLASS(dev, 0x0055, GR);
1272
1273 /* nv01 chroma */
1274 NVOBJ_CLASS(dev, 0x0017, GR);
1275
1276 /* nv04 chroma */
1277 NVOBJ_CLASS(dev, 0x0057, GR);
1278
1279 /* surf_dst */
1280 NVOBJ_CLASS(dev, 0x0058, GR);
1281
1282 /* surf_src */
1283 NVOBJ_CLASS(dev, 0x0059, GR);
1284
1285 /* surf_color */
1286 NVOBJ_CLASS(dev, 0x005a, GR);
1287
1288 /* surf_zeta */
1289 NVOBJ_CLASS(dev, 0x005b, GR);
1290
1291 /* nv01 line */
1292 NVOBJ_CLASS(dev, 0x001c, GR);
1293 NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip);
1294 NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt);
1295 NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop);
1296 NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1);
1297 NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst);
1298 NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation);
1299
1300 /* nv04 line */
1301 NVOBJ_CLASS(dev, 0x005c, GR);
1302 NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip);
1303 NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt);
1304 NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop);
1305 NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1);
1306 NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4);
1307 NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d);
1308 NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation);
1309
1310 /* nv01 tri */
1311 NVOBJ_CLASS(dev, 0x001d, GR);
1312 NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip);
1313 NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt);
1314 NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop);
1315 NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1);
1316 NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst);
1317 NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation);
1318
1319 /* nv04 tri */
1320 NVOBJ_CLASS(dev, 0x005d, GR);
1321 NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip);
1322 NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt);
1323 NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop);
1324 NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1);
1325 NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4);
1326 NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d);
1327 NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation);
1328
1329 /* nv01 rect */
1330 NVOBJ_CLASS(dev, 0x001e, GR);
1331 NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip);
1332 NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt);
1333 NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop);
1334 NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1);
1335 NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst);
1336 NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation);
1337
1338 /* nv04 rect */
1339 NVOBJ_CLASS(dev, 0x005e, GR);
1340 NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip);
1341 NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt);
1342 NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop);
1343 NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1);
1344 NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4);
1345 NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d);
1346 NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation);
1347
1348 /* nvsw */
1349 NVOBJ_CLASS(dev, 0x506e, SW);
1350 NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref);
1351 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
1352 return 0;
1353}
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c
new file mode 100644
index 00000000000..c1248e0740a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c
@@ -0,0 +1,192 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_ramht.h"
5
6/* returns the size of fifo context */
7static int
8nouveau_fifo_ctx_size(struct drm_device *dev)
9{
10 struct drm_nouveau_private *dev_priv = dev->dev_private;
11
12 if (dev_priv->chipset >= 0x40)
13 return 128;
14 else
15 if (dev_priv->chipset >= 0x17)
16 return 64;
17
18 return 32;
19}
20
21int nv04_instmem_init(struct drm_device *dev)
22{
23 struct drm_nouveau_private *dev_priv = dev->dev_private;
24 struct nouveau_gpuobj *ramht = NULL;
25 u32 offset, length;
26 int ret;
27
28 /* RAMIN always available */
29 dev_priv->ramin_available = true;
30
31 /* Reserve space at end of VRAM for PRAMIN */
32 if (dev_priv->card_type >= NV_40) {
33 u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
34 u32 rsvd;
35
36 /* estimate grctx size, the magics come from nv40_grctx.c */
37 if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
38 else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs;
39 else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs;
40 else rsvd = 0x4a40 * vs;
41 rsvd += 16 * 1024;
42 rsvd *= dev_priv->engine.fifo.channels;
43
44 /* pciegart table */
45 if (pci_is_pcie(dev->pdev))
46 rsvd += 512 * 1024;
47
48 /* object storage */
49 rsvd += 512 * 1024;
50
51 dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
52 } else {
53 dev_priv->ramin_rsvd_vram = 512 * 1024;
54 }
55
56 /* Setup shared RAMHT */
57 ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
58 NVOBJ_FLAG_ZERO_ALLOC, &ramht);
59 if (ret)
60 return ret;
61
62 ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht);
63 nouveau_gpuobj_ref(NULL, &ramht);
64 if (ret)
65 return ret;
66
67 /* And RAMRO */
68 ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512,
69 NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro);
70 if (ret)
71 return ret;
72
73 /* And RAMFC */
74 length = dev_priv->engine.fifo.channels * nouveau_fifo_ctx_size(dev);
75 switch (dev_priv->card_type) {
76 case NV_40:
77 offset = 0x20000;
78 break;
79 default:
80 offset = 0x11400;
81 break;
82 }
83
84 ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length,
85 NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc);
86 if (ret)
87 return ret;
88
89 /* Only allow space after RAMFC to be used for object allocation */
90 offset += length;
91
92 /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230
93 * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0
94 * ("new style" control) the upper 16-bits of 0x2220 points at this
95 * other mysterious table that's clobbering important things.
96 *
97 * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting
98 * smashed to pieces on us, so reserve 0x30000-0x40000 too..
99 */
100 if (dev_priv->card_type >= NV_40) {
101 if (offset < 0x40000)
102 offset = 0x40000;
103 }
104
105 ret = drm_mm_init(&dev_priv->ramin_heap, offset,
106 dev_priv->ramin_rsvd_vram - offset);
107 if (ret) {
108 NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret);
109 return ret;
110 }
111
112 return 0;
113}
114
115void
116nv04_instmem_takedown(struct drm_device *dev)
117{
118 struct drm_nouveau_private *dev_priv = dev->dev_private;
119
120 nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL);
121 nouveau_gpuobj_ref(NULL, &dev_priv->ramro);
122 nouveau_gpuobj_ref(NULL, &dev_priv->ramfc);
123
124 if (drm_mm_initialized(&dev_priv->ramin_heap))
125 drm_mm_takedown(&dev_priv->ramin_heap);
126}
127
128int
129nv04_instmem_suspend(struct drm_device *dev)
130{
131 return 0;
132}
133
134void
135nv04_instmem_resume(struct drm_device *dev)
136{
137}
138
139int
140nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
141 u32 size, u32 align)
142{
143 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
144 struct drm_mm_node *ramin = NULL;
145
146 do {
147 if (drm_mm_pre_get(&dev_priv->ramin_heap))
148 return -ENOMEM;
149
150 spin_lock(&dev_priv->ramin_lock);
151 ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0);
152 if (ramin == NULL) {
153 spin_unlock(&dev_priv->ramin_lock);
154 return -ENOMEM;
155 }
156
157 ramin = drm_mm_get_block_atomic(ramin, size, align);
158 spin_unlock(&dev_priv->ramin_lock);
159 } while (ramin == NULL);
160
161 gpuobj->node = ramin;
162 gpuobj->vinst = ramin->start;
163 return 0;
164}
165
166void
167nv04_instmem_put(struct nouveau_gpuobj *gpuobj)
168{
169 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
170
171 spin_lock(&dev_priv->ramin_lock);
172 drm_mm_put_block(gpuobj->node);
173 gpuobj->node = NULL;
174 spin_unlock(&dev_priv->ramin_lock);
175}
176
177int
178nv04_instmem_map(struct nouveau_gpuobj *gpuobj)
179{
180 gpuobj->pinst = gpuobj->vinst;
181 return 0;
182}
183
184void
185nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj)
186{
187}
188
189void
190nv04_instmem_flush(struct drm_device *dev)
191{
192}
diff --git a/drivers/gpu/drm/nouveau/nv04_mc.c b/drivers/gpu/drm/nouveau/nv04_mc.c
new file mode 100644
index 00000000000..2af43a1cb2e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv04_mc.c
@@ -0,0 +1,24 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6int
7nv04_mc_init(struct drm_device *dev)
8{
9 /* Power up everything, resetting each individual unit will
10 * be done later if needed.
11 */
12
13 nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
14
15 /* Disable PROM access. */
16 nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
17
18 return 0;
19}
20
21void
22nv04_mc_takedown(struct drm_device *dev)
23{
24}
diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c
new file mode 100644
index 00000000000..1d09ddd5739
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv04_timer.c
@@ -0,0 +1,51 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6int
7nv04_timer_init(struct drm_device *dev)
8{
9 nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
10 nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
11
12 /* Just use the pre-existing values when possible for now; these regs
13 * are not written in nv (driver writer missed a /4 on the address), and
14 * writing 8 and 3 to the correct regs breaks the timings on the LVDS
15 * hardware sequencing microcode.
16 * A correct solution (involving calculations with the GPU PLL) can
17 * be done when kernel modesetting lands
18 */
19 if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
20 !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
21 nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008);
22 nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003);
23 }
24
25 return 0;
26}
27
28uint64_t
29nv04_timer_read(struct drm_device *dev)
30{
31 uint32_t low;
32 /* From kmmio dumps on nv28 this looks like how the blob does this.
33 * It reads the high dword twice, before and after.
34 * The only explanation seems to be that the 64-bit timer counter
35 * advances between high and low dword reads and may corrupt the
36 * result. Not confirmed.
37 */
38 uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
39 uint32_t high1;
40 do {
41 high1 = high2;
42 low = nv_rd32(dev, NV04_PTIMER_TIME_0);
43 high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
44 } while (high1 != high2);
45 return (((uint64_t)high2) << 32) | (uint64_t)low;
46}
47
48void
49nv04_timer_takedown(struct drm_device *dev)
50{
51}
diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c
new file mode 100644
index 00000000000..f78181a59b4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv10_fb.c
@@ -0,0 +1,144 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6static struct drm_mm_node *
7nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
8{
9 struct drm_nouveau_private *dev_priv = dev->dev_private;
10 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
11 struct drm_mm_node *mem;
12 int ret;
13
14 ret = drm_mm_pre_get(&pfb->tag_heap);
15 if (ret)
16 return NULL;
17
18 spin_lock(&dev_priv->tile.lock);
19 mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
20 if (mem)
21 mem = drm_mm_get_block_atomic(mem, size, 0);
22 spin_unlock(&dev_priv->tile.lock);
23
24 return mem;
25}
26
27static void
28nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem)
29{
30 struct drm_nouveau_private *dev_priv = dev->dev_private;
31
32 spin_lock(&dev_priv->tile.lock);
33 drm_mm_put_block(mem);
34 spin_unlock(&dev_priv->tile.lock);
35}
36
37void
38nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
39 uint32_t size, uint32_t pitch, uint32_t flags)
40{
41 struct drm_nouveau_private *dev_priv = dev->dev_private;
42 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
43 int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
44
45 tile->addr = addr;
46 tile->limit = max(1u, addr + size) - 1;
47 tile->pitch = pitch;
48
49 if (dev_priv->card_type == NV_20) {
50 if (flags & NOUVEAU_GEM_TILE_ZETA) {
51 /*
52 * Allocate some of the on-die tag memory,
53 * used to store Z compression meta-data (most
54 * likely just a bitmap determining if a given
55 * tile is compressed or not).
56 */
57 tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
58
59 if (tile->tag_mem) {
60 /* Enable Z compression */
61 if (dev_priv->chipset >= 0x25)
62 tile->zcomp = tile->tag_mem->start |
63 (bpp == 16 ?
64 NV25_PFB_ZCOMP_MODE_16 :
65 NV25_PFB_ZCOMP_MODE_32);
66 else
67 tile->zcomp = tile->tag_mem->start |
68 NV20_PFB_ZCOMP_EN |
69 (bpp == 16 ? 0 :
70 NV20_PFB_ZCOMP_MODE_32);
71 }
72
73 tile->addr |= 3;
74 } else {
75 tile->addr |= 1;
76 }
77
78 } else {
79 tile->addr |= 1 << 31;
80 }
81}
82
83void
84nv10_fb_free_tile_region(struct drm_device *dev, int i)
85{
86 struct drm_nouveau_private *dev_priv = dev->dev_private;
87 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
88
89 if (tile->tag_mem) {
90 nv20_fb_free_tag(dev, tile->tag_mem);
91 tile->tag_mem = NULL;
92 }
93
94 tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
95}
96
97void
98nv10_fb_set_tile_region(struct drm_device *dev, int i)
99{
100 struct drm_nouveau_private *dev_priv = dev->dev_private;
101 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
102
103 nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
104 nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
105 nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
106
107 if (dev_priv->card_type == NV_20)
108 nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
109}
110
111int
112nv10_fb_init(struct drm_device *dev)
113{
114 struct drm_nouveau_private *dev_priv = dev->dev_private;
115 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
116 int i;
117
118 pfb->num_tiles = NV10_PFB_TILE__SIZE;
119
120 if (dev_priv->card_type == NV_20)
121 drm_mm_init(&pfb->tag_heap, 0,
122 (dev_priv->chipset >= 0x25 ?
123 64 * 1024 : 32 * 1024));
124
125 /* Turn all the tiling regions off. */
126 for (i = 0; i < pfb->num_tiles; i++)
127 pfb->set_tile_region(dev, i);
128
129 return 0;
130}
131
132void
133nv10_fb_takedown(struct drm_device *dev)
134{
135 struct drm_nouveau_private *dev_priv = dev->dev_private;
136 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
137 int i;
138
139 for (i = 0; i < pfb->num_tiles; i++)
140 pfb->free_tile_region(dev, i);
141
142 if (dev_priv->card_type == NV_20)
143 drm_mm_takedown(&pfb->tag_heap);
144}
diff --git a/drivers/gpu/drm/nouveau/nv10_fifo.c b/drivers/gpu/drm/nouveau/nv10_fifo.c
new file mode 100644
index 00000000000..d2ecbff4bee
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv10_fifo.c
@@ -0,0 +1,246 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30#include "nouveau_ramht.h"
31
32#define NV10_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV10_RAMFC__SIZE))
33#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32)
34
35int
36nv10_fifo_channel_id(struct drm_device *dev)
37{
38 return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) &
39 NV10_PFIFO_CACHE1_PUSH1_CHID_MASK;
40}
41
42int
43nv10_fifo_create_context(struct nouveau_channel *chan)
44{
45 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
46 struct drm_device *dev = chan->dev;
47 uint32_t fc = NV10_RAMFC(chan->id);
48 int ret;
49
50 ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0,
51 NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC |
52 NVOBJ_FLAG_ZERO_FREE, &chan->ramfc);
53 if (ret)
54 return ret;
55
56 chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
57 NV03_USER(chan->id), PAGE_SIZE);
58 if (!chan->user)
59 return -ENOMEM;
60
61 /* Fill entries that are seen filled in dumps of nvidia driver just
62 * after channel's is put into DMA mode
63 */
64 nv_wi32(dev, fc + 0, chan->pushbuf_base);
65 nv_wi32(dev, fc + 4, chan->pushbuf_base);
66 nv_wi32(dev, fc + 12, chan->pushbuf->pinst >> 4);
67 nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
68 NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
69 NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
70#ifdef __BIG_ENDIAN
71 NV_PFIFO_CACHE1_BIG_ENDIAN |
72#endif
73 0);
74
75 /* enable the fifo dma operation */
76 nv_wr32(dev, NV04_PFIFO_MODE,
77 nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
78 return 0;
79}
80
81static void
82nv10_fifo_do_load_context(struct drm_device *dev, int chid)
83{
84 struct drm_nouveau_private *dev_priv = dev->dev_private;
85 uint32_t fc = NV10_RAMFC(chid), tmp;
86
87 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
88 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
89 nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
90
91 tmp = nv_ri32(dev, fc + 12);
92 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
93 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
94
95 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 16));
96 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 20));
97 nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 24));
98 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 28));
99
100 if (dev_priv->chipset < 0x17)
101 goto out;
102
103 nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE, nv_ri32(dev, fc + 32));
104 tmp = nv_ri32(dev, fc + 36);
105 nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, tmp);
106 nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, nv_ri32(dev, fc + 40));
107 nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, nv_ri32(dev, fc + 44));
108 nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48));
109
110out:
111 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
112 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
113}
114
115int
116nv10_fifo_load_context(struct nouveau_channel *chan)
117{
118 struct drm_device *dev = chan->dev;
119 uint32_t tmp;
120
121 nv10_fifo_do_load_context(dev, chan->id);
122
123 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1,
124 NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
125 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
126
127 /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
128 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
129 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
130
131 return 0;
132}
133
134int
135nv10_fifo_unload_context(struct drm_device *dev)
136{
137 struct drm_nouveau_private *dev_priv = dev->dev_private;
138 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
139 uint32_t fc, tmp;
140 int chid;
141
142 chid = pfifo->channel_id(dev);
143 if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
144 return 0;
145 fc = NV10_RAMFC(chid);
146
147 nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
148 nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
149 nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
150 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE) & 0xFFFF;
151 tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16);
152 nv_wi32(dev, fc + 12, tmp);
153 nv_wi32(dev, fc + 16, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
154 nv_wi32(dev, fc + 20, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
155 nv_wi32(dev, fc + 24, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
156 nv_wi32(dev, fc + 28, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
157
158 if (dev_priv->chipset < 0x17)
159 goto out;
160
161 nv_wi32(dev, fc + 32, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
162 tmp = nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP);
163 nv_wi32(dev, fc + 36, tmp);
164 nv_wi32(dev, fc + 40, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
165 nv_wi32(dev, fc + 44, nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE));
166 nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
167
168out:
169 nv10_fifo_do_load_context(dev, pfifo->channels - 1);
170 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
171 return 0;
172}
173
174static void
175nv10_fifo_init_reset(struct drm_device *dev)
176{
177 nv_wr32(dev, NV03_PMC_ENABLE,
178 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
179 nv_wr32(dev, NV03_PMC_ENABLE,
180 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO);
181
182 nv_wr32(dev, 0x003224, 0x000f0078);
183 nv_wr32(dev, 0x002044, 0x0101ffff);
184 nv_wr32(dev, 0x002040, 0x000000ff);
185 nv_wr32(dev, 0x002500, 0x00000000);
186 nv_wr32(dev, 0x003000, 0x00000000);
187 nv_wr32(dev, 0x003050, 0x00000000);
188
189 nv_wr32(dev, 0x003258, 0x00000000);
190 nv_wr32(dev, 0x003210, 0x00000000);
191 nv_wr32(dev, 0x003270, 0x00000000);
192}
193
194static void
195nv10_fifo_init_ramxx(struct drm_device *dev)
196{
197 struct drm_nouveau_private *dev_priv = dev->dev_private;
198
199 nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
200 ((dev_priv->ramht->bits - 9) << 16) |
201 (dev_priv->ramht->gpuobj->pinst >> 8));
202 nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8);
203
204 if (dev_priv->chipset < 0x17) {
205 nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc->pinst >> 8);
206 } else {
207 nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc->pinst >> 8) |
208 (1 << 16) /* 64 Bytes entry*/);
209 /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */
210 }
211}
212
213static void
214nv10_fifo_init_intr(struct drm_device *dev)
215{
216 nouveau_irq_register(dev, 8, nv04_fifo_isr);
217 nv_wr32(dev, 0x002100, 0xffffffff);
218 nv_wr32(dev, 0x002140, 0xffffffff);
219}
220
221int
222nv10_fifo_init(struct drm_device *dev)
223{
224 struct drm_nouveau_private *dev_priv = dev->dev_private;
225 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
226 int i;
227
228 nv10_fifo_init_reset(dev);
229 nv10_fifo_init_ramxx(dev);
230
231 nv10_fifo_do_load_context(dev, pfifo->channels - 1);
232 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
233
234 nv10_fifo_init_intr(dev);
235 pfifo->enable(dev);
236 pfifo->reassign(dev, true);
237
238 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
239 if (dev_priv->channels.ptr[i]) {
240 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
241 nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
242 }
243 }
244
245 return 0;
246}
diff --git a/drivers/gpu/drm/nouveau/nv10_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c
new file mode 100644
index 00000000000..007fc29e2f8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv10_gpio.c
@@ -0,0 +1,92 @@
1/*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "nouveau_drv.h"
29#include "nouveau_hw.h"
30
31static bool
32get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
33 uint32_t *mask)
34{
35 if (ent->line < 2) {
36 *reg = NV_PCRTC_GPIO;
37 *shift = ent->line * 16;
38 *mask = 0x11;
39
40 } else if (ent->line < 10) {
41 *reg = NV_PCRTC_GPIO_EXT;
42 *shift = (ent->line - 2) * 4;
43 *mask = 0x3;
44
45 } else if (ent->line < 14) {
46 *reg = NV_PCRTC_850;
47 *shift = (ent->line - 10) * 4;
48 *mask = 0x3;
49
50 } else {
51 return false;
52 }
53
54 return true;
55}
56
57int
58nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
59{
60 struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
61 uint32_t reg, shift, mask, value;
62
63 if (!ent)
64 return -ENODEV;
65
66 if (!get_gpio_location(ent, &reg, &shift, &mask))
67 return -ENODEV;
68
69 value = NVReadCRTC(dev, 0, reg) >> shift;
70
71 return (ent->invert ? 1 : 0) ^ (value & 1);
72}
73
74int
75nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
76{
77 struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
78 uint32_t reg, shift, mask, value;
79
80 if (!ent)
81 return -ENODEV;
82
83 if (!get_gpio_location(ent, &reg, &shift, &mask))
84 return -ENODEV;
85
86 value = ((ent->invert ? 1 : 0) ^ (state ? 1 : 0)) << shift;
87 mask = ~(mask << shift);
88
89 NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask));
90
91 return 0;
92}
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c
new file mode 100644
index 00000000000..7255e4a4d3f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv10_graph.c
@@ -0,0 +1,1194 @@
1/*
2 * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr>
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include "drmP.h"
26#include "drm.h"
27#include "nouveau_drm.h"
28#include "nouveau_drv.h"
29#include "nouveau_util.h"
30
31struct nv10_graph_engine {
32 struct nouveau_exec_engine base;
33};
34
35struct pipe_state {
36 uint32_t pipe_0x0000[0x040/4];
37 uint32_t pipe_0x0040[0x010/4];
38 uint32_t pipe_0x0200[0x0c0/4];
39 uint32_t pipe_0x4400[0x080/4];
40 uint32_t pipe_0x6400[0x3b0/4];
41 uint32_t pipe_0x6800[0x2f0/4];
42 uint32_t pipe_0x6c00[0x030/4];
43 uint32_t pipe_0x7000[0x130/4];
44 uint32_t pipe_0x7400[0x0c0/4];
45 uint32_t pipe_0x7800[0x0c0/4];
46};
47
48static int nv10_graph_ctx_regs[] = {
49 NV10_PGRAPH_CTX_SWITCH(0),
50 NV10_PGRAPH_CTX_SWITCH(1),
51 NV10_PGRAPH_CTX_SWITCH(2),
52 NV10_PGRAPH_CTX_SWITCH(3),
53 NV10_PGRAPH_CTX_SWITCH(4),
54 NV10_PGRAPH_CTX_CACHE(0, 0),
55 NV10_PGRAPH_CTX_CACHE(0, 1),
56 NV10_PGRAPH_CTX_CACHE(0, 2),
57 NV10_PGRAPH_CTX_CACHE(0, 3),
58 NV10_PGRAPH_CTX_CACHE(0, 4),
59 NV10_PGRAPH_CTX_CACHE(1, 0),
60 NV10_PGRAPH_CTX_CACHE(1, 1),
61 NV10_PGRAPH_CTX_CACHE(1, 2),
62 NV10_PGRAPH_CTX_CACHE(1, 3),
63 NV10_PGRAPH_CTX_CACHE(1, 4),
64 NV10_PGRAPH_CTX_CACHE(2, 0),
65 NV10_PGRAPH_CTX_CACHE(2, 1),
66 NV10_PGRAPH_CTX_CACHE(2, 2),
67 NV10_PGRAPH_CTX_CACHE(2, 3),
68 NV10_PGRAPH_CTX_CACHE(2, 4),
69 NV10_PGRAPH_CTX_CACHE(3, 0),
70 NV10_PGRAPH_CTX_CACHE(3, 1),
71 NV10_PGRAPH_CTX_CACHE(3, 2),
72 NV10_PGRAPH_CTX_CACHE(3, 3),
73 NV10_PGRAPH_CTX_CACHE(3, 4),
74 NV10_PGRAPH_CTX_CACHE(4, 0),
75 NV10_PGRAPH_CTX_CACHE(4, 1),
76 NV10_PGRAPH_CTX_CACHE(4, 2),
77 NV10_PGRAPH_CTX_CACHE(4, 3),
78 NV10_PGRAPH_CTX_CACHE(4, 4),
79 NV10_PGRAPH_CTX_CACHE(5, 0),
80 NV10_PGRAPH_CTX_CACHE(5, 1),
81 NV10_PGRAPH_CTX_CACHE(5, 2),
82 NV10_PGRAPH_CTX_CACHE(5, 3),
83 NV10_PGRAPH_CTX_CACHE(5, 4),
84 NV10_PGRAPH_CTX_CACHE(6, 0),
85 NV10_PGRAPH_CTX_CACHE(6, 1),
86 NV10_PGRAPH_CTX_CACHE(6, 2),
87 NV10_PGRAPH_CTX_CACHE(6, 3),
88 NV10_PGRAPH_CTX_CACHE(6, 4),
89 NV10_PGRAPH_CTX_CACHE(7, 0),
90 NV10_PGRAPH_CTX_CACHE(7, 1),
91 NV10_PGRAPH_CTX_CACHE(7, 2),
92 NV10_PGRAPH_CTX_CACHE(7, 3),
93 NV10_PGRAPH_CTX_CACHE(7, 4),
94 NV10_PGRAPH_CTX_USER,
95 NV04_PGRAPH_DMA_START_0,
96 NV04_PGRAPH_DMA_START_1,
97 NV04_PGRAPH_DMA_LENGTH,
98 NV04_PGRAPH_DMA_MISC,
99 NV10_PGRAPH_DMA_PITCH,
100 NV04_PGRAPH_BOFFSET0,
101 NV04_PGRAPH_BBASE0,
102 NV04_PGRAPH_BLIMIT0,
103 NV04_PGRAPH_BOFFSET1,
104 NV04_PGRAPH_BBASE1,
105 NV04_PGRAPH_BLIMIT1,
106 NV04_PGRAPH_BOFFSET2,
107 NV04_PGRAPH_BBASE2,
108 NV04_PGRAPH_BLIMIT2,
109 NV04_PGRAPH_BOFFSET3,
110 NV04_PGRAPH_BBASE3,
111 NV04_PGRAPH_BLIMIT3,
112 NV04_PGRAPH_BOFFSET4,
113 NV04_PGRAPH_BBASE4,
114 NV04_PGRAPH_BLIMIT4,
115 NV04_PGRAPH_BOFFSET5,
116 NV04_PGRAPH_BBASE5,
117 NV04_PGRAPH_BLIMIT5,
118 NV04_PGRAPH_BPITCH0,
119 NV04_PGRAPH_BPITCH1,
120 NV04_PGRAPH_BPITCH2,
121 NV04_PGRAPH_BPITCH3,
122 NV04_PGRAPH_BPITCH4,
123 NV10_PGRAPH_SURFACE,
124 NV10_PGRAPH_STATE,
125 NV04_PGRAPH_BSWIZZLE2,
126 NV04_PGRAPH_BSWIZZLE5,
127 NV04_PGRAPH_BPIXEL,
128 NV10_PGRAPH_NOTIFY,
129 NV04_PGRAPH_PATT_COLOR0,
130 NV04_PGRAPH_PATT_COLOR1,
131 NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */
132 0x00400904,
133 0x00400908,
134 0x0040090c,
135 0x00400910,
136 0x00400914,
137 0x00400918,
138 0x0040091c,
139 0x00400920,
140 0x00400924,
141 0x00400928,
142 0x0040092c,
143 0x00400930,
144 0x00400934,
145 0x00400938,
146 0x0040093c,
147 0x00400940,
148 0x00400944,
149 0x00400948,
150 0x0040094c,
151 0x00400950,
152 0x00400954,
153 0x00400958,
154 0x0040095c,
155 0x00400960,
156 0x00400964,
157 0x00400968,
158 0x0040096c,
159 0x00400970,
160 0x00400974,
161 0x00400978,
162 0x0040097c,
163 0x00400980,
164 0x00400984,
165 0x00400988,
166 0x0040098c,
167 0x00400990,
168 0x00400994,
169 0x00400998,
170 0x0040099c,
171 0x004009a0,
172 0x004009a4,
173 0x004009a8,
174 0x004009ac,
175 0x004009b0,
176 0x004009b4,
177 0x004009b8,
178 0x004009bc,
179 0x004009c0,
180 0x004009c4,
181 0x004009c8,
182 0x004009cc,
183 0x004009d0,
184 0x004009d4,
185 0x004009d8,
186 0x004009dc,
187 0x004009e0,
188 0x004009e4,
189 0x004009e8,
190 0x004009ec,
191 0x004009f0,
192 0x004009f4,
193 0x004009f8,
194 0x004009fc,
195 NV04_PGRAPH_PATTERN, /* 2 values from 0x400808 to 0x40080c */
196 0x0040080c,
197 NV04_PGRAPH_PATTERN_SHAPE,
198 NV03_PGRAPH_MONO_COLOR0,
199 NV04_PGRAPH_ROP3,
200 NV04_PGRAPH_CHROMA,
201 NV04_PGRAPH_BETA_AND,
202 NV04_PGRAPH_BETA_PREMULT,
203 0x00400e70,
204 0x00400e74,
205 0x00400e78,
206 0x00400e7c,
207 0x00400e80,
208 0x00400e84,
209 0x00400e88,
210 0x00400e8c,
211 0x00400ea0,
212 0x00400ea4,
213 0x00400ea8,
214 0x00400e90,
215 0x00400e94,
216 0x00400e98,
217 0x00400e9c,
218 NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */
219 NV10_PGRAPH_WINDOWCLIP_VERTICAL, /* 8 values from 0x400f20-0x400f3c */
220 0x00400f04,
221 0x00400f24,
222 0x00400f08,
223 0x00400f28,
224 0x00400f0c,
225 0x00400f2c,
226 0x00400f10,
227 0x00400f30,
228 0x00400f14,
229 0x00400f34,
230 0x00400f18,
231 0x00400f38,
232 0x00400f1c,
233 0x00400f3c,
234 NV10_PGRAPH_XFMODE0,
235 NV10_PGRAPH_XFMODE1,
236 NV10_PGRAPH_GLOBALSTATE0,
237 NV10_PGRAPH_GLOBALSTATE1,
238 NV04_PGRAPH_STORED_FMT,
239 NV04_PGRAPH_SOURCE_COLOR,
240 NV03_PGRAPH_ABS_X_RAM, /* 32 values from 0x400400 to 0x40047c */
241 NV03_PGRAPH_ABS_Y_RAM, /* 32 values from 0x400480 to 0x4004fc */
242 0x00400404,
243 0x00400484,
244 0x00400408,
245 0x00400488,
246 0x0040040c,
247 0x0040048c,
248 0x00400410,
249 0x00400490,
250 0x00400414,
251 0x00400494,
252 0x00400418,
253 0x00400498,
254 0x0040041c,
255 0x0040049c,
256 0x00400420,
257 0x004004a0,
258 0x00400424,
259 0x004004a4,
260 0x00400428,
261 0x004004a8,
262 0x0040042c,
263 0x004004ac,
264 0x00400430,
265 0x004004b0,
266 0x00400434,
267 0x004004b4,
268 0x00400438,
269 0x004004b8,
270 0x0040043c,
271 0x004004bc,
272 0x00400440,
273 0x004004c0,
274 0x00400444,
275 0x004004c4,
276 0x00400448,
277 0x004004c8,
278 0x0040044c,
279 0x004004cc,
280 0x00400450,
281 0x004004d0,
282 0x00400454,
283 0x004004d4,
284 0x00400458,
285 0x004004d8,
286 0x0040045c,
287 0x004004dc,
288 0x00400460,
289 0x004004e0,
290 0x00400464,
291 0x004004e4,
292 0x00400468,
293 0x004004e8,
294 0x0040046c,
295 0x004004ec,
296 0x00400470,
297 0x004004f0,
298 0x00400474,
299 0x004004f4,
300 0x00400478,
301 0x004004f8,
302 0x0040047c,
303 0x004004fc,
304 NV03_PGRAPH_ABS_UCLIP_XMIN,
305 NV03_PGRAPH_ABS_UCLIP_XMAX,
306 NV03_PGRAPH_ABS_UCLIP_YMIN,
307 NV03_PGRAPH_ABS_UCLIP_YMAX,
308 0x00400550,
309 0x00400558,
310 0x00400554,
311 0x0040055c,
312 NV03_PGRAPH_ABS_UCLIPA_XMIN,
313 NV03_PGRAPH_ABS_UCLIPA_XMAX,
314 NV03_PGRAPH_ABS_UCLIPA_YMIN,
315 NV03_PGRAPH_ABS_UCLIPA_YMAX,
316 NV03_PGRAPH_ABS_ICLIP_XMAX,
317 NV03_PGRAPH_ABS_ICLIP_YMAX,
318 NV03_PGRAPH_XY_LOGIC_MISC0,
319 NV03_PGRAPH_XY_LOGIC_MISC1,
320 NV03_PGRAPH_XY_LOGIC_MISC2,
321 NV03_PGRAPH_XY_LOGIC_MISC3,
322 NV03_PGRAPH_CLIPX_0,
323 NV03_PGRAPH_CLIPX_1,
324 NV03_PGRAPH_CLIPY_0,
325 NV03_PGRAPH_CLIPY_1,
326 NV10_PGRAPH_COMBINER0_IN_ALPHA,
327 NV10_PGRAPH_COMBINER1_IN_ALPHA,
328 NV10_PGRAPH_COMBINER0_IN_RGB,
329 NV10_PGRAPH_COMBINER1_IN_RGB,
330 NV10_PGRAPH_COMBINER_COLOR0,
331 NV10_PGRAPH_COMBINER_COLOR1,
332 NV10_PGRAPH_COMBINER0_OUT_ALPHA,
333 NV10_PGRAPH_COMBINER1_OUT_ALPHA,
334 NV10_PGRAPH_COMBINER0_OUT_RGB,
335 NV10_PGRAPH_COMBINER1_OUT_RGB,
336 NV10_PGRAPH_COMBINER_FINAL0,
337 NV10_PGRAPH_COMBINER_FINAL1,
338 0x00400e00,
339 0x00400e04,
340 0x00400e08,
341 0x00400e0c,
342 0x00400e10,
343 0x00400e14,
344 0x00400e18,
345 0x00400e1c,
346 0x00400e20,
347 0x00400e24,
348 0x00400e28,
349 0x00400e2c,
350 0x00400e30,
351 0x00400e34,
352 0x00400e38,
353 0x00400e3c,
354 NV04_PGRAPH_PASSTHRU_0,
355 NV04_PGRAPH_PASSTHRU_1,
356 NV04_PGRAPH_PASSTHRU_2,
357 NV10_PGRAPH_DIMX_TEXTURE,
358 NV10_PGRAPH_WDIMX_TEXTURE,
359 NV10_PGRAPH_DVD_COLORFMT,
360 NV10_PGRAPH_SCALED_FORMAT,
361 NV04_PGRAPH_MISC24_0,
362 NV04_PGRAPH_MISC24_1,
363 NV04_PGRAPH_MISC24_2,
364 NV03_PGRAPH_X_MISC,
365 NV03_PGRAPH_Y_MISC,
366 NV04_PGRAPH_VALID1,
367 NV04_PGRAPH_VALID2,
368};
369
370static int nv17_graph_ctx_regs[] = {
371 NV10_PGRAPH_DEBUG_4,
372 0x004006b0,
373 0x00400eac,
374 0x00400eb0,
375 0x00400eb4,
376 0x00400eb8,
377 0x00400ebc,
378 0x00400ec0,
379 0x00400ec4,
380 0x00400ec8,
381 0x00400ecc,
382 0x00400ed0,
383 0x00400ed4,
384 0x00400ed8,
385 0x00400edc,
386 0x00400ee0,
387 0x00400a00,
388 0x00400a04,
389};
390
391struct graph_state {
392 int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)];
393 int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)];
394 struct pipe_state pipe_state;
395 uint32_t lma_window[4];
396};
397
398#define PIPE_SAVE(dev, state, addr) \
399 do { \
400 int __i; \
401 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \
402 for (__i = 0; __i < ARRAY_SIZE(state); __i++) \
403 state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \
404 } while (0)
405
406#define PIPE_RESTORE(dev, state, addr) \
407 do { \
408 int __i; \
409 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \
410 for (__i = 0; __i < ARRAY_SIZE(state); __i++) \
411 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \
412 } while (0)
413
414static void nv10_graph_save_pipe(struct nouveau_channel *chan)
415{
416 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
417 struct pipe_state *pipe = &pgraph_ctx->pipe_state;
418 struct drm_device *dev = chan->dev;
419
420 PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
421 PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
422 PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400);
423 PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800);
424 PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00);
425 PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000);
426 PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400);
427 PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800);
428 PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040);
429 PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000);
430}
431
432static void nv10_graph_load_pipe(struct nouveau_channel *chan)
433{
434 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
435 struct pipe_state *pipe = &pgraph_ctx->pipe_state;
436 struct drm_device *dev = chan->dev;
437 uint32_t xfmode0, xfmode1;
438 int i;
439
440 nouveau_wait_for_idle(dev);
441 /* XXX check haiku comments */
442 xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
443 xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
444 nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
445 nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
446 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
447 for (i = 0; i < 4; i++)
448 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
449 for (i = 0; i < 4; i++)
450 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
451
452 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
453 for (i = 0; i < 3; i++)
454 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
455
456 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
457 for (i = 0; i < 3; i++)
458 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
459
460 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
461 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
462
463
464 PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
465 nouveau_wait_for_idle(dev);
466
467 /* restore XFMODE */
468 nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
469 nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
470 PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400);
471 PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800);
472 PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00);
473 PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000);
474 PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400);
475 PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800);
476 PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
477 PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000);
478 PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040);
479 nouveau_wait_for_idle(dev);
480}
481
482static void nv10_graph_create_pipe(struct nouveau_channel *chan)
483{
484 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
485 struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
486 struct drm_device *dev = chan->dev;
487 uint32_t *fifo_pipe_state_addr;
488 int i;
489#define PIPE_INIT(addr) \
490 do { \
491 fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \
492 } while (0)
493#define PIPE_INIT_END(addr) \
494 do { \
495 uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \
496 ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \
497 if (fifo_pipe_state_addr != __end_addr) \
498 NV_ERROR(dev, "incomplete pipe init for 0x%x : %p/%p\n", \
499 addr, fifo_pipe_state_addr, __end_addr); \
500 } while (0)
501#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value
502
503 PIPE_INIT(0x0200);
504 for (i = 0; i < 48; i++)
505 NV_WRITE_PIPE_INIT(0x00000000);
506 PIPE_INIT_END(0x0200);
507
508 PIPE_INIT(0x6400);
509 for (i = 0; i < 211; i++)
510 NV_WRITE_PIPE_INIT(0x00000000);
511 NV_WRITE_PIPE_INIT(0x3f800000);
512 NV_WRITE_PIPE_INIT(0x40000000);
513 NV_WRITE_PIPE_INIT(0x40000000);
514 NV_WRITE_PIPE_INIT(0x40000000);
515 NV_WRITE_PIPE_INIT(0x40000000);
516 NV_WRITE_PIPE_INIT(0x00000000);
517 NV_WRITE_PIPE_INIT(0x00000000);
518 NV_WRITE_PIPE_INIT(0x3f800000);
519 NV_WRITE_PIPE_INIT(0x00000000);
520 NV_WRITE_PIPE_INIT(0x3f000000);
521 NV_WRITE_PIPE_INIT(0x3f000000);
522 NV_WRITE_PIPE_INIT(0x00000000);
523 NV_WRITE_PIPE_INIT(0x00000000);
524 NV_WRITE_PIPE_INIT(0x00000000);
525 NV_WRITE_PIPE_INIT(0x00000000);
526 NV_WRITE_PIPE_INIT(0x3f800000);
527 NV_WRITE_PIPE_INIT(0x00000000);
528 NV_WRITE_PIPE_INIT(0x00000000);
529 NV_WRITE_PIPE_INIT(0x00000000);
530 NV_WRITE_PIPE_INIT(0x00000000);
531 NV_WRITE_PIPE_INIT(0x00000000);
532 NV_WRITE_PIPE_INIT(0x3f800000);
533 NV_WRITE_PIPE_INIT(0x3f800000);
534 NV_WRITE_PIPE_INIT(0x3f800000);
535 NV_WRITE_PIPE_INIT(0x3f800000);
536 PIPE_INIT_END(0x6400);
537
538 PIPE_INIT(0x6800);
539 for (i = 0; i < 162; i++)
540 NV_WRITE_PIPE_INIT(0x00000000);
541 NV_WRITE_PIPE_INIT(0x3f800000);
542 for (i = 0; i < 25; i++)
543 NV_WRITE_PIPE_INIT(0x00000000);
544 PIPE_INIT_END(0x6800);
545
546 PIPE_INIT(0x6c00);
547 NV_WRITE_PIPE_INIT(0x00000000);
548 NV_WRITE_PIPE_INIT(0x00000000);
549 NV_WRITE_PIPE_INIT(0x00000000);
550 NV_WRITE_PIPE_INIT(0x00000000);
551 NV_WRITE_PIPE_INIT(0xbf800000);
552 NV_WRITE_PIPE_INIT(0x00000000);
553 NV_WRITE_PIPE_INIT(0x00000000);
554 NV_WRITE_PIPE_INIT(0x00000000);
555 NV_WRITE_PIPE_INIT(0x00000000);
556 NV_WRITE_PIPE_INIT(0x00000000);
557 NV_WRITE_PIPE_INIT(0x00000000);
558 NV_WRITE_PIPE_INIT(0x00000000);
559 PIPE_INIT_END(0x6c00);
560
561 PIPE_INIT(0x7000);
562 NV_WRITE_PIPE_INIT(0x00000000);
563 NV_WRITE_PIPE_INIT(0x00000000);
564 NV_WRITE_PIPE_INIT(0x00000000);
565 NV_WRITE_PIPE_INIT(0x00000000);
566 NV_WRITE_PIPE_INIT(0x00000000);
567 NV_WRITE_PIPE_INIT(0x00000000);
568 NV_WRITE_PIPE_INIT(0x00000000);
569 NV_WRITE_PIPE_INIT(0x00000000);
570 NV_WRITE_PIPE_INIT(0x00000000);
571 NV_WRITE_PIPE_INIT(0x00000000);
572 NV_WRITE_PIPE_INIT(0x00000000);
573 NV_WRITE_PIPE_INIT(0x00000000);
574 NV_WRITE_PIPE_INIT(0x7149f2ca);
575 NV_WRITE_PIPE_INIT(0x00000000);
576 NV_WRITE_PIPE_INIT(0x00000000);
577 NV_WRITE_PIPE_INIT(0x00000000);
578 NV_WRITE_PIPE_INIT(0x7149f2ca);
579 NV_WRITE_PIPE_INIT(0x00000000);
580 NV_WRITE_PIPE_INIT(0x00000000);
581 NV_WRITE_PIPE_INIT(0x00000000);
582 NV_WRITE_PIPE_INIT(0x7149f2ca);
583 NV_WRITE_PIPE_INIT(0x00000000);
584 NV_WRITE_PIPE_INIT(0x00000000);
585 NV_WRITE_PIPE_INIT(0x00000000);
586 NV_WRITE_PIPE_INIT(0x7149f2ca);
587 NV_WRITE_PIPE_INIT(0x00000000);
588 NV_WRITE_PIPE_INIT(0x00000000);
589 NV_WRITE_PIPE_INIT(0x00000000);
590 NV_WRITE_PIPE_INIT(0x7149f2ca);
591 NV_WRITE_PIPE_INIT(0x00000000);
592 NV_WRITE_PIPE_INIT(0x00000000);
593 NV_WRITE_PIPE_INIT(0x00000000);
594 NV_WRITE_PIPE_INIT(0x7149f2ca);
595 NV_WRITE_PIPE_INIT(0x00000000);
596 NV_WRITE_PIPE_INIT(0x00000000);
597 NV_WRITE_PIPE_INIT(0x00000000);
598 NV_WRITE_PIPE_INIT(0x7149f2ca);
599 NV_WRITE_PIPE_INIT(0x00000000);
600 NV_WRITE_PIPE_INIT(0x00000000);
601 NV_WRITE_PIPE_INIT(0x00000000);
602 NV_WRITE_PIPE_INIT(0x7149f2ca);
603 for (i = 0; i < 35; i++)
604 NV_WRITE_PIPE_INIT(0x00000000);
605 PIPE_INIT_END(0x7000);
606
607 PIPE_INIT(0x7400);
608 for (i = 0; i < 48; i++)
609 NV_WRITE_PIPE_INIT(0x00000000);
610 PIPE_INIT_END(0x7400);
611
612 PIPE_INIT(0x7800);
613 for (i = 0; i < 48; i++)
614 NV_WRITE_PIPE_INIT(0x00000000);
615 PIPE_INIT_END(0x7800);
616
617 PIPE_INIT(0x4400);
618 for (i = 0; i < 32; i++)
619 NV_WRITE_PIPE_INIT(0x00000000);
620 PIPE_INIT_END(0x4400);
621
622 PIPE_INIT(0x0000);
623 for (i = 0; i < 16; i++)
624 NV_WRITE_PIPE_INIT(0x00000000);
625 PIPE_INIT_END(0x0000);
626
627 PIPE_INIT(0x0040);
628 for (i = 0; i < 4; i++)
629 NV_WRITE_PIPE_INIT(0x00000000);
630 PIPE_INIT_END(0x0040);
631
632#undef PIPE_INIT
633#undef PIPE_INIT_END
634#undef NV_WRITE_PIPE_INIT
635}
636
637static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
638{
639 int i;
640 for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) {
641 if (nv10_graph_ctx_regs[i] == reg)
642 return i;
643 }
644 NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg);
645 return -1;
646}
647
648static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
649{
650 int i;
651 for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) {
652 if (nv17_graph_ctx_regs[i] == reg)
653 return i;
654 }
655 NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg);
656 return -1;
657}
658
659static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
660 uint32_t inst)
661{
662 struct drm_device *dev = chan->dev;
663 uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4];
664 uint32_t ctx_user, ctx_switch[5];
665 int i, subchan = -1;
666
667 /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state
668 * that cannot be restored via MMIO. Do it through the FIFO
669 * instead.
670 */
671
672 /* Look for a celsius object */
673 for (i = 0; i < 8; i++) {
674 int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff;
675
676 if (class == 0x56 || class == 0x96 || class == 0x99) {
677 subchan = i;
678 break;
679 }
680 }
681
682 if (subchan < 0 || !inst)
683 return;
684
685 /* Save the current ctx object */
686 ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
687 for (i = 0; i < 5; i++)
688 ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i));
689
690 /* Save the FIFO state */
691 st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2);
692 st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL);
693 st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH);
694 fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR);
695
696 for (i = 0; i < ARRAY_SIZE(fifo); i++)
697 fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i);
698
699 /* Switch to the celsius subchannel */
700 for (i = 0; i < 5; i++)
701 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i),
702 nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i)));
703 nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13);
704
705 /* Inject NV10TCL_DMA_VTXBUF */
706 nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0);
707 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2,
708 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
709 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
710 nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
711 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
712 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
713
714 /* Restore the FIFO state */
715 for (i = 0; i < ARRAY_SIZE(fifo); i++)
716 nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]);
717
718 nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr);
719 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2);
720 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl);
721 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh);
722
723 /* Restore the current ctx object */
724 for (i = 0; i < 5; i++)
725 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]);
726 nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user);
727}
728
729static int
730nv10_graph_load_context(struct nouveau_channel *chan)
731{
732 struct drm_device *dev = chan->dev;
733 struct drm_nouveau_private *dev_priv = dev->dev_private;
734 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
735 uint32_t tmp;
736 int i;
737
738 for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
739 nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]);
740 if (dev_priv->chipset >= 0x17) {
741 for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
742 nv_wr32(dev, nv17_graph_ctx_regs[i],
743 pgraph_ctx->nv17[i]);
744 }
745
746 nv10_graph_load_pipe(chan);
747 nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1)
748 & 0xffff));
749
750 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
751 tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
752 nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24);
753 tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2);
754 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff);
755 return 0;
756}
757
758static int
759nv10_graph_unload_context(struct drm_device *dev)
760{
761 struct drm_nouveau_private *dev_priv = dev->dev_private;
762 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
763 struct nouveau_channel *chan;
764 struct graph_state *ctx;
765 uint32_t tmp;
766 int i;
767
768 chan = nv10_graph_channel(dev);
769 if (!chan)
770 return 0;
771 ctx = chan->engctx[NVOBJ_ENGINE_GR];
772
773 for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
774 ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]);
775
776 if (dev_priv->chipset >= 0x17) {
777 for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
778 ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]);
779 }
780
781 nv10_graph_save_pipe(chan);
782
783 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
784 tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
785 tmp |= (pfifo->channels - 1) << 24;
786 nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
787 return 0;
788}
789
790static void
791nv10_graph_context_switch(struct drm_device *dev)
792{
793 struct drm_nouveau_private *dev_priv = dev->dev_private;
794 struct nouveau_channel *chan = NULL;
795 int chid;
796
797 nouveau_wait_for_idle(dev);
798
799 /* If previous context is valid, we need to save it */
800 nv10_graph_unload_context(dev);
801
802 /* Load context for next channel */
803 chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
804 chan = dev_priv->channels.ptr[chid];
805 if (chan && chan->engctx[NVOBJ_ENGINE_GR])
806 nv10_graph_load_context(chan);
807}
808
809#define NV_WRITE_CTX(reg, val) do { \
810 int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
811 if (offset > 0) \
812 pgraph_ctx->nv10[offset] = val; \
813 } while (0)
814
815#define NV17_WRITE_CTX(reg, val) do { \
816 int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \
817 if (offset > 0) \
818 pgraph_ctx->nv17[offset] = val; \
819 } while (0)
820
821struct nouveau_channel *
822nv10_graph_channel(struct drm_device *dev)
823{
824 struct drm_nouveau_private *dev_priv = dev->dev_private;
825 int chid = dev_priv->engine.fifo.channels;
826
827 if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000)
828 chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24;
829
830 if (chid >= dev_priv->engine.fifo.channels)
831 return NULL;
832
833 return dev_priv->channels.ptr[chid];
834}
835
836static int
837nv10_graph_context_new(struct nouveau_channel *chan, int engine)
838{
839 struct drm_device *dev = chan->dev;
840 struct drm_nouveau_private *dev_priv = dev->dev_private;
841 struct graph_state *pgraph_ctx;
842
843 NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id);
844
845 pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL);
846 if (pgraph_ctx == NULL)
847 return -ENOMEM;
848 chan->engctx[engine] = pgraph_ctx;
849
850 NV_WRITE_CTX(0x00400e88, 0x08000000);
851 NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
852 NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
853 NV_WRITE_CTX(0x00400e10, 0x00001000);
854 NV_WRITE_CTX(0x00400e14, 0x00001000);
855 NV_WRITE_CTX(0x00400e30, 0x00080008);
856 NV_WRITE_CTX(0x00400e34, 0x00080008);
857 if (dev_priv->chipset >= 0x17) {
858 /* is it really needed ??? */
859 NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
860 nv_rd32(dev, NV10_PGRAPH_DEBUG_4));
861 NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0));
862 NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
863 NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
864 NV17_WRITE_CTX(0x00400ec0, 0x00000080);
865 NV17_WRITE_CTX(0x00400ed0, 0x00000080);
866 }
867 NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24);
868
869 nv10_graph_create_pipe(chan);
870 return 0;
871}
872
873static void
874nv10_graph_context_del(struct nouveau_channel *chan, int engine)
875{
876 struct drm_device *dev = chan->dev;
877 struct drm_nouveau_private *dev_priv = dev->dev_private;
878 struct graph_state *pgraph_ctx = chan->engctx[engine];
879 unsigned long flags;
880
881 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
882 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
883
884 /* Unload the context if it's the currently active one */
885 if (nv10_graph_channel(dev) == chan)
886 nv10_graph_unload_context(dev);
887
888 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
889 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
890
891 /* Free the context resources */
892 chan->engctx[engine] = NULL;
893 kfree(pgraph_ctx);
894}
895
896static void
897nv10_graph_set_tile_region(struct drm_device *dev, int i)
898{
899 struct drm_nouveau_private *dev_priv = dev->dev_private;
900 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
901
902 nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit);
903 nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch);
904 nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr);
905}
906
907static int
908nv10_graph_init(struct drm_device *dev, int engine)
909{
910 struct drm_nouveau_private *dev_priv = dev->dev_private;
911 u32 tmp;
912 int i;
913
914 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
915 ~NV_PMC_ENABLE_PGRAPH);
916 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
917 NV_PMC_ENABLE_PGRAPH);
918
919 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
920 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
921
922 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
923 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
924 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700);
925 /* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
926 nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
927 nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
928 (1<<29) |
929 (1<<31));
930 if (dev_priv->chipset >= 0x17) {
931 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000);
932 nv_wr32(dev, 0x400a10, 0x3ff3fb6);
933 nv_wr32(dev, 0x400838, 0x2f8684);
934 nv_wr32(dev, 0x40083c, 0x115f3f);
935 nv_wr32(dev, 0x004006b0, 0x40000020);
936 } else
937 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
938
939 /* Turn all the tiling regions off. */
940 for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
941 nv10_graph_set_tile_region(dev, i);
942
943 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000);
944 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000);
945 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000);
946 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000);
947 nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000);
948 nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF);
949
950 tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
951 tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
952 nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
953 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
954 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
955
956 return 0;
957}
958
959static int
960nv10_graph_fini(struct drm_device *dev, int engine, bool suspend)
961{
962 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
963 if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
964 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
965 return -EBUSY;
966 }
967 nv10_graph_unload_context(dev);
968 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
969 return 0;
970}
971
972static int
973nv17_graph_mthd_lma_window(struct nouveau_channel *chan,
974 u32 class, u32 mthd, u32 data)
975{
976 struct graph_state *ctx = chan->engctx[NVOBJ_ENGINE_GR];
977 struct drm_device *dev = chan->dev;
978 struct pipe_state *pipe = &ctx->pipe_state;
979 uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
980 uint32_t xfmode0, xfmode1;
981 int i;
982
983 ctx->lma_window[(mthd - 0x1638) / 4] = data;
984
985 if (mthd != 0x1644)
986 return 0;
987
988 nouveau_wait_for_idle(dev);
989
990 PIPE_SAVE(dev, pipe_0x0040, 0x0040);
991 PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
992
993 PIPE_RESTORE(dev, ctx->lma_window, 0x6790);
994
995 nouveau_wait_for_idle(dev);
996
997 xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
998 xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
999
1000 PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
1001 PIPE_SAVE(dev, pipe_0x64c0, 0x64c0);
1002 PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0);
1003 PIPE_SAVE(dev, pipe_0x6a80, 0x6a80);
1004
1005 nouveau_wait_for_idle(dev);
1006
1007 nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
1008 nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
1009 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
1010 for (i = 0; i < 4; i++)
1011 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
1012 for (i = 0; i < 4; i++)
1013 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
1014
1015 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
1016 for (i = 0; i < 3; i++)
1017 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
1018
1019 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
1020 for (i = 0; i < 3; i++)
1021 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
1022
1023 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
1024 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
1025
1026 PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
1027
1028 nouveau_wait_for_idle(dev);
1029
1030 PIPE_RESTORE(dev, pipe_0x0040, 0x0040);
1031
1032 nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
1033 nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
1034
1035 PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0);
1036 PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0);
1037 PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80);
1038 PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
1039
1040 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
1041 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
1042
1043 nouveau_wait_for_idle(dev);
1044
1045 return 0;
1046}
1047
1048static int
1049nv17_graph_mthd_lma_enable(struct nouveau_channel *chan,
1050 u32 class, u32 mthd, u32 data)
1051{
1052 struct drm_device *dev = chan->dev;
1053
1054 nouveau_wait_for_idle(dev);
1055
1056 nv_wr32(dev, NV10_PGRAPH_DEBUG_4,
1057 nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8);
1058 nv_wr32(dev, 0x004006b0,
1059 nv_rd32(dev, 0x004006b0) | 0x8 << 24);
1060
1061 return 0;
1062}
1063
1064struct nouveau_bitfield nv10_graph_intr[] = {
1065 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1066 { NV_PGRAPH_INTR_ERROR, "ERROR" },
1067 {}
1068};
1069
1070struct nouveau_bitfield nv10_graph_nstatus[] = {
1071 { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
1072 { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
1073 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
1074 { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
1075 {}
1076};
1077
1078static void
1079nv10_graph_isr(struct drm_device *dev)
1080{
1081 u32 stat;
1082
1083 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1084 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
1085 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
1086 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
1087 u32 chid = (addr & 0x01f00000) >> 20;
1088 u32 subc = (addr & 0x00070000) >> 16;
1089 u32 mthd = (addr & 0x00001ffc);
1090 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
1091 u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
1092 u32 show = stat;
1093
1094 if (stat & NV_PGRAPH_INTR_ERROR) {
1095 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
1096 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
1097 show &= ~NV_PGRAPH_INTR_ERROR;
1098 }
1099 }
1100
1101 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1102 nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1103 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1104 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1105 nv10_graph_context_switch(dev);
1106 }
1107
1108 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
1109 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
1110
1111 if (show && nouveau_ratelimit()) {
1112 NV_INFO(dev, "PGRAPH -");
1113 nouveau_bitfield_print(nv10_graph_intr, show);
1114 printk(" nsource:");
1115 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1116 printk(" nstatus:");
1117 nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
1118 printk("\n");
1119 NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
1120 "mthd 0x%04x data 0x%08x\n",
1121 chid, subc, class, mthd, data);
1122 }
1123 }
1124}
1125
1126static void
1127nv10_graph_destroy(struct drm_device *dev, int engine)
1128{
1129 struct nv10_graph_engine *pgraph = nv_engine(dev, engine);
1130
1131 nouveau_irq_unregister(dev, 12);
1132 kfree(pgraph);
1133}
1134
1135int
1136nv10_graph_create(struct drm_device *dev)
1137{
1138 struct drm_nouveau_private *dev_priv = dev->dev_private;
1139 struct nv10_graph_engine *pgraph;
1140
1141 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
1142 if (!pgraph)
1143 return -ENOMEM;
1144
1145 pgraph->base.destroy = nv10_graph_destroy;
1146 pgraph->base.init = nv10_graph_init;
1147 pgraph->base.fini = nv10_graph_fini;
1148 pgraph->base.context_new = nv10_graph_context_new;
1149 pgraph->base.context_del = nv10_graph_context_del;
1150 pgraph->base.object_new = nv04_graph_object_new;
1151 pgraph->base.set_tile_region = nv10_graph_set_tile_region;
1152
1153 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
1154 nouveau_irq_register(dev, 12, nv10_graph_isr);
1155
1156 /* nvsw */
1157 NVOBJ_CLASS(dev, 0x506e, SW);
1158 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
1159
1160 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
1161 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
1162 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
1163 NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */
1164 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
1165 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
1166 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
1167 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
1168 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
1169 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
1170 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
1171 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
1172 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
1173 NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */
1174 NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */
1175 NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */
1176 NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */
1177
1178 /* celcius */
1179 if (dev_priv->chipset <= 0x10) {
1180 NVOBJ_CLASS(dev, 0x0056, GR);
1181 } else
1182 if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) {
1183 NVOBJ_CLASS(dev, 0x0096, GR);
1184 } else {
1185 NVOBJ_CLASS(dev, 0x0099, GR);
1186 NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window);
1187 NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window);
1188 NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window);
1189 NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window);
1190 NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable);
1191 }
1192
1193 return 0;
1194}
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c
new file mode 100644
index 00000000000..183e37512ef
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv20_graph.c
@@ -0,0 +1,842 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6/*
7 * NV20
8 * -----
9 * There are 3 families :
10 * NV20 is 0x10de:0x020*
11 * NV25/28 is 0x10de:0x025* / 0x10de:0x028*
12 * NV2A is 0x10de:0x02A0
13 *
14 * NV30
15 * -----
16 * There are 3 families :
17 * NV30/31 is 0x10de:0x030* / 0x10de:0x031*
18 * NV34 is 0x10de:0x032*
19 * NV35/36 is 0x10de:0x033* / 0x10de:0x034*
20 *
21 * Not seen in the wild, no dumps (probably NV35) :
22 * NV37 is 0x10de:0x00fc, 0x10de:0x00fd
23 * NV38 is 0x10de:0x0333, 0x10de:0x00fe
24 *
25 */
26
27struct nv20_graph_engine {
28 struct nouveau_exec_engine base;
29 struct nouveau_gpuobj *ctxtab;
30 void (*grctx_init)(struct nouveau_gpuobj *);
31 u32 grctx_size;
32 u32 grctx_user;
33};
34
35#define NV20_GRCTX_SIZE (3580*4)
36#define NV25_GRCTX_SIZE (3529*4)
37#define NV2A_GRCTX_SIZE (3500*4)
38
39#define NV30_31_GRCTX_SIZE (24392)
40#define NV34_GRCTX_SIZE (18140)
41#define NV35_36_GRCTX_SIZE (22396)
42
43int
44nv20_graph_unload_context(struct drm_device *dev)
45{
46 struct drm_nouveau_private *dev_priv = dev->dev_private;
47 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
48 struct nouveau_channel *chan;
49 struct nouveau_gpuobj *grctx;
50 u32 tmp;
51
52 chan = nv10_graph_channel(dev);
53 if (!chan)
54 return 0;
55 grctx = chan->engctx[NVOBJ_ENGINE_GR];
56
57 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->pinst >> 4);
58 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
59 NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
60
61 nouveau_wait_for_idle(dev);
62
63 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
64 tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
65 tmp |= (pfifo->channels - 1) << 24;
66 nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
67 return 0;
68}
69
70static void
71nv20_graph_rdi(struct drm_device *dev)
72{
73 struct drm_nouveau_private *dev_priv = dev->dev_private;
74 int i, writecount = 32;
75 uint32_t rdi_index = 0x2c80000;
76
77 if (dev_priv->chipset == 0x20) {
78 rdi_index = 0x3d0000;
79 writecount = 15;
80 }
81
82 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index);
83 for (i = 0; i < writecount; i++)
84 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0);
85
86 nouveau_wait_for_idle(dev);
87}
88
89static void
90nv20_graph_context_init(struct nouveau_gpuobj *ctx)
91{
92 int i;
93
94 nv_wo32(ctx, 0x033c, 0xffff0000);
95 nv_wo32(ctx, 0x03a0, 0x0fff0000);
96 nv_wo32(ctx, 0x03a4, 0x0fff0000);
97 nv_wo32(ctx, 0x047c, 0x00000101);
98 nv_wo32(ctx, 0x0490, 0x00000111);
99 nv_wo32(ctx, 0x04a8, 0x44400000);
100 for (i = 0x04d4; i <= 0x04e0; i += 4)
101 nv_wo32(ctx, i, 0x00030303);
102 for (i = 0x04f4; i <= 0x0500; i += 4)
103 nv_wo32(ctx, i, 0x00080000);
104 for (i = 0x050c; i <= 0x0518; i += 4)
105 nv_wo32(ctx, i, 0x01012000);
106 for (i = 0x051c; i <= 0x0528; i += 4)
107 nv_wo32(ctx, i, 0x000105b8);
108 for (i = 0x052c; i <= 0x0538; i += 4)
109 nv_wo32(ctx, i, 0x00080008);
110 for (i = 0x055c; i <= 0x0598; i += 4)
111 nv_wo32(ctx, i, 0x07ff0000);
112 nv_wo32(ctx, 0x05a4, 0x4b7fffff);
113 nv_wo32(ctx, 0x05fc, 0x00000001);
114 nv_wo32(ctx, 0x0604, 0x00004000);
115 nv_wo32(ctx, 0x0610, 0x00000001);
116 nv_wo32(ctx, 0x0618, 0x00040000);
117 nv_wo32(ctx, 0x061c, 0x00010000);
118 for (i = 0x1c1c; i <= 0x248c; i += 16) {
119 nv_wo32(ctx, (i + 0), 0x10700ff9);
120 nv_wo32(ctx, (i + 4), 0x0436086c);
121 nv_wo32(ctx, (i + 8), 0x000c001b);
122 }
123 nv_wo32(ctx, 0x281c, 0x3f800000);
124 nv_wo32(ctx, 0x2830, 0x3f800000);
125 nv_wo32(ctx, 0x285c, 0x40000000);
126 nv_wo32(ctx, 0x2860, 0x3f800000);
127 nv_wo32(ctx, 0x2864, 0x3f000000);
128 nv_wo32(ctx, 0x286c, 0x40000000);
129 nv_wo32(ctx, 0x2870, 0x3f800000);
130 nv_wo32(ctx, 0x2878, 0xbf800000);
131 nv_wo32(ctx, 0x2880, 0xbf800000);
132 nv_wo32(ctx, 0x34a4, 0x000fe000);
133 nv_wo32(ctx, 0x3530, 0x000003f8);
134 nv_wo32(ctx, 0x3540, 0x002fe000);
135 for (i = 0x355c; i <= 0x3578; i += 4)
136 nv_wo32(ctx, i, 0x001c527c);
137}
138
139static void
140nv25_graph_context_init(struct nouveau_gpuobj *ctx)
141{
142 int i;
143
144 nv_wo32(ctx, 0x035c, 0xffff0000);
145 nv_wo32(ctx, 0x03c0, 0x0fff0000);
146 nv_wo32(ctx, 0x03c4, 0x0fff0000);
147 nv_wo32(ctx, 0x049c, 0x00000101);
148 nv_wo32(ctx, 0x04b0, 0x00000111);
149 nv_wo32(ctx, 0x04c8, 0x00000080);
150 nv_wo32(ctx, 0x04cc, 0xffff0000);
151 nv_wo32(ctx, 0x04d0, 0x00000001);
152 nv_wo32(ctx, 0x04e4, 0x44400000);
153 nv_wo32(ctx, 0x04fc, 0x4b800000);
154 for (i = 0x0510; i <= 0x051c; i += 4)
155 nv_wo32(ctx, i, 0x00030303);
156 for (i = 0x0530; i <= 0x053c; i += 4)
157 nv_wo32(ctx, i, 0x00080000);
158 for (i = 0x0548; i <= 0x0554; i += 4)
159 nv_wo32(ctx, i, 0x01012000);
160 for (i = 0x0558; i <= 0x0564; i += 4)
161 nv_wo32(ctx, i, 0x000105b8);
162 for (i = 0x0568; i <= 0x0574; i += 4)
163 nv_wo32(ctx, i, 0x00080008);
164 for (i = 0x0598; i <= 0x05d4; i += 4)
165 nv_wo32(ctx, i, 0x07ff0000);
166 nv_wo32(ctx, 0x05e0, 0x4b7fffff);
167 nv_wo32(ctx, 0x0620, 0x00000080);
168 nv_wo32(ctx, 0x0624, 0x30201000);
169 nv_wo32(ctx, 0x0628, 0x70605040);
170 nv_wo32(ctx, 0x062c, 0xb0a09080);
171 nv_wo32(ctx, 0x0630, 0xf0e0d0c0);
172 nv_wo32(ctx, 0x0664, 0x00000001);
173 nv_wo32(ctx, 0x066c, 0x00004000);
174 nv_wo32(ctx, 0x0678, 0x00000001);
175 nv_wo32(ctx, 0x0680, 0x00040000);
176 nv_wo32(ctx, 0x0684, 0x00010000);
177 for (i = 0x1b04; i <= 0x2374; i += 16) {
178 nv_wo32(ctx, (i + 0), 0x10700ff9);
179 nv_wo32(ctx, (i + 4), 0x0436086c);
180 nv_wo32(ctx, (i + 8), 0x000c001b);
181 }
182 nv_wo32(ctx, 0x2704, 0x3f800000);
183 nv_wo32(ctx, 0x2718, 0x3f800000);
184 nv_wo32(ctx, 0x2744, 0x40000000);
185 nv_wo32(ctx, 0x2748, 0x3f800000);
186 nv_wo32(ctx, 0x274c, 0x3f000000);
187 nv_wo32(ctx, 0x2754, 0x40000000);
188 nv_wo32(ctx, 0x2758, 0x3f800000);
189 nv_wo32(ctx, 0x2760, 0xbf800000);
190 nv_wo32(ctx, 0x2768, 0xbf800000);
191 nv_wo32(ctx, 0x308c, 0x000fe000);
192 nv_wo32(ctx, 0x3108, 0x000003f8);
193 nv_wo32(ctx, 0x3468, 0x002fe000);
194 for (i = 0x3484; i <= 0x34a0; i += 4)
195 nv_wo32(ctx, i, 0x001c527c);
196}
197
198static void
199nv2a_graph_context_init(struct nouveau_gpuobj *ctx)
200{
201 int i;
202
203 nv_wo32(ctx, 0x033c, 0xffff0000);
204 nv_wo32(ctx, 0x03a0, 0x0fff0000);
205 nv_wo32(ctx, 0x03a4, 0x0fff0000);
206 nv_wo32(ctx, 0x047c, 0x00000101);
207 nv_wo32(ctx, 0x0490, 0x00000111);
208 nv_wo32(ctx, 0x04a8, 0x44400000);
209 for (i = 0x04d4; i <= 0x04e0; i += 4)
210 nv_wo32(ctx, i, 0x00030303);
211 for (i = 0x04f4; i <= 0x0500; i += 4)
212 nv_wo32(ctx, i, 0x00080000);
213 for (i = 0x050c; i <= 0x0518; i += 4)
214 nv_wo32(ctx, i, 0x01012000);
215 for (i = 0x051c; i <= 0x0528; i += 4)
216 nv_wo32(ctx, i, 0x000105b8);
217 for (i = 0x052c; i <= 0x0538; i += 4)
218 nv_wo32(ctx, i, 0x00080008);
219 for (i = 0x055c; i <= 0x0598; i += 4)
220 nv_wo32(ctx, i, 0x07ff0000);
221 nv_wo32(ctx, 0x05a4, 0x4b7fffff);
222 nv_wo32(ctx, 0x05fc, 0x00000001);
223 nv_wo32(ctx, 0x0604, 0x00004000);
224 nv_wo32(ctx, 0x0610, 0x00000001);
225 nv_wo32(ctx, 0x0618, 0x00040000);
226 nv_wo32(ctx, 0x061c, 0x00010000);
227 for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */
228 nv_wo32(ctx, (i + 0), 0x10700ff9);
229 nv_wo32(ctx, (i + 4), 0x0436086c);
230 nv_wo32(ctx, (i + 8), 0x000c001b);
231 }
232 nv_wo32(ctx, 0x269c, 0x3f800000);
233 nv_wo32(ctx, 0x26b0, 0x3f800000);
234 nv_wo32(ctx, 0x26dc, 0x40000000);
235 nv_wo32(ctx, 0x26e0, 0x3f800000);
236 nv_wo32(ctx, 0x26e4, 0x3f000000);
237 nv_wo32(ctx, 0x26ec, 0x40000000);
238 nv_wo32(ctx, 0x26f0, 0x3f800000);
239 nv_wo32(ctx, 0x26f8, 0xbf800000);
240 nv_wo32(ctx, 0x2700, 0xbf800000);
241 nv_wo32(ctx, 0x3024, 0x000fe000);
242 nv_wo32(ctx, 0x30a0, 0x000003f8);
243 nv_wo32(ctx, 0x33fc, 0x002fe000);
244 for (i = 0x341c; i <= 0x3438; i += 4)
245 nv_wo32(ctx, i, 0x001c527c);
246}
247
248static void
249nv30_31_graph_context_init(struct nouveau_gpuobj *ctx)
250{
251 int i;
252
253 nv_wo32(ctx, 0x0410, 0x00000101);
254 nv_wo32(ctx, 0x0424, 0x00000111);
255 nv_wo32(ctx, 0x0428, 0x00000060);
256 nv_wo32(ctx, 0x0444, 0x00000080);
257 nv_wo32(ctx, 0x0448, 0xffff0000);
258 nv_wo32(ctx, 0x044c, 0x00000001);
259 nv_wo32(ctx, 0x0460, 0x44400000);
260 nv_wo32(ctx, 0x048c, 0xffff0000);
261 for (i = 0x04e0; i < 0x04e8; i += 4)
262 nv_wo32(ctx, i, 0x0fff0000);
263 nv_wo32(ctx, 0x04ec, 0x00011100);
264 for (i = 0x0508; i < 0x0548; i += 4)
265 nv_wo32(ctx, i, 0x07ff0000);
266 nv_wo32(ctx, 0x0550, 0x4b7fffff);
267 nv_wo32(ctx, 0x058c, 0x00000080);
268 nv_wo32(ctx, 0x0590, 0x30201000);
269 nv_wo32(ctx, 0x0594, 0x70605040);
270 nv_wo32(ctx, 0x0598, 0xb8a89888);
271 nv_wo32(ctx, 0x059c, 0xf8e8d8c8);
272 nv_wo32(ctx, 0x05b0, 0xb0000000);
273 for (i = 0x0600; i < 0x0640; i += 4)
274 nv_wo32(ctx, i, 0x00010588);
275 for (i = 0x0640; i < 0x0680; i += 4)
276 nv_wo32(ctx, i, 0x00030303);
277 for (i = 0x06c0; i < 0x0700; i += 4)
278 nv_wo32(ctx, i, 0x0008aae4);
279 for (i = 0x0700; i < 0x0740; i += 4)
280 nv_wo32(ctx, i, 0x01012000);
281 for (i = 0x0740; i < 0x0780; i += 4)
282 nv_wo32(ctx, i, 0x00080008);
283 nv_wo32(ctx, 0x085c, 0x00040000);
284 nv_wo32(ctx, 0x0860, 0x00010000);
285 for (i = 0x0864; i < 0x0874; i += 4)
286 nv_wo32(ctx, i, 0x00040004);
287 for (i = 0x1f18; i <= 0x3088 ; i += 16) {
288 nv_wo32(ctx, i + 0, 0x10700ff9);
289 nv_wo32(ctx, i + 1, 0x0436086c);
290 nv_wo32(ctx, i + 2, 0x000c001b);
291 }
292 for (i = 0x30b8; i < 0x30c8; i += 4)
293 nv_wo32(ctx, i, 0x0000ffff);
294 nv_wo32(ctx, 0x344c, 0x3f800000);
295 nv_wo32(ctx, 0x3808, 0x3f800000);
296 nv_wo32(ctx, 0x381c, 0x3f800000);
297 nv_wo32(ctx, 0x3848, 0x40000000);
298 nv_wo32(ctx, 0x384c, 0x3f800000);
299 nv_wo32(ctx, 0x3850, 0x3f000000);
300 nv_wo32(ctx, 0x3858, 0x40000000);
301 nv_wo32(ctx, 0x385c, 0x3f800000);
302 nv_wo32(ctx, 0x3864, 0xbf800000);
303 nv_wo32(ctx, 0x386c, 0xbf800000);
304}
305
306static void
307nv34_graph_context_init(struct nouveau_gpuobj *ctx)
308{
309 int i;
310
311 nv_wo32(ctx, 0x040c, 0x01000101);
312 nv_wo32(ctx, 0x0420, 0x00000111);
313 nv_wo32(ctx, 0x0424, 0x00000060);
314 nv_wo32(ctx, 0x0440, 0x00000080);
315 nv_wo32(ctx, 0x0444, 0xffff0000);
316 nv_wo32(ctx, 0x0448, 0x00000001);
317 nv_wo32(ctx, 0x045c, 0x44400000);
318 nv_wo32(ctx, 0x0480, 0xffff0000);
319 for (i = 0x04d4; i < 0x04dc; i += 4)
320 nv_wo32(ctx, i, 0x0fff0000);
321 nv_wo32(ctx, 0x04e0, 0x00011100);
322 for (i = 0x04fc; i < 0x053c; i += 4)
323 nv_wo32(ctx, i, 0x07ff0000);
324 nv_wo32(ctx, 0x0544, 0x4b7fffff);
325 nv_wo32(ctx, 0x057c, 0x00000080);
326 nv_wo32(ctx, 0x0580, 0x30201000);
327 nv_wo32(ctx, 0x0584, 0x70605040);
328 nv_wo32(ctx, 0x0588, 0xb8a89888);
329 nv_wo32(ctx, 0x058c, 0xf8e8d8c8);
330 nv_wo32(ctx, 0x05a0, 0xb0000000);
331 for (i = 0x05f0; i < 0x0630; i += 4)
332 nv_wo32(ctx, i, 0x00010588);
333 for (i = 0x0630; i < 0x0670; i += 4)
334 nv_wo32(ctx, i, 0x00030303);
335 for (i = 0x06b0; i < 0x06f0; i += 4)
336 nv_wo32(ctx, i, 0x0008aae4);
337 for (i = 0x06f0; i < 0x0730; i += 4)
338 nv_wo32(ctx, i, 0x01012000);
339 for (i = 0x0730; i < 0x0770; i += 4)
340 nv_wo32(ctx, i, 0x00080008);
341 nv_wo32(ctx, 0x0850, 0x00040000);
342 nv_wo32(ctx, 0x0854, 0x00010000);
343 for (i = 0x0858; i < 0x0868; i += 4)
344 nv_wo32(ctx, i, 0x00040004);
345 for (i = 0x15ac; i <= 0x271c ; i += 16) {
346 nv_wo32(ctx, i + 0, 0x10700ff9);
347 nv_wo32(ctx, i + 1, 0x0436086c);
348 nv_wo32(ctx, i + 2, 0x000c001b);
349 }
350 for (i = 0x274c; i < 0x275c; i += 4)
351 nv_wo32(ctx, i, 0x0000ffff);
352 nv_wo32(ctx, 0x2ae0, 0x3f800000);
353 nv_wo32(ctx, 0x2e9c, 0x3f800000);
354 nv_wo32(ctx, 0x2eb0, 0x3f800000);
355 nv_wo32(ctx, 0x2edc, 0x40000000);
356 nv_wo32(ctx, 0x2ee0, 0x3f800000);
357 nv_wo32(ctx, 0x2ee4, 0x3f000000);
358 nv_wo32(ctx, 0x2eec, 0x40000000);
359 nv_wo32(ctx, 0x2ef0, 0x3f800000);
360 nv_wo32(ctx, 0x2ef8, 0xbf800000);
361 nv_wo32(ctx, 0x2f00, 0xbf800000);
362}
363
364static void
365nv35_36_graph_context_init(struct nouveau_gpuobj *ctx)
366{
367 int i;
368
369 nv_wo32(ctx, 0x040c, 0x00000101);
370 nv_wo32(ctx, 0x0420, 0x00000111);
371 nv_wo32(ctx, 0x0424, 0x00000060);
372 nv_wo32(ctx, 0x0440, 0x00000080);
373 nv_wo32(ctx, 0x0444, 0xffff0000);
374 nv_wo32(ctx, 0x0448, 0x00000001);
375 nv_wo32(ctx, 0x045c, 0x44400000);
376 nv_wo32(ctx, 0x0488, 0xffff0000);
377 for (i = 0x04dc; i < 0x04e4; i += 4)
378 nv_wo32(ctx, i, 0x0fff0000);
379 nv_wo32(ctx, 0x04e8, 0x00011100);
380 for (i = 0x0504; i < 0x0544; i += 4)
381 nv_wo32(ctx, i, 0x07ff0000);
382 nv_wo32(ctx, 0x054c, 0x4b7fffff);
383 nv_wo32(ctx, 0x0588, 0x00000080);
384 nv_wo32(ctx, 0x058c, 0x30201000);
385 nv_wo32(ctx, 0x0590, 0x70605040);
386 nv_wo32(ctx, 0x0594, 0xb8a89888);
387 nv_wo32(ctx, 0x0598, 0xf8e8d8c8);
388 nv_wo32(ctx, 0x05ac, 0xb0000000);
389 for (i = 0x0604; i < 0x0644; i += 4)
390 nv_wo32(ctx, i, 0x00010588);
391 for (i = 0x0644; i < 0x0684; i += 4)
392 nv_wo32(ctx, i, 0x00030303);
393 for (i = 0x06c4; i < 0x0704; i += 4)
394 nv_wo32(ctx, i, 0x0008aae4);
395 for (i = 0x0704; i < 0x0744; i += 4)
396 nv_wo32(ctx, i, 0x01012000);
397 for (i = 0x0744; i < 0x0784; i += 4)
398 nv_wo32(ctx, i, 0x00080008);
399 nv_wo32(ctx, 0x0860, 0x00040000);
400 nv_wo32(ctx, 0x0864, 0x00010000);
401 for (i = 0x0868; i < 0x0878; i += 4)
402 nv_wo32(ctx, i, 0x00040004);
403 for (i = 0x1f1c; i <= 0x308c ; i += 16) {
404 nv_wo32(ctx, i + 0, 0x10700ff9);
405 nv_wo32(ctx, i + 4, 0x0436086c);
406 nv_wo32(ctx, i + 8, 0x000c001b);
407 }
408 for (i = 0x30bc; i < 0x30cc; i += 4)
409 nv_wo32(ctx, i, 0x0000ffff);
410 nv_wo32(ctx, 0x3450, 0x3f800000);
411 nv_wo32(ctx, 0x380c, 0x3f800000);
412 nv_wo32(ctx, 0x3820, 0x3f800000);
413 nv_wo32(ctx, 0x384c, 0x40000000);
414 nv_wo32(ctx, 0x3850, 0x3f800000);
415 nv_wo32(ctx, 0x3854, 0x3f000000);
416 nv_wo32(ctx, 0x385c, 0x40000000);
417 nv_wo32(ctx, 0x3860, 0x3f800000);
418 nv_wo32(ctx, 0x3868, 0xbf800000);
419 nv_wo32(ctx, 0x3870, 0xbf800000);
420}
421
422int
423nv20_graph_context_new(struct nouveau_channel *chan, int engine)
424{
425 struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine);
426 struct nouveau_gpuobj *grctx = NULL;
427 struct drm_device *dev = chan->dev;
428 int ret;
429
430 ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16,
431 NVOBJ_FLAG_ZERO_ALLOC, &grctx);
432 if (ret)
433 return ret;
434
435 /* Initialise default context values */
436 pgraph->grctx_init(grctx);
437
438 /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */
439 /* CTX_USER */
440 nv_wo32(grctx, pgraph->grctx_user, (chan->id << 24) | 0x1);
441
442 nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->pinst >> 4);
443 chan->engctx[engine] = grctx;
444 return 0;
445}
446
447void
448nv20_graph_context_del(struct nouveau_channel *chan, int engine)
449{
450 struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine);
451 struct nouveau_gpuobj *grctx = chan->engctx[engine];
452 struct drm_device *dev = chan->dev;
453 struct drm_nouveau_private *dev_priv = dev->dev_private;
454 unsigned long flags;
455
456 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
457 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
458
459 /* Unload the context if it's the currently active one */
460 if (nv10_graph_channel(dev) == chan)
461 nv20_graph_unload_context(dev);
462
463 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
464 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
465
466 /* Free the context resources */
467 nv_wo32(pgraph->ctxtab, chan->id * 4, 0);
468
469 nouveau_gpuobj_ref(NULL, &grctx);
470 chan->engctx[engine] = NULL;
471}
472
473static void
474nv20_graph_set_tile_region(struct drm_device *dev, int i)
475{
476 struct drm_nouveau_private *dev_priv = dev->dev_private;
477 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
478
479 nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
480 nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
481 nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr);
482
483 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i);
484 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->limit);
485 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i);
486 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch);
487 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i);
488 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr);
489
490 if (dev_priv->card_type == NV_20) {
491 nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp);
492 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i);
493 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp);
494 }
495}
496
497int
498nv20_graph_init(struct drm_device *dev, int engine)
499{
500 struct nv20_graph_engine *pgraph = nv_engine(dev, engine);
501 struct drm_nouveau_private *dev_priv = dev->dev_private;
502 uint32_t tmp, vramsz;
503 int i;
504
505 nv_wr32(dev, NV03_PMC_ENABLE,
506 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH);
507 nv_wr32(dev, NV03_PMC_ENABLE,
508 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH);
509
510 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->pinst >> 4);
511
512 nv20_graph_rdi(dev);
513
514 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
515 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
516
517 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
518 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
519 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700);
520 nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */
521 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
522 nv_wr32(dev, 0x40009C , 0x00000040);
523
524 if (dev_priv->chipset >= 0x25) {
525 nv_wr32(dev, 0x400890, 0x00a8cfff);
526 nv_wr32(dev, 0x400610, 0x304B1FB6);
527 nv_wr32(dev, 0x400B80, 0x1cbd3883);
528 nv_wr32(dev, 0x400B84, 0x44000000);
529 nv_wr32(dev, 0x400098, 0x40000080);
530 nv_wr32(dev, 0x400B88, 0x000000ff);
531
532 } else {
533 nv_wr32(dev, 0x400880, 0x0008c7df);
534 nv_wr32(dev, 0x400094, 0x00000005);
535 nv_wr32(dev, 0x400B80, 0x45eae20e);
536 nv_wr32(dev, 0x400B84, 0x24000000);
537 nv_wr32(dev, 0x400098, 0x00000040);
538 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038);
539 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030);
540 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E10038);
541 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030);
542 }
543
544 /* Turn all the tiling regions off. */
545 for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
546 nv20_graph_set_tile_region(dev, i);
547
548 nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324));
549 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C);
550 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324));
551
552 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
553 nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF);
554
555 tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) & 0x0007ff00;
556 nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp);
557 tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) | 0x00020100;
558 nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp);
559
560 /* begin RAM config */
561 vramsz = pci_resource_len(dev->pdev, 0) - 1;
562 nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0));
563 nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1));
564 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
565 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG0));
566 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004);
567 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG1));
568 nv_wr32(dev, 0x400820, 0);
569 nv_wr32(dev, 0x400824, 0);
570 nv_wr32(dev, 0x400864, vramsz - 1);
571 nv_wr32(dev, 0x400868, vramsz - 1);
572
573 /* interesting.. the below overwrites some of the tile setup above.. */
574 nv_wr32(dev, 0x400B20, 0x00000000);
575 nv_wr32(dev, 0x400B04, 0xFFFFFFFF);
576
577 nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMIN, 0);
578 nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
579 nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
580 nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
581
582 return 0;
583}
584
585int
586nv30_graph_init(struct drm_device *dev, int engine)
587{
588 struct nv20_graph_engine *pgraph = nv_engine(dev, engine);
589 struct drm_nouveau_private *dev_priv = dev->dev_private;
590 int i;
591
592 nv_wr32(dev, NV03_PMC_ENABLE,
593 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH);
594 nv_wr32(dev, NV03_PMC_ENABLE,
595 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH);
596
597 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->pinst >> 4);
598
599 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
600 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
601
602 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
603 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
604 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0);
605 nv_wr32(dev, 0x400890, 0x01b463ff);
606 nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf2de0475);
607 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000);
608 nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6);
609 nv_wr32(dev, 0x400B80, 0x1003d888);
610 nv_wr32(dev, 0x400B84, 0x0c000000);
611 nv_wr32(dev, 0x400098, 0x00000000);
612 nv_wr32(dev, 0x40009C, 0x0005ad00);
613 nv_wr32(dev, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */
614 nv_wr32(dev, 0x4000a0, 0x00000000);
615 nv_wr32(dev, 0x4000a4, 0x00000008);
616 nv_wr32(dev, 0x4008a8, 0xb784a400);
617 nv_wr32(dev, 0x400ba0, 0x002f8685);
618 nv_wr32(dev, 0x400ba4, 0x00231f3f);
619 nv_wr32(dev, 0x4008a4, 0x40000020);
620
621 if (dev_priv->chipset == 0x34) {
622 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004);
623 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00200201);
624 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0008);
625 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000008);
626 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
627 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000032);
628 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00004);
629 nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000002);
630 }
631
632 nv_wr32(dev, 0x4000c0, 0x00000016);
633
634 /* Turn all the tiling regions off. */
635 for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
636 nv20_graph_set_tile_region(dev, i);
637
638 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
639 nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF);
640 nv_wr32(dev, 0x0040075c , 0x00000001);
641
642 /* begin RAM config */
643 /* vramsz = pci_resource_len(dev->pdev, 0) - 1; */
644 nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0));
645 nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1));
646 if (dev_priv->chipset != 0x34) {
647 nv_wr32(dev, 0x400750, 0x00EA0000);
648 nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG0));
649 nv_wr32(dev, 0x400750, 0x00EA0004);
650 nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG1));
651 }
652
653 return 0;
654}
655
656int
657nv20_graph_fini(struct drm_device *dev, int engine, bool suspend)
658{
659 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
660 if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
661 nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
662 return -EBUSY;
663 }
664 nv20_graph_unload_context(dev);
665 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
666 return 0;
667}
668
669static void
670nv20_graph_isr(struct drm_device *dev)
671{
672 u32 stat;
673
674 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
675 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
676 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
677 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
678 u32 chid = (addr & 0x01f00000) >> 20;
679 u32 subc = (addr & 0x00070000) >> 16;
680 u32 mthd = (addr & 0x00001ffc);
681 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
682 u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
683 u32 show = stat;
684
685 if (stat & NV_PGRAPH_INTR_ERROR) {
686 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
687 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
688 show &= ~NV_PGRAPH_INTR_ERROR;
689 }
690 }
691
692 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
693 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
694
695 if (show && nouveau_ratelimit()) {
696 NV_INFO(dev, "PGRAPH -");
697 nouveau_bitfield_print(nv10_graph_intr, show);
698 printk(" nsource:");
699 nouveau_bitfield_print(nv04_graph_nsource, nsource);
700 printk(" nstatus:");
701 nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
702 printk("\n");
703 NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
704 "mthd 0x%04x data 0x%08x\n",
705 chid, subc, class, mthd, data);
706 }
707 }
708}
709
710static void
711nv20_graph_destroy(struct drm_device *dev, int engine)
712{
713 struct nv20_graph_engine *pgraph = nv_engine(dev, engine);
714
715 nouveau_irq_unregister(dev, 12);
716 nouveau_gpuobj_ref(NULL, &pgraph->ctxtab);
717
718 NVOBJ_ENGINE_DEL(dev, GR);
719 kfree(pgraph);
720}
721
722int
723nv20_graph_create(struct drm_device *dev)
724{
725 struct drm_nouveau_private *dev_priv = dev->dev_private;
726 struct nv20_graph_engine *pgraph;
727 int ret;
728
729 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
730 if (!pgraph)
731 return -ENOMEM;
732
733 pgraph->base.destroy = nv20_graph_destroy;
734 pgraph->base.fini = nv20_graph_fini;
735 pgraph->base.context_new = nv20_graph_context_new;
736 pgraph->base.context_del = nv20_graph_context_del;
737 pgraph->base.object_new = nv04_graph_object_new;
738 pgraph->base.set_tile_region = nv20_graph_set_tile_region;
739
740 pgraph->grctx_user = 0x0028;
741 if (dev_priv->card_type == NV_20) {
742 pgraph->base.init = nv20_graph_init;
743 switch (dev_priv->chipset) {
744 case 0x20:
745 pgraph->grctx_init = nv20_graph_context_init;
746 pgraph->grctx_size = NV20_GRCTX_SIZE;
747 pgraph->grctx_user = 0x0000;
748 break;
749 case 0x25:
750 case 0x28:
751 pgraph->grctx_init = nv25_graph_context_init;
752 pgraph->grctx_size = NV25_GRCTX_SIZE;
753 break;
754 case 0x2a:
755 pgraph->grctx_init = nv2a_graph_context_init;
756 pgraph->grctx_size = NV2A_GRCTX_SIZE;
757 pgraph->grctx_user = 0x0000;
758 break;
759 default:
760 NV_ERROR(dev, "PGRAPH: unknown chipset\n");
761 kfree(pgraph);
762 return 0;
763 }
764 } else {
765 pgraph->base.init = nv30_graph_init;
766 switch (dev_priv->chipset) {
767 case 0x30:
768 case 0x31:
769 pgraph->grctx_init = nv30_31_graph_context_init;
770 pgraph->grctx_size = NV30_31_GRCTX_SIZE;
771 break;
772 case 0x34:
773 pgraph->grctx_init = nv34_graph_context_init;
774 pgraph->grctx_size = NV34_GRCTX_SIZE;
775 break;
776 case 0x35:
777 case 0x36:
778 pgraph->grctx_init = nv35_36_graph_context_init;
779 pgraph->grctx_size = NV35_36_GRCTX_SIZE;
780 break;
781 default:
782 NV_ERROR(dev, "PGRAPH: unknown chipset\n");
783 kfree(pgraph);
784 return 0;
785 }
786 }
787
788 /* Create Context Pointer Table */
789 ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC,
790 &pgraph->ctxtab);
791 if (ret) {
792 kfree(pgraph);
793 return ret;
794 }
795
796 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
797 nouveau_irq_register(dev, 12, nv20_graph_isr);
798
799 /* nvsw */
800 NVOBJ_CLASS(dev, 0x506e, SW);
801 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
802
803 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
804 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
805 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
806 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
807 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
808 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
809 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
810 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
811 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
812 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
813 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
814 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
815 if (dev_priv->card_type == NV_20) {
816 NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */
817 NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */
818
819 /* kelvin */
820 if (dev_priv->chipset < 0x25)
821 NVOBJ_CLASS(dev, 0x0097, GR);
822 else
823 NVOBJ_CLASS(dev, 0x0597, GR);
824 } else {
825 NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */
826 NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */
827 NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */
828 NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */
829
830 /* rankine */
831 if (0x00000003 & (1 << (dev_priv->chipset & 0x0f)))
832 NVOBJ_CLASS(dev, 0x0397, GR);
833 else
834 if (0x00000010 & (1 << (dev_priv->chipset & 0x0f)))
835 NVOBJ_CLASS(dev, 0x0697, GR);
836 else
837 if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f)))
838 NVOBJ_CLASS(dev, 0x0497, GR);
839 }
840
841 return 0;
842}
diff --git a/drivers/gpu/drm/nouveau/nv30_fb.c b/drivers/gpu/drm/nouveau/nv30_fb.c
new file mode 100644
index 00000000000..e0135f0e214
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv30_fb.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) 2010 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30#include "nouveau_drm.h"
31
32void
33nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
34 uint32_t size, uint32_t pitch, uint32_t flags)
35{
36 struct drm_nouveau_private *dev_priv = dev->dev_private;
37 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
38
39 tile->addr = addr | 1;
40 tile->limit = max(1u, addr + size) - 1;
41 tile->pitch = pitch;
42}
43
44void
45nv30_fb_free_tile_region(struct drm_device *dev, int i)
46{
47 struct drm_nouveau_private *dev_priv = dev->dev_private;
48 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
49
50 tile->addr = tile->limit = tile->pitch = 0;
51}
52
53static int
54calc_bias(struct drm_device *dev, int k, int i, int j)
55{
56 struct drm_nouveau_private *dev_priv = dev->dev_private;
57 int b = (dev_priv->chipset > 0x30 ?
58 nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) :
59 0) & 0xf;
60
61 return 2 * (b & 0x8 ? b - 0x10 : b);
62}
63
64static int
65calc_ref(struct drm_device *dev, int l, int k, int i)
66{
67 int j, x = 0;
68
69 for (j = 0; j < 4; j++) {
70 int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j);
71
72 x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j);
73 }
74
75 return x;
76}
77
78int
79nv30_fb_init(struct drm_device *dev)
80{
81 struct drm_nouveau_private *dev_priv = dev->dev_private;
82 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
83 int i, j;
84
85 pfb->num_tiles = NV10_PFB_TILE__SIZE;
86
87 /* Turn all the tiling regions off. */
88 for (i = 0; i < pfb->num_tiles; i++)
89 pfb->set_tile_region(dev, i);
90
91 /* Init the memory timing regs at 0x10037c/0x1003ac */
92 if (dev_priv->chipset == 0x30 ||
93 dev_priv->chipset == 0x31 ||
94 dev_priv->chipset == 0x35) {
95 /* Related to ROP count */
96 int n = (dev_priv->chipset == 0x31 ? 2 : 4);
97 int l = nv_rd32(dev, 0x1003d0);
98
99 for (i = 0; i < n; i++) {
100 for (j = 0; j < 3; j++)
101 nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j,
102 calc_ref(dev, l, 0, j));
103
104 for (j = 0; j < 2; j++)
105 nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j,
106 calc_ref(dev, l, 1, j));
107 }
108 }
109
110 return 0;
111}
112
113void
114nv30_fb_takedown(struct drm_device *dev)
115{
116}
diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c
new file mode 100644
index 00000000000..f0ac2a768c6
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_fb.c
@@ -0,0 +1,118 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6void
7nv40_fb_set_tile_region(struct drm_device *dev, int i)
8{
9 struct drm_nouveau_private *dev_priv = dev->dev_private;
10 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
11
12 switch (dev_priv->chipset) {
13 case 0x40:
14 nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
15 nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
16 nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
17 break;
18
19 default:
20 nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit);
21 nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch);
22 nv_wr32(dev, NV40_PFB_TILE(i), tile->addr);
23 break;
24 }
25}
26
27static void
28nv40_fb_init_gart(struct drm_device *dev)
29{
30 struct drm_nouveau_private *dev_priv = dev->dev_private;
31 struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
32
33 if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
34 nv_wr32(dev, 0x100800, 0x00000001);
35 return;
36 }
37
38 nv_wr32(dev, 0x100800, gart->pinst | 0x00000002);
39 nv_mask(dev, 0x10008c, 0x00000100, 0x00000100);
40 nv_wr32(dev, 0x100820, 0x00000000);
41}
42
43static void
44nv44_fb_init_gart(struct drm_device *dev)
45{
46 struct drm_nouveau_private *dev_priv = dev->dev_private;
47 struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
48 u32 vinst;
49
50 if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
51 nv_wr32(dev, 0x100850, 0x80000000);
52 nv_wr32(dev, 0x100800, 0x00000001);
53 return;
54 }
55
56 /* calculate vram address of this PRAMIN block, object
57 * must be allocated on 512KiB alignment, and not exceed
58 * a total size of 512KiB for this to work correctly
59 */
60 vinst = nv_rd32(dev, 0x10020c);
61 vinst -= ((gart->pinst >> 19) + 1) << 19;
62
63 nv_wr32(dev, 0x100850, 0x80000000);
64 nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr);
65
66 nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size);
67 nv_wr32(dev, 0x100850, 0x00008000);
68 nv_mask(dev, 0x10008c, 0x00000200, 0x00000200);
69 nv_wr32(dev, 0x100820, 0x00000000);
70 nv_wr32(dev, 0x10082c, 0x00000001);
71 nv_wr32(dev, 0x100800, vinst | 0x00000010);
72}
73
74int
75nv40_fb_init(struct drm_device *dev)
76{
77 struct drm_nouveau_private *dev_priv = dev->dev_private;
78 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
79 uint32_t tmp;
80 int i;
81
82 if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
83 if (nv44_graph_class(dev))
84 nv44_fb_init_gart(dev);
85 else
86 nv40_fb_init_gart(dev);
87 }
88
89 switch (dev_priv->chipset) {
90 case 0x40:
91 case 0x45:
92 tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2);
93 nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15));
94 pfb->num_tiles = NV10_PFB_TILE__SIZE;
95 break;
96 case 0x46: /* G72 */
97 case 0x47: /* G70 */
98 case 0x49: /* G71 */
99 case 0x4b: /* G73 */
100 case 0x4c: /* C51 (G7X version) */
101 pfb->num_tiles = NV40_PFB_TILE__SIZE_1;
102 break;
103 default:
104 pfb->num_tiles = NV40_PFB_TILE__SIZE_0;
105 break;
106 }
107
108 /* Turn all the tiling regions off. */
109 for (i = 0; i < pfb->num_tiles; i++)
110 pfb->set_tile_region(dev, i);
111
112 return 0;
113}
114
115void
116nv40_fb_takedown(struct drm_device *dev)
117{
118}
diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c
new file mode 100644
index 00000000000..68cb2d991c8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_fifo.c
@@ -0,0 +1,307 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "nouveau_drv.h"
29#include "nouveau_drm.h"
30#include "nouveau_ramht.h"
31
32#define NV40_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV40_RAMFC__SIZE))
33#define NV40_RAMFC__SIZE 128
34
35int
36nv40_fifo_create_context(struct nouveau_channel *chan)
37{
38 struct drm_device *dev = chan->dev;
39 struct drm_nouveau_private *dev_priv = dev->dev_private;
40 uint32_t fc = NV40_RAMFC(chan->id);
41 unsigned long flags;
42 int ret;
43
44 ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0,
45 NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC |
46 NVOBJ_FLAG_ZERO_FREE, &chan->ramfc);
47 if (ret)
48 return ret;
49
50 chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
51 NV40_USER(chan->id), PAGE_SIZE);
52 if (!chan->user)
53 return -ENOMEM;
54
55 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
56
57 nv_wi32(dev, fc + 0, chan->pushbuf_base);
58 nv_wi32(dev, fc + 4, chan->pushbuf_base);
59 nv_wi32(dev, fc + 12, chan->pushbuf->pinst >> 4);
60 nv_wi32(dev, fc + 24, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
61 NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
62 NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
63#ifdef __BIG_ENDIAN
64 NV_PFIFO_CACHE1_BIG_ENDIAN |
65#endif
66 0x30000000 /* no idea.. */);
67 nv_wi32(dev, fc + 60, 0x0001FFFF);
68
69 /* enable the fifo dma operation */
70 nv_wr32(dev, NV04_PFIFO_MODE,
71 nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
72
73 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
74 return 0;
75}
76
77static void
78nv40_fifo_do_load_context(struct drm_device *dev, int chid)
79{
80 struct drm_nouveau_private *dev_priv = dev->dev_private;
81 uint32_t fc = NV40_RAMFC(chid), tmp, tmp2;
82
83 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
84 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
85 nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
86 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, nv_ri32(dev, fc + 12));
87 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, nv_ri32(dev, fc + 16));
88 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 20));
89
90 /* No idea what 0x2058 is.. */
91 tmp = nv_ri32(dev, fc + 24);
92 tmp2 = nv_rd32(dev, 0x2058) & 0xFFF;
93 tmp2 |= (tmp & 0x30000000);
94 nv_wr32(dev, 0x2058, tmp2);
95 tmp &= ~0x30000000;
96 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, tmp);
97
98 nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 28));
99 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 32));
100 nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE, nv_ri32(dev, fc + 36));
101 tmp = nv_ri32(dev, fc + 40);
102 nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, tmp);
103 nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, nv_ri32(dev, fc + 44));
104 nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, nv_ri32(dev, fc + 48));
105 nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 52));
106 nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, nv_ri32(dev, fc + 56));
107
108 /* Don't clobber the TIMEOUT_ENABLED flag when restoring from RAMFC */
109 tmp = nv_rd32(dev, NV04_PFIFO_DMA_TIMESLICE) & ~0x1FFFF;
110 tmp |= nv_ri32(dev, fc + 60) & 0x1FFFF;
111 nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, tmp);
112
113 nv_wr32(dev, 0x32e4, nv_ri32(dev, fc + 64));
114 /* NVIDIA does this next line twice... */
115 nv_wr32(dev, 0x32e8, nv_ri32(dev, fc + 68));
116 nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76));
117 nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80));
118 nv_wr32(dev, 0x330c, nv_ri32(dev, fc + 84));
119
120 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
121 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
122}
123
124int
125nv40_fifo_load_context(struct nouveau_channel *chan)
126{
127 struct drm_device *dev = chan->dev;
128 uint32_t tmp;
129
130 nv40_fifo_do_load_context(dev, chan->id);
131
132 /* Set channel active, and in DMA mode */
133 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1,
134 NV40_PFIFO_CACHE1_PUSH1_DMA | chan->id);
135 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
136
137 /* Reset DMA_CTL_AT_INFO to INVALID */
138 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
139 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
140
141 return 0;
142}
143
144int
145nv40_fifo_unload_context(struct drm_device *dev)
146{
147 struct drm_nouveau_private *dev_priv = dev->dev_private;
148 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
149 uint32_t fc, tmp;
150 int chid;
151
152 chid = pfifo->channel_id(dev);
153 if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
154 return 0;
155 fc = NV40_RAMFC(chid);
156
157 nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
158 nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
159 nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
160 nv_wi32(dev, fc + 12, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE));
161 nv_wi32(dev, fc + 16, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT));
162 nv_wi32(dev, fc + 20, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
163 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH);
164 tmp |= nv_rd32(dev, 0x2058) & 0x30000000;
165 nv_wi32(dev, fc + 24, tmp);
166 nv_wi32(dev, fc + 28, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
167 nv_wi32(dev, fc + 32, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
168 nv_wi32(dev, fc + 36, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
169 tmp = nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP);
170 nv_wi32(dev, fc + 40, tmp);
171 nv_wi32(dev, fc + 44, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
172 nv_wi32(dev, fc + 48, nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE));
173 /* NVIDIA read 0x3228 first, then write DMA_GET here.. maybe something
174 * more involved depending on the value of 0x3228?
175 */
176 nv_wi32(dev, fc + 52, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
177 nv_wi32(dev, fc + 56, nv_rd32(dev, NV40_PFIFO_GRCTX_INSTANCE));
178 nv_wi32(dev, fc + 60, nv_rd32(dev, NV04_PFIFO_DMA_TIMESLICE) & 0x1ffff);
179 /* No idea what the below is for exactly, ripped from a mmio-trace */
180 nv_wi32(dev, fc + 64, nv_rd32(dev, NV40_PFIFO_UNK32E4));
181 /* NVIDIA do this next line twice.. bug? */
182 nv_wi32(dev, fc + 68, nv_rd32(dev, 0x32e8));
183 nv_wi32(dev, fc + 76, nv_rd32(dev, 0x2088));
184 nv_wi32(dev, fc + 80, nv_rd32(dev, 0x3300));
185#if 0 /* no real idea which is PUT/GET in UNK_48.. */
186 tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_GET);
187 tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16);
188 nv_wi32(dev, fc + 72, tmp);
189#endif
190 nv_wi32(dev, fc + 84, nv_rd32(dev, 0x330c));
191
192 nv40_fifo_do_load_context(dev, pfifo->channels - 1);
193 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1,
194 NV40_PFIFO_CACHE1_PUSH1_DMA | (pfifo->channels - 1));
195 return 0;
196}
197
198static void
199nv40_fifo_init_reset(struct drm_device *dev)
200{
201 int i;
202
203 nv_wr32(dev, NV03_PMC_ENABLE,
204 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
205 nv_wr32(dev, NV03_PMC_ENABLE,
206 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO);
207
208 nv_wr32(dev, 0x003224, 0x000f0078);
209 nv_wr32(dev, 0x003210, 0x00000000);
210 nv_wr32(dev, 0x003270, 0x00000000);
211 nv_wr32(dev, 0x003240, 0x00000000);
212 nv_wr32(dev, 0x003244, 0x00000000);
213 nv_wr32(dev, 0x003258, 0x00000000);
214 nv_wr32(dev, 0x002504, 0x00000000);
215 for (i = 0; i < 16; i++)
216 nv_wr32(dev, 0x002510 + (i * 4), 0x00000000);
217 nv_wr32(dev, 0x00250c, 0x0000ffff);
218 nv_wr32(dev, 0x002048, 0x00000000);
219 nv_wr32(dev, 0x003228, 0x00000000);
220 nv_wr32(dev, 0x0032e8, 0x00000000);
221 nv_wr32(dev, 0x002410, 0x00000000);
222 nv_wr32(dev, 0x002420, 0x00000000);
223 nv_wr32(dev, 0x002058, 0x00000001);
224 nv_wr32(dev, 0x00221c, 0x00000000);
225 /* something with 0x2084, read/modify/write, no change */
226 nv_wr32(dev, 0x002040, 0x000000ff);
227 nv_wr32(dev, 0x002500, 0x00000000);
228 nv_wr32(dev, 0x003200, 0x00000000);
229
230 nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff);
231}
232
233static void
234nv40_fifo_init_ramxx(struct drm_device *dev)
235{
236 struct drm_nouveau_private *dev_priv = dev->dev_private;
237
238 nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
239 ((dev_priv->ramht->bits - 9) << 16) |
240 (dev_priv->ramht->gpuobj->pinst >> 8));
241 nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro->pinst >> 8);
242
243 switch (dev_priv->chipset) {
244 case 0x47:
245 case 0x49:
246 case 0x4b:
247 nv_wr32(dev, 0x2230, 1);
248 break;
249 default:
250 break;
251 }
252
253 switch (dev_priv->chipset) {
254 case 0x40:
255 case 0x41:
256 case 0x42:
257 case 0x43:
258 case 0x45:
259 case 0x47:
260 case 0x48:
261 case 0x49:
262 case 0x4b:
263 nv_wr32(dev, NV40_PFIFO_RAMFC, 0x30002);
264 break;
265 default:
266 nv_wr32(dev, 0x2230, 0);
267 nv_wr32(dev, NV40_PFIFO_RAMFC,
268 ((dev_priv->vram_size - 512 * 1024 +
269 dev_priv->ramfc->pinst) >> 16) | (3 << 16));
270 break;
271 }
272}
273
274static void
275nv40_fifo_init_intr(struct drm_device *dev)
276{
277 nouveau_irq_register(dev, 8, nv04_fifo_isr);
278 nv_wr32(dev, 0x002100, 0xffffffff);
279 nv_wr32(dev, 0x002140, 0xffffffff);
280}
281
282int
283nv40_fifo_init(struct drm_device *dev)
284{
285 struct drm_nouveau_private *dev_priv = dev->dev_private;
286 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
287 int i;
288
289 nv40_fifo_init_reset(dev);
290 nv40_fifo_init_ramxx(dev);
291
292 nv40_fifo_do_load_context(dev, pfifo->channels - 1);
293 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
294
295 nv40_fifo_init_intr(dev);
296 pfifo->enable(dev);
297 pfifo->reassign(dev, true);
298
299 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
300 if (dev_priv->channels.ptr[i]) {
301 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
302 nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
303 }
304 }
305
306 return 0;
307}
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c
new file mode 100644
index 00000000000..ba14a93d8af
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -0,0 +1,490 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30#include "nouveau_grctx.h"
31#include "nouveau_ramht.h"
32
33struct nv40_graph_engine {
34 struct nouveau_exec_engine base;
35 u32 grctx_size;
36};
37
38static int
39nv40_graph_context_new(struct nouveau_channel *chan, int engine)
40{
41 struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine);
42 struct drm_device *dev = chan->dev;
43 struct drm_nouveau_private *dev_priv = dev->dev_private;
44 struct nouveau_gpuobj *grctx = NULL;
45 struct nouveau_grctx ctx = {};
46 unsigned long flags;
47 int ret;
48
49 ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16,
50 NVOBJ_FLAG_ZERO_ALLOC, &grctx);
51 if (ret)
52 return ret;
53
54 /* Initialise default context values */
55 ctx.dev = chan->dev;
56 ctx.mode = NOUVEAU_GRCTX_VALS;
57 ctx.data = grctx;
58 nv40_grctx_init(&ctx);
59
60 nv_wo32(grctx, 0, grctx->vinst);
61
62 /* init grctx pointer in ramfc, and on PFIFO if channel is
63 * already active there
64 */
65 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
66 nv_wo32(chan->ramfc, 0x38, grctx->vinst >> 4);
67 nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
68 if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id)
69 nv_wr32(dev, 0x0032e0, grctx->vinst >> 4);
70 nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
71 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
72
73 chan->engctx[engine] = grctx;
74 return 0;
75}
76
77static void
78nv40_graph_context_del(struct nouveau_channel *chan, int engine)
79{
80 struct nouveau_gpuobj *grctx = chan->engctx[engine];
81 struct drm_device *dev = chan->dev;
82 struct drm_nouveau_private *dev_priv = dev->dev_private;
83 u32 inst = 0x01000000 | (grctx->pinst >> 4);
84 unsigned long flags;
85
86 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
87 nv_mask(dev, 0x400720, 0x00000000, 0x00000001);
88 if (nv_rd32(dev, 0x40032c) == inst)
89 nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
90 if (nv_rd32(dev, 0x400330) == inst)
91 nv_mask(dev, 0x400330, 0x01000000, 0x00000000);
92 nv_mask(dev, 0x400720, 0x00000001, 0x00000001);
93 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
94
95 /* Free the context resources */
96 nouveau_gpuobj_ref(NULL, &grctx);
97 chan->engctx[engine] = NULL;
98}
99
100int
101nv40_graph_object_new(struct nouveau_channel *chan, int engine,
102 u32 handle, u16 class)
103{
104 struct drm_device *dev = chan->dev;
105 struct nouveau_gpuobj *obj = NULL;
106 int ret;
107
108 ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
109 if (ret)
110 return ret;
111 obj->engine = 1;
112 obj->class = class;
113
114 nv_wo32(obj, 0x00, class);
115 nv_wo32(obj, 0x04, 0x00000000);
116#ifndef __BIG_ENDIAN
117 nv_wo32(obj, 0x08, 0x00000000);
118#else
119 nv_wo32(obj, 0x08, 0x01000000);
120#endif
121 nv_wo32(obj, 0x0c, 0x00000000);
122 nv_wo32(obj, 0x10, 0x00000000);
123
124 ret = nouveau_ramht_insert(chan, handle, obj);
125 nouveau_gpuobj_ref(NULL, &obj);
126 return ret;
127}
128
129static void
130nv40_graph_set_tile_region(struct drm_device *dev, int i)
131{
132 struct drm_nouveau_private *dev_priv = dev->dev_private;
133 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
134
135 switch (dev_priv->chipset) {
136 case 0x40:
137 case 0x41: /* guess */
138 case 0x42:
139 case 0x43:
140 case 0x45: /* guess */
141 case 0x4e:
142 nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
143 nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
144 nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr);
145 nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch);
146 nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit);
147 nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr);
148 break;
149 case 0x44:
150 case 0x4a:
151 nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch);
152 nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit);
153 nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr);
154 break;
155 case 0x46:
156 case 0x47:
157 case 0x49:
158 case 0x4b:
159 case 0x4c:
160 case 0x67:
161 default:
162 nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch);
163 nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit);
164 nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr);
165 nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch);
166 nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit);
167 nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr);
168 break;
169 }
170}
171
172/*
173 * G70 0x47
174 * G71 0x49
175 * NV45 0x48
176 * G72[M] 0x46
177 * G73 0x4b
178 * C51_G7X 0x4c
179 * C51 0x4e
180 */
181int
182nv40_graph_init(struct drm_device *dev, int engine)
183{
184 struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
185 struct drm_nouveau_private *dev_priv = dev->dev_private;
186 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
187 struct nouveau_grctx ctx = {};
188 uint32_t vramsz, *cp;
189 int i, j;
190
191 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
192 ~NV_PMC_ENABLE_PGRAPH);
193 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
194 NV_PMC_ENABLE_PGRAPH);
195
196 cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL);
197 if (!cp)
198 return -ENOMEM;
199
200 ctx.dev = dev;
201 ctx.mode = NOUVEAU_GRCTX_PROG;
202 ctx.data = cp;
203 ctx.ctxprog_max = 256;
204 nv40_grctx_init(&ctx);
205 pgraph->grctx_size = ctx.ctxvals_pos * 4;
206
207 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
208 for (i = 0; i < ctx.ctxprog_len; i++)
209 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
210
211 kfree(cp);
212
213 /* No context present currently */
214 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
215
216 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
217 nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
218
219 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
220 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
221 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0);
222 nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xe0de8055);
223 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000);
224 nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f);
225
226 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
227 nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF);
228
229 j = nv_rd32(dev, 0x1540) & 0xff;
230 if (j) {
231 for (i = 0; !(j & 1); j >>= 1, i++)
232 ;
233 nv_wr32(dev, 0x405000, i);
234 }
235
236 if (dev_priv->chipset == 0x40) {
237 nv_wr32(dev, 0x4009b0, 0x83280fff);
238 nv_wr32(dev, 0x4009b4, 0x000000a0);
239 } else {
240 nv_wr32(dev, 0x400820, 0x83280eff);
241 nv_wr32(dev, 0x400824, 0x000000a0);
242 }
243
244 switch (dev_priv->chipset) {
245 case 0x40:
246 case 0x45:
247 nv_wr32(dev, 0x4009b8, 0x0078e366);
248 nv_wr32(dev, 0x4009bc, 0x0000014c);
249 break;
250 case 0x41:
251 case 0x42: /* pciid also 0x00Cx */
252 /* case 0x0120: XXX (pciid) */
253 nv_wr32(dev, 0x400828, 0x007596ff);
254 nv_wr32(dev, 0x40082c, 0x00000108);
255 break;
256 case 0x43:
257 nv_wr32(dev, 0x400828, 0x0072cb77);
258 nv_wr32(dev, 0x40082c, 0x00000108);
259 break;
260 case 0x44:
261 case 0x46: /* G72 */
262 case 0x4a:
263 case 0x4c: /* G7x-based C51 */
264 case 0x4e:
265 nv_wr32(dev, 0x400860, 0);
266 nv_wr32(dev, 0x400864, 0);
267 break;
268 case 0x47: /* G70 */
269 case 0x49: /* G71 */
270 case 0x4b: /* G73 */
271 nv_wr32(dev, 0x400828, 0x07830610);
272 nv_wr32(dev, 0x40082c, 0x0000016A);
273 break;
274 default:
275 break;
276 }
277
278 nv_wr32(dev, 0x400b38, 0x2ffff800);
279 nv_wr32(dev, 0x400b3c, 0x00006000);
280
281 /* Tiling related stuff. */
282 switch (dev_priv->chipset) {
283 case 0x44:
284 case 0x4a:
285 nv_wr32(dev, 0x400bc4, 0x1003d888);
286 nv_wr32(dev, 0x400bbc, 0xb7a7b500);
287 break;
288 case 0x46:
289 nv_wr32(dev, 0x400bc4, 0x0000e024);
290 nv_wr32(dev, 0x400bbc, 0xb7a7b520);
291 break;
292 case 0x4c:
293 case 0x4e:
294 case 0x67:
295 nv_wr32(dev, 0x400bc4, 0x1003d888);
296 nv_wr32(dev, 0x400bbc, 0xb7a7b540);
297 break;
298 default:
299 break;
300 }
301
302 /* Turn all the tiling regions off. */
303 for (i = 0; i < pfb->num_tiles; i++)
304 nv40_graph_set_tile_region(dev, i);
305
306 /* begin RAM config */
307 vramsz = pci_resource_len(dev->pdev, 0) - 1;
308 switch (dev_priv->chipset) {
309 case 0x40:
310 nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0));
311 nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1));
312 nv_wr32(dev, 0x4069A4, nv_rd32(dev, NV04_PFB_CFG0));
313 nv_wr32(dev, 0x4069A8, nv_rd32(dev, NV04_PFB_CFG1));
314 nv_wr32(dev, 0x400820, 0);
315 nv_wr32(dev, 0x400824, 0);
316 nv_wr32(dev, 0x400864, vramsz);
317 nv_wr32(dev, 0x400868, vramsz);
318 break;
319 default:
320 switch (dev_priv->chipset) {
321 case 0x41:
322 case 0x42:
323 case 0x43:
324 case 0x45:
325 case 0x4e:
326 case 0x44:
327 case 0x4a:
328 nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0));
329 nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1));
330 break;
331 default:
332 nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0));
333 nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1));
334 break;
335 }
336 nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0));
337 nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1));
338 nv_wr32(dev, 0x400840, 0);
339 nv_wr32(dev, 0x400844, 0);
340 nv_wr32(dev, 0x4008A0, vramsz);
341 nv_wr32(dev, 0x4008A4, vramsz);
342 break;
343 }
344
345 return 0;
346}
347
348static int
349nv40_graph_fini(struct drm_device *dev, int engine, bool suspend)
350{
351 u32 inst = nv_rd32(dev, 0x40032c);
352 if (inst & 0x01000000) {
353 nv_wr32(dev, 0x400720, 0x00000000);
354 nv_wr32(dev, 0x400784, inst);
355 nv_mask(dev, 0x400310, 0x00000020, 0x00000020);
356 nv_mask(dev, 0x400304, 0x00000001, 0x00000001);
357 if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) {
358 u32 insn = nv_rd32(dev, 0x400308);
359 NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn);
360 }
361 nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
362 }
363 return 0;
364}
365
366static int
367nv40_graph_isr_chid(struct drm_device *dev, u32 inst)
368{
369 struct drm_nouveau_private *dev_priv = dev->dev_private;
370 struct nouveau_gpuobj *grctx;
371 unsigned long flags;
372 int i;
373
374 spin_lock_irqsave(&dev_priv->channels.lock, flags);
375 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
376 if (!dev_priv->channels.ptr[i])
377 continue;
378 grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
379
380 if (grctx && grctx->pinst == inst)
381 break;
382 }
383 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
384 return i;
385}
386
387static void
388nv40_graph_isr(struct drm_device *dev)
389{
390 u32 stat;
391
392 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
393 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
394 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
395 u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4;
396 u32 chid = nv40_graph_isr_chid(dev, inst);
397 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
398 u32 subc = (addr & 0x00070000) >> 16;
399 u32 mthd = (addr & 0x00001ffc);
400 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
401 u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff;
402 u32 show = stat;
403
404 if (stat & NV_PGRAPH_INTR_ERROR) {
405 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
406 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
407 show &= ~NV_PGRAPH_INTR_ERROR;
408 } else
409 if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
410 nv_mask(dev, 0x402000, 0, 0);
411 }
412 }
413
414 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
415 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
416
417 if (show && nouveau_ratelimit()) {
418 NV_INFO(dev, "PGRAPH -");
419 nouveau_bitfield_print(nv10_graph_intr, show);
420 printk(" nsource:");
421 nouveau_bitfield_print(nv04_graph_nsource, nsource);
422 printk(" nstatus:");
423 nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
424 printk("\n");
425 NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d "
426 "class 0x%04x mthd 0x%04x data 0x%08x\n",
427 chid, inst, subc, class, mthd, data);
428 }
429 }
430}
431
432static void
433nv40_graph_destroy(struct drm_device *dev, int engine)
434{
435 struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
436
437 nouveau_irq_unregister(dev, 12);
438
439 NVOBJ_ENGINE_DEL(dev, GR);
440 kfree(pgraph);
441}
442
443int
444nv40_graph_create(struct drm_device *dev)
445{
446 struct nv40_graph_engine *pgraph;
447
448 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
449 if (!pgraph)
450 return -ENOMEM;
451
452 pgraph->base.destroy = nv40_graph_destroy;
453 pgraph->base.init = nv40_graph_init;
454 pgraph->base.fini = nv40_graph_fini;
455 pgraph->base.context_new = nv40_graph_context_new;
456 pgraph->base.context_del = nv40_graph_context_del;
457 pgraph->base.object_new = nv40_graph_object_new;
458 pgraph->base.set_tile_region = nv40_graph_set_tile_region;
459
460 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
461 nouveau_irq_register(dev, 12, nv40_graph_isr);
462
463 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
464 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
465 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
466 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
467 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
468 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
469 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
470 NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
471 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
472 NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
473 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
474 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
475 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
476 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
477 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
478 NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
479
480 /* curie */
481 if (nv44_graph_class(dev))
482 NVOBJ_CLASS(dev, 0x4497, GR);
483 else
484 NVOBJ_CLASS(dev, 0x4097, GR);
485
486 /* nvsw */
487 NVOBJ_CLASS(dev, 0x506e, SW);
488 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
489 return 0;
490}
diff --git a/drivers/gpu/drm/nouveau/nv40_grctx.c b/drivers/gpu/drm/nouveau/nv40_grctx.c
new file mode 100644
index 00000000000..f70447d131d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_grctx.c
@@ -0,0 +1,662 @@
1/*
2 * Copyright 2009 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/* NVIDIA context programs handle a number of other conditions which are
26 * not implemented in our versions. It's not clear why NVIDIA context
27 * programs have this code, nor whether it's strictly necessary for
28 * correct operation. We'll implement additional handling if/when we
29 * discover it's necessary.
30 *
31 * - On context save, NVIDIA set 0x400314 bit 0 to 1 if the "3D state"
32 * flag is set, this gets saved into the context.
33 * - On context save, the context program for all cards load nsource
34 * into a flag register and check for ILLEGAL_MTHD. If it's set,
35 * opcode 0x60000d is called before resuming normal operation.
36 * - Some context programs check more conditions than the above. NV44
37 * checks: ((nsource & 0x0857) || (0x400718 & 0x0100) || (intr & 0x0001))
38 * and calls 0x60000d before resuming normal operation.
39 * - At the very beginning of NVIDIA's context programs, flag 9 is checked
40 * and if true 0x800001 is called with count=0, pos=0, the flag is cleared
41 * and then the ctxprog is aborted. It looks like a complicated NOP,
42 * its purpose is unknown.
43 * - In the section of code that loads the per-vs state, NVIDIA check
44 * flag 10. If it's set, they only transfer the small 0x300 byte block
45 * of state + the state for a single vs as opposed to the state for
46 * all vs units. It doesn't seem likely that it'll occur in normal
47 * operation, especially seeing as it appears NVIDIA may have screwed
48 * up the ctxprogs for some cards and have an invalid instruction
49 * rather than a cp_lsr(ctx, dwords_for_1_vs_unit) instruction.
50 * - There's a number of places where context offset 0 (where we place
51 * the PRAMIN offset of the context) is loaded into either 0x408000,
52 * 0x408004 or 0x408008. Not sure what's up there either.
53 * - The ctxprogs for some cards save 0x400a00 again during the cleanup
54 * path for auto-loadctx.
55 */
56
57#define CP_FLAG_CLEAR 0
58#define CP_FLAG_SET 1
59#define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0)
60#define CP_FLAG_SWAP_DIRECTION_LOAD 0
61#define CP_FLAG_SWAP_DIRECTION_SAVE 1
62#define CP_FLAG_USER_SAVE ((0 * 32) + 5)
63#define CP_FLAG_USER_SAVE_NOT_PENDING 0
64#define CP_FLAG_USER_SAVE_PENDING 1
65#define CP_FLAG_USER_LOAD ((0 * 32) + 6)
66#define CP_FLAG_USER_LOAD_NOT_PENDING 0
67#define CP_FLAG_USER_LOAD_PENDING 1
68#define CP_FLAG_STATUS ((3 * 32) + 0)
69#define CP_FLAG_STATUS_IDLE 0
70#define CP_FLAG_STATUS_BUSY 1
71#define CP_FLAG_AUTO_SAVE ((3 * 32) + 4)
72#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0
73#define CP_FLAG_AUTO_SAVE_PENDING 1
74#define CP_FLAG_AUTO_LOAD ((3 * 32) + 5)
75#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0
76#define CP_FLAG_AUTO_LOAD_PENDING 1
77#define CP_FLAG_UNK54 ((3 * 32) + 6)
78#define CP_FLAG_UNK54_CLEAR 0
79#define CP_FLAG_UNK54_SET 1
80#define CP_FLAG_ALWAYS ((3 * 32) + 8)
81#define CP_FLAG_ALWAYS_FALSE 0
82#define CP_FLAG_ALWAYS_TRUE 1
83#define CP_FLAG_UNK57 ((3 * 32) + 9)
84#define CP_FLAG_UNK57_CLEAR 0
85#define CP_FLAG_UNK57_SET 1
86
87#define CP_CTX 0x00100000
88#define CP_CTX_COUNT 0x000fc000
89#define CP_CTX_COUNT_SHIFT 14
90#define CP_CTX_REG 0x00003fff
91#define CP_LOAD_SR 0x00200000
92#define CP_LOAD_SR_VALUE 0x000fffff
93#define CP_BRA 0x00400000
94#define CP_BRA_IP 0x0000ff00
95#define CP_BRA_IP_SHIFT 8
96#define CP_BRA_IF_CLEAR 0x00000080
97#define CP_BRA_FLAG 0x0000007f
98#define CP_WAIT 0x00500000
99#define CP_WAIT_SET 0x00000080
100#define CP_WAIT_FLAG 0x0000007f
101#define CP_SET 0x00700000
102#define CP_SET_1 0x00000080
103#define CP_SET_FLAG 0x0000007f
104#define CP_NEXT_TO_SWAP 0x00600007
105#define CP_NEXT_TO_CURRENT 0x00600009
106#define CP_SET_CONTEXT_POINTER 0x0060000a
107#define CP_END 0x0060000e
108#define CP_LOAD_MAGIC_UNK01 0x00800001 /* unknown */
109#define CP_LOAD_MAGIC_NV44TCL 0x00800029 /* per-vs state (0x4497) */
110#define CP_LOAD_MAGIC_NV40TCL 0x00800041 /* per-vs state (0x4097) */
111
112#include "drmP.h"
113#include "nouveau_drv.h"
114#include "nouveau_grctx.h"
115
116/* TODO:
117 * - get vs count from 0x1540
118 */
119
120static int
121nv40_graph_vs_count(struct drm_device *dev)
122{
123 struct drm_nouveau_private *dev_priv = dev->dev_private;
124
125 switch (dev_priv->chipset) {
126 case 0x47:
127 case 0x49:
128 case 0x4b:
129 return 8;
130 case 0x40:
131 return 6;
132 case 0x41:
133 case 0x42:
134 return 5;
135 case 0x43:
136 case 0x44:
137 case 0x46:
138 case 0x4a:
139 return 3;
140 case 0x4c:
141 case 0x4e:
142 case 0x67:
143 default:
144 return 1;
145 }
146}
147
148
149enum cp_label {
150 cp_check_load = 1,
151 cp_setup_auto_load,
152 cp_setup_load,
153 cp_setup_save,
154 cp_swap_state,
155 cp_swap_state3d_3_is_save,
156 cp_prepare_exit,
157 cp_exit,
158};
159
160static void
161nv40_graph_construct_general(struct nouveau_grctx *ctx)
162{
163 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
164 int i;
165
166 cp_ctx(ctx, 0x4000a4, 1);
167 gr_def(ctx, 0x4000a4, 0x00000008);
168 cp_ctx(ctx, 0x400144, 58);
169 gr_def(ctx, 0x400144, 0x00000001);
170 cp_ctx(ctx, 0x400314, 1);
171 gr_def(ctx, 0x400314, 0x00000000);
172 cp_ctx(ctx, 0x400400, 10);
173 cp_ctx(ctx, 0x400480, 10);
174 cp_ctx(ctx, 0x400500, 19);
175 gr_def(ctx, 0x400514, 0x00040000);
176 gr_def(ctx, 0x400524, 0x55555555);
177 gr_def(ctx, 0x400528, 0x55555555);
178 gr_def(ctx, 0x40052c, 0x55555555);
179 gr_def(ctx, 0x400530, 0x55555555);
180 cp_ctx(ctx, 0x400560, 6);
181 gr_def(ctx, 0x400568, 0x0000ffff);
182 gr_def(ctx, 0x40056c, 0x0000ffff);
183 cp_ctx(ctx, 0x40057c, 5);
184 cp_ctx(ctx, 0x400710, 3);
185 gr_def(ctx, 0x400710, 0x20010001);
186 gr_def(ctx, 0x400714, 0x0f73ef00);
187 cp_ctx(ctx, 0x400724, 1);
188 gr_def(ctx, 0x400724, 0x02008821);
189 cp_ctx(ctx, 0x400770, 3);
190 if (dev_priv->chipset == 0x40) {
191 cp_ctx(ctx, 0x400814, 4);
192 cp_ctx(ctx, 0x400828, 5);
193 cp_ctx(ctx, 0x400840, 5);
194 gr_def(ctx, 0x400850, 0x00000040);
195 cp_ctx(ctx, 0x400858, 4);
196 gr_def(ctx, 0x400858, 0x00000040);
197 gr_def(ctx, 0x40085c, 0x00000040);
198 gr_def(ctx, 0x400864, 0x80000000);
199 cp_ctx(ctx, 0x40086c, 9);
200 gr_def(ctx, 0x40086c, 0x80000000);
201 gr_def(ctx, 0x400870, 0x80000000);
202 gr_def(ctx, 0x400874, 0x80000000);
203 gr_def(ctx, 0x400878, 0x80000000);
204 gr_def(ctx, 0x400888, 0x00000040);
205 gr_def(ctx, 0x40088c, 0x80000000);
206 cp_ctx(ctx, 0x4009c0, 8);
207 gr_def(ctx, 0x4009cc, 0x80000000);
208 gr_def(ctx, 0x4009dc, 0x80000000);
209 } else {
210 cp_ctx(ctx, 0x400840, 20);
211 if (nv44_graph_class(ctx->dev)) {
212 for (i = 0; i < 8; i++)
213 gr_def(ctx, 0x400860 + (i * 4), 0x00000001);
214 }
215 gr_def(ctx, 0x400880, 0x00000040);
216 gr_def(ctx, 0x400884, 0x00000040);
217 gr_def(ctx, 0x400888, 0x00000040);
218 cp_ctx(ctx, 0x400894, 11);
219 gr_def(ctx, 0x400894, 0x00000040);
220 if (!nv44_graph_class(ctx->dev)) {
221 for (i = 0; i < 8; i++)
222 gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000);
223 }
224 cp_ctx(ctx, 0x4008e0, 2);
225 cp_ctx(ctx, 0x4008f8, 2);
226 if (dev_priv->chipset == 0x4c ||
227 (dev_priv->chipset & 0xf0) == 0x60)
228 cp_ctx(ctx, 0x4009f8, 1);
229 }
230 cp_ctx(ctx, 0x400a00, 73);
231 gr_def(ctx, 0x400b0c, 0x0b0b0b0c);
232 cp_ctx(ctx, 0x401000, 4);
233 cp_ctx(ctx, 0x405004, 1);
234 switch (dev_priv->chipset) {
235 case 0x47:
236 case 0x49:
237 case 0x4b:
238 cp_ctx(ctx, 0x403448, 1);
239 gr_def(ctx, 0x403448, 0x00001010);
240 break;
241 default:
242 cp_ctx(ctx, 0x403440, 1);
243 switch (dev_priv->chipset) {
244 case 0x40:
245 gr_def(ctx, 0x403440, 0x00000010);
246 break;
247 case 0x44:
248 case 0x46:
249 case 0x4a:
250 gr_def(ctx, 0x403440, 0x00003010);
251 break;
252 case 0x41:
253 case 0x42:
254 case 0x43:
255 case 0x4c:
256 case 0x4e:
257 case 0x67:
258 default:
259 gr_def(ctx, 0x403440, 0x00001010);
260 break;
261 }
262 break;
263 }
264}
265
266static void
267nv40_graph_construct_state3d(struct nouveau_grctx *ctx)
268{
269 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
270 int i;
271
272 if (dev_priv->chipset == 0x40) {
273 cp_ctx(ctx, 0x401880, 51);
274 gr_def(ctx, 0x401940, 0x00000100);
275 } else
276 if (dev_priv->chipset == 0x46 || dev_priv->chipset == 0x47 ||
277 dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) {
278 cp_ctx(ctx, 0x401880, 32);
279 for (i = 0; i < 16; i++)
280 gr_def(ctx, 0x401880 + (i * 4), 0x00000111);
281 if (dev_priv->chipset == 0x46)
282 cp_ctx(ctx, 0x401900, 16);
283 cp_ctx(ctx, 0x401940, 3);
284 }
285 cp_ctx(ctx, 0x40194c, 18);
286 gr_def(ctx, 0x401954, 0x00000111);
287 gr_def(ctx, 0x401958, 0x00080060);
288 gr_def(ctx, 0x401974, 0x00000080);
289 gr_def(ctx, 0x401978, 0xffff0000);
290 gr_def(ctx, 0x40197c, 0x00000001);
291 gr_def(ctx, 0x401990, 0x46400000);
292 if (dev_priv->chipset == 0x40) {
293 cp_ctx(ctx, 0x4019a0, 2);
294 cp_ctx(ctx, 0x4019ac, 5);
295 } else {
296 cp_ctx(ctx, 0x4019a0, 1);
297 cp_ctx(ctx, 0x4019b4, 3);
298 }
299 gr_def(ctx, 0x4019bc, 0xffff0000);
300 switch (dev_priv->chipset) {
301 case 0x46:
302 case 0x47:
303 case 0x49:
304 case 0x4b:
305 cp_ctx(ctx, 0x4019c0, 18);
306 for (i = 0; i < 16; i++)
307 gr_def(ctx, 0x4019c0 + (i * 4), 0x88888888);
308 break;
309 }
310 cp_ctx(ctx, 0x401a08, 8);
311 gr_def(ctx, 0x401a10, 0x0fff0000);
312 gr_def(ctx, 0x401a14, 0x0fff0000);
313 gr_def(ctx, 0x401a1c, 0x00011100);
314 cp_ctx(ctx, 0x401a2c, 4);
315 cp_ctx(ctx, 0x401a44, 26);
316 for (i = 0; i < 16; i++)
317 gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000);
318 gr_def(ctx, 0x401a8c, 0x4b7fffff);
319 if (dev_priv->chipset == 0x40) {
320 cp_ctx(ctx, 0x401ab8, 3);
321 } else {
322 cp_ctx(ctx, 0x401ab8, 1);
323 cp_ctx(ctx, 0x401ac0, 1);
324 }
325 cp_ctx(ctx, 0x401ad0, 8);
326 gr_def(ctx, 0x401ad0, 0x30201000);
327 gr_def(ctx, 0x401ad4, 0x70605040);
328 gr_def(ctx, 0x401ad8, 0xb8a89888);
329 gr_def(ctx, 0x401adc, 0xf8e8d8c8);
330 cp_ctx(ctx, 0x401b10, dev_priv->chipset == 0x40 ? 2 : 1);
331 gr_def(ctx, 0x401b10, 0x40100000);
332 cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5);
333 gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ?
334 0x00000004 : 0x00000000);
335 cp_ctx(ctx, 0x401b30, 25);
336 gr_def(ctx, 0x401b34, 0x0000ffff);
337 gr_def(ctx, 0x401b68, 0x435185d6);
338 gr_def(ctx, 0x401b6c, 0x2155b699);
339 gr_def(ctx, 0x401b70, 0xfedcba98);
340 gr_def(ctx, 0x401b74, 0x00000098);
341 gr_def(ctx, 0x401b84, 0xffffffff);
342 gr_def(ctx, 0x401b88, 0x00ff7000);
343 gr_def(ctx, 0x401b8c, 0x0000ffff);
344 if (dev_priv->chipset != 0x44 && dev_priv->chipset != 0x4a &&
345 dev_priv->chipset != 0x4e)
346 cp_ctx(ctx, 0x401b94, 1);
347 cp_ctx(ctx, 0x401b98, 8);
348 gr_def(ctx, 0x401b9c, 0x00ff0000);
349 cp_ctx(ctx, 0x401bc0, 9);
350 gr_def(ctx, 0x401be0, 0x00ffff00);
351 cp_ctx(ctx, 0x401c00, 192);
352 for (i = 0; i < 16; i++) { /* fragment texture units */
353 gr_def(ctx, 0x401c40 + (i * 4), 0x00018488);
354 gr_def(ctx, 0x401c80 + (i * 4), 0x00028202);
355 gr_def(ctx, 0x401d00 + (i * 4), 0x0000aae4);
356 gr_def(ctx, 0x401d40 + (i * 4), 0x01012000);
357 gr_def(ctx, 0x401d80 + (i * 4), 0x00080008);
358 gr_def(ctx, 0x401e00 + (i * 4), 0x00100008);
359 }
360 for (i = 0; i < 4; i++) { /* vertex texture units */
361 gr_def(ctx, 0x401e90 + (i * 4), 0x0001bc80);
362 gr_def(ctx, 0x401ea0 + (i * 4), 0x00000202);
363 gr_def(ctx, 0x401ec0 + (i * 4), 0x00000008);
364 gr_def(ctx, 0x401ee0 + (i * 4), 0x00080008);
365 }
366 cp_ctx(ctx, 0x400f5c, 3);
367 gr_def(ctx, 0x400f5c, 0x00000002);
368 cp_ctx(ctx, 0x400f84, 1);
369}
370
371static void
372nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx)
373{
374 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
375 int i;
376
377 cp_ctx(ctx, 0x402000, 1);
378 cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2);
379 switch (dev_priv->chipset) {
380 case 0x40:
381 gr_def(ctx, 0x402404, 0x00000001);
382 break;
383 case 0x4c:
384 case 0x4e:
385 case 0x67:
386 gr_def(ctx, 0x402404, 0x00000020);
387 break;
388 case 0x46:
389 case 0x49:
390 case 0x4b:
391 gr_def(ctx, 0x402404, 0x00000421);
392 break;
393 default:
394 gr_def(ctx, 0x402404, 0x00000021);
395 }
396 if (dev_priv->chipset != 0x40)
397 gr_def(ctx, 0x402408, 0x030c30c3);
398 switch (dev_priv->chipset) {
399 case 0x44:
400 case 0x46:
401 case 0x4a:
402 case 0x4c:
403 case 0x4e:
404 case 0x67:
405 cp_ctx(ctx, 0x402440, 1);
406 gr_def(ctx, 0x402440, 0x00011001);
407 break;
408 default:
409 break;
410 }
411 cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9);
412 gr_def(ctx, 0x402488, 0x3e020200);
413 gr_def(ctx, 0x40248c, 0x00ffffff);
414 switch (dev_priv->chipset) {
415 case 0x40:
416 gr_def(ctx, 0x402490, 0x60103f00);
417 break;
418 case 0x47:
419 gr_def(ctx, 0x402490, 0x40103f00);
420 break;
421 case 0x41:
422 case 0x42:
423 case 0x49:
424 case 0x4b:
425 gr_def(ctx, 0x402490, 0x20103f00);
426 break;
427 default:
428 gr_def(ctx, 0x402490, 0x0c103f00);
429 break;
430 }
431 gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ?
432 0x00020000 : 0x00040000);
433 cp_ctx(ctx, 0x402500, 31);
434 gr_def(ctx, 0x402530, 0x00008100);
435 if (dev_priv->chipset == 0x40)
436 cp_ctx(ctx, 0x40257c, 6);
437 cp_ctx(ctx, 0x402594, 16);
438 cp_ctx(ctx, 0x402800, 17);
439 gr_def(ctx, 0x402800, 0x00000001);
440 switch (dev_priv->chipset) {
441 case 0x47:
442 case 0x49:
443 case 0x4b:
444 cp_ctx(ctx, 0x402864, 1);
445 gr_def(ctx, 0x402864, 0x00001001);
446 cp_ctx(ctx, 0x402870, 3);
447 gr_def(ctx, 0x402878, 0x00000003);
448 if (dev_priv->chipset != 0x47) { /* belong at end!! */
449 cp_ctx(ctx, 0x402900, 1);
450 cp_ctx(ctx, 0x402940, 1);
451 cp_ctx(ctx, 0x402980, 1);
452 cp_ctx(ctx, 0x4029c0, 1);
453 cp_ctx(ctx, 0x402a00, 1);
454 cp_ctx(ctx, 0x402a40, 1);
455 cp_ctx(ctx, 0x402a80, 1);
456 cp_ctx(ctx, 0x402ac0, 1);
457 }
458 break;
459 case 0x40:
460 cp_ctx(ctx, 0x402844, 1);
461 gr_def(ctx, 0x402844, 0x00000001);
462 cp_ctx(ctx, 0x402850, 1);
463 break;
464 default:
465 cp_ctx(ctx, 0x402844, 1);
466 gr_def(ctx, 0x402844, 0x00001001);
467 cp_ctx(ctx, 0x402850, 2);
468 gr_def(ctx, 0x402854, 0x00000003);
469 break;
470 }
471
472 cp_ctx(ctx, 0x402c00, 4);
473 gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ?
474 0x80800001 : 0x00888001);
475 switch (dev_priv->chipset) {
476 case 0x47:
477 case 0x49:
478 case 0x4b:
479 cp_ctx(ctx, 0x402c20, 40);
480 for (i = 0; i < 32; i++)
481 gr_def(ctx, 0x402c40 + (i * 4), 0xffffffff);
482 cp_ctx(ctx, 0x4030b8, 13);
483 gr_def(ctx, 0x4030dc, 0x00000005);
484 gr_def(ctx, 0x4030e8, 0x0000ffff);
485 break;
486 default:
487 cp_ctx(ctx, 0x402c10, 4);
488 if (dev_priv->chipset == 0x40)
489 cp_ctx(ctx, 0x402c20, 36);
490 else
491 if (dev_priv->chipset <= 0x42)
492 cp_ctx(ctx, 0x402c20, 24);
493 else
494 if (dev_priv->chipset <= 0x4a)
495 cp_ctx(ctx, 0x402c20, 16);
496 else
497 cp_ctx(ctx, 0x402c20, 8);
498 cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13);
499 gr_def(ctx, 0x402cd4, 0x00000005);
500 if (dev_priv->chipset != 0x40)
501 gr_def(ctx, 0x402ce0, 0x0000ffff);
502 break;
503 }
504
505 cp_ctx(ctx, 0x403400, dev_priv->chipset == 0x40 ? 4 : 3);
506 cp_ctx(ctx, 0x403410, dev_priv->chipset == 0x40 ? 4 : 3);
507 cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->dev));
508 for (i = 0; i < nv40_graph_vs_count(ctx->dev); i++)
509 gr_def(ctx, 0x403420 + (i * 4), 0x00005555);
510
511 if (dev_priv->chipset != 0x40) {
512 cp_ctx(ctx, 0x403600, 1);
513 gr_def(ctx, 0x403600, 0x00000001);
514 }
515 cp_ctx(ctx, 0x403800, 1);
516
517 cp_ctx(ctx, 0x403c18, 1);
518 gr_def(ctx, 0x403c18, 0x00000001);
519 switch (dev_priv->chipset) {
520 case 0x46:
521 case 0x47:
522 case 0x49:
523 case 0x4b:
524 cp_ctx(ctx, 0x405018, 1);
525 gr_def(ctx, 0x405018, 0x08e00001);
526 cp_ctx(ctx, 0x405c24, 1);
527 gr_def(ctx, 0x405c24, 0x000e3000);
528 break;
529 }
530 if (dev_priv->chipset != 0x4e)
531 cp_ctx(ctx, 0x405800, 11);
532 cp_ctx(ctx, 0x407000, 1);
533}
534
535static void
536nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx)
537{
538 int len = nv44_graph_class(ctx->dev) ? 0x0084 : 0x0684;
539
540 cp_out (ctx, 0x300000);
541 cp_lsr (ctx, len - 4);
542 cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_swap_state3d_3_is_save);
543 cp_lsr (ctx, len);
544 cp_name(ctx, cp_swap_state3d_3_is_save);
545 cp_out (ctx, 0x800001);
546
547 ctx->ctxvals_pos += len;
548}
549
550static void
551nv40_graph_construct_shader(struct nouveau_grctx *ctx)
552{
553 struct drm_device *dev = ctx->dev;
554 struct drm_nouveau_private *dev_priv = dev->dev_private;
555 struct nouveau_gpuobj *obj = ctx->data;
556 int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset;
557 int offset, i;
558
559 vs_nr = nv40_graph_vs_count(ctx->dev);
560 vs_nr_b0 = 363;
561 vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64;
562 if (dev_priv->chipset == 0x40) {
563 b0_offset = 0x2200/4; /* 33a0 */
564 b1_offset = 0x55a0/4; /* 1500 */
565 vs_len = 0x6aa0/4;
566 } else
567 if (dev_priv->chipset == 0x41 || dev_priv->chipset == 0x42) {
568 b0_offset = 0x2200/4; /* 2200 */
569 b1_offset = 0x4400/4; /* 0b00 */
570 vs_len = 0x4f00/4;
571 } else {
572 b0_offset = 0x1d40/4; /* 2200 */
573 b1_offset = 0x3f40/4; /* 0b00 : 0a40 */
574 vs_len = nv44_graph_class(dev) ? 0x4980/4 : 0x4a40/4;
575 }
576
577 cp_lsr(ctx, vs_len * vs_nr + 0x300/4);
578 cp_out(ctx, nv44_graph_class(dev) ? 0x800029 : 0x800041);
579
580 offset = ctx->ctxvals_pos;
581 ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len));
582
583 if (ctx->mode != NOUVEAU_GRCTX_VALS)
584 return;
585
586 offset += 0x0280/4;
587 for (i = 0; i < 16; i++, offset += 2)
588 nv_wo32(obj, offset * 4, 0x3f800000);
589
590 for (vs = 0; vs < vs_nr; vs++, offset += vs_len) {
591 for (i = 0; i < vs_nr_b0 * 6; i += 6)
592 nv_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001);
593 for (i = 0; i < vs_nr_b1 * 4; i += 4)
594 nv_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000);
595 }
596}
597
598void
599nv40_grctx_init(struct nouveau_grctx *ctx)
600{
601 /* decide whether we're loading/unloading the context */
602 cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
603 cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
604
605 cp_name(ctx, cp_check_load);
606 cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);
607 cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);
608 cp_bra (ctx, ALWAYS, TRUE, cp_exit);
609
610 /* setup for context load */
611 cp_name(ctx, cp_setup_auto_load);
612 cp_wait(ctx, STATUS, IDLE);
613 cp_out (ctx, CP_NEXT_TO_SWAP);
614 cp_name(ctx, cp_setup_load);
615 cp_wait(ctx, STATUS, IDLE);
616 cp_set (ctx, SWAP_DIRECTION, LOAD);
617 cp_out (ctx, 0x00910880); /* ?? */
618 cp_out (ctx, 0x00901ffe); /* ?? */
619 cp_out (ctx, 0x01940000); /* ?? */
620 cp_lsr (ctx, 0x20);
621 cp_out (ctx, 0x0060000b); /* ?? */
622 cp_wait(ctx, UNK57, CLEAR);
623 cp_out (ctx, 0x0060000c); /* ?? */
624 cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);
625
626 /* setup for context save */
627 cp_name(ctx, cp_setup_save);
628 cp_set (ctx, SWAP_DIRECTION, SAVE);
629
630 /* general PGRAPH state */
631 cp_name(ctx, cp_swap_state);
632 cp_pos (ctx, 0x00020/4);
633 nv40_graph_construct_general(ctx);
634 cp_wait(ctx, STATUS, IDLE);
635
636 /* 3D state, block 1 */
637 cp_bra (ctx, UNK54, CLEAR, cp_prepare_exit);
638 nv40_graph_construct_state3d(ctx);
639 cp_wait(ctx, STATUS, IDLE);
640
641 /* 3D state, block 2 */
642 nv40_graph_construct_state3d_2(ctx);
643
644 /* Some other block of "random" state */
645 nv40_graph_construct_state3d_3(ctx);
646
647 /* Per-vertex shader state */
648 cp_pos (ctx, ctx->ctxvals_pos);
649 nv40_graph_construct_shader(ctx);
650
651 /* pre-exit state updates */
652 cp_name(ctx, cp_prepare_exit);
653 cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);
654 cp_bra (ctx, USER_SAVE, PENDING, cp_exit);
655 cp_out (ctx, CP_NEXT_TO_CURRENT);
656
657 cp_name(ctx, cp_exit);
658 cp_set (ctx, USER_SAVE, NOT_PENDING);
659 cp_set (ctx, USER_LOAD, NOT_PENDING);
660 cp_out (ctx, CP_END);
661}
662
diff --git a/drivers/gpu/drm/nouveau/nv40_mc.c b/drivers/gpu/drm/nouveau/nv40_mc.c
new file mode 100644
index 00000000000..03c0d4c3f35
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_mc.c
@@ -0,0 +1,28 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6int
7nv40_mc_init(struct drm_device *dev)
8{
9 /* Power up everything, resetting each individual unit will
10 * be done later if needed.
11 */
12 nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
13
14 if (nv44_graph_class(dev)) {
15 u32 tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA);
16 nv_wr32(dev, NV40_PMC_1700, tmp);
17 nv_wr32(dev, NV40_PMC_1704, 0);
18 nv_wr32(dev, NV40_PMC_1708, 0);
19 nv_wr32(dev, NV40_PMC_170C, tmp);
20 }
21
22 return 0;
23}
24
25void
26nv40_mc_takedown(struct drm_device *dev)
27{
28}
diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c
new file mode 100644
index 00000000000..ad03a0e1fc7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c
@@ -0,0 +1,311 @@
1/*
2 * Copyright 2011 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_ramht.h"
28
29struct nv40_mpeg_engine {
30 struct nouveau_exec_engine base;
31};
32
33static int
34nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
35{
36 struct drm_device *dev = chan->dev;
37 struct drm_nouveau_private *dev_priv = dev->dev_private;
38 struct nouveau_gpuobj *ctx = NULL;
39 unsigned long flags;
40 int ret;
41
42 NV_DEBUG(dev, "ch%d\n", chan->id);
43
44 ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
45 NVOBJ_FLAG_ZERO_FREE, &ctx);
46 if (ret)
47 return ret;
48
49 nv_wo32(ctx, 0x78, 0x02001ec1);
50
51 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
52 nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
53 if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
54 nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
55 nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
56 nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
57 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
58
59 chan->engctx[engine] = ctx;
60 return 0;
61}
62
63static void
64nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
65{
66 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
67 struct nouveau_gpuobj *ctx = chan->engctx[engine];
68 struct drm_device *dev = chan->dev;
69 unsigned long flags;
70 u32 inst = 0x80000000 | (ctx->pinst >> 4);
71
72 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
73 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
74 if (nv_rd32(dev, 0x00b318) == inst)
75 nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
76 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
77 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
78
79 nouveau_gpuobj_ref(NULL, &ctx);
80 chan->engctx[engine] = NULL;
81}
82
83static int
84nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
85 u32 handle, u16 class)
86{
87 struct drm_device *dev = chan->dev;
88 struct nouveau_gpuobj *obj = NULL;
89 int ret;
90
91 ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
92 NVOBJ_FLAG_ZERO_FREE, &obj);
93 if (ret)
94 return ret;
95 obj->engine = 2;
96 obj->class = class;
97
98 nv_wo32(obj, 0x00, class);
99
100 ret = nouveau_ramht_insert(chan, handle, obj);
101 nouveau_gpuobj_ref(NULL, &obj);
102 return ret;
103}
104
105static int
106nv40_mpeg_init(struct drm_device *dev, int engine)
107{
108 struct drm_nouveau_private *dev_priv = dev->dev_private;
109 struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
110 int i;
111
112 /* VPE init */
113 nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
114 nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
115 nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
116 nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
117
118 for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
119 pmpeg->base.set_tile_region(dev, i);
120
121 /* PMPEG init */
122 nv_wr32(dev, 0x00b32c, 0x00000000);
123 nv_wr32(dev, 0x00b314, 0x00000100);
124 nv_wr32(dev, 0x00b220, 0x00000044);
125 nv_wr32(dev, 0x00b300, 0x02001ec1);
126 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
127
128 nv_wr32(dev, 0x00b100, 0xffffffff);
129 nv_wr32(dev, 0x00b140, 0xffffffff);
130
131 if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
132 NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
133 return -EBUSY;
134 }
135
136 return 0;
137}
138
139static int
140nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
141{
142 /*XXX: context save? */
143 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
144 nv_wr32(dev, 0x00b140, 0x00000000);
145 return 0;
146}
147
148static int
149nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
150{
151 struct drm_device *dev = chan->dev;
152 u32 inst = data << 4;
153 u32 dma0 = nv_ri32(dev, inst + 0);
154 u32 dma1 = nv_ri32(dev, inst + 4);
155 u32 dma2 = nv_ri32(dev, inst + 8);
156 u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
157 u32 size = dma1 + 1;
158
159 /* only allow linear DMA objects */
160 if (!(dma0 & 0x00002000))
161 return -EINVAL;
162
163 if (mthd == 0x0190) {
164 /* DMA_CMD */
165 nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
166 nv_wr32(dev, 0x00b334, base);
167 nv_wr32(dev, 0x00b324, size);
168 } else
169 if (mthd == 0x01a0) {
170 /* DMA_DATA */
171 nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
172 nv_wr32(dev, 0x00b360, base);
173 nv_wr32(dev, 0x00b364, size);
174 } else {
175 /* DMA_IMAGE, VRAM only */
176 if (dma0 & 0x000c0000)
177 return -EINVAL;
178
179 nv_wr32(dev, 0x00b370, base);
180 nv_wr32(dev, 0x00b374, size);
181 }
182
183 return 0;
184}
185
186static int
187nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
188{
189 struct drm_nouveau_private *dev_priv = dev->dev_private;
190 struct nouveau_gpuobj *ctx;
191 unsigned long flags;
192 int i;
193
194 spin_lock_irqsave(&dev_priv->channels.lock, flags);
195 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
196 if (!dev_priv->channels.ptr[i])
197 continue;
198
199 ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
200 if (ctx && ctx->pinst == inst)
201 break;
202 }
203 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
204 return i;
205}
206
207static void
208nv40_vpe_set_tile_region(struct drm_device *dev, int i)
209{
210 struct drm_nouveau_private *dev_priv = dev->dev_private;
211 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
212
213 nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
214 nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
215 nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
216}
217
218static void
219nv40_mpeg_isr(struct drm_device *dev)
220{
221 u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
222 u32 chid = nv40_mpeg_isr_chid(dev, inst);
223 u32 stat = nv_rd32(dev, 0x00b100);
224 u32 type = nv_rd32(dev, 0x00b230);
225 u32 mthd = nv_rd32(dev, 0x00b234);
226 u32 data = nv_rd32(dev, 0x00b238);
227 u32 show = stat;
228
229 if (stat & 0x01000000) {
230 /* happens on initial binding of the object */
231 if (type == 0x00000020 && mthd == 0x0000) {
232 nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
233 show &= ~0x01000000;
234 }
235
236 if (type == 0x00000010) {
237 if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
238 show &= ~0x01000000;
239 }
240 }
241
242 nv_wr32(dev, 0x00b100, stat);
243 nv_wr32(dev, 0x00b230, 0x00000001);
244
245 if (show && nouveau_ratelimit()) {
246 NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
247 chid, inst, stat, type, mthd, data);
248 }
249}
250
251static void
252nv40_vpe_isr(struct drm_device *dev)
253{
254 if (nv_rd32(dev, 0x00b100))
255 nv40_mpeg_isr(dev);
256
257 if (nv_rd32(dev, 0x00b800)) {
258 u32 stat = nv_rd32(dev, 0x00b800);
259 NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
260 nv_wr32(dev, 0xb800, stat);
261 }
262}
263
264static void
265nv40_mpeg_destroy(struct drm_device *dev, int engine)
266{
267 struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
268
269 nouveau_irq_unregister(dev, 0);
270
271 NVOBJ_ENGINE_DEL(dev, MPEG);
272 kfree(pmpeg);
273}
274
275int
276nv40_mpeg_create(struct drm_device *dev)
277{
278 struct nv40_mpeg_engine *pmpeg;
279
280 pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
281 if (!pmpeg)
282 return -ENOMEM;
283
284 pmpeg->base.destroy = nv40_mpeg_destroy;
285 pmpeg->base.init = nv40_mpeg_init;
286 pmpeg->base.fini = nv40_mpeg_fini;
287 pmpeg->base.context_new = nv40_mpeg_context_new;
288 pmpeg->base.context_del = nv40_mpeg_context_del;
289 pmpeg->base.object_new = nv40_mpeg_object_new;
290
291 /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between
292 * all VPE engines, for this driver's purposes the PMPEG engine
293 * will be treated as the "master" and handle the global VPE
294 * bits too
295 */
296 pmpeg->base.set_tile_region = nv40_vpe_set_tile_region;
297 nouveau_irq_register(dev, 0, nv40_vpe_isr);
298
299 NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
300 NVOBJ_CLASS(dev, 0x3174, MPEG);
301 NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma);
302 NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma);
303 NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma);
304
305#if 0
306 NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
307 NVOBJ_CLASS(dev, 0x4075, ME);
308#endif
309 return 0;
310
311}
diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c
new file mode 100644
index 00000000000..8cf63a8b30c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_calc.c
@@ -0,0 +1,97 @@
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
29int
30nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk,
31 int *N1, int *M1, int *N2, int *M2, int *P)
32{
33 struct nouveau_pll_vals pll_vals;
34 int ret;
35
36 ret = nouveau_calc_pll_mnp(dev, pll, clk, &pll_vals);
37 if (ret <= 0)
38 return ret;
39
40 *N1 = pll_vals.N1;
41 *M1 = pll_vals.M1;
42 *N2 = pll_vals.N2;
43 *M2 = pll_vals.M2;
44 *P = pll_vals.log2P;
45 return ret;
46}
47
48int
49nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk,
50 int *pN, int *pfN, int *pM, int *P)
51{
52 u32 best_err = ~0, err;
53 int M, lM, hM, N, fN;
54
55 *P = pll->vco1.maxfreq / clk;
56 if (*P > pll->max_p)
57 *P = pll->max_p;
58 if (*P < pll->min_p)
59 *P = pll->min_p;
60
61 lM = (pll->refclk + pll->vco1.max_inputfreq) / pll->vco1.max_inputfreq;
62 lM = max(lM, (int)pll->vco1.min_m);
63 hM = (pll->refclk + pll->vco1.min_inputfreq) / pll->vco1.min_inputfreq;
64 hM = min(hM, (int)pll->vco1.max_m);
65
66 for (M = lM; M <= hM; M++) {
67 u32 tmp = clk * *P * M;
68 N = tmp / pll->refclk;
69 fN = tmp % pll->refclk;
70 if (!pfN && fN >= pll->refclk / 2)
71 N++;
72
73 if (N < pll->vco1.min_n)
74 continue;
75 if (N > pll->vco1.max_n)
76 break;
77
78 err = abs(clk - (pll->refclk * N / M / *P));
79 if (err < best_err) {
80 best_err = err;
81 *pN = N;
82 *pM = M;
83 }
84
85 if (pfN) {
86 *pfN = (((fN << 13) / pll->refclk) - 4096) & 0xffff;
87 return clk;
88 }
89 }
90
91 if (unlikely(best_err == ~0)) {
92 NV_ERROR(dev, "unable to find matching pll values\n");
93 return -EINVAL;
94 }
95
96 return pll->refclk * *pN / *pM / *P;
97}
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
new file mode 100644
index 00000000000..5d989073ba6
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -0,0 +1,796 @@
1/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm_mode.h"
29#include "drm_crtc_helper.h"
30
31#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
32#include "nouveau_reg.h"
33#include "nouveau_drv.h"
34#include "nouveau_hw.h"
35#include "nouveau_encoder.h"
36#include "nouveau_crtc.h"
37#include "nouveau_fb.h"
38#include "nouveau_connector.h"
39#include "nv50_display.h"
40
41static void
42nv50_crtc_lut_load(struct drm_crtc *crtc)
43{
44 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
45 void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
46 int i;
47
48 NV_DEBUG_KMS(crtc->dev, "\n");
49
50 for (i = 0; i < 256; i++) {
51 writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0);
52 writew(nv_crtc->lut.g[i] >> 2, lut + 8*i + 2);
53 writew(nv_crtc->lut.b[i] >> 2, lut + 8*i + 4);
54 }
55
56 if (nv_crtc->lut.depth == 30) {
57 writew(nv_crtc->lut.r[i - 1] >> 2, lut + 8*i + 0);
58 writew(nv_crtc->lut.g[i - 1] >> 2, lut + 8*i + 2);
59 writew(nv_crtc->lut.b[i - 1] >> 2, lut + 8*i + 4);
60 }
61}
62
63int
64nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
65{
66 struct drm_device *dev = nv_crtc->base.dev;
67 struct drm_nouveau_private *dev_priv = dev->dev_private;
68 struct nouveau_channel *evo = nv50_display(dev)->master;
69 int index = nv_crtc->index, ret;
70
71 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
72 NV_DEBUG_KMS(dev, "%s\n", blanked ? "blanked" : "unblanked");
73
74 if (blanked) {
75 nv_crtc->cursor.hide(nv_crtc, false);
76
77 ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 7 : 5);
78 if (ret) {
79 NV_ERROR(dev, "no space while blanking crtc\n");
80 return ret;
81 }
82 BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2);
83 OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK);
84 OUT_RING(evo, 0);
85 if (dev_priv->chipset != 0x50) {
86 BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
87 OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE);
88 }
89
90 BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
91 OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
92 } else {
93 if (nv_crtc->cursor.visible)
94 nv_crtc->cursor.show(nv_crtc, false);
95 else
96 nv_crtc->cursor.hide(nv_crtc, false);
97
98 ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 10 : 8);
99 if (ret) {
100 NV_ERROR(dev, "no space while unblanking crtc\n");
101 return ret;
102 }
103 BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2);
104 OUT_RING(evo, nv_crtc->lut.depth == 8 ?
105 NV50_EVO_CRTC_CLUT_MODE_OFF :
106 NV50_EVO_CRTC_CLUT_MODE_ON);
107 OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8);
108 if (dev_priv->chipset != 0x50) {
109 BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
110 OUT_RING(evo, NvEvoVRAM);
111 }
112
113 BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_OFFSET), 2);
114 OUT_RING(evo, nv_crtc->fb.offset >> 8);
115 OUT_RING(evo, 0);
116 BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
117 if (dev_priv->chipset != 0x50)
118 if (nv_crtc->fb.tile_flags == 0x7a00 ||
119 nv_crtc->fb.tile_flags == 0xfe00)
120 OUT_RING(evo, NvEvoFB32);
121 else
122 if (nv_crtc->fb.tile_flags == 0x7000)
123 OUT_RING(evo, NvEvoFB16);
124 else
125 OUT_RING(evo, NvEvoVRAM_LP);
126 else
127 OUT_RING(evo, NvEvoVRAM_LP);
128 }
129
130 nv_crtc->fb.blanked = blanked;
131 return 0;
132}
133
134static int
135nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
136{
137 struct drm_device *dev = nv_crtc->base.dev;
138 struct nouveau_channel *evo = nv50_display(dev)->master;
139 int ret;
140
141 NV_DEBUG_KMS(dev, "\n");
142
143 ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
144 if (ret) {
145 NV_ERROR(dev, "no space while setting dither\n");
146 return ret;
147 }
148
149 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DITHER_CTRL), 1);
150 if (on)
151 OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_ON);
152 else
153 OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_OFF);
154
155 if (update) {
156 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
157 OUT_RING(evo, 0);
158 FIRE_RING(evo);
159 }
160
161 return 0;
162}
163
164struct nouveau_connector *
165nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
166{
167 struct drm_device *dev = nv_crtc->base.dev;
168 struct drm_connector *connector;
169 struct drm_crtc *crtc = to_drm_crtc(nv_crtc);
170
171 /* The safest approach is to find an encoder with the right crtc, that
172 * is also linked to a connector. */
173 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
174 if (connector->encoder)
175 if (connector->encoder->crtc == crtc)
176 return nouveau_connector(connector);
177 }
178
179 return NULL;
180}
181
182static int
183nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update)
184{
185 struct nouveau_connector *nv_connector =
186 nouveau_crtc_connector_get(nv_crtc);
187 struct drm_device *dev = nv_crtc->base.dev;
188 struct nouveau_channel *evo = nv50_display(dev)->master;
189 struct drm_display_mode *native_mode = NULL;
190 struct drm_display_mode *mode = &nv_crtc->base.mode;
191 uint32_t outX, outY, horiz, vert;
192 int ret;
193
194 NV_DEBUG_KMS(dev, "\n");
195
196 switch (scaling_mode) {
197 case DRM_MODE_SCALE_NONE:
198 break;
199 default:
200 if (!nv_connector || !nv_connector->native_mode) {
201 NV_ERROR(dev, "No native mode, forcing panel scaling\n");
202 scaling_mode = DRM_MODE_SCALE_NONE;
203 } else {
204 native_mode = nv_connector->native_mode;
205 }
206 break;
207 }
208
209 switch (scaling_mode) {
210 case DRM_MODE_SCALE_ASPECT:
211 horiz = (native_mode->hdisplay << 19) / mode->hdisplay;
212 vert = (native_mode->vdisplay << 19) / mode->vdisplay;
213
214 if (vert > horiz) {
215 outX = (mode->hdisplay * horiz) >> 19;
216 outY = (mode->vdisplay * horiz) >> 19;
217 } else {
218 outX = (mode->hdisplay * vert) >> 19;
219 outY = (mode->vdisplay * vert) >> 19;
220 }
221 break;
222 case DRM_MODE_SCALE_FULLSCREEN:
223 outX = native_mode->hdisplay;
224 outY = native_mode->vdisplay;
225 break;
226 case DRM_MODE_SCALE_CENTER:
227 case DRM_MODE_SCALE_NONE:
228 default:
229 outX = mode->hdisplay;
230 outY = mode->vdisplay;
231 break;
232 }
233
234 ret = RING_SPACE(evo, update ? 7 : 5);
235 if (ret)
236 return ret;
237
238 /* Got a better name for SCALER_ACTIVE? */
239 /* One day i've got to really figure out why this is needed. */
240 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1);
241 if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) ||
242 (mode->flags & DRM_MODE_FLAG_INTERLACE) ||
243 mode->hdisplay != outX || mode->vdisplay != outY) {
244 OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_ACTIVE);
245 } else {
246 OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_INACTIVE);
247 }
248
249 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2);
250 OUT_RING(evo, outY << 16 | outX);
251 OUT_RING(evo, outY << 16 | outX);
252
253 if (update) {
254 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
255 OUT_RING(evo, 0);
256 FIRE_RING(evo);
257 }
258
259 return 0;
260}
261
262int
263nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
264{
265 struct drm_nouveau_private *dev_priv = dev->dev_private;
266 struct pll_lims pll;
267 uint32_t reg1, reg2;
268 int ret, N1, M1, N2, M2, P;
269
270 ret = get_pll_limits(dev, PLL_VPLL0 + head, &pll);
271 if (ret)
272 return ret;
273
274 if (pll.vco2.maxfreq) {
275 ret = nv50_calc_pll(dev, &pll, pclk, &N1, &M1, &N2, &M2, &P);
276 if (ret <= 0)
277 return 0;
278
279 NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n",
280 pclk, ret, N1, M1, N2, M2, P);
281
282 reg1 = nv_rd32(dev, pll.reg + 4) & 0xff00ff00;
283 reg2 = nv_rd32(dev, pll.reg + 8) & 0x8000ff00;
284 nv_wr32(dev, pll.reg + 0, 0x10000611);
285 nv_wr32(dev, pll.reg + 4, reg1 | (M1 << 16) | N1);
286 nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2);
287 } else
288 if (dev_priv->chipset < NV_C0) {
289 ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P);
290 if (ret <= 0)
291 return 0;
292
293 NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n",
294 pclk, ret, N1, N2, M1, P);
295
296 reg1 = nv_rd32(dev, pll.reg + 4) & 0xffc00000;
297 nv_wr32(dev, pll.reg + 0, 0x50000610);
298 nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1);
299 nv_wr32(dev, pll.reg + 8, N2);
300 } else {
301 ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P);
302 if (ret <= 0)
303 return 0;
304
305 NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n",
306 pclk, ret, N1, N2, M1, P);
307
308 nv_mask(dev, pll.reg + 0x0c, 0x00000000, 0x00000100);
309 nv_wr32(dev, pll.reg + 0x04, (P << 16) | (N1 << 8) | M1);
310 nv_wr32(dev, pll.reg + 0x10, N2 << 16);
311 }
312
313 return 0;
314}
315
316static void
317nv50_crtc_destroy(struct drm_crtc *crtc)
318{
319 struct drm_device *dev;
320 struct nouveau_crtc *nv_crtc;
321
322 if (!crtc)
323 return;
324
325 dev = crtc->dev;
326 nv_crtc = nouveau_crtc(crtc);
327
328 NV_DEBUG_KMS(dev, "\n");
329
330 drm_crtc_cleanup(&nv_crtc->base);
331
332 nv50_cursor_fini(nv_crtc);
333
334 nouveau_bo_unmap(nv_crtc->lut.nvbo);
335 nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
336 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
337 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
338 kfree(nv_crtc->mode);
339 kfree(nv_crtc);
340}
341
342int
343nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
344 uint32_t buffer_handle, uint32_t width, uint32_t height)
345{
346 struct drm_device *dev = crtc->dev;
347 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
348 struct nouveau_bo *cursor = NULL;
349 struct drm_gem_object *gem;
350 int ret = 0, i;
351
352 if (!buffer_handle) {
353 nv_crtc->cursor.hide(nv_crtc, true);
354 return 0;
355 }
356
357 if (width != 64 || height != 64)
358 return -EINVAL;
359
360 gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
361 if (!gem)
362 return -ENOENT;
363 cursor = nouveau_gem_object(gem);
364
365 ret = nouveau_bo_map(cursor);
366 if (ret)
367 goto out;
368
369 /* The simple will do for now. */
370 for (i = 0; i < 64 * 64; i++)
371 nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, nouveau_bo_rd32(cursor, i));
372
373 nouveau_bo_unmap(cursor);
374
375 nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
376 nv_crtc->cursor.show(nv_crtc, true);
377
378out:
379 drm_gem_object_unreference_unlocked(gem);
380 return ret;
381}
382
383int
384nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
385{
386 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
387
388 nv_crtc->cursor.set_pos(nv_crtc, x, y);
389 return 0;
390}
391
392static void
393nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
394 uint32_t start, uint32_t size)
395{
396 int end = (start + size > 256) ? 256 : start + size, i;
397 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
398
399 for (i = start; i < end; i++) {
400 nv_crtc->lut.r[i] = r[i];
401 nv_crtc->lut.g[i] = g[i];
402 nv_crtc->lut.b[i] = b[i];
403 }
404
405 /* We need to know the depth before we upload, but it's possible to
406 * get called before a framebuffer is bound. If this is the case,
407 * mark the lut values as dirty by setting depth==0, and it'll be
408 * uploaded on the first mode_set_base()
409 */
410 if (!nv_crtc->base.fb) {
411 nv_crtc->lut.depth = 0;
412 return;
413 }
414
415 nv50_crtc_lut_load(crtc);
416}
417
418static void
419nv50_crtc_save(struct drm_crtc *crtc)
420{
421 NV_ERROR(crtc->dev, "!!\n");
422}
423
424static void
425nv50_crtc_restore(struct drm_crtc *crtc)
426{
427 NV_ERROR(crtc->dev, "!!\n");
428}
429
430static const struct drm_crtc_funcs nv50_crtc_funcs = {
431 .save = nv50_crtc_save,
432 .restore = nv50_crtc_restore,
433 .cursor_set = nv50_crtc_cursor_set,
434 .cursor_move = nv50_crtc_cursor_move,
435 .gamma_set = nv50_crtc_gamma_set,
436 .set_config = drm_crtc_helper_set_config,
437 .page_flip = nouveau_crtc_page_flip,
438 .destroy = nv50_crtc_destroy,
439};
440
441static void
442nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
443{
444}
445
446static int
447nv50_crtc_wait_complete(struct drm_crtc *crtc)
448{
449 struct drm_device *dev = crtc->dev;
450 struct drm_nouveau_private *dev_priv = dev->dev_private;
451 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
452 struct nv50_display *disp = nv50_display(dev);
453 struct nouveau_channel *evo = disp->master;
454 u64 start;
455 int ret;
456
457 ret = RING_SPACE(evo, 6);
458 if (ret)
459 return ret;
460 BEGIN_RING(evo, 0, 0x0084, 1);
461 OUT_RING (evo, 0x80000000);
462 BEGIN_RING(evo, 0, 0x0080, 1);
463 OUT_RING (evo, 0);
464 BEGIN_RING(evo, 0, 0x0084, 1);
465 OUT_RING (evo, 0x00000000);
466
467 nv_wo32(disp->ntfy, 0x000, 0x00000000);
468 FIRE_RING (evo);
469
470 start = ptimer->read(dev);
471 do {
472 if (nv_ro32(disp->ntfy, 0x000))
473 return 0;
474 } while (ptimer->read(dev) - start < 2000000000ULL);
475
476 return -EBUSY;
477}
478
479static void
480nv50_crtc_prepare(struct drm_crtc *crtc)
481{
482 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
483 struct drm_device *dev = crtc->dev;
484
485 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
486
487 nv50_display_flip_stop(crtc);
488 drm_vblank_pre_modeset(dev, nv_crtc->index);
489 nv50_crtc_blank(nv_crtc, true);
490}
491
492static void
493nv50_crtc_commit(struct drm_crtc *crtc)
494{
495 struct drm_device *dev = crtc->dev;
496 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
497
498 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
499
500 nv50_crtc_blank(nv_crtc, false);
501 drm_vblank_post_modeset(dev, nv_crtc->index);
502 nv50_crtc_wait_complete(crtc);
503 nv50_display_flip_next(crtc, crtc->fb, NULL);
504}
505
506static bool
507nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
508 struct drm_display_mode *adjusted_mode)
509{
510 return true;
511}
512
513static int
514nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
515 struct drm_framebuffer *passed_fb,
516 int x, int y, bool atomic)
517{
518 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
519 struct drm_device *dev = nv_crtc->base.dev;
520 struct drm_nouveau_private *dev_priv = dev->dev_private;
521 struct nouveau_channel *evo = nv50_display(dev)->master;
522 struct drm_framebuffer *drm_fb;
523 struct nouveau_framebuffer *fb;
524 int ret;
525
526 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
527
528 /* no fb bound */
529 if (!atomic && !crtc->fb) {
530 NV_DEBUG_KMS(dev, "No FB bound\n");
531 return 0;
532 }
533
534 /* If atomic, we want to switch to the fb we were passed, so
535 * now we update pointers to do that. (We don't pin; just
536 * assume we're already pinned and update the base address.)
537 */
538 if (atomic) {
539 drm_fb = passed_fb;
540 fb = nouveau_framebuffer(passed_fb);
541 } else {
542 drm_fb = crtc->fb;
543 fb = nouveau_framebuffer(crtc->fb);
544 /* If not atomic, we can go ahead and pin, and unpin the
545 * old fb we were passed.
546 */
547 ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
548 if (ret)
549 return ret;
550
551 if (passed_fb) {
552 struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
553 nouveau_bo_unpin(ofb->nvbo);
554 }
555 }
556
557 nv_crtc->fb.offset = fb->nvbo->bo.offset;
558 nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
559 nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
560 if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
561 ret = RING_SPACE(evo, 2);
562 if (ret)
563 return ret;
564
565 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
566 OUT_RING (evo, fb->r_dma);
567 }
568
569 ret = RING_SPACE(evo, 12);
570 if (ret)
571 return ret;
572
573 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5);
574 OUT_RING (evo, nv_crtc->fb.offset >> 8);
575 OUT_RING (evo, 0);
576 OUT_RING (evo, (drm_fb->height << 16) | drm_fb->width);
577 OUT_RING (evo, fb->r_pitch);
578 OUT_RING (evo, fb->r_format);
579
580 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1);
581 OUT_RING (evo, fb->base.depth == 8 ?
582 NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
583
584 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
585 OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
586 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
587 OUT_RING (evo, (y << 16) | x);
588
589 if (nv_crtc->lut.depth != fb->base.depth) {
590 nv_crtc->lut.depth = fb->base.depth;
591 nv50_crtc_lut_load(crtc);
592 }
593
594 return 0;
595}
596
597static int
598nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
599 struct drm_display_mode *adjusted_mode, int x, int y,
600 struct drm_framebuffer *old_fb)
601{
602 struct drm_device *dev = crtc->dev;
603 struct nouveau_channel *evo = nv50_display(dev)->master;
604 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
605 struct nouveau_connector *nv_connector = NULL;
606 uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end;
607 uint32_t hunk1, vunk1, vunk2a, vunk2b;
608 int ret;
609
610 /* Find the connector attached to this CRTC */
611 nv_connector = nouveau_crtc_connector_get(nv_crtc);
612
613 *nv_crtc->mode = *adjusted_mode;
614
615 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
616
617 hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
618 vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
619 hsync_start_to_end = adjusted_mode->htotal - adjusted_mode->hsync_start;
620 vsync_start_to_end = adjusted_mode->vtotal - adjusted_mode->vsync_start;
621 /* I can't give this a proper name, anyone else can? */
622 hunk1 = adjusted_mode->htotal -
623 adjusted_mode->hsync_start + adjusted_mode->hdisplay;
624 vunk1 = adjusted_mode->vtotal -
625 adjusted_mode->vsync_start + adjusted_mode->vdisplay;
626 /* Another strange value, this time only for interlaced adjusted_modes. */
627 vunk2a = 2 * adjusted_mode->vtotal -
628 adjusted_mode->vsync_start + adjusted_mode->vdisplay;
629 vunk2b = adjusted_mode->vtotal -
630 adjusted_mode->vsync_start + adjusted_mode->vtotal;
631
632 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
633 vsync_dur /= 2;
634 vsync_start_to_end /= 2;
635 vunk1 /= 2;
636 vunk2a /= 2;
637 vunk2b /= 2;
638 /* magic */
639 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) {
640 vsync_start_to_end -= 1;
641 vunk1 -= 1;
642 vunk2a -= 1;
643 vunk2b -= 1;
644 }
645 }
646
647 ret = RING_SPACE(evo, 17);
648 if (ret)
649 return ret;
650
651 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLOCK), 2);
652 OUT_RING(evo, adjusted_mode->clock | 0x800000);
653 OUT_RING(evo, (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0);
654
655 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DISPLAY_START), 5);
656 OUT_RING(evo, 0);
657 OUT_RING(evo, (adjusted_mode->vtotal << 16) | adjusted_mode->htotal);
658 OUT_RING(evo, (vsync_dur - 1) << 16 | (hsync_dur - 1));
659 OUT_RING(evo, (vsync_start_to_end - 1) << 16 |
660 (hsync_start_to_end - 1));
661 OUT_RING(evo, (vunk1 - 1) << 16 | (hunk1 - 1));
662
663 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
664 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK0824), 1);
665 OUT_RING(evo, (vunk2b - 1) << 16 | (vunk2a - 1));
666 } else {
667 OUT_RING(evo, 0);
668 OUT_RING(evo, 0);
669 }
670
671 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK082C), 1);
672 OUT_RING(evo, 0);
673
674 /* This is the actual resolution of the mode. */
675 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, REAL_RES), 1);
676 OUT_RING(evo, (mode->vdisplay << 16) | mode->hdisplay);
677 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CENTER_OFFSET), 1);
678 OUT_RING(evo, NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(0, 0));
679
680 nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false);
681 nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false);
682
683 return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
684}
685
686static int
687nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
688 struct drm_framebuffer *old_fb)
689{
690 int ret;
691
692 nv50_display_flip_stop(crtc);
693 ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
694 if (ret)
695 return ret;
696
697 ret = nv50_crtc_wait_complete(crtc);
698 if (ret)
699 return ret;
700
701 return nv50_display_flip_next(crtc, crtc->fb, NULL);
702}
703
704static int
705nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
706 struct drm_framebuffer *fb,
707 int x, int y, enum mode_set_atomic state)
708{
709 int ret;
710
711 nv50_display_flip_stop(crtc);
712 ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true);
713 if (ret)
714 return ret;
715
716 return nv50_crtc_wait_complete(crtc);
717}
718
719static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
720 .dpms = nv50_crtc_dpms,
721 .prepare = nv50_crtc_prepare,
722 .commit = nv50_crtc_commit,
723 .mode_fixup = nv50_crtc_mode_fixup,
724 .mode_set = nv50_crtc_mode_set,
725 .mode_set_base = nv50_crtc_mode_set_base,
726 .mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
727 .load_lut = nv50_crtc_lut_load,
728};
729
730int
731nv50_crtc_create(struct drm_device *dev, int index)
732{
733 struct nouveau_crtc *nv_crtc = NULL;
734 int ret, i;
735
736 NV_DEBUG_KMS(dev, "\n");
737
738 nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
739 if (!nv_crtc)
740 return -ENOMEM;
741
742 nv_crtc->mode = kzalloc(sizeof(*nv_crtc->mode), GFP_KERNEL);
743 if (!nv_crtc->mode) {
744 kfree(nv_crtc);
745 return -ENOMEM;
746 }
747
748 /* Default CLUT parameters, will be activated on the hw upon
749 * first mode set.
750 */
751 for (i = 0; i < 256; i++) {
752 nv_crtc->lut.r[i] = i << 8;
753 nv_crtc->lut.g[i] = i << 8;
754 nv_crtc->lut.b[i] = i << 8;
755 }
756 nv_crtc->lut.depth = 0;
757
758 ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM,
759 0, 0x0000, &nv_crtc->lut.nvbo);
760 if (!ret) {
761 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
762 if (!ret)
763 ret = nouveau_bo_map(nv_crtc->lut.nvbo);
764 if (ret)
765 nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
766 }
767
768 if (ret) {
769 kfree(nv_crtc->mode);
770 kfree(nv_crtc);
771 return ret;
772 }
773
774 nv_crtc->index = index;
775
776 /* set function pointers */
777 nv_crtc->set_dither = nv50_crtc_set_dither;
778 nv_crtc->set_scale = nv50_crtc_set_scale;
779
780 drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs);
781 drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
782 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
783
784 ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
785 0, 0x0000, &nv_crtc->cursor.nvbo);
786 if (!ret) {
787 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
788 if (!ret)
789 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
790 if (ret)
791 nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
792 }
793
794 nv50_cursor_init(nv_crtc);
795 return 0;
796}
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c
new file mode 100644
index 00000000000..9752c35bb84
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm_mode.h"
29
30#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
31#include "nouveau_reg.h"
32#include "nouveau_drv.h"
33#include "nouveau_crtc.h"
34#include "nv50_display.h"
35
36static void
37nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
38{
39 struct drm_device *dev = nv_crtc->base.dev;
40 struct drm_nouveau_private *dev_priv = dev->dev_private;
41 struct nouveau_channel *evo = nv50_display(dev)->master;
42 int ret;
43
44 NV_DEBUG_KMS(dev, "\n");
45
46 if (update && nv_crtc->cursor.visible)
47 return;
48
49 ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2);
50 if (ret) {
51 NV_ERROR(dev, "no space while unhiding cursor\n");
52 return;
53 }
54
55 if (dev_priv->chipset != 0x50) {
56 BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
57 OUT_RING(evo, NvEvoVRAM);
58 }
59 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2);
60 OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_SHOW);
61 OUT_RING(evo, nv_crtc->cursor.offset >> 8);
62
63 if (update) {
64 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
65 OUT_RING(evo, 0);
66 FIRE_RING(evo);
67 nv_crtc->cursor.visible = true;
68 }
69}
70
71static void
72nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
73{
74 struct drm_device *dev = nv_crtc->base.dev;
75 struct drm_nouveau_private *dev_priv = dev->dev_private;
76 struct nouveau_channel *evo = nv50_display(dev)->master;
77 int ret;
78
79 NV_DEBUG_KMS(dev, "\n");
80
81 if (update && !nv_crtc->cursor.visible)
82 return;
83
84 ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2);
85 if (ret) {
86 NV_ERROR(dev, "no space while hiding cursor\n");
87 return;
88 }
89 BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2);
90 OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE);
91 OUT_RING(evo, 0);
92 if (dev_priv->chipset != 0x50) {
93 BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
94 OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE);
95 }
96
97 if (update) {
98 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
99 OUT_RING(evo, 0);
100 FIRE_RING(evo);
101 nv_crtc->cursor.visible = false;
102 }
103}
104
105static void
106nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
107{
108 struct drm_device *dev = nv_crtc->base.dev;
109
110 nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
111 nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
112 ((y & 0xFFFF) << 16) | (x & 0xFFFF));
113 /* Needed to make the cursor move. */
114 nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0);
115}
116
117static void
118nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
119{
120 NV_DEBUG_KMS(nv_crtc->base.dev, "\n");
121 if (offset == nv_crtc->cursor.offset)
122 return;
123
124 nv_crtc->cursor.offset = offset;
125 if (nv_crtc->cursor.visible) {
126 nv_crtc->cursor.visible = false;
127 nv_crtc->cursor.show(nv_crtc, true);
128 }
129}
130
131int
132nv50_cursor_init(struct nouveau_crtc *nv_crtc)
133{
134 nv_crtc->cursor.set_offset = nv50_cursor_set_offset;
135 nv_crtc->cursor.set_pos = nv50_cursor_set_pos;
136 nv_crtc->cursor.hide = nv50_cursor_hide;
137 nv_crtc->cursor.show = nv50_cursor_show;
138 return 0;
139}
140
141void
142nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
143{
144 struct drm_device *dev = nv_crtc->base.dev;
145 int idx = nv_crtc->index;
146
147 NV_DEBUG_KMS(dev, "\n");
148
149 nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
150 if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
151 NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
152 NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
153 NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
154 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx)));
155 }
156}
157
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
new file mode 100644
index 00000000000..808f3ec8f82
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -0,0 +1,319 @@
1/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm_crtc_helper.h"
29
30#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
31#include "nouveau_reg.h"
32#include "nouveau_drv.h"
33#include "nouveau_dma.h"
34#include "nouveau_encoder.h"
35#include "nouveau_connector.h"
36#include "nouveau_crtc.h"
37#include "nv50_display.h"
38
39static void
40nv50_dac_disconnect(struct drm_encoder *encoder)
41{
42 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
43 struct drm_device *dev = encoder->dev;
44 struct nouveau_channel *evo = nv50_display(dev)->master;
45 int ret;
46
47 if (!nv_encoder->crtc)
48 return;
49 nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);
50
51 NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or);
52
53 ret = RING_SPACE(evo, 4);
54 if (ret) {
55 NV_ERROR(dev, "no space while disconnecting DAC\n");
56 return;
57 }
58 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
59 OUT_RING (evo, 0);
60 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
61 OUT_RING (evo, 0);
62
63 nv_encoder->crtc = NULL;
64}
65
66static enum drm_connector_status
67nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
68{
69 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
70 struct drm_device *dev = encoder->dev;
71 struct drm_nouveau_private *dev_priv = dev->dev_private;
72 enum drm_connector_status status = connector_status_disconnected;
73 uint32_t dpms_state, load_pattern, load_state;
74 int or = nv_encoder->or;
75
76 nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001);
77 dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or));
78
79 nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
80 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
81 if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
82 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
83 NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
84 NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
85 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
86 return status;
87 }
88
89 /* Use bios provided value if possible. */
90 if (dev_priv->vbios.dactestval) {
91 load_pattern = dev_priv->vbios.dactestval;
92 NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
93 load_pattern);
94 } else {
95 load_pattern = 340;
96 NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n",
97 load_pattern);
98 }
99
100 nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or),
101 NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern);
102 mdelay(45); /* give it some time to process */
103 load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or));
104
105 nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0);
106 nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state |
107 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
108
109 if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) ==
110 NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT)
111 status = connector_status_connected;
112
113 if (status == connector_status_connected)
114 NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or);
115 else
116 NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or);
117
118 return status;
119}
120
121static void
122nv50_dac_dpms(struct drm_encoder *encoder, int mode)
123{
124 struct drm_device *dev = encoder->dev;
125 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
126 uint32_t val;
127 int or = nv_encoder->or;
128
129 NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
130
131 /* wait for it to be done */
132 if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
133 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
134 NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
135 NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
136 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
137 return;
138 }
139
140 val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F;
141
142 if (mode != DRM_MODE_DPMS_ON)
143 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED;
144
145 switch (mode) {
146 case DRM_MODE_DPMS_STANDBY:
147 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
148 break;
149 case DRM_MODE_DPMS_SUSPEND:
150 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
151 break;
152 case DRM_MODE_DPMS_OFF:
153 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF;
154 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
155 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
156 break;
157 default:
158 break;
159 }
160
161 nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val |
162 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
163}
164
165static void
166nv50_dac_save(struct drm_encoder *encoder)
167{
168 NV_ERROR(encoder->dev, "!!\n");
169}
170
171static void
172nv50_dac_restore(struct drm_encoder *encoder)
173{
174 NV_ERROR(encoder->dev, "!!\n");
175}
176
177static bool
178nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
179 struct drm_display_mode *adjusted_mode)
180{
181 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
182 struct nouveau_connector *connector;
183
184 NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);
185
186 connector = nouveau_encoder_connector_get(nv_encoder);
187 if (!connector) {
188 NV_ERROR(encoder->dev, "Encoder has no connector\n");
189 return false;
190 }
191
192 if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
193 connector->native_mode) {
194 int id = adjusted_mode->base.id;
195 *adjusted_mode = *connector->native_mode;
196 adjusted_mode->base.id = id;
197 }
198
199 return true;
200}
201
202static void
203nv50_dac_prepare(struct drm_encoder *encoder)
204{
205}
206
207static void
208nv50_dac_commit(struct drm_encoder *encoder)
209{
210}
211
212static void
213nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
214 struct drm_display_mode *adjusted_mode)
215{
216 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
217 struct drm_device *dev = encoder->dev;
218 struct nouveau_channel *evo = nv50_display(dev)->master;
219 struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
220 uint32_t mode_ctl = 0, mode_ctl2 = 0;
221 int ret;
222
223 NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n",
224 nv_encoder->or, nv_encoder->dcb->type, crtc->index);
225
226 nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
227
228 if (crtc->index == 1)
229 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1;
230 else
231 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0;
232
233 /* Lacking a working tv-out, this is not a 100% sure. */
234 if (nv_encoder->dcb->type == OUTPUT_ANALOG)
235 mode_ctl |= 0x40;
236 else
237 if (nv_encoder->dcb->type == OUTPUT_TV)
238 mode_ctl |= 0x100;
239
240 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
241 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC;
242
243 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
244 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC;
245
246 ret = RING_SPACE(evo, 3);
247 if (ret) {
248 NV_ERROR(dev, "no space while connecting DAC\n");
249 return;
250 }
251 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2);
252 OUT_RING(evo, mode_ctl);
253 OUT_RING(evo, mode_ctl2);
254
255 nv_encoder->crtc = encoder->crtc;
256}
257
258static struct drm_crtc *
259nv50_dac_crtc_get(struct drm_encoder *encoder)
260{
261 return nouveau_encoder(encoder)->crtc;
262}
263
264static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = {
265 .dpms = nv50_dac_dpms,
266 .save = nv50_dac_save,
267 .restore = nv50_dac_restore,
268 .mode_fixup = nv50_dac_mode_fixup,
269 .prepare = nv50_dac_prepare,
270 .commit = nv50_dac_commit,
271 .mode_set = nv50_dac_mode_set,
272 .get_crtc = nv50_dac_crtc_get,
273 .detect = nv50_dac_detect,
274 .disable = nv50_dac_disconnect
275};
276
277static void
278nv50_dac_destroy(struct drm_encoder *encoder)
279{
280 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
281
282 if (!encoder)
283 return;
284
285 NV_DEBUG_KMS(encoder->dev, "\n");
286
287 drm_encoder_cleanup(encoder);
288 kfree(nv_encoder);
289}
290
291static const struct drm_encoder_funcs nv50_dac_encoder_funcs = {
292 .destroy = nv50_dac_destroy,
293};
294
295int
296nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
297{
298 struct nouveau_encoder *nv_encoder;
299 struct drm_encoder *encoder;
300
301 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
302 if (!nv_encoder)
303 return -ENOMEM;
304 encoder = to_drm_encoder(nv_encoder);
305
306 nv_encoder->dcb = entry;
307 nv_encoder->or = ffs(entry->or) - 1;
308
309 drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
310 DRM_MODE_ENCODER_DAC);
311 drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
312
313 encoder->possible_crtcs = entry->heads;
314 encoder->possible_clones = 0;
315
316 drm_mode_connector_attach_encoder(connector, encoder);
317 return 0;
318}
319
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c
new file mode 100644
index 00000000000..c99d9751880
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_evo.c
@@ -0,0 +1,425 @@
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_dma.h"
29#include "nouveau_ramht.h"
30#include "nv50_display.h"
31
32static void
33nv50_evo_channel_del(struct nouveau_channel **pevo)
34{
35 struct nouveau_channel *evo = *pevo;
36
37 if (!evo)
38 return;
39 *pevo = NULL;
40
41 nouveau_ramht_ref(NULL, &evo->ramht, evo);
42 nouveau_gpuobj_channel_takedown(evo);
43 nouveau_bo_unmap(evo->pushbuf_bo);
44 nouveau_bo_ref(NULL, &evo->pushbuf_bo);
45
46 if (evo->user)
47 iounmap(evo->user);
48
49 kfree(evo);
50}
51
52void
53nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size)
54{
55 struct drm_nouveau_private *dev_priv = obj->dev->dev_private;
56 u32 flags5;
57
58 if (dev_priv->chipset < 0xc0) {
59 /* not supported on 0x50, specified in format mthd */
60 if (dev_priv->chipset == 0x50)
61 memtype = 0;
62 flags5 = 0x00010000;
63 } else {
64 if (memtype & 0x80000000)
65 flags5 = 0x00000000; /* large pages */
66 else
67 flags5 = 0x00020000;
68 }
69
70 nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM,
71 NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0);
72 nv_wo32(obj, 0x14, flags5);
73 dev_priv->engine.instmem.flush(obj->dev);
74}
75
76int
77nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype,
78 u64 base, u64 size, struct nouveau_gpuobj **pobj)
79{
80 struct nv50_display *disp = nv50_display(evo->dev);
81 struct nouveau_gpuobj *obj = NULL;
82 int ret;
83
84 ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj);
85 if (ret)
86 return ret;
87 obj->engine = NVOBJ_ENGINE_DISPLAY;
88
89 nv50_evo_dmaobj_init(obj, memtype, base, size);
90
91 ret = nouveau_ramht_insert(evo, handle, obj);
92 if (ret)
93 goto out;
94
95 if (pobj)
96 nouveau_gpuobj_ref(obj, pobj);
97out:
98 nouveau_gpuobj_ref(NULL, &obj);
99 return ret;
100}
101
102static int
103nv50_evo_channel_new(struct drm_device *dev, int chid,
104 struct nouveau_channel **pevo)
105{
106 struct nv50_display *disp = nv50_display(dev);
107 struct nouveau_channel *evo;
108 int ret;
109
110 evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL);
111 if (!evo)
112 return -ENOMEM;
113 *pevo = evo;
114
115 evo->id = chid;
116 evo->dev = dev;
117 evo->user_get = 4;
118 evo->user_put = 0;
119
120 ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
121 &evo->pushbuf_bo);
122 if (ret == 0)
123 ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
124 if (ret) {
125 NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret);
126 nv50_evo_channel_del(pevo);
127 return ret;
128 }
129
130 ret = nouveau_bo_map(evo->pushbuf_bo);
131 if (ret) {
132 NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret);
133 nv50_evo_channel_del(pevo);
134 return ret;
135 }
136
137 evo->user = ioremap(pci_resource_start(dev->pdev, 0) +
138 NV50_PDISPLAY_USER(evo->id), PAGE_SIZE);
139 if (!evo->user) {
140 NV_ERROR(dev, "Error mapping EVO control regs.\n");
141 nv50_evo_channel_del(pevo);
142 return -ENOMEM;
143 }
144
145 /* bind primary evo channel's ramht to the channel */
146 if (disp->master && evo != disp->master)
147 nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL);
148
149 return 0;
150}
151
152static int
153nv50_evo_channel_init(struct nouveau_channel *evo)
154{
155 struct drm_device *dev = evo->dev;
156 int id = evo->id, ret, i;
157 u64 pushbuf = evo->pushbuf_bo->bo.offset;
158 u32 tmp;
159
160 tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
161 if ((tmp & 0x009f0000) == 0x00020000)
162 nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000);
163
164 tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
165 if ((tmp & 0x003f0000) == 0x00030000)
166 nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000);
167
168 /* initialise fifo */
169 nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 |
170 NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM |
171 NV50_PDISPLAY_EVO_DMA_CB_VALID);
172 nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000);
173 nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id);
174 nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA,
175 NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED);
176
177 nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000);
178 nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 |
179 NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED);
180 if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) {
181 NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id,
182 nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)));
183 return -EBUSY;
184 }
185
186 /* enable error reporting on the channel */
187 nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id);
188
189 evo->dma.max = (4096/4) - 2;
190 evo->dma.max &= ~7;
191 evo->dma.put = 0;
192 evo->dma.cur = evo->dma.put;
193 evo->dma.free = evo->dma.max - evo->dma.cur;
194
195 ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS);
196 if (ret)
197 return ret;
198
199 for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
200 OUT_RING(evo, 0);
201
202 return 0;
203}
204
205static void
206nv50_evo_channel_fini(struct nouveau_channel *evo)
207{
208 struct drm_device *dev = evo->dev;
209 int id = evo->id;
210
211 nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000);
212 nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000);
213 nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id));
214 nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000);
215 if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) {
216 NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id,
217 nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)));
218 }
219}
220
221static void
222nv50_evo_destroy(struct drm_device *dev)
223{
224 struct nv50_display *disp = nv50_display(dev);
225 int i;
226
227 for (i = 0; i < 2; i++) {
228 if (disp->crtc[i].sem.bo) {
229 nouveau_bo_unmap(disp->crtc[i].sem.bo);
230 nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo);
231 }
232 nv50_evo_channel_del(&disp->crtc[i].sync);
233 }
234 nouveau_gpuobj_ref(NULL, &disp->ntfy);
235 nv50_evo_channel_del(&disp->master);
236}
237
238static int
239nv50_evo_create(struct drm_device *dev)
240{
241 struct drm_nouveau_private *dev_priv = dev->dev_private;
242 struct nv50_display *disp = nv50_display(dev);
243 struct nouveau_gpuobj *ramht = NULL;
244 struct nouveau_channel *evo;
245 int ret, i, j;
246
247 /* create primary evo channel, the one we use for modesetting
248 * purporses
249 */
250 ret = nv50_evo_channel_new(dev, 0, &disp->master);
251 if (ret)
252 return ret;
253 evo = disp->master;
254
255 /* setup object management on it, any other evo channel will
256 * use this also as there's no per-channel support on the
257 * hardware
258 */
259 ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536,
260 NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin);
261 if (ret) {
262 NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret);
263 goto err;
264 }
265
266 ret = drm_mm_init(&evo->ramin_heap, 0, 32768);
267 if (ret) {
268 NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret);
269 goto err;
270 }
271
272 ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht);
273 if (ret) {
274 NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret);
275 goto err;
276 }
277
278 ret = nouveau_ramht_new(dev, ramht, &evo->ramht);
279 nouveau_gpuobj_ref(NULL, &ramht);
280 if (ret)
281 goto err;
282
283 /* not sure exactly what this is..
284 *
285 * the first dword of the structure is used by nvidia to wait on
286 * full completion of an EVO "update" command.
287 *
288 * method 0x8c on the master evo channel will fill a lot more of
289 * this structure with some undefined info
290 */
291 ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0,
292 NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy);
293 if (ret)
294 goto err;
295
296 ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000,
297 disp->ntfy->vinst, disp->ntfy->size, NULL);
298 if (ret)
299 goto err;
300
301 /* create some default objects for the scanout memtypes we support */
302 ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000,
303 0, dev_priv->vram_size, NULL);
304 if (ret)
305 goto err;
306
307 ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000,
308 0, dev_priv->vram_size, NULL);
309 if (ret)
310 goto err;
311
312 ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 |
313 (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00),
314 0, dev_priv->vram_size, NULL);
315 if (ret)
316 goto err;
317
318 ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 |
319 (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00),
320 0, dev_priv->vram_size, NULL);
321 if (ret)
322 goto err;
323
324 /* create "display sync" channels and other structures we need
325 * to implement page flipping
326 */
327 for (i = 0; i < 2; i++) {
328 struct nv50_display_crtc *dispc = &disp->crtc[i];
329 u64 offset;
330
331 ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync);
332 if (ret)
333 goto err;
334
335 ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
336 0, 0x0000, &dispc->sem.bo);
337 if (!ret) {
338 ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
339 if (!ret)
340 ret = nouveau_bo_map(dispc->sem.bo);
341 if (ret)
342 nouveau_bo_ref(NULL, &dispc->sem.bo);
343 offset = dispc->sem.bo->bo.offset;
344 }
345
346 if (ret)
347 goto err;
348
349 ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000,
350 offset, 4096, NULL);
351 if (ret)
352 goto err;
353
354 ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000,
355 0, dev_priv->vram_size, NULL);
356 if (ret)
357 goto err;
358
359 ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 |
360 (dev_priv->chipset < 0xc0 ?
361 0x7a00 : 0xfe00),
362 0, dev_priv->vram_size, NULL);
363 if (ret)
364 goto err;
365
366 ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 |
367 (dev_priv->chipset < 0xc0 ?
368 0x7000 : 0xfe00),
369 0, dev_priv->vram_size, NULL);
370 if (ret)
371 goto err;
372
373 for (j = 0; j < 4096; j += 4)
374 nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000);
375 dispc->sem.offset = 0;
376 }
377
378 return 0;
379
380err:
381 nv50_evo_destroy(dev);
382 return ret;
383}
384
385int
386nv50_evo_init(struct drm_device *dev)
387{
388 struct nv50_display *disp = nv50_display(dev);
389 int ret, i;
390
391 if (!disp->master) {
392 ret = nv50_evo_create(dev);
393 if (ret)
394 return ret;
395 }
396
397 ret = nv50_evo_channel_init(disp->master);
398 if (ret)
399 return ret;
400
401 for (i = 0; i < 2; i++) {
402 ret = nv50_evo_channel_init(disp->crtc[i].sync);
403 if (ret)
404 return ret;
405 }
406
407 return 0;
408}
409
410void
411nv50_evo_fini(struct drm_device *dev)
412{
413 struct nv50_display *disp = nv50_display(dev);
414 int i;
415
416 for (i = 0; i < 2; i++) {
417 if (disp->crtc[i].sync)
418 nv50_evo_channel_fini(disp->crtc[i].sync);
419 }
420
421 if (disp->master)
422 nv50_evo_channel_fini(disp->master);
423
424 nv50_evo_destroy(dev);
425}
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h
new file mode 100644
index 00000000000..3860ca62cb1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_evo.h
@@ -0,0 +1,119 @@
1/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#ifndef __NV50_EVO_H__
28#define __NV50_EVO_H__
29
30#define NV50_EVO_UPDATE 0x00000080
31#define NV50_EVO_UNK84 0x00000084
32#define NV50_EVO_UNK84_NOTIFY 0x40000000
33#define NV50_EVO_UNK84_NOTIFY_DISABLED 0x00000000
34#define NV50_EVO_UNK84_NOTIFY_ENABLED 0x40000000
35#define NV50_EVO_DMA_NOTIFY 0x00000088
36#define NV50_EVO_DMA_NOTIFY_HANDLE 0xffffffff
37#define NV50_EVO_DMA_NOTIFY_HANDLE_NONE 0x00000000
38#define NV50_EVO_UNK8C 0x0000008C
39
40#define NV50_EVO_DAC(n, r) ((n) * 0x80 + NV50_EVO_DAC_##r)
41#define NV50_EVO_DAC_MODE_CTRL 0x00000400
42#define NV50_EVO_DAC_MODE_CTRL_CRTC0 0x00000001
43#define NV50_EVO_DAC_MODE_CTRL_CRTC1 0x00000002
44#define NV50_EVO_DAC_MODE_CTRL2 0x00000404
45#define NV50_EVO_DAC_MODE_CTRL2_NHSYNC 0x00000001
46#define NV50_EVO_DAC_MODE_CTRL2_NVSYNC 0x00000002
47
48#define NV50_EVO_SOR(n, r) ((n) * 0x40 + NV50_EVO_SOR_##r)
49#define NV50_EVO_SOR_MODE_CTRL 0x00000600
50#define NV50_EVO_SOR_MODE_CTRL_CRTC0 0x00000001
51#define NV50_EVO_SOR_MODE_CTRL_CRTC1 0x00000002
52#define NV50_EVO_SOR_MODE_CTRL_TMDS 0x00000100
53#define NV50_EVO_SOR_MODE_CTRL_TMDS_DUAL_LINK 0x00000400
54#define NV50_EVO_SOR_MODE_CTRL_NHSYNC 0x00001000
55#define NV50_EVO_SOR_MODE_CTRL_NVSYNC 0x00002000
56
57#define NV50_EVO_CRTC(n, r) ((n) * 0x400 + NV50_EVO_CRTC_##r)
58#define NV84_EVO_CRTC(n, r) ((n) * 0x400 + NV84_EVO_CRTC_##r)
59#define NV50_EVO_CRTC_UNK0800 0x00000800
60#define NV50_EVO_CRTC_CLOCK 0x00000804
61#define NV50_EVO_CRTC_INTERLACE 0x00000808
62#define NV50_EVO_CRTC_DISPLAY_START 0x00000810
63#define NV50_EVO_CRTC_DISPLAY_TOTAL 0x00000814
64#define NV50_EVO_CRTC_SYNC_DURATION 0x00000818
65#define NV50_EVO_CRTC_SYNC_START_TO_BLANK_END 0x0000081c
66#define NV50_EVO_CRTC_UNK0820 0x00000820
67#define NV50_EVO_CRTC_UNK0824 0x00000824
68#define NV50_EVO_CRTC_UNK082C 0x0000082c
69#define NV50_EVO_CRTC_CLUT_MODE 0x00000840
70/* You can't have a palette in 8 bit mode (=OFF) */
71#define NV50_EVO_CRTC_CLUT_MODE_BLANK 0x00000000
72#define NV50_EVO_CRTC_CLUT_MODE_OFF 0x80000000
73#define NV50_EVO_CRTC_CLUT_MODE_ON 0xC0000000
74#define NV50_EVO_CRTC_CLUT_OFFSET 0x00000844
75#define NV84_EVO_CRTC_CLUT_DMA 0x0000085C
76#define NV84_EVO_CRTC_CLUT_DMA_HANDLE 0xffffffff
77#define NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE 0x00000000
78#define NV50_EVO_CRTC_FB_OFFSET 0x00000860
79#define NV50_EVO_CRTC_FB_SIZE 0x00000868
80#define NV50_EVO_CRTC_FB_CONFIG 0x0000086c
81#define NV50_EVO_CRTC_FB_CONFIG_MODE 0x00100000
82#define NV50_EVO_CRTC_FB_CONFIG_MODE_TILE 0x00000000
83#define NV50_EVO_CRTC_FB_CONFIG_MODE_PITCH 0x00100000
84#define NV50_EVO_CRTC_FB_DEPTH 0x00000870
85#define NV50_EVO_CRTC_FB_DEPTH_8 0x00001e00
86#define NV50_EVO_CRTC_FB_DEPTH_15 0x0000e900
87#define NV50_EVO_CRTC_FB_DEPTH_16 0x0000e800
88#define NV50_EVO_CRTC_FB_DEPTH_24 0x0000cf00
89#define NV50_EVO_CRTC_FB_DEPTH_30 0x0000d100
90#define NV50_EVO_CRTC_FB_DMA 0x00000874
91#define NV50_EVO_CRTC_FB_DMA_HANDLE 0xffffffff
92#define NV50_EVO_CRTC_FB_DMA_HANDLE_NONE 0x00000000
93#define NV50_EVO_CRTC_CURSOR_CTRL 0x00000880
94#define NV50_EVO_CRTC_CURSOR_CTRL_HIDE 0x05000000
95#define NV50_EVO_CRTC_CURSOR_CTRL_SHOW 0x85000000
96#define NV50_EVO_CRTC_CURSOR_OFFSET 0x00000884
97#define NV84_EVO_CRTC_CURSOR_DMA 0x0000089c
98#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE 0xffffffff
99#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE 0x00000000
100#define NV50_EVO_CRTC_DITHER_CTRL 0x000008a0
101#define NV50_EVO_CRTC_DITHER_CTRL_OFF 0x00000000
102#define NV50_EVO_CRTC_DITHER_CTRL_ON 0x00000011
103#define NV50_EVO_CRTC_SCALE_CTRL 0x000008a4
104#define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000
105#define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009
106#define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8
107#define NV50_EVO_CRTC_COLOR_CTRL_COLOR 0x00040000
108#define NV50_EVO_CRTC_FB_POS 0x000008c0
109#define NV50_EVO_CRTC_REAL_RES 0x000008c8
110#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4
111#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) \
112 ((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF))
113/* Both of these are needed, otherwise nothing happens. */
114#define NV50_EVO_CRTC_SCALE_RES1 0x000008d8
115#define NV50_EVO_CRTC_SCALE_RES2 0x000008dc
116#define NV50_EVO_CRTC_UNK900 0x00000900
117#define NV50_EVO_CRTC_UNK904 0x00000904
118
119#endif
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
new file mode 100644
index 00000000000..bdd2afe2920
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_fb.c
@@ -0,0 +1,294 @@
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
6struct nv50_fb_priv {
7 struct page *r100c08_page;
8 dma_addr_t r100c08;
9};
10
11static void
12nv50_fb_destroy(struct drm_device *dev)
13{
14 struct drm_nouveau_private *dev_priv = dev->dev_private;
15 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
16 struct nv50_fb_priv *priv = pfb->priv;
17
18 if (drm_mm_initialized(&pfb->tag_heap))
19 drm_mm_takedown(&pfb->tag_heap);
20
21 if (priv->r100c08_page) {
22 pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
23 PCI_DMA_BIDIRECTIONAL);
24 __free_page(priv->r100c08_page);
25 }
26
27 kfree(priv);
28 pfb->priv = NULL;
29}
30
31static int
32nv50_fb_create(struct drm_device *dev)
33{
34 struct drm_nouveau_private *dev_priv = dev->dev_private;
35 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
36 struct nv50_fb_priv *priv;
37 u32 tagmem;
38 int ret;
39
40 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
41 if (!priv)
42 return -ENOMEM;
43 pfb->priv = priv;
44
45 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
46 if (!priv->r100c08_page) {
47 nv50_fb_destroy(dev);
48 return -ENOMEM;
49 }
50
51 priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
52 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
53 if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
54 nv50_fb_destroy(dev);
55 return -EFAULT;
56 }
57
58 tagmem = nv_rd32(dev, 0x100320);
59 NV_DEBUG(dev, "%d tags available\n", tagmem);
60 ret = drm_mm_init(&pfb->tag_heap, 0, tagmem);
61 if (ret) {
62 nv50_fb_destroy(dev);
63 return ret;
64 }
65
66 return 0;
67}
68
69int
70nv50_fb_init(struct drm_device *dev)
71{
72 struct drm_nouveau_private *dev_priv = dev->dev_private;
73 struct nv50_fb_priv *priv;
74 int ret;
75
76 if (!dev_priv->engine.fb.priv) {
77 ret = nv50_fb_create(dev);
78 if (ret)
79 return ret;
80 }
81 priv = dev_priv->engine.fb.priv;
82
83 /* Not a clue what this is exactly. Without pointing it at a
84 * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
85 * cause IOMMU "read from address 0" errors (rh#561267)
86 */
87 nv_wr32(dev, 0x100c08, priv->r100c08 >> 8);
88
89 /* This is needed to get meaningful information from 100c90
90 * on traps. No idea what these values mean exactly. */
91 switch (dev_priv->chipset) {
92 case 0x50:
93 nv_wr32(dev, 0x100c90, 0x000707ff);
94 break;
95 case 0xa3:
96 case 0xa5:
97 case 0xa8:
98 nv_wr32(dev, 0x100c90, 0x000d0fff);
99 break;
100 case 0xaf:
101 nv_wr32(dev, 0x100c90, 0x089d1fff);
102 break;
103 default:
104 nv_wr32(dev, 0x100c90, 0x001d07ff);
105 break;
106 }
107
108 return 0;
109}
110
111void
112nv50_fb_takedown(struct drm_device *dev)
113{
114 nv50_fb_destroy(dev);
115}
116
117static struct nouveau_enum vm_dispatch_subclients[] = {
118 { 0x00000000, "GRCTX", NULL },
119 { 0x00000001, "NOTIFY", NULL },
120 { 0x00000002, "QUERY", NULL },
121 { 0x00000003, "COND", NULL },
122 { 0x00000004, "M2M_IN", NULL },
123 { 0x00000005, "M2M_OUT", NULL },
124 { 0x00000006, "M2M_NOTIFY", NULL },
125 {}
126};
127
128static struct nouveau_enum vm_ccache_subclients[] = {
129 { 0x00000000, "CB", NULL },
130 { 0x00000001, "TIC", NULL },
131 { 0x00000002, "TSC", NULL },
132 {}
133};
134
135static struct nouveau_enum vm_prop_subclients[] = {
136 { 0x00000000, "RT0", NULL },
137 { 0x00000001, "RT1", NULL },
138 { 0x00000002, "RT2", NULL },
139 { 0x00000003, "RT3", NULL },
140 { 0x00000004, "RT4", NULL },
141 { 0x00000005, "RT5", NULL },
142 { 0x00000006, "RT6", NULL },
143 { 0x00000007, "RT7", NULL },
144 { 0x00000008, "ZETA", NULL },
145 { 0x00000009, "LOCAL", NULL },
146 { 0x0000000a, "GLOBAL", NULL },
147 { 0x0000000b, "STACK", NULL },
148 { 0x0000000c, "DST2D", NULL },
149 {}
150};
151
152static struct nouveau_enum vm_pfifo_subclients[] = {
153 { 0x00000000, "PUSHBUF", NULL },
154 { 0x00000001, "SEMAPHORE", NULL },
155 {}
156};
157
158static struct nouveau_enum vm_bar_subclients[] = {
159 { 0x00000000, "FB", NULL },
160 { 0x00000001, "IN", NULL },
161 {}
162};
163
164static struct nouveau_enum vm_client[] = {
165 { 0x00000000, "STRMOUT", NULL },
166 { 0x00000003, "DISPATCH", vm_dispatch_subclients },
167 { 0x00000004, "PFIFO_WRITE", NULL },
168 { 0x00000005, "CCACHE", vm_ccache_subclients },
169 { 0x00000006, "PPPP", NULL },
170 { 0x00000007, "CLIPID", NULL },
171 { 0x00000008, "PFIFO_READ", NULL },
172 { 0x00000009, "VFETCH", NULL },
173 { 0x0000000a, "TEXTURE", NULL },
174 { 0x0000000b, "PROP", vm_prop_subclients },
175 { 0x0000000c, "PVP", NULL },
176 { 0x0000000d, "PBSP", NULL },
177 { 0x0000000e, "PCRYPT", NULL },
178 { 0x0000000f, "PCOUNTER", NULL },
179 { 0x00000011, "PDAEMON", NULL },
180 {}
181};
182
183static struct nouveau_enum vm_engine[] = {
184 { 0x00000000, "PGRAPH", NULL },
185 { 0x00000001, "PVP", NULL },
186 { 0x00000004, "PEEPHOLE", NULL },
187 { 0x00000005, "PFIFO", vm_pfifo_subclients },
188 { 0x00000006, "BAR", vm_bar_subclients },
189 { 0x00000008, "PPPP", NULL },
190 { 0x00000009, "PBSP", NULL },
191 { 0x0000000a, "PCRYPT", NULL },
192 { 0x0000000b, "PCOUNTER", NULL },
193 { 0x0000000c, "SEMAPHORE_BG", NULL },
194 { 0x0000000d, "PCOPY", NULL },
195 { 0x0000000e, "PDAEMON", NULL },
196 {}
197};
198
199static struct nouveau_enum vm_fault[] = {
200 { 0x00000000, "PT_NOT_PRESENT", NULL },
201 { 0x00000001, "PT_TOO_SHORT", NULL },
202 { 0x00000002, "PAGE_NOT_PRESENT", NULL },
203 { 0x00000003, "PAGE_SYSTEM_ONLY", NULL },
204 { 0x00000004, "PAGE_READ_ONLY", NULL },
205 { 0x00000006, "NULL_DMAOBJ", NULL },
206 { 0x00000007, "WRONG_MEMTYPE", NULL },
207 { 0x0000000b, "VRAM_LIMIT", NULL },
208 { 0x0000000f, "DMAOBJ_LIMIT", NULL },
209 {}
210};
211
212void
213nv50_fb_vm_trap(struct drm_device *dev, int display)
214{
215 struct drm_nouveau_private *dev_priv = dev->dev_private;
216 const struct nouveau_enum *en, *cl;
217 unsigned long flags;
218 u32 trap[6], idx, chinst;
219 u8 st0, st1, st2, st3;
220 int i, ch;
221
222 idx = nv_rd32(dev, 0x100c90);
223 if (!(idx & 0x80000000))
224 return;
225 idx &= 0x00ffffff;
226
227 for (i = 0; i < 6; i++) {
228 nv_wr32(dev, 0x100c90, idx | i << 24);
229 trap[i] = nv_rd32(dev, 0x100c94);
230 }
231 nv_wr32(dev, 0x100c90, idx | 0x80000000);
232
233 if (!display)
234 return;
235
236 /* lookup channel id */
237 chinst = (trap[2] << 16) | trap[1];
238 spin_lock_irqsave(&dev_priv->channels.lock, flags);
239 for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
240 struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
241
242 if (!chan || !chan->ramin)
243 continue;
244
245 if (chinst == chan->ramin->vinst >> 12)
246 break;
247 }
248 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
249
250 /* decode status bits into something more useful */
251 if (dev_priv->chipset < 0xa3 ||
252 dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
253 st0 = (trap[0] & 0x0000000f) >> 0;
254 st1 = (trap[0] & 0x000000f0) >> 4;
255 st2 = (trap[0] & 0x00000f00) >> 8;
256 st3 = (trap[0] & 0x0000f000) >> 12;
257 } else {
258 st0 = (trap[0] & 0x000000ff) >> 0;
259 st1 = (trap[0] & 0x0000ff00) >> 8;
260 st2 = (trap[0] & 0x00ff0000) >> 16;
261 st3 = (trap[0] & 0xff000000) >> 24;
262 }
263
264 NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ",
265 (trap[5] & 0x00000100) ? "read" : "write",
266 trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst);
267
268 en = nouveau_enum_find(vm_engine, st0);
269 if (en)
270 printk("%s/", en->name);
271 else
272 printk("%02x/", st0);
273
274 cl = nouveau_enum_find(vm_client, st2);
275 if (cl)
276 printk("%s/", cl->name);
277 else
278 printk("%02x/", st2);
279
280 if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3);
281 else if (en && en->data) cl = nouveau_enum_find(en->data, st3);
282 else cl = NULL;
283 if (cl)
284 printk("%s", cl->name);
285 else
286 printk("%02x", st3);
287
288 printk(" reason: ");
289 en = nouveau_enum_find(vm_fault, st1);
290 if (en)
291 printk("%s\n", en->name);
292 else
293 printk("0x%08x\n", st1);
294}
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
new file mode 100644
index 00000000000..c34a074f7ea
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
@@ -0,0 +1,504 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30#include "nouveau_ramht.h"
31#include "nouveau_vm.h"
32
33static void
34nv50_fifo_playlist_update(struct drm_device *dev)
35{
36 struct drm_nouveau_private *dev_priv = dev->dev_private;
37 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
38 struct nouveau_gpuobj *cur;
39 int i, nr;
40
41 NV_DEBUG(dev, "\n");
42
43 cur = pfifo->playlist[pfifo->cur_playlist];
44 pfifo->cur_playlist = !pfifo->cur_playlist;
45
46 /* We never schedule channel 0 or 127 */
47 for (i = 1, nr = 0; i < 127; i++) {
48 if (dev_priv->channels.ptr[i] &&
49 dev_priv->channels.ptr[i]->ramfc) {
50 nv_wo32(cur, (nr * 4), i);
51 nr++;
52 }
53 }
54 dev_priv->engine.instmem.flush(dev);
55
56 nv_wr32(dev, 0x32f4, cur->vinst >> 12);
57 nv_wr32(dev, 0x32ec, nr);
58 nv_wr32(dev, 0x2500, 0x101);
59}
60
61static void
62nv50_fifo_channel_enable(struct drm_device *dev, int channel)
63{
64 struct drm_nouveau_private *dev_priv = dev->dev_private;
65 struct nouveau_channel *chan = dev_priv->channels.ptr[channel];
66 uint32_t inst;
67
68 NV_DEBUG(dev, "ch%d\n", channel);
69
70 if (dev_priv->chipset == 0x50)
71 inst = chan->ramfc->vinst >> 12;
72 else
73 inst = chan->ramfc->vinst >> 8;
74
75 nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst |
76 NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
77}
78
79static void
80nv50_fifo_channel_disable(struct drm_device *dev, int channel)
81{
82 struct drm_nouveau_private *dev_priv = dev->dev_private;
83 uint32_t inst;
84
85 NV_DEBUG(dev, "ch%d\n", channel);
86
87 if (dev_priv->chipset == 0x50)
88 inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80;
89 else
90 inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84;
91 nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst);
92}
93
94static void
95nv50_fifo_init_reset(struct drm_device *dev)
96{
97 uint32_t pmc_e = NV_PMC_ENABLE_PFIFO;
98
99 NV_DEBUG(dev, "\n");
100
101 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
102 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e);
103}
104
105static void
106nv50_fifo_init_intr(struct drm_device *dev)
107{
108 NV_DEBUG(dev, "\n");
109
110 nouveau_irq_register(dev, 8, nv04_fifo_isr);
111 nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF);
112 nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
113}
114
115static void
116nv50_fifo_init_context_table(struct drm_device *dev)
117{
118 struct drm_nouveau_private *dev_priv = dev->dev_private;
119 int i;
120
121 NV_DEBUG(dev, "\n");
122
123 for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) {
124 if (dev_priv->channels.ptr[i])
125 nv50_fifo_channel_enable(dev, i);
126 else
127 nv50_fifo_channel_disable(dev, i);
128 }
129
130 nv50_fifo_playlist_update(dev);
131}
132
133static void
134nv50_fifo_init_regs__nv(struct drm_device *dev)
135{
136 NV_DEBUG(dev, "\n");
137
138 nv_wr32(dev, 0x250c, 0x6f3cfc34);
139}
140
141static void
142nv50_fifo_init_regs(struct drm_device *dev)
143{
144 NV_DEBUG(dev, "\n");
145
146 nv_wr32(dev, 0x2500, 0);
147 nv_wr32(dev, 0x3250, 0);
148 nv_wr32(dev, 0x3220, 0);
149 nv_wr32(dev, 0x3204, 0);
150 nv_wr32(dev, 0x3210, 0);
151 nv_wr32(dev, 0x3270, 0);
152 nv_wr32(dev, 0x2044, 0x01003fff);
153
154 /* Enable dummy channels setup by nv50_instmem.c */
155 nv50_fifo_channel_enable(dev, 0);
156 nv50_fifo_channel_enable(dev, 127);
157}
158
159int
160nv50_fifo_init(struct drm_device *dev)
161{
162 struct drm_nouveau_private *dev_priv = dev->dev_private;
163 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
164 int ret;
165
166 NV_DEBUG(dev, "\n");
167
168 if (pfifo->playlist[0]) {
169 pfifo->cur_playlist = !pfifo->cur_playlist;
170 goto just_reset;
171 }
172
173 ret = nouveau_gpuobj_new(dev, NULL, 128*4, 0x1000,
174 NVOBJ_FLAG_ZERO_ALLOC,
175 &pfifo->playlist[0]);
176 if (ret) {
177 NV_ERROR(dev, "error creating playlist 0: %d\n", ret);
178 return ret;
179 }
180
181 ret = nouveau_gpuobj_new(dev, NULL, 128*4, 0x1000,
182 NVOBJ_FLAG_ZERO_ALLOC,
183 &pfifo->playlist[1]);
184 if (ret) {
185 nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]);
186 NV_ERROR(dev, "error creating playlist 1: %d\n", ret);
187 return ret;
188 }
189
190just_reset:
191 nv50_fifo_init_reset(dev);
192 nv50_fifo_init_intr(dev);
193 nv50_fifo_init_context_table(dev);
194 nv50_fifo_init_regs__nv(dev);
195 nv50_fifo_init_regs(dev);
196 dev_priv->engine.fifo.enable(dev);
197 dev_priv->engine.fifo.reassign(dev, true);
198
199 return 0;
200}
201
202void
203nv50_fifo_takedown(struct drm_device *dev)
204{
205 struct drm_nouveau_private *dev_priv = dev->dev_private;
206 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
207
208 NV_DEBUG(dev, "\n");
209
210 if (!pfifo->playlist[0])
211 return;
212
213 nv_wr32(dev, 0x2140, 0x00000000);
214 nouveau_irq_unregister(dev, 8);
215
216 nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]);
217 nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]);
218}
219
220int
221nv50_fifo_channel_id(struct drm_device *dev)
222{
223 return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) &
224 NV50_PFIFO_CACHE1_PUSH1_CHID_MASK;
225}
226
227int
228nv50_fifo_create_context(struct nouveau_channel *chan)
229{
230 struct drm_device *dev = chan->dev;
231 struct drm_nouveau_private *dev_priv = dev->dev_private;
232 struct nouveau_gpuobj *ramfc = NULL;
233 unsigned long flags;
234 int ret;
235
236 NV_DEBUG(dev, "ch%d\n", chan->id);
237
238 if (dev_priv->chipset == 0x50) {
239 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst,
240 chan->ramin->vinst, 0x100,
241 NVOBJ_FLAG_ZERO_ALLOC |
242 NVOBJ_FLAG_ZERO_FREE,
243 &chan->ramfc);
244 if (ret)
245 return ret;
246
247 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst + 0x0400,
248 chan->ramin->vinst + 0x0400,
249 4096, 0, &chan->cache);
250 if (ret)
251 return ret;
252 } else {
253 ret = nouveau_gpuobj_new(dev, chan, 0x100, 256,
254 NVOBJ_FLAG_ZERO_ALLOC |
255 NVOBJ_FLAG_ZERO_FREE, &chan->ramfc);
256 if (ret)
257 return ret;
258
259 ret = nouveau_gpuobj_new(dev, chan, 4096, 1024,
260 0, &chan->cache);
261 if (ret)
262 return ret;
263 }
264 ramfc = chan->ramfc;
265
266 chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
267 NV50_USER(chan->id), PAGE_SIZE);
268 if (!chan->user)
269 return -ENOMEM;
270
271 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
272
273 nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4);
274 nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
275 (4 << 24) /* SEARCH_FULL */ |
276 (chan->ramht->gpuobj->cinst >> 4));
277 nv_wo32(ramfc, 0x44, 0x01003fff);
278 nv_wo32(ramfc, 0x60, 0x7fffffff);
279 nv_wo32(ramfc, 0x40, 0x00000000);
280 nv_wo32(ramfc, 0x7c, 0x30000001);
281 nv_wo32(ramfc, 0x78, 0x00000000);
282 nv_wo32(ramfc, 0x3c, 0x403f6078);
283 nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4);
284 nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16);
285
286 if (dev_priv->chipset != 0x50) {
287 nv_wo32(chan->ramin, 0, chan->id);
288 nv_wo32(chan->ramin, 4, chan->ramfc->vinst >> 8);
289
290 nv_wo32(ramfc, 0x88, chan->cache->vinst >> 10);
291 nv_wo32(ramfc, 0x98, chan->ramin->vinst >> 12);
292 }
293
294 dev_priv->engine.instmem.flush(dev);
295
296 nv50_fifo_channel_enable(dev, chan->id);
297 nv50_fifo_playlist_update(dev);
298 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
299 return 0;
300}
301
302void
303nv50_fifo_destroy_context(struct nouveau_channel *chan)
304{
305 struct drm_device *dev = chan->dev;
306 struct drm_nouveau_private *dev_priv = dev->dev_private;
307 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
308 struct nouveau_gpuobj *ramfc = NULL;
309 unsigned long flags;
310
311 NV_DEBUG(dev, "ch%d\n", chan->id);
312
313 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
314 pfifo->reassign(dev, false);
315
316 /* Unload the context if it's the currently active one */
317 if (pfifo->channel_id(dev) == chan->id) {
318 pfifo->disable(dev);
319 pfifo->unload_context(dev);
320 pfifo->enable(dev);
321 }
322
323 /* This will ensure the channel is seen as disabled. */
324 nouveau_gpuobj_ref(chan->ramfc, &ramfc);
325 nouveau_gpuobj_ref(NULL, &chan->ramfc);
326 nv50_fifo_channel_disable(dev, chan->id);
327
328 /* Dummy channel, also used on ch 127 */
329 if (chan->id == 0)
330 nv50_fifo_channel_disable(dev, 127);
331 nv50_fifo_playlist_update(dev);
332
333 pfifo->reassign(dev, true);
334 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
335
336 /* Free the channel resources */
337 if (chan->user) {
338 iounmap(chan->user);
339 chan->user = NULL;
340 }
341 nouveau_gpuobj_ref(NULL, &ramfc);
342 nouveau_gpuobj_ref(NULL, &chan->cache);
343}
344
345int
346nv50_fifo_load_context(struct nouveau_channel *chan)
347{
348 struct drm_device *dev = chan->dev;
349 struct drm_nouveau_private *dev_priv = dev->dev_private;
350 struct nouveau_gpuobj *ramfc = chan->ramfc;
351 struct nouveau_gpuobj *cache = chan->cache;
352 int ptr, cnt;
353
354 NV_DEBUG(dev, "ch%d\n", chan->id);
355
356 nv_wr32(dev, 0x3330, nv_ro32(ramfc, 0x00));
357 nv_wr32(dev, 0x3334, nv_ro32(ramfc, 0x04));
358 nv_wr32(dev, 0x3240, nv_ro32(ramfc, 0x08));
359 nv_wr32(dev, 0x3320, nv_ro32(ramfc, 0x0c));
360 nv_wr32(dev, 0x3244, nv_ro32(ramfc, 0x10));
361 nv_wr32(dev, 0x3328, nv_ro32(ramfc, 0x14));
362 nv_wr32(dev, 0x3368, nv_ro32(ramfc, 0x18));
363 nv_wr32(dev, 0x336c, nv_ro32(ramfc, 0x1c));
364 nv_wr32(dev, 0x3370, nv_ro32(ramfc, 0x20));
365 nv_wr32(dev, 0x3374, nv_ro32(ramfc, 0x24));
366 nv_wr32(dev, 0x3378, nv_ro32(ramfc, 0x28));
367 nv_wr32(dev, 0x337c, nv_ro32(ramfc, 0x2c));
368 nv_wr32(dev, 0x3228, nv_ro32(ramfc, 0x30));
369 nv_wr32(dev, 0x3364, nv_ro32(ramfc, 0x34));
370 nv_wr32(dev, 0x32a0, nv_ro32(ramfc, 0x38));
371 nv_wr32(dev, 0x3224, nv_ro32(ramfc, 0x3c));
372 nv_wr32(dev, 0x324c, nv_ro32(ramfc, 0x40));
373 nv_wr32(dev, 0x2044, nv_ro32(ramfc, 0x44));
374 nv_wr32(dev, 0x322c, nv_ro32(ramfc, 0x48));
375 nv_wr32(dev, 0x3234, nv_ro32(ramfc, 0x4c));
376 nv_wr32(dev, 0x3340, nv_ro32(ramfc, 0x50));
377 nv_wr32(dev, 0x3344, nv_ro32(ramfc, 0x54));
378 nv_wr32(dev, 0x3280, nv_ro32(ramfc, 0x58));
379 nv_wr32(dev, 0x3254, nv_ro32(ramfc, 0x5c));
380 nv_wr32(dev, 0x3260, nv_ro32(ramfc, 0x60));
381 nv_wr32(dev, 0x3264, nv_ro32(ramfc, 0x64));
382 nv_wr32(dev, 0x3268, nv_ro32(ramfc, 0x68));
383 nv_wr32(dev, 0x326c, nv_ro32(ramfc, 0x6c));
384 nv_wr32(dev, 0x32e4, nv_ro32(ramfc, 0x70));
385 nv_wr32(dev, 0x3248, nv_ro32(ramfc, 0x74));
386 nv_wr32(dev, 0x2088, nv_ro32(ramfc, 0x78));
387 nv_wr32(dev, 0x2058, nv_ro32(ramfc, 0x7c));
388 nv_wr32(dev, 0x2210, nv_ro32(ramfc, 0x80));
389
390 cnt = nv_ro32(ramfc, 0x84);
391 for (ptr = 0; ptr < cnt; ptr++) {
392 nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr),
393 nv_ro32(cache, (ptr * 8) + 0));
394 nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr),
395 nv_ro32(cache, (ptr * 8) + 4));
396 }
397 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2);
398 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
399
400 /* guessing that all the 0x34xx regs aren't on NV50 */
401 if (dev_priv->chipset != 0x50) {
402 nv_wr32(dev, 0x340c, nv_ro32(ramfc, 0x88));
403 nv_wr32(dev, 0x3400, nv_ro32(ramfc, 0x8c));
404 nv_wr32(dev, 0x3404, nv_ro32(ramfc, 0x90));
405 nv_wr32(dev, 0x3408, nv_ro32(ramfc, 0x94));
406 nv_wr32(dev, 0x3410, nv_ro32(ramfc, 0x98));
407 }
408
409 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
410 return 0;
411}
412
413int
414nv50_fifo_unload_context(struct drm_device *dev)
415{
416 struct drm_nouveau_private *dev_priv = dev->dev_private;
417 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
418 struct nouveau_gpuobj *ramfc, *cache;
419 struct nouveau_channel *chan = NULL;
420 int chid, get, put, ptr;
421
422 NV_DEBUG(dev, "\n");
423
424 chid = pfifo->channel_id(dev);
425 if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1)
426 return 0;
427
428 chan = dev_priv->channels.ptr[chid];
429 if (!chan) {
430 NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
431 return -EINVAL;
432 }
433 NV_DEBUG(dev, "ch%d\n", chan->id);
434 ramfc = chan->ramfc;
435 cache = chan->cache;
436
437 nv_wo32(ramfc, 0x00, nv_rd32(dev, 0x3330));
438 nv_wo32(ramfc, 0x04, nv_rd32(dev, 0x3334));
439 nv_wo32(ramfc, 0x08, nv_rd32(dev, 0x3240));
440 nv_wo32(ramfc, 0x0c, nv_rd32(dev, 0x3320));
441 nv_wo32(ramfc, 0x10, nv_rd32(dev, 0x3244));
442 nv_wo32(ramfc, 0x14, nv_rd32(dev, 0x3328));
443 nv_wo32(ramfc, 0x18, nv_rd32(dev, 0x3368));
444 nv_wo32(ramfc, 0x1c, nv_rd32(dev, 0x336c));
445 nv_wo32(ramfc, 0x20, nv_rd32(dev, 0x3370));
446 nv_wo32(ramfc, 0x24, nv_rd32(dev, 0x3374));
447 nv_wo32(ramfc, 0x28, nv_rd32(dev, 0x3378));
448 nv_wo32(ramfc, 0x2c, nv_rd32(dev, 0x337c));
449 nv_wo32(ramfc, 0x30, nv_rd32(dev, 0x3228));
450 nv_wo32(ramfc, 0x34, nv_rd32(dev, 0x3364));
451 nv_wo32(ramfc, 0x38, nv_rd32(dev, 0x32a0));
452 nv_wo32(ramfc, 0x3c, nv_rd32(dev, 0x3224));
453 nv_wo32(ramfc, 0x40, nv_rd32(dev, 0x324c));
454 nv_wo32(ramfc, 0x44, nv_rd32(dev, 0x2044));
455 nv_wo32(ramfc, 0x48, nv_rd32(dev, 0x322c));
456 nv_wo32(ramfc, 0x4c, nv_rd32(dev, 0x3234));
457 nv_wo32(ramfc, 0x50, nv_rd32(dev, 0x3340));
458 nv_wo32(ramfc, 0x54, nv_rd32(dev, 0x3344));
459 nv_wo32(ramfc, 0x58, nv_rd32(dev, 0x3280));
460 nv_wo32(ramfc, 0x5c, nv_rd32(dev, 0x3254));
461 nv_wo32(ramfc, 0x60, nv_rd32(dev, 0x3260));
462 nv_wo32(ramfc, 0x64, nv_rd32(dev, 0x3264));
463 nv_wo32(ramfc, 0x68, nv_rd32(dev, 0x3268));
464 nv_wo32(ramfc, 0x6c, nv_rd32(dev, 0x326c));
465 nv_wo32(ramfc, 0x70, nv_rd32(dev, 0x32e4));
466 nv_wo32(ramfc, 0x74, nv_rd32(dev, 0x3248));
467 nv_wo32(ramfc, 0x78, nv_rd32(dev, 0x2088));
468 nv_wo32(ramfc, 0x7c, nv_rd32(dev, 0x2058));
469 nv_wo32(ramfc, 0x80, nv_rd32(dev, 0x2210));
470
471 put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2;
472 get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2;
473 ptr = 0;
474 while (put != get) {
475 nv_wo32(cache, ptr + 0,
476 nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get)));
477 nv_wo32(cache, ptr + 4,
478 nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get)));
479 get = (get + 1) & 0x1ff;
480 ptr += 8;
481 }
482
483 /* guessing that all the 0x34xx regs aren't on NV50 */
484 if (dev_priv->chipset != 0x50) {
485 nv_wo32(ramfc, 0x84, ptr >> 3);
486 nv_wo32(ramfc, 0x88, nv_rd32(dev, 0x340c));
487 nv_wo32(ramfc, 0x8c, nv_rd32(dev, 0x3400));
488 nv_wo32(ramfc, 0x90, nv_rd32(dev, 0x3404));
489 nv_wo32(ramfc, 0x94, nv_rd32(dev, 0x3408));
490 nv_wo32(ramfc, 0x98, nv_rd32(dev, 0x3410));
491 }
492
493 dev_priv->engine.instmem.flush(dev);
494
495 /*XXX: probably reload ch127 (NULL) state back too */
496 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 127);
497 return 0;
498}
499
500void
501nv50_fifo_tlb_flush(struct drm_device *dev)
502{
503 nv50_vm_flush_engine(dev, 5);
504}
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c
new file mode 100644
index 00000000000..d4f4206dad7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -0,0 +1,302 @@
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
29#include "nv50_display.h"
30
31static void nv50_gpio_isr(struct drm_device *dev);
32static void nv50_gpio_isr_bh(struct work_struct *work);
33
34struct nv50_gpio_priv {
35 struct list_head handlers;
36 spinlock_t lock;
37};
38
39struct nv50_gpio_handler {
40 struct drm_device *dev;
41 struct list_head head;
42 struct work_struct work;
43 bool inhibit;
44
45 struct dcb_gpio_entry *gpio;
46
47 void (*handler)(void *data, int state);
48 void *data;
49};
50
51static int
52nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift)
53{
54 const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
55
56 if (gpio->line >= 32)
57 return -EINVAL;
58
59 *reg = nv50_gpio_reg[gpio->line >> 3];
60 *shift = (gpio->line & 7) << 2;
61 return 0;
62}
63
64int
65nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
66{
67 struct dcb_gpio_entry *gpio;
68 uint32_t r, s, v;
69
70 gpio = nouveau_bios_gpio_entry(dev, tag);
71 if (!gpio)
72 return -ENOENT;
73
74 if (nv50_gpio_location(gpio, &r, &s))
75 return -EINVAL;
76
77 v = nv_rd32(dev, r) >> (s + 2);
78 return ((v & 1) == (gpio->state[1] & 1));
79}
80
81int
82nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
83{
84 struct dcb_gpio_entry *gpio;
85 uint32_t r, s, v;
86
87 gpio = nouveau_bios_gpio_entry(dev, tag);
88 if (!gpio)
89 return -ENOENT;
90
91 if (nv50_gpio_location(gpio, &r, &s))
92 return -EINVAL;
93
94 v = nv_rd32(dev, r) & ~(0x3 << s);
95 v |= (gpio->state[state] ^ 2) << s;
96 nv_wr32(dev, r, v);
97 return 0;
98}
99
100int
101nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag,
102 void (*handler)(void *, int), void *data)
103{
104 struct drm_nouveau_private *dev_priv = dev->dev_private;
105 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
106 struct nv50_gpio_priv *priv = pgpio->priv;
107 struct nv50_gpio_handler *gpioh;
108 struct dcb_gpio_entry *gpio;
109 unsigned long flags;
110
111 gpio = nouveau_bios_gpio_entry(dev, tag);
112 if (!gpio)
113 return -ENOENT;
114
115 gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL);
116 if (!gpioh)
117 return -ENOMEM;
118
119 INIT_WORK(&gpioh->work, nv50_gpio_isr_bh);
120 gpioh->dev = dev;
121 gpioh->gpio = gpio;
122 gpioh->handler = handler;
123 gpioh->data = data;
124
125 spin_lock_irqsave(&priv->lock, flags);
126 list_add(&gpioh->head, &priv->handlers);
127 spin_unlock_irqrestore(&priv->lock, flags);
128 return 0;
129}
130
131void
132nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag,
133 void (*handler)(void *, int), void *data)
134{
135 struct drm_nouveau_private *dev_priv = dev->dev_private;
136 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
137 struct nv50_gpio_priv *priv = pgpio->priv;
138 struct nv50_gpio_handler *gpioh, *tmp;
139 struct dcb_gpio_entry *gpio;
140 LIST_HEAD(tofree);
141 unsigned long flags;
142
143 gpio = nouveau_bios_gpio_entry(dev, tag);
144 if (!gpio)
145 return;
146
147 spin_lock_irqsave(&priv->lock, flags);
148 list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) {
149 if (gpioh->gpio != gpio ||
150 gpioh->handler != handler ||
151 gpioh->data != data)
152 continue;
153 list_move(&gpioh->head, &tofree);
154 }
155 spin_unlock_irqrestore(&priv->lock, flags);
156
157 list_for_each_entry_safe(gpioh, tmp, &tofree, head) {
158 flush_work_sync(&gpioh->work);
159 kfree(gpioh);
160 }
161}
162
163bool
164nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on)
165{
166 struct dcb_gpio_entry *gpio;
167 u32 reg, mask;
168
169 gpio = nouveau_bios_gpio_entry(dev, tag);
170 if (!gpio)
171 return false;
172
173 reg = gpio->line < 16 ? 0xe050 : 0xe070;
174 mask = 0x00010001 << (gpio->line & 0xf);
175
176 nv_wr32(dev, reg + 4, mask);
177 reg = nv_mask(dev, reg + 0, mask, on ? mask : 0);
178 return (reg & mask) == mask;
179}
180
181static int
182nv50_gpio_create(struct drm_device *dev)
183{
184 struct drm_nouveau_private *dev_priv = dev->dev_private;
185 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
186 struct nv50_gpio_priv *priv;
187
188 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
189 if (!priv)
190 return -ENOMEM;
191
192 INIT_LIST_HEAD(&priv->handlers);
193 spin_lock_init(&priv->lock);
194 pgpio->priv = priv;
195 return 0;
196}
197
198static void
199nv50_gpio_destroy(struct drm_device *dev)
200{
201 struct drm_nouveau_private *dev_priv = dev->dev_private;
202 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
203
204 kfree(pgpio->priv);
205 pgpio->priv = NULL;
206}
207
208int
209nv50_gpio_init(struct drm_device *dev)
210{
211 struct drm_nouveau_private *dev_priv = dev->dev_private;
212 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
213 int ret;
214
215 if (!pgpio->priv) {
216 ret = nv50_gpio_create(dev);
217 if (ret)
218 return ret;
219 }
220
221 /* disable, and ack any pending gpio interrupts */
222 nv_wr32(dev, 0xe050, 0x00000000);
223 nv_wr32(dev, 0xe054, 0xffffffff);
224 if (dev_priv->chipset >= 0x90) {
225 nv_wr32(dev, 0xe070, 0x00000000);
226 nv_wr32(dev, 0xe074, 0xffffffff);
227 }
228
229 nouveau_irq_register(dev, 21, nv50_gpio_isr);
230 return 0;
231}
232
233void
234nv50_gpio_fini(struct drm_device *dev)
235{
236 struct drm_nouveau_private *dev_priv = dev->dev_private;
237
238 nv_wr32(dev, 0xe050, 0x00000000);
239 if (dev_priv->chipset >= 0x90)
240 nv_wr32(dev, 0xe070, 0x00000000);
241 nouveau_irq_unregister(dev, 21);
242
243 nv50_gpio_destroy(dev);
244}
245
246static void
247nv50_gpio_isr_bh(struct work_struct *work)
248{
249 struct nv50_gpio_handler *gpioh =
250 container_of(work, struct nv50_gpio_handler, work);
251 struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private;
252 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
253 struct nv50_gpio_priv *priv = pgpio->priv;
254 unsigned long flags;
255 int state;
256
257 state = pgpio->get(gpioh->dev, gpioh->gpio->tag);
258 if (state < 0)
259 return;
260
261 gpioh->handler(gpioh->data, state);
262
263 spin_lock_irqsave(&priv->lock, flags);
264 gpioh->inhibit = false;
265 spin_unlock_irqrestore(&priv->lock, flags);
266}
267
268static void
269nv50_gpio_isr(struct drm_device *dev)
270{
271 struct drm_nouveau_private *dev_priv = dev->dev_private;
272 struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
273 struct nv50_gpio_priv *priv = pgpio->priv;
274 struct nv50_gpio_handler *gpioh;
275 u32 intr0, intr1 = 0;
276 u32 hi, lo, ch;
277
278 intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050);
279 if (dev_priv->chipset >= 0x90)
280 intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070);
281
282 hi = (intr0 & 0x0000ffff) | (intr1 << 16);
283 lo = (intr0 >> 16) | (intr1 & 0xffff0000);
284 ch = hi | lo;
285
286 nv_wr32(dev, 0xe054, intr0);
287 if (dev_priv->chipset >= 0x90)
288 nv_wr32(dev, 0xe074, intr1);
289
290 spin_lock(&priv->lock);
291 list_for_each_entry(gpioh, &priv->handlers, head) {
292 if (!(ch & (1 << gpioh->gpio->line)))
293 continue;
294
295 if (gpioh->inhibit)
296 continue;
297 gpioh->inhibit = true;
298
299 schedule_work(&gpioh->work);
300 }
301 spin_unlock(&priv->lock);
302}
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
new file mode 100644
index 00000000000..d43c46caa76
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -0,0 +1,1123 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30#include "nouveau_ramht.h"
31#include "nouveau_grctx.h"
32#include "nouveau_dma.h"
33#include "nouveau_vm.h"
34#include "nv50_evo.h"
35
36struct nv50_graph_engine {
37 struct nouveau_exec_engine base;
38 u32 ctxprog[512];
39 u32 ctxprog_size;
40 u32 grctx_size;
41};
42
43static void
44nv50_graph_fifo_access(struct drm_device *dev, bool enabled)
45{
46 const uint32_t mask = 0x00010001;
47
48 if (enabled)
49 nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | mask);
50 else
51 nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) & ~mask);
52}
53
54static struct nouveau_channel *
55nv50_graph_channel(struct drm_device *dev)
56{
57 struct drm_nouveau_private *dev_priv = dev->dev_private;
58 uint32_t inst;
59 int i;
60
61 /* Be sure we're not in the middle of a context switch or bad things
62 * will happen, such as unloading the wrong pgraph context.
63 */
64 if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000))
65 NV_ERROR(dev, "Ctxprog is still running\n");
66
67 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
68 if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
69 return NULL;
70 inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12;
71
72 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
73 struct nouveau_channel *chan = dev_priv->channels.ptr[i];
74
75 if (chan && chan->ramin && chan->ramin->vinst == inst)
76 return chan;
77 }
78
79 return NULL;
80}
81
82static int
83nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst)
84{
85 uint32_t fifo = nv_rd32(dev, 0x400500);
86
87 nv_wr32(dev, 0x400500, fifo & ~1);
88 nv_wr32(dev, 0x400784, inst);
89 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x40);
90 nv_wr32(dev, 0x400320, nv_rd32(dev, 0x400320) | 0x11);
91 nv_wr32(dev, 0x400040, 0xffffffff);
92 (void)nv_rd32(dev, 0x400040);
93 nv_wr32(dev, 0x400040, 0x00000000);
94 nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 1);
95
96 if (nouveau_wait_for_idle(dev))
97 nv_wr32(dev, 0x40032c, inst | (1<<31));
98 nv_wr32(dev, 0x400500, fifo);
99
100 return 0;
101}
102
103static int
104nv50_graph_unload_context(struct drm_device *dev)
105{
106 uint32_t inst;
107
108 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
109 if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
110 return 0;
111 inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
112
113 nouveau_wait_for_idle(dev);
114 nv_wr32(dev, 0x400784, inst);
115 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
116 nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01);
117 nouveau_wait_for_idle(dev);
118
119 nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst);
120 return 0;
121}
122
123static void
124nv50_graph_init_reset(struct drm_device *dev)
125{
126 uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
127 NV_DEBUG(dev, "\n");
128
129 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
130 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e);
131}
132
133static void
134nv50_graph_init_intr(struct drm_device *dev)
135{
136 NV_DEBUG(dev, "\n");
137
138 nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
139 nv_wr32(dev, 0x400138, 0xffffffff);
140 nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
141}
142
143static void
144nv50_graph_init_regs__nv(struct drm_device *dev)
145{
146 struct drm_nouveau_private *dev_priv = dev->dev_private;
147 uint32_t units = nv_rd32(dev, 0x1540);
148 int i;
149
150 NV_DEBUG(dev, "\n");
151
152 nv_wr32(dev, 0x400804, 0xc0000000);
153 nv_wr32(dev, 0x406800, 0xc0000000);
154 nv_wr32(dev, 0x400c04, 0xc0000000);
155 nv_wr32(dev, 0x401800, 0xc0000000);
156 nv_wr32(dev, 0x405018, 0xc0000000);
157 nv_wr32(dev, 0x402000, 0xc0000000);
158
159 for (i = 0; i < 16; i++) {
160 if (units & 1 << i) {
161 if (dev_priv->chipset < 0xa0) {
162 nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
163 nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
164 nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
165 } else {
166 nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
167 nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
168 nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
169 }
170 }
171 }
172
173 nv_wr32(dev, 0x400108, 0xffffffff);
174
175 nv_wr32(dev, 0x400824, 0x00004000);
176 nv_wr32(dev, 0x400500, 0x00010001);
177}
178
179static void
180nv50_graph_init_zcull(struct drm_device *dev)
181{
182 struct drm_nouveau_private *dev_priv = dev->dev_private;
183 int i;
184
185 NV_DEBUG(dev, "\n");
186
187 switch (dev_priv->chipset & 0xf0) {
188 case 0x50:
189 case 0x80:
190 case 0x90:
191 nv_wr32(dev, 0x402ca8, 0x00000800);
192 break;
193 case 0xa0:
194 default:
195 nv_wr32(dev, 0x402cc0, 0x00000000);
196 if (dev_priv->chipset == 0xa0 ||
197 dev_priv->chipset == 0xaa ||
198 dev_priv->chipset == 0xac) {
199 nv_wr32(dev, 0x402ca8, 0x00000802);
200 } else {
201 nv_wr32(dev, 0x402cc0, 0x00000000);
202 nv_wr32(dev, 0x402ca8, 0x00000002);
203 }
204
205 break;
206 }
207
208 /* zero out zcull regions */
209 for (i = 0; i < 8; i++) {
210 nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000);
211 nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000);
212 nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
213 nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
214 }
215}
216
217static int
218nv50_graph_init_ctxctl(struct drm_device *dev)
219{
220 struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR);
221 int i;
222
223 NV_DEBUG(dev, "\n");
224
225 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
226 for (i = 0; i < pgraph->ctxprog_size; i++)
227 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]);
228
229 nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
230 nv_wr32(dev, 0x400320, 4);
231 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
232 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
233 return 0;
234}
235
236static int
237nv50_graph_init(struct drm_device *dev, int engine)
238{
239 int ret;
240
241 NV_DEBUG(dev, "\n");
242
243 nv50_graph_init_reset(dev);
244 nv50_graph_init_regs__nv(dev);
245 nv50_graph_init_zcull(dev);
246
247 ret = nv50_graph_init_ctxctl(dev);
248 if (ret)
249 return ret;
250
251 nv50_graph_init_intr(dev);
252 return 0;
253}
254
255static int
256nv50_graph_fini(struct drm_device *dev, int engine, bool suspend)
257{
258 nv_mask(dev, 0x400500, 0x00010001, 0x00000000);
259 if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) {
260 nv_mask(dev, 0x400500, 0x00010001, 0x00010001);
261 return -EBUSY;
262 }
263 nv50_graph_unload_context(dev);
264 nv_wr32(dev, 0x40013c, 0x00000000);
265 return 0;
266}
267
268static int
269nv50_graph_context_new(struct nouveau_channel *chan, int engine)
270{
271 struct drm_device *dev = chan->dev;
272 struct drm_nouveau_private *dev_priv = dev->dev_private;
273 struct nouveau_gpuobj *ramin = chan->ramin;
274 struct nouveau_gpuobj *grctx = NULL;
275 struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
276 struct nouveau_grctx ctx = {};
277 int hdr, ret;
278
279 NV_DEBUG(dev, "ch%d\n", chan->id);
280
281 ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 0,
282 NVOBJ_FLAG_ZERO_ALLOC |
283 NVOBJ_FLAG_ZERO_FREE, &grctx);
284 if (ret)
285 return ret;
286
287 hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
288 nv_wo32(ramin, hdr + 0x00, 0x00190002);
289 nv_wo32(ramin, hdr + 0x04, grctx->vinst + grctx->size - 1);
290 nv_wo32(ramin, hdr + 0x08, grctx->vinst);
291 nv_wo32(ramin, hdr + 0x0c, 0);
292 nv_wo32(ramin, hdr + 0x10, 0);
293 nv_wo32(ramin, hdr + 0x14, 0x00010000);
294
295 ctx.dev = chan->dev;
296 ctx.mode = NOUVEAU_GRCTX_VALS;
297 ctx.data = grctx;
298 nv50_grctx_init(&ctx);
299
300 nv_wo32(grctx, 0x00000, chan->ramin->vinst >> 12);
301
302 dev_priv->engine.instmem.flush(dev);
303
304 atomic_inc(&chan->vm->engref[NVOBJ_ENGINE_GR]);
305 chan->engctx[NVOBJ_ENGINE_GR] = grctx;
306 return 0;
307}
308
309static void
310nv50_graph_context_del(struct nouveau_channel *chan, int engine)
311{
312 struct nouveau_gpuobj *grctx = chan->engctx[engine];
313 struct drm_device *dev = chan->dev;
314 struct drm_nouveau_private *dev_priv = dev->dev_private;
315 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
316 int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
317 unsigned long flags;
318
319 NV_DEBUG(dev, "ch%d\n", chan->id);
320
321 if (!chan->ramin)
322 return;
323
324 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
325 pfifo->reassign(dev, false);
326 nv50_graph_fifo_access(dev, false);
327
328 if (nv50_graph_channel(dev) == chan)
329 nv50_graph_unload_context(dev);
330
331 for (i = hdr; i < hdr + 24; i += 4)
332 nv_wo32(chan->ramin, i, 0);
333 dev_priv->engine.instmem.flush(dev);
334
335 nv50_graph_fifo_access(dev, true);
336 pfifo->reassign(dev, true);
337 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
338
339 nouveau_gpuobj_ref(NULL, &grctx);
340
341 atomic_dec(&chan->vm->engref[engine]);
342 chan->engctx[engine] = NULL;
343}
344
345static int
346nv50_graph_object_new(struct nouveau_channel *chan, int engine,
347 u32 handle, u16 class)
348{
349 struct drm_device *dev = chan->dev;
350 struct drm_nouveau_private *dev_priv = dev->dev_private;
351 struct nouveau_gpuobj *obj = NULL;
352 int ret;
353
354 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
355 if (ret)
356 return ret;
357 obj->engine = 1;
358 obj->class = class;
359
360 nv_wo32(obj, 0x00, class);
361 nv_wo32(obj, 0x04, 0x00000000);
362 nv_wo32(obj, 0x08, 0x00000000);
363 nv_wo32(obj, 0x0c, 0x00000000);
364 dev_priv->engine.instmem.flush(dev);
365
366 ret = nouveau_ramht_insert(chan, handle, obj);
367 nouveau_gpuobj_ref(NULL, &obj);
368 return ret;
369}
370
371static void
372nv50_graph_context_switch(struct drm_device *dev)
373{
374 uint32_t inst;
375
376 nv50_graph_unload_context(dev);
377
378 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_NEXT);
379 inst &= NV50_PGRAPH_CTXCTL_NEXT_INSTANCE;
380 nv50_graph_do_load_context(dev, inst);
381
382 nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
383 NV40_PGRAPH_INTR_EN) | NV_PGRAPH_INTR_CONTEXT_SWITCH);
384}
385
386static int
387nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan,
388 u32 class, u32 mthd, u32 data)
389{
390 struct nouveau_gpuobj *gpuobj;
391
392 gpuobj = nouveau_ramht_find(chan, data);
393 if (!gpuobj)
394 return -ENOENT;
395
396 if (nouveau_notifier_offset(gpuobj, NULL))
397 return -EINVAL;
398
399 chan->nvsw.vblsem = gpuobj;
400 chan->nvsw.vblsem_offset = ~0;
401 return 0;
402}
403
404static int
405nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan,
406 u32 class, u32 mthd, u32 data)
407{
408 if (nouveau_notifier_offset(chan->nvsw.vblsem, &data))
409 return -ERANGE;
410
411 chan->nvsw.vblsem_offset = data >> 2;
412 return 0;
413}
414
415static int
416nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan,
417 u32 class, u32 mthd, u32 data)
418{
419 chan->nvsw.vblsem_rval = data;
420 return 0;
421}
422
423static int
424nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan,
425 u32 class, u32 mthd, u32 data)
426{
427 struct drm_device *dev = chan->dev;
428 struct drm_nouveau_private *dev_priv = dev->dev_private;
429
430 if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1)
431 return -EINVAL;
432
433 drm_vblank_get(dev, data);
434
435 chan->nvsw.vblsem_head = data;
436 list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);
437
438 return 0;
439}
440
441static int
442nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan,
443 u32 class, u32 mthd, u32 data)
444{
445 nouveau_finish_page_flip(chan, NULL);
446 return 0;
447}
448
449
450static void
451nv50_graph_tlb_flush(struct drm_device *dev, int engine)
452{
453 nv50_vm_flush_engine(dev, 0);
454}
455
456static void
457nv84_graph_tlb_flush(struct drm_device *dev, int engine)
458{
459 struct drm_nouveau_private *dev_priv = dev->dev_private;
460 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
461 bool idle, timeout = false;
462 unsigned long flags;
463 u64 start;
464 u32 tmp;
465
466 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
467 nv_mask(dev, 0x400500, 0x00000001, 0x00000000);
468
469 start = ptimer->read(dev);
470 do {
471 idle = true;
472
473 for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) {
474 if ((tmp & 7) == 1)
475 idle = false;
476 }
477
478 for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) {
479 if ((tmp & 7) == 1)
480 idle = false;
481 }
482
483 for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) {
484 if ((tmp & 7) == 1)
485 idle = false;
486 }
487 } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000));
488
489 if (timeout) {
490 NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: "
491 "0x%08x 0x%08x 0x%08x 0x%08x\n",
492 nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380),
493 nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388));
494 }
495
496 nv50_vm_flush_engine(dev, 0);
497
498 nv_mask(dev, 0x400500, 0x00000001, 0x00000001);
499 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
500}
501
502static struct nouveau_enum nv50_mp_exec_error_names[] = {
503 { 3, "STACK_UNDERFLOW", NULL },
504 { 4, "QUADON_ACTIVE", NULL },
505 { 8, "TIMEOUT", NULL },
506 { 0x10, "INVALID_OPCODE", NULL },
507 { 0x40, "BREAKPOINT", NULL },
508 {}
509};
510
511static struct nouveau_bitfield nv50_graph_trap_m2mf[] = {
512 { 0x00000001, "NOTIFY" },
513 { 0x00000002, "IN" },
514 { 0x00000004, "OUT" },
515 {}
516};
517
518static struct nouveau_bitfield nv50_graph_trap_vfetch[] = {
519 { 0x00000001, "FAULT" },
520 {}
521};
522
523static struct nouveau_bitfield nv50_graph_trap_strmout[] = {
524 { 0x00000001, "FAULT" },
525 {}
526};
527
528static struct nouveau_bitfield nv50_graph_trap_ccache[] = {
529 { 0x00000001, "FAULT" },
530 {}
531};
532
533/* There must be a *lot* of these. Will take some time to gather them up. */
534struct nouveau_enum nv50_data_error_names[] = {
535 { 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL },
536 { 0x00000004, "INVALID_VALUE", NULL },
537 { 0x00000005, "INVALID_ENUM", NULL },
538 { 0x00000008, "INVALID_OBJECT", NULL },
539 { 0x00000009, "READ_ONLY_OBJECT", NULL },
540 { 0x0000000a, "SUPERVISOR_OBJECT", NULL },
541 { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
542 { 0x0000000c, "INVALID_BITFIELD", NULL },
543 { 0x0000000d, "BEGIN_END_ACTIVE", NULL },
544 { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
545 { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
546 { 0x00000010, "RT_DOUBLE_BIND", NULL },
547 { 0x00000011, "RT_TYPES_MISMATCH", NULL },
548 { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
549 { 0x00000015, "FP_TOO_FEW_REGS", NULL },
550 { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
551 { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
552 { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
553 { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
554 { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
555 { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
556 { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
557 { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
558 { 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
559 { 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
560 { 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
561 { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
562 { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
563 { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
564 { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
565 { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
566 { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
567 { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
568 { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
569 { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
570 { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
571 { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
572 { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
573 { 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
574 { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
575 { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
576 {}
577};
578
579static struct nouveau_bitfield nv50_graph_intr[] = {
580 { 0x00000001, "NOTIFY" },
581 { 0x00000002, "COMPUTE_QUERY" },
582 { 0x00000010, "ILLEGAL_MTHD" },
583 { 0x00000020, "ILLEGAL_CLASS" },
584 { 0x00000040, "DOUBLE_NOTIFY" },
585 { 0x00001000, "CONTEXT_SWITCH" },
586 { 0x00010000, "BUFFER_NOTIFY" },
587 { 0x00100000, "DATA_ERROR" },
588 { 0x00200000, "TRAP" },
589 { 0x01000000, "SINGLE_STEP" },
590 {}
591};
592
593static void
594nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
595{
596 struct drm_nouveau_private *dev_priv = dev->dev_private;
597 uint32_t units = nv_rd32(dev, 0x1540);
598 uint32_t addr, mp10, status, pc, oplow, ophigh;
599 int i;
600 int mps = 0;
601 for (i = 0; i < 4; i++) {
602 if (!(units & 1 << (i+24)))
603 continue;
604 if (dev_priv->chipset < 0xa0)
605 addr = 0x408200 + (tpid << 12) + (i << 7);
606 else
607 addr = 0x408100 + (tpid << 11) + (i << 7);
608 mp10 = nv_rd32(dev, addr + 0x10);
609 status = nv_rd32(dev, addr + 0x14);
610 if (!status)
611 continue;
612 if (display) {
613 nv_rd32(dev, addr + 0x20);
614 pc = nv_rd32(dev, addr + 0x24);
615 oplow = nv_rd32(dev, addr + 0x70);
616 ophigh = nv_rd32(dev, addr + 0x74);
617 NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
618 "TP %d MP %d: ", tpid, i);
619 nouveau_enum_print(nv50_mp_exec_error_names, status);
620 printk(" at %06x warp %d, opcode %08x %08x\n",
621 pc&0xffffff, pc >> 24,
622 oplow, ophigh);
623 }
624 nv_wr32(dev, addr + 0x10, mp10);
625 nv_wr32(dev, addr + 0x14, 0);
626 mps++;
627 }
628 if (!mps && display)
629 NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: "
630 "No MPs claiming errors?\n", tpid);
631}
632
633static void
634nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
635 uint32_t ustatus_new, int display, const char *name)
636{
637 struct drm_nouveau_private *dev_priv = dev->dev_private;
638 int tps = 0;
639 uint32_t units = nv_rd32(dev, 0x1540);
640 int i, r;
641 uint32_t ustatus_addr, ustatus;
642 for (i = 0; i < 16; i++) {
643 if (!(units & (1 << i)))
644 continue;
645 if (dev_priv->chipset < 0xa0)
646 ustatus_addr = ustatus_old + (i << 12);
647 else
648 ustatus_addr = ustatus_new + (i << 11);
649 ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff;
650 if (!ustatus)
651 continue;
652 tps++;
653 switch (type) {
654 case 6: /* texture error... unknown for now */
655 if (display) {
656 NV_ERROR(dev, "magic set %d:\n", i);
657 for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
658 NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
659 nv_rd32(dev, r));
660 }
661 break;
662 case 7: /* MP error */
663 if (ustatus & 0x00010000) {
664 nv50_pgraph_mp_trap(dev, i, display);
665 ustatus &= ~0x00010000;
666 }
667 break;
668 case 8: /* TPDMA error */
669 {
670 uint32_t e0c = nv_rd32(dev, ustatus_addr + 4);
671 uint32_t e10 = nv_rd32(dev, ustatus_addr + 8);
672 uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc);
673 uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10);
674 uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
675 uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
676 uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
677 /* 2d engine destination */
678 if (ustatus & 0x00000010) {
679 if (display) {
680 NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
681 i, e14, e10);
682 NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
683 i, e0c, e18, e1c, e20, e24);
684 }
685 ustatus &= ~0x00000010;
686 }
687 /* Render target */
688 if (ustatus & 0x00000040) {
689 if (display) {
690 NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
691 i, e14, e10);
692 NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
693 i, e0c, e18, e1c, e20, e24);
694 }
695 ustatus &= ~0x00000040;
696 }
697 /* CUDA memory: l[], g[] or stack. */
698 if (ustatus & 0x00000080) {
699 if (display) {
700 if (e18 & 0x80000000) {
701 /* g[] read fault? */
702 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
703 i, e14, e10 | ((e18 >> 24) & 0x1f));
704 e18 &= ~0x1f000000;
705 } else if (e18 & 0xc) {
706 /* g[] write fault? */
707 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
708 i, e14, e10 | ((e18 >> 7) & 0x1f));
709 e18 &= ~0x00000f80;
710 } else {
711 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
712 i, e14, e10);
713 }
714 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
715 i, e0c, e18, e1c, e20, e24);
716 }
717 ustatus &= ~0x00000080;
718 }
719 }
720 break;
721 }
722 if (ustatus) {
723 if (display)
724 NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus);
725 }
726 nv_wr32(dev, ustatus_addr, 0xc0000000);
727 }
728
729 if (!tps && display)
730 NV_INFO(dev, "%s - No TPs claiming errors?\n", name);
731}
732
733static int
734nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid)
735{
736 u32 status = nv_rd32(dev, 0x400108);
737 u32 ustatus;
738
739 if (!status && display) {
740 NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n");
741 return 1;
742 }
743
744 /* DISPATCH: Relays commands to other units and handles NOTIFY,
745 * COND, QUERY. If you get a trap from it, the command is still stuck
746 * in DISPATCH and you need to do something about it. */
747 if (status & 0x001) {
748 ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff;
749 if (!ustatus && display) {
750 NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n");
751 }
752
753 nv_wr32(dev, 0x400500, 0x00000000);
754
755 /* Known to be triggered by screwed up NOTIFY and COND... */
756 if (ustatus & 0x00000001) {
757 u32 addr = nv_rd32(dev, 0x400808);
758 u32 subc = (addr & 0x00070000) >> 16;
759 u32 mthd = (addr & 0x00001ffc);
760 u32 datal = nv_rd32(dev, 0x40080c);
761 u32 datah = nv_rd32(dev, 0x400810);
762 u32 class = nv_rd32(dev, 0x400814);
763 u32 r848 = nv_rd32(dev, 0x400848);
764
765 NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n");
766 if (display && (addr & 0x80000000)) {
767 NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) "
768 "subc %d class 0x%04x mthd 0x%04x "
769 "data 0x%08x%08x "
770 "400808 0x%08x 400848 0x%08x\n",
771 chid, inst, subc, class, mthd, datah,
772 datal, addr, r848);
773 } else
774 if (display) {
775 NV_INFO(dev, "PGRAPH - no stuck command?\n");
776 }
777
778 nv_wr32(dev, 0x400808, 0);
779 nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3);
780 nv_wr32(dev, 0x400848, 0);
781 ustatus &= ~0x00000001;
782 }
783
784 if (ustatus & 0x00000002) {
785 u32 addr = nv_rd32(dev, 0x40084c);
786 u32 subc = (addr & 0x00070000) >> 16;
787 u32 mthd = (addr & 0x00001ffc);
788 u32 data = nv_rd32(dev, 0x40085c);
789 u32 class = nv_rd32(dev, 0x400814);
790
791 NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n");
792 if (display && (addr & 0x80000000)) {
793 NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) "
794 "subc %d class 0x%04x mthd 0x%04x "
795 "data 0x%08x 40084c 0x%08x\n",
796 chid, inst, subc, class, mthd,
797 data, addr);
798 } else
799 if (display) {
800 NV_INFO(dev, "PGRAPH - no stuck command?\n");
801 }
802
803 nv_wr32(dev, 0x40084c, 0);
804 ustatus &= ~0x00000002;
805 }
806
807 if (ustatus && display) {
808 NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown "
809 "0x%08x)\n", ustatus);
810 }
811
812 nv_wr32(dev, 0x400804, 0xc0000000);
813 nv_wr32(dev, 0x400108, 0x001);
814 status &= ~0x001;
815 if (!status)
816 return 0;
817 }
818
819 /* M2MF: Memory to memory copy engine. */
820 if (status & 0x002) {
821 u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff;
822 if (display) {
823 NV_INFO(dev, "PGRAPH - TRAP_M2MF");
824 nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus);
825 printk("\n");
826 NV_INFO(dev, "PGRAPH - TRAP_M2MF %08x %08x %08x %08x\n",
827 nv_rd32(dev, 0x406804), nv_rd32(dev, 0x406808),
828 nv_rd32(dev, 0x40680c), nv_rd32(dev, 0x406810));
829
830 }
831
832 /* No sane way found yet -- just reset the bugger. */
833 nv_wr32(dev, 0x400040, 2);
834 nv_wr32(dev, 0x400040, 0);
835 nv_wr32(dev, 0x406800, 0xc0000000);
836 nv_wr32(dev, 0x400108, 0x002);
837 status &= ~0x002;
838 }
839
840 /* VFETCH: Fetches data from vertex buffers. */
841 if (status & 0x004) {
842 u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff;
843 if (display) {
844 NV_INFO(dev, "PGRAPH - TRAP_VFETCH");
845 nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus);
846 printk("\n");
847 NV_INFO(dev, "PGRAPH - TRAP_VFETCH %08x %08x %08x %08x\n",
848 nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08),
849 nv_rd32(dev, 0x400c0c), nv_rd32(dev, 0x400c10));
850 }
851
852 nv_wr32(dev, 0x400c04, 0xc0000000);
853 nv_wr32(dev, 0x400108, 0x004);
854 status &= ~0x004;
855 }
856
857 /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
858 if (status & 0x008) {
859 ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff;
860 if (display) {
861 NV_INFO(dev, "PGRAPH - TRAP_STRMOUT");
862 nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus);
863 printk("\n");
864 NV_INFO(dev, "PGRAPH - TRAP_STRMOUT %08x %08x %08x %08x\n",
865 nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808),
866 nv_rd32(dev, 0x40180c), nv_rd32(dev, 0x401810));
867
868 }
869
870 /* No sane way found yet -- just reset the bugger. */
871 nv_wr32(dev, 0x400040, 0x80);
872 nv_wr32(dev, 0x400040, 0);
873 nv_wr32(dev, 0x401800, 0xc0000000);
874 nv_wr32(dev, 0x400108, 0x008);
875 status &= ~0x008;
876 }
877
878 /* CCACHE: Handles code and c[] caches and fills them. */
879 if (status & 0x010) {
880 ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff;
881 if (display) {
882 NV_INFO(dev, "PGRAPH - TRAP_CCACHE");
883 nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus);
884 printk("\n");
885 NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x"
886 " %08x %08x %08x\n",
887 nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004),
888 nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c),
889 nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014),
890 nv_rd32(dev, 0x40501c));
891
892 }
893
894 nv_wr32(dev, 0x405018, 0xc0000000);
895 nv_wr32(dev, 0x400108, 0x010);
896 status &= ~0x010;
897 }
898
899 /* Unknown, not seen yet... 0x402000 is the only trap status reg
900 * remaining, so try to handle it anyway. Perhaps related to that
901 * unknown DMA slot on tesla? */
902 if (status & 0x20) {
903 ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
904 if (display)
905 NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus);
906 nv_wr32(dev, 0x402000, 0xc0000000);
907 /* no status modifiction on purpose */
908 }
909
910 /* TEXTURE: CUDA texturing units */
911 if (status & 0x040) {
912 nv50_pgraph_tp_trap(dev, 6, 0x408900, 0x408600, display,
913 "PGRAPH - TRAP_TEXTURE");
914 nv_wr32(dev, 0x400108, 0x040);
915 status &= ~0x040;
916 }
917
918 /* MP: CUDA execution engines. */
919 if (status & 0x080) {
920 nv50_pgraph_tp_trap(dev, 7, 0x408314, 0x40831c, display,
921 "PGRAPH - TRAP_MP");
922 nv_wr32(dev, 0x400108, 0x080);
923 status &= ~0x080;
924 }
925
926 /* TPDMA: Handles TP-initiated uncached memory accesses:
927 * l[], g[], stack, 2d surfaces, render targets. */
928 if (status & 0x100) {
929 nv50_pgraph_tp_trap(dev, 8, 0x408e08, 0x408708, display,
930 "PGRAPH - TRAP_TPDMA");
931 nv_wr32(dev, 0x400108, 0x100);
932 status &= ~0x100;
933 }
934
935 if (status) {
936 if (display)
937 NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status);
938 nv_wr32(dev, 0x400108, status);
939 }
940
941 return 1;
942}
943
944int
945nv50_graph_isr_chid(struct drm_device *dev, u64 inst)
946{
947 struct drm_nouveau_private *dev_priv = dev->dev_private;
948 struct nouveau_channel *chan;
949 unsigned long flags;
950 int i;
951
952 spin_lock_irqsave(&dev_priv->channels.lock, flags);
953 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
954 chan = dev_priv->channels.ptr[i];
955 if (!chan || !chan->ramin)
956 continue;
957
958 if (inst == chan->ramin->vinst)
959 break;
960 }
961 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
962 return i;
963}
964
965static void
966nv50_graph_isr(struct drm_device *dev)
967{
968 u32 stat;
969
970 while ((stat = nv_rd32(dev, 0x400100))) {
971 u64 inst = (u64)(nv_rd32(dev, 0x40032c) & 0x0fffffff) << 12;
972 u32 chid = nv50_graph_isr_chid(dev, inst);
973 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
974 u32 subc = (addr & 0x00070000) >> 16;
975 u32 mthd = (addr & 0x00001ffc);
976 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
977 u32 class = nv_rd32(dev, 0x400814);
978 u32 show = stat;
979
980 if (stat & 0x00000010) {
981 if (!nouveau_gpuobj_mthd_call2(dev, chid, class,
982 mthd, data))
983 show &= ~0x00000010;
984 }
985
986 if (stat & 0x00001000) {
987 nv_wr32(dev, 0x400500, 0x00000000);
988 nv_wr32(dev, 0x400100, 0x00001000);
989 nv_mask(dev, 0x40013c, 0x00001000, 0x00000000);
990 nv50_graph_context_switch(dev);
991 stat &= ~0x00001000;
992 show &= ~0x00001000;
993 }
994
995 show = (show && nouveau_ratelimit()) ? show : 0;
996
997 if (show & 0x00100000) {
998 u32 ecode = nv_rd32(dev, 0x400110);
999 NV_INFO(dev, "PGRAPH - DATA_ERROR ");
1000 nouveau_enum_print(nv50_data_error_names, ecode);
1001 printk("\n");
1002 }
1003
1004 if (stat & 0x00200000) {
1005 if (!nv50_pgraph_trap_handler(dev, show, inst, chid))
1006 show &= ~0x00200000;
1007 }
1008
1009 nv_wr32(dev, 0x400100, stat);
1010 nv_wr32(dev, 0x400500, 0x00010001);
1011
1012 if (show) {
1013 NV_INFO(dev, "PGRAPH -");
1014 nouveau_bitfield_print(nv50_graph_intr, show);
1015 printk("\n");
1016 NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d "
1017 "class 0x%04x mthd 0x%04x data 0x%08x\n",
1018 chid, inst, subc, class, mthd, data);
1019 nv50_fb_vm_trap(dev, 1);
1020 }
1021 }
1022
1023 if (nv_rd32(dev, 0x400824) & (1 << 31))
1024 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
1025}
1026
1027static void
1028nv50_graph_destroy(struct drm_device *dev, int engine)
1029{
1030 struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
1031
1032 NVOBJ_ENGINE_DEL(dev, GR);
1033
1034 nouveau_irq_unregister(dev, 12);
1035 kfree(pgraph);
1036}
1037
1038int
1039nv50_graph_create(struct drm_device *dev)
1040{
1041 struct drm_nouveau_private *dev_priv = dev->dev_private;
1042 struct nv50_graph_engine *pgraph;
1043 struct nouveau_grctx ctx = {};
1044 int ret;
1045
1046 pgraph = kzalloc(sizeof(*pgraph),GFP_KERNEL);
1047 if (!pgraph)
1048 return -ENOMEM;
1049
1050 ctx.dev = dev;
1051 ctx.mode = NOUVEAU_GRCTX_PROG;
1052 ctx.data = pgraph->ctxprog;
1053 ctx.ctxprog_max = ARRAY_SIZE(pgraph->ctxprog);
1054
1055 ret = nv50_grctx_init(&ctx);
1056 if (ret) {
1057 NV_ERROR(dev, "PGRAPH: ctxprog build failed\n");
1058 kfree(pgraph);
1059 return 0;
1060 }
1061
1062 pgraph->grctx_size = ctx.ctxvals_pos * 4;
1063 pgraph->ctxprog_size = ctx.ctxprog_len;
1064
1065 pgraph->base.destroy = nv50_graph_destroy;
1066 pgraph->base.init = nv50_graph_init;
1067 pgraph->base.fini = nv50_graph_fini;
1068 pgraph->base.context_new = nv50_graph_context_new;
1069 pgraph->base.context_del = nv50_graph_context_del;
1070 pgraph->base.object_new = nv50_graph_object_new;
1071 if (dev_priv->chipset == 0x50 || dev_priv->chipset == 0xac)
1072 pgraph->base.tlb_flush = nv50_graph_tlb_flush;
1073 else
1074 pgraph->base.tlb_flush = nv84_graph_tlb_flush;
1075
1076 nouveau_irq_register(dev, 12, nv50_graph_isr);
1077
1078 /* NVSW really doesn't live here... */
1079 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
1080 NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem);
1081 NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset);
1082 NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val);
1083 NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release);
1084 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip);
1085
1086 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
1087 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
1088 NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */
1089 NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */
1090
1091 /* tesla */
1092 if (dev_priv->chipset == 0x50)
1093 NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */
1094 else
1095 if (dev_priv->chipset < 0xa0)
1096 NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */
1097 else {
1098 switch (dev_priv->chipset) {
1099 case 0xa0:
1100 case 0xaa:
1101 case 0xac:
1102 NVOBJ_CLASS(dev, 0x8397, GR);
1103 break;
1104 case 0xa3:
1105 case 0xa5:
1106 case 0xa8:
1107 NVOBJ_CLASS(dev, 0x8597, GR);
1108 break;
1109 case 0xaf:
1110 NVOBJ_CLASS(dev, 0x8697, GR);
1111 break;
1112 }
1113 }
1114
1115 /* compute */
1116 NVOBJ_CLASS(dev, 0x50c0, GR);
1117 if (dev_priv->chipset > 0xa0 &&
1118 dev_priv->chipset != 0xaa &&
1119 dev_priv->chipset != 0xac)
1120 NVOBJ_CLASS(dev, 0x85c0, GR);
1121
1122 return 0;
1123}
diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c
new file mode 100644
index 00000000000..de9abff12b9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_grctx.c
@@ -0,0 +1,3322 @@
1/*
2 * Copyright 2009 Marcin Kościelnicki
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
23#define CP_FLAG_CLEAR 0
24#define CP_FLAG_SET 1
25#define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0)
26#define CP_FLAG_SWAP_DIRECTION_LOAD 0
27#define CP_FLAG_SWAP_DIRECTION_SAVE 1
28#define CP_FLAG_UNK01 ((0 * 32) + 1)
29#define CP_FLAG_UNK01_CLEAR 0
30#define CP_FLAG_UNK01_SET 1
31#define CP_FLAG_UNK03 ((0 * 32) + 3)
32#define CP_FLAG_UNK03_CLEAR 0
33#define CP_FLAG_UNK03_SET 1
34#define CP_FLAG_USER_SAVE ((0 * 32) + 5)
35#define CP_FLAG_USER_SAVE_NOT_PENDING 0
36#define CP_FLAG_USER_SAVE_PENDING 1
37#define CP_FLAG_USER_LOAD ((0 * 32) + 6)
38#define CP_FLAG_USER_LOAD_NOT_PENDING 0
39#define CP_FLAG_USER_LOAD_PENDING 1
40#define CP_FLAG_UNK0B ((0 * 32) + 0xb)
41#define CP_FLAG_UNK0B_CLEAR 0
42#define CP_FLAG_UNK0B_SET 1
43#define CP_FLAG_UNK1D ((0 * 32) + 0x1d)
44#define CP_FLAG_UNK1D_CLEAR 0
45#define CP_FLAG_UNK1D_SET 1
46#define CP_FLAG_UNK20 ((1 * 32) + 0)
47#define CP_FLAG_UNK20_CLEAR 0
48#define CP_FLAG_UNK20_SET 1
49#define CP_FLAG_STATUS ((2 * 32) + 0)
50#define CP_FLAG_STATUS_BUSY 0
51#define CP_FLAG_STATUS_IDLE 1
52#define CP_FLAG_AUTO_SAVE ((2 * 32) + 4)
53#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0
54#define CP_FLAG_AUTO_SAVE_PENDING 1
55#define CP_FLAG_AUTO_LOAD ((2 * 32) + 5)
56#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0
57#define CP_FLAG_AUTO_LOAD_PENDING 1
58#define CP_FLAG_NEWCTX ((2 * 32) + 10)
59#define CP_FLAG_NEWCTX_BUSY 0
60#define CP_FLAG_NEWCTX_DONE 1
61#define CP_FLAG_XFER ((2 * 32) + 11)
62#define CP_FLAG_XFER_IDLE 0
63#define CP_FLAG_XFER_BUSY 1
64#define CP_FLAG_ALWAYS ((2 * 32) + 13)
65#define CP_FLAG_ALWAYS_FALSE 0
66#define CP_FLAG_ALWAYS_TRUE 1
67#define CP_FLAG_INTR ((2 * 32) + 15)
68#define CP_FLAG_INTR_NOT_PENDING 0
69#define CP_FLAG_INTR_PENDING 1
70
71#define CP_CTX 0x00100000
72#define CP_CTX_COUNT 0x000f0000
73#define CP_CTX_COUNT_SHIFT 16
74#define CP_CTX_REG 0x00003fff
75#define CP_LOAD_SR 0x00200000
76#define CP_LOAD_SR_VALUE 0x000fffff
77#define CP_BRA 0x00400000
78#define CP_BRA_IP 0x0001ff00
79#define CP_BRA_IP_SHIFT 8
80#define CP_BRA_IF_CLEAR 0x00000080
81#define CP_BRA_FLAG 0x0000007f
82#define CP_WAIT 0x00500000
83#define CP_WAIT_SET 0x00000080
84#define CP_WAIT_FLAG 0x0000007f
85#define CP_SET 0x00700000
86#define CP_SET_1 0x00000080
87#define CP_SET_FLAG 0x0000007f
88#define CP_NEWCTX 0x00600004
89#define CP_NEXT_TO_SWAP 0x00600005
90#define CP_SET_CONTEXT_POINTER 0x00600006
91#define CP_SET_XFER_POINTER 0x00600007
92#define CP_ENABLE 0x00600009
93#define CP_END 0x0060000c
94#define CP_NEXT_TO_CURRENT 0x0060000d
95#define CP_DISABLE1 0x0090ffff
96#define CP_DISABLE2 0x0091ffff
97#define CP_XFER_1 0x008000ff
98#define CP_XFER_2 0x008800ff
99#define CP_SEEK_1 0x00c000ff
100#define CP_SEEK_2 0x00c800ff
101
102#include "drmP.h"
103#include "nouveau_drv.h"
104#include "nouveau_grctx.h"
105
106#define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf)
107#define IS_NVAAF(x) ((x) >= 0xaa && (x) <= 0xac)
108
109/*
110 * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's
111 * the GPU itself that does context-switching, but it needs a special
112 * microcode to do it. And it's the driver's task to supply this microcode,
113 * further known as ctxprog, as well as the initial context values, known
114 * as ctxvals.
115 *
116 * Without ctxprog, you cannot switch contexts. Not even in software, since
117 * the majority of context [xfer strands] isn't accessible directly. You're
118 * stuck with a single channel, and you also suffer all the problems resulting
119 * from missing ctxvals, since you cannot load them.
120 *
121 * Without ctxvals, you're stuck with PGRAPH's default context. It's enough to
122 * run 2d operations, but trying to utilise 3d or CUDA will just lock you up,
123 * since you don't have... some sort of needed setup.
124 *
125 * Nouveau will just disable acceleration if not given ctxprog + ctxvals, since
126 * it's too much hassle to handle no-ctxprog as a special case.
127 */
128
129/*
130 * How ctxprogs work.
131 *
132 * The ctxprog is written in its own kind of microcode, with very small and
133 * crappy set of available commands. You upload it to a small [512 insns]
134 * area of memory on PGRAPH, and it'll be run when PFIFO wants PGRAPH to
135 * switch channel. or when the driver explicitely requests it. Stuff visible
136 * to ctxprog consists of: PGRAPH MMIO registers, PGRAPH context strands,
137 * the per-channel context save area in VRAM [known as ctxvals or grctx],
138 * 4 flags registers, a scratch register, two grctx pointers, plus many
139 * random poorly-understood details.
140 *
141 * When ctxprog runs, it's supposed to check what operations are asked of it,
142 * save old context if requested, optionally reset PGRAPH and switch to the
143 * new channel, and load the new context. Context consists of three major
144 * parts: subset of MMIO registers and two "xfer areas".
145 */
146
147/* TODO:
148 * - document unimplemented bits compared to nvidia
149 * - NVAx: make a TP subroutine, use it.
150 * - use 0x4008fc instead of 0x1540?
151 */
152
153enum cp_label {
154 cp_check_load = 1,
155 cp_setup_auto_load,
156 cp_setup_load,
157 cp_setup_save,
158 cp_swap_state,
159 cp_prepare_exit,
160 cp_exit,
161};
162
163static void nv50_graph_construct_mmio(struct nouveau_grctx *ctx);
164static void nv50_graph_construct_xfer1(struct nouveau_grctx *ctx);
165static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx);
166
167/* Main function: construct the ctxprog skeleton, call the other functions. */
168
169int
170nv50_grctx_init(struct nouveau_grctx *ctx)
171{
172 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
173
174 switch (dev_priv->chipset) {
175 case 0x50:
176 case 0x84:
177 case 0x86:
178 case 0x92:
179 case 0x94:
180 case 0x96:
181 case 0x98:
182 case 0xa0:
183 case 0xa3:
184 case 0xa5:
185 case 0xa8:
186 case 0xaa:
187 case 0xac:
188 case 0xaf:
189 break;
190 default:
191 NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for "
192 "your NV%x card.\n", dev_priv->chipset);
193 NV_ERROR(ctx->dev, "Disabling acceleration. Please contact "
194 "the devs.\n");
195 return -ENOSYS;
196 }
197 /* decide whether we're loading/unloading the context */
198 cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
199 cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
200
201 cp_name(ctx, cp_check_load);
202 cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);
203 cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);
204 cp_bra (ctx, ALWAYS, TRUE, cp_exit);
205
206 /* setup for context load */
207 cp_name(ctx, cp_setup_auto_load);
208 cp_out (ctx, CP_DISABLE1);
209 cp_out (ctx, CP_DISABLE2);
210 cp_out (ctx, CP_ENABLE);
211 cp_out (ctx, CP_NEXT_TO_SWAP);
212 cp_set (ctx, UNK01, SET);
213 cp_name(ctx, cp_setup_load);
214 cp_out (ctx, CP_NEWCTX);
215 cp_wait(ctx, NEWCTX, BUSY);
216 cp_set (ctx, UNK1D, CLEAR);
217 cp_set (ctx, SWAP_DIRECTION, LOAD);
218 cp_bra (ctx, UNK0B, SET, cp_prepare_exit);
219 cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);
220
221 /* setup for context save */
222 cp_name(ctx, cp_setup_save);
223 cp_set (ctx, UNK1D, SET);
224 cp_wait(ctx, STATUS, BUSY);
225 cp_wait(ctx, INTR, PENDING);
226 cp_bra (ctx, STATUS, BUSY, cp_setup_save);
227 cp_set (ctx, UNK01, SET);
228 cp_set (ctx, SWAP_DIRECTION, SAVE);
229
230 /* general PGRAPH state */
231 cp_name(ctx, cp_swap_state);
232 cp_set (ctx, UNK03, SET);
233 cp_pos (ctx, 0x00004/4);
234 cp_ctx (ctx, 0x400828, 1); /* needed. otherwise, flickering happens. */
235 cp_pos (ctx, 0x00100/4);
236 nv50_graph_construct_mmio(ctx);
237 nv50_graph_construct_xfer1(ctx);
238 nv50_graph_construct_xfer2(ctx);
239
240 cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);
241
242 cp_set (ctx, UNK20, SET);
243 cp_set (ctx, SWAP_DIRECTION, SAVE); /* no idea why this is needed, but fixes at least one lockup. */
244 cp_lsr (ctx, ctx->ctxvals_base);
245 cp_out (ctx, CP_SET_XFER_POINTER);
246 cp_lsr (ctx, 4);
247 cp_out (ctx, CP_SEEK_1);
248 cp_out (ctx, CP_XFER_1);
249 cp_wait(ctx, XFER, BUSY);
250
251 /* pre-exit state updates */
252 cp_name(ctx, cp_prepare_exit);
253 cp_set (ctx, UNK01, CLEAR);
254 cp_set (ctx, UNK03, CLEAR);
255 cp_set (ctx, UNK1D, CLEAR);
256
257 cp_bra (ctx, USER_SAVE, PENDING, cp_exit);
258 cp_out (ctx, CP_NEXT_TO_CURRENT);
259
260 cp_name(ctx, cp_exit);
261 cp_set (ctx, USER_SAVE, NOT_PENDING);
262 cp_set (ctx, USER_LOAD, NOT_PENDING);
263 cp_out (ctx, CP_END);
264 ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */
265
266 return 0;
267}
268
269/*
270 * Constructs MMIO part of ctxprog and ctxvals. Just a matter of knowing which
271 * registers to save/restore and the default values for them.
272 */
273
274static void
275nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx);
276
277static void
278nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
279{
280 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
281 int i, j;
282 int offset, base;
283 uint32_t units = nv_rd32 (ctx->dev, 0x1540);
284
285 /* 0800: DISPATCH */
286 cp_ctx(ctx, 0x400808, 7);
287 gr_def(ctx, 0x400814, 0x00000030);
288 cp_ctx(ctx, 0x400834, 0x32);
289 if (dev_priv->chipset == 0x50) {
290 gr_def(ctx, 0x400834, 0xff400040);
291 gr_def(ctx, 0x400838, 0xfff00080);
292 gr_def(ctx, 0x40083c, 0xfff70090);
293 gr_def(ctx, 0x400840, 0xffe806a8);
294 }
295 gr_def(ctx, 0x400844, 0x00000002);
296 if (IS_NVA3F(dev_priv->chipset))
297 gr_def(ctx, 0x400894, 0x00001000);
298 gr_def(ctx, 0x4008e8, 0x00000003);
299 gr_def(ctx, 0x4008ec, 0x00001000);
300 if (dev_priv->chipset == 0x50)
301 cp_ctx(ctx, 0x400908, 0xb);
302 else if (dev_priv->chipset < 0xa0)
303 cp_ctx(ctx, 0x400908, 0xc);
304 else
305 cp_ctx(ctx, 0x400908, 0xe);
306
307 if (dev_priv->chipset >= 0xa0)
308 cp_ctx(ctx, 0x400b00, 0x1);
309 if (IS_NVA3F(dev_priv->chipset)) {
310 cp_ctx(ctx, 0x400b10, 0x1);
311 gr_def(ctx, 0x400b10, 0x0001629d);
312 cp_ctx(ctx, 0x400b20, 0x1);
313 gr_def(ctx, 0x400b20, 0x0001629d);
314 }
315
316 nv50_graph_construct_mmio_ddata(ctx);
317
318 /* 0C00: VFETCH */
319 cp_ctx(ctx, 0x400c08, 0x2);
320 gr_def(ctx, 0x400c08, 0x0000fe0c);
321
322 /* 1000 */
323 if (dev_priv->chipset < 0xa0) {
324 cp_ctx(ctx, 0x401008, 0x4);
325 gr_def(ctx, 0x401014, 0x00001000);
326 } else if (!IS_NVA3F(dev_priv->chipset)) {
327 cp_ctx(ctx, 0x401008, 0x5);
328 gr_def(ctx, 0x401018, 0x00001000);
329 } else {
330 cp_ctx(ctx, 0x401008, 0x5);
331 gr_def(ctx, 0x401018, 0x00004000);
332 }
333
334 /* 1400 */
335 cp_ctx(ctx, 0x401400, 0x8);
336 cp_ctx(ctx, 0x401424, 0x3);
337 if (dev_priv->chipset == 0x50)
338 gr_def(ctx, 0x40142c, 0x0001fd87);
339 else
340 gr_def(ctx, 0x40142c, 0x00000187);
341 cp_ctx(ctx, 0x401540, 0x5);
342 gr_def(ctx, 0x401550, 0x00001018);
343
344 /* 1800: STREAMOUT */
345 cp_ctx(ctx, 0x401814, 0x1);
346 gr_def(ctx, 0x401814, 0x000000ff);
347 if (dev_priv->chipset == 0x50) {
348 cp_ctx(ctx, 0x40181c, 0xe);
349 gr_def(ctx, 0x401850, 0x00000004);
350 } else if (dev_priv->chipset < 0xa0) {
351 cp_ctx(ctx, 0x40181c, 0xf);
352 gr_def(ctx, 0x401854, 0x00000004);
353 } else {
354 cp_ctx(ctx, 0x40181c, 0x13);
355 gr_def(ctx, 0x401864, 0x00000004);
356 }
357
358 /* 1C00 */
359 cp_ctx(ctx, 0x401c00, 0x1);
360 switch (dev_priv->chipset) {
361 case 0x50:
362 gr_def(ctx, 0x401c00, 0x0001005f);
363 break;
364 case 0x84:
365 case 0x86:
366 case 0x94:
367 gr_def(ctx, 0x401c00, 0x044d00df);
368 break;
369 case 0x92:
370 case 0x96:
371 case 0x98:
372 case 0xa0:
373 case 0xaa:
374 case 0xac:
375 gr_def(ctx, 0x401c00, 0x042500df);
376 break;
377 case 0xa3:
378 case 0xa5:
379 case 0xa8:
380 case 0xaf:
381 gr_def(ctx, 0x401c00, 0x142500df);
382 break;
383 }
384
385 /* 2000 */
386
387 /* 2400 */
388 cp_ctx(ctx, 0x402400, 0x1);
389 if (dev_priv->chipset == 0x50)
390 cp_ctx(ctx, 0x402408, 0x1);
391 else
392 cp_ctx(ctx, 0x402408, 0x2);
393 gr_def(ctx, 0x402408, 0x00000600);
394
395 /* 2800: CSCHED */
396 cp_ctx(ctx, 0x402800, 0x1);
397 if (dev_priv->chipset == 0x50)
398 gr_def(ctx, 0x402800, 0x00000006);
399
400 /* 2C00: ZCULL */
401 cp_ctx(ctx, 0x402c08, 0x6);
402 if (dev_priv->chipset != 0x50)
403 gr_def(ctx, 0x402c14, 0x01000000);
404 gr_def(ctx, 0x402c18, 0x000000ff);
405 if (dev_priv->chipset == 0x50)
406 cp_ctx(ctx, 0x402ca0, 0x1);
407 else
408 cp_ctx(ctx, 0x402ca0, 0x2);
409 if (dev_priv->chipset < 0xa0)
410 gr_def(ctx, 0x402ca0, 0x00000400);
411 else if (!IS_NVA3F(dev_priv->chipset))
412 gr_def(ctx, 0x402ca0, 0x00000800);
413 else
414 gr_def(ctx, 0x402ca0, 0x00000400);
415 cp_ctx(ctx, 0x402cac, 0x4);
416
417 /* 3000: ENG2D */
418 cp_ctx(ctx, 0x403004, 0x1);
419 gr_def(ctx, 0x403004, 0x00000001);
420
421 /* 3400 */
422 if (dev_priv->chipset >= 0xa0) {
423 cp_ctx(ctx, 0x403404, 0x1);
424 gr_def(ctx, 0x403404, 0x00000001);
425 }
426
427 /* 5000: CCACHE */
428 cp_ctx(ctx, 0x405000, 0x1);
429 switch (dev_priv->chipset) {
430 case 0x50:
431 gr_def(ctx, 0x405000, 0x00300080);
432 break;
433 case 0x84:
434 case 0xa0:
435 case 0xa3:
436 case 0xa5:
437 case 0xa8:
438 case 0xaa:
439 case 0xac:
440 case 0xaf:
441 gr_def(ctx, 0x405000, 0x000e0080);
442 break;
443 case 0x86:
444 case 0x92:
445 case 0x94:
446 case 0x96:
447 case 0x98:
448 gr_def(ctx, 0x405000, 0x00000080);
449 break;
450 }
451 cp_ctx(ctx, 0x405014, 0x1);
452 gr_def(ctx, 0x405014, 0x00000004);
453 cp_ctx(ctx, 0x40501c, 0x1);
454 cp_ctx(ctx, 0x405024, 0x1);
455 cp_ctx(ctx, 0x40502c, 0x1);
456
457 /* 6000? */
458 if (dev_priv->chipset == 0x50)
459 cp_ctx(ctx, 0x4063e0, 0x1);
460
461 /* 6800: M2MF */
462 if (dev_priv->chipset < 0x90) {
463 cp_ctx(ctx, 0x406814, 0x2b);
464 gr_def(ctx, 0x406818, 0x00000f80);
465 gr_def(ctx, 0x406860, 0x007f0080);
466 gr_def(ctx, 0x40689c, 0x007f0080);
467 } else {
468 cp_ctx(ctx, 0x406814, 0x4);
469 if (dev_priv->chipset == 0x98)
470 gr_def(ctx, 0x406818, 0x00000f80);
471 else
472 gr_def(ctx, 0x406818, 0x00001f80);
473 if (IS_NVA3F(dev_priv->chipset))
474 gr_def(ctx, 0x40681c, 0x00000030);
475 cp_ctx(ctx, 0x406830, 0x3);
476 }
477
478 /* 7000: per-ROP group state */
479 for (i = 0; i < 8; i++) {
480 if (units & (1<<(i+16))) {
481 cp_ctx(ctx, 0x407000 + (i<<8), 3);
482 if (dev_priv->chipset == 0x50)
483 gr_def(ctx, 0x407000 + (i<<8), 0x1b74f820);
484 else if (dev_priv->chipset != 0xa5)
485 gr_def(ctx, 0x407000 + (i<<8), 0x3b74f821);
486 else
487 gr_def(ctx, 0x407000 + (i<<8), 0x7b74f821);
488 gr_def(ctx, 0x407004 + (i<<8), 0x89058001);
489
490 if (dev_priv->chipset == 0x50) {
491 cp_ctx(ctx, 0x407010 + (i<<8), 1);
492 } else if (dev_priv->chipset < 0xa0) {
493 cp_ctx(ctx, 0x407010 + (i<<8), 2);
494 gr_def(ctx, 0x407010 + (i<<8), 0x00001000);
495 gr_def(ctx, 0x407014 + (i<<8), 0x0000001f);
496 } else {
497 cp_ctx(ctx, 0x407010 + (i<<8), 3);
498 gr_def(ctx, 0x407010 + (i<<8), 0x00001000);
499 if (dev_priv->chipset != 0xa5)
500 gr_def(ctx, 0x407014 + (i<<8), 0x000000ff);
501 else
502 gr_def(ctx, 0x407014 + (i<<8), 0x000001ff);
503 }
504
505 cp_ctx(ctx, 0x407080 + (i<<8), 4);
506 if (dev_priv->chipset != 0xa5)
507 gr_def(ctx, 0x407080 + (i<<8), 0x027c10fa);
508 else
509 gr_def(ctx, 0x407080 + (i<<8), 0x827c10fa);
510 if (dev_priv->chipset == 0x50)
511 gr_def(ctx, 0x407084 + (i<<8), 0x000000c0);
512 else
513 gr_def(ctx, 0x407084 + (i<<8), 0x400000c0);
514 gr_def(ctx, 0x407088 + (i<<8), 0xb7892080);
515
516 if (dev_priv->chipset < 0xa0)
517 cp_ctx(ctx, 0x407094 + (i<<8), 1);
518 else if (!IS_NVA3F(dev_priv->chipset))
519 cp_ctx(ctx, 0x407094 + (i<<8), 3);
520 else {
521 cp_ctx(ctx, 0x407094 + (i<<8), 4);
522 gr_def(ctx, 0x4070a0 + (i<<8), 1);
523 }
524 }
525 }
526
527 cp_ctx(ctx, 0x407c00, 0x3);
528 if (dev_priv->chipset < 0x90)
529 gr_def(ctx, 0x407c00, 0x00010040);
530 else if (dev_priv->chipset < 0xa0)
531 gr_def(ctx, 0x407c00, 0x00390040);
532 else
533 gr_def(ctx, 0x407c00, 0x003d0040);
534 gr_def(ctx, 0x407c08, 0x00000022);
535 if (dev_priv->chipset >= 0xa0) {
536 cp_ctx(ctx, 0x407c10, 0x3);
537 cp_ctx(ctx, 0x407c20, 0x1);
538 cp_ctx(ctx, 0x407c2c, 0x1);
539 }
540
541 if (dev_priv->chipset < 0xa0) {
542 cp_ctx(ctx, 0x407d00, 0x9);
543 } else {
544 cp_ctx(ctx, 0x407d00, 0x15);
545 }
546 if (dev_priv->chipset == 0x98)
547 gr_def(ctx, 0x407d08, 0x00380040);
548 else {
549 if (dev_priv->chipset < 0x90)
550 gr_def(ctx, 0x407d08, 0x00010040);
551 else if (dev_priv->chipset < 0xa0)
552 gr_def(ctx, 0x407d08, 0x00390040);
553 else
554 gr_def(ctx, 0x407d08, 0x003d0040);
555 gr_def(ctx, 0x407d0c, 0x00000022);
556 }
557
558 /* 8000+: per-TP state */
559 for (i = 0; i < 10; i++) {
560 if (units & (1<<i)) {
561 if (dev_priv->chipset < 0xa0)
562 base = 0x408000 + (i<<12);
563 else
564 base = 0x408000 + (i<<11);
565 if (dev_priv->chipset < 0xa0)
566 offset = base + 0xc00;
567 else
568 offset = base + 0x80;
569 cp_ctx(ctx, offset + 0x00, 1);
570 gr_def(ctx, offset + 0x00, 0x0000ff0a);
571 cp_ctx(ctx, offset + 0x08, 1);
572
573 /* per-MP state */
574 for (j = 0; j < (dev_priv->chipset < 0xa0 ? 2 : 4); j++) {
575 if (!(units & (1 << (j+24)))) continue;
576 if (dev_priv->chipset < 0xa0)
577 offset = base + 0x200 + (j<<7);
578 else
579 offset = base + 0x100 + (j<<7);
580 cp_ctx(ctx, offset, 0x20);
581 gr_def(ctx, offset + 0x00, 0x01800000);
582 gr_def(ctx, offset + 0x04, 0x00160000);
583 gr_def(ctx, offset + 0x08, 0x01800000);
584 gr_def(ctx, offset + 0x18, 0x0003ffff);
585 switch (dev_priv->chipset) {
586 case 0x50:
587 gr_def(ctx, offset + 0x1c, 0x00080000);
588 break;
589 case 0x84:
590 gr_def(ctx, offset + 0x1c, 0x00880000);
591 break;
592 case 0x86:
593 gr_def(ctx, offset + 0x1c, 0x008c0000);
594 break;
595 case 0x92:
596 case 0x96:
597 case 0x98:
598 gr_def(ctx, offset + 0x1c, 0x118c0000);
599 break;
600 case 0x94:
601 gr_def(ctx, offset + 0x1c, 0x10880000);
602 break;
603 case 0xa0:
604 case 0xa5:
605 gr_def(ctx, offset + 0x1c, 0x310c0000);
606 break;
607 case 0xa3:
608 case 0xa8:
609 case 0xaa:
610 case 0xac:
611 case 0xaf:
612 gr_def(ctx, offset + 0x1c, 0x300c0000);
613 break;
614 }
615 gr_def(ctx, offset + 0x40, 0x00010401);
616 if (dev_priv->chipset == 0x50)
617 gr_def(ctx, offset + 0x48, 0x00000040);
618 else
619 gr_def(ctx, offset + 0x48, 0x00000078);
620 gr_def(ctx, offset + 0x50, 0x000000bf);
621 gr_def(ctx, offset + 0x58, 0x00001210);
622 if (dev_priv->chipset == 0x50)
623 gr_def(ctx, offset + 0x5c, 0x00000080);
624 else
625 gr_def(ctx, offset + 0x5c, 0x08000080);
626 if (dev_priv->chipset >= 0xa0)
627 gr_def(ctx, offset + 0x68, 0x0000003e);
628 }
629
630 if (dev_priv->chipset < 0xa0)
631 cp_ctx(ctx, base + 0x300, 0x4);
632 else
633 cp_ctx(ctx, base + 0x300, 0x5);
634 if (dev_priv->chipset == 0x50)
635 gr_def(ctx, base + 0x304, 0x00007070);
636 else if (dev_priv->chipset < 0xa0)
637 gr_def(ctx, base + 0x304, 0x00027070);
638 else if (!IS_NVA3F(dev_priv->chipset))
639 gr_def(ctx, base + 0x304, 0x01127070);
640 else
641 gr_def(ctx, base + 0x304, 0x05127070);
642
643 if (dev_priv->chipset < 0xa0)
644 cp_ctx(ctx, base + 0x318, 1);
645 else
646 cp_ctx(ctx, base + 0x320, 1);
647 if (dev_priv->chipset == 0x50)
648 gr_def(ctx, base + 0x318, 0x0003ffff);
649 else if (dev_priv->chipset < 0xa0)
650 gr_def(ctx, base + 0x318, 0x03ffffff);
651 else
652 gr_def(ctx, base + 0x320, 0x07ffffff);
653
654 if (dev_priv->chipset < 0xa0)
655 cp_ctx(ctx, base + 0x324, 5);
656 else
657 cp_ctx(ctx, base + 0x328, 4);
658
659 if (dev_priv->chipset < 0xa0) {
660 cp_ctx(ctx, base + 0x340, 9);
661 offset = base + 0x340;
662 } else if (!IS_NVA3F(dev_priv->chipset)) {
663 cp_ctx(ctx, base + 0x33c, 0xb);
664 offset = base + 0x344;
665 } else {
666 cp_ctx(ctx, base + 0x33c, 0xd);
667 offset = base + 0x344;
668 }
669 gr_def(ctx, offset + 0x0, 0x00120407);
670 gr_def(ctx, offset + 0x4, 0x05091507);
671 if (dev_priv->chipset == 0x84)
672 gr_def(ctx, offset + 0x8, 0x05100202);
673 else
674 gr_def(ctx, offset + 0x8, 0x05010202);
675 gr_def(ctx, offset + 0xc, 0x00030201);
676 if (dev_priv->chipset == 0xa3)
677 cp_ctx(ctx, base + 0x36c, 1);
678
679 cp_ctx(ctx, base + 0x400, 2);
680 gr_def(ctx, base + 0x404, 0x00000040);
681 cp_ctx(ctx, base + 0x40c, 2);
682 gr_def(ctx, base + 0x40c, 0x0d0c0b0a);
683 gr_def(ctx, base + 0x410, 0x00141210);
684
685 if (dev_priv->chipset < 0xa0)
686 offset = base + 0x800;
687 else
688 offset = base + 0x500;
689 cp_ctx(ctx, offset, 6);
690 gr_def(ctx, offset + 0x0, 0x000001f0);
691 gr_def(ctx, offset + 0x4, 0x00000001);
692 gr_def(ctx, offset + 0x8, 0x00000003);
693 if (dev_priv->chipset == 0x50 || IS_NVAAF(dev_priv->chipset))
694 gr_def(ctx, offset + 0xc, 0x00008000);
695 gr_def(ctx, offset + 0x14, 0x00039e00);
696 cp_ctx(ctx, offset + 0x1c, 2);
697 if (dev_priv->chipset == 0x50)
698 gr_def(ctx, offset + 0x1c, 0x00000040);
699 else
700 gr_def(ctx, offset + 0x1c, 0x00000100);
701 gr_def(ctx, offset + 0x20, 0x00003800);
702
703 if (dev_priv->chipset >= 0xa0) {
704 cp_ctx(ctx, base + 0x54c, 2);
705 if (!IS_NVA3F(dev_priv->chipset))
706 gr_def(ctx, base + 0x54c, 0x003fe006);
707 else
708 gr_def(ctx, base + 0x54c, 0x003fe007);
709 gr_def(ctx, base + 0x550, 0x003fe000);
710 }
711
712 if (dev_priv->chipset < 0xa0)
713 offset = base + 0xa00;
714 else
715 offset = base + 0x680;
716 cp_ctx(ctx, offset, 1);
717 gr_def(ctx, offset, 0x00404040);
718
719 if (dev_priv->chipset < 0xa0)
720 offset = base + 0xe00;
721 else
722 offset = base + 0x700;
723 cp_ctx(ctx, offset, 2);
724 if (dev_priv->chipset < 0xa0)
725 gr_def(ctx, offset, 0x0077f005);
726 else if (dev_priv->chipset == 0xa5)
727 gr_def(ctx, offset, 0x6cf7f007);
728 else if (dev_priv->chipset == 0xa8)
729 gr_def(ctx, offset, 0x6cfff007);
730 else if (dev_priv->chipset == 0xac)
731 gr_def(ctx, offset, 0x0cfff007);
732 else
733 gr_def(ctx, offset, 0x0cf7f007);
734 if (dev_priv->chipset == 0x50)
735 gr_def(ctx, offset + 0x4, 0x00007fff);
736 else if (dev_priv->chipset < 0xa0)
737 gr_def(ctx, offset + 0x4, 0x003f7fff);
738 else
739 gr_def(ctx, offset + 0x4, 0x02bf7fff);
740 cp_ctx(ctx, offset + 0x2c, 1);
741 if (dev_priv->chipset == 0x50) {
742 cp_ctx(ctx, offset + 0x50, 9);
743 gr_def(ctx, offset + 0x54, 0x000003ff);
744 gr_def(ctx, offset + 0x58, 0x00000003);
745 gr_def(ctx, offset + 0x5c, 0x00000003);
746 gr_def(ctx, offset + 0x60, 0x000001ff);
747 gr_def(ctx, offset + 0x64, 0x0000001f);
748 gr_def(ctx, offset + 0x68, 0x0000000f);
749 gr_def(ctx, offset + 0x6c, 0x0000000f);
750 } else if (dev_priv->chipset < 0xa0) {
751 cp_ctx(ctx, offset + 0x50, 1);
752 cp_ctx(ctx, offset + 0x70, 1);
753 } else {
754 cp_ctx(ctx, offset + 0x50, 1);
755 cp_ctx(ctx, offset + 0x60, 5);
756 }
757 }
758 }
759}
760
761static void
762dd_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
770static void
771nv50_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
1091/*
1092 * xfer areas. These are a pain.
1093 *
1094 * There are 2 xfer areas: the first one is big and contains all sorts of
1095 * stuff, the second is small and contains some per-TP context.
1096 *
1097 * Each area is split into 8 "strands". The areas, when saved to grctx,
1098 * are made of 8-word blocks. Each block contains a single word from
1099 * each strand. The strands are independent of each other, their
1100 * addresses are unrelated to each other, and data in them is closely
1101 * packed together. The strand layout varies a bit between cards: here
1102 * and there, a single word is thrown out in the middle and the whole
1103 * strand is offset by a bit from corresponding one on another chipset.
1104 * For this reason, addresses of stuff in strands are almost useless.
1105 * Knowing sequence of stuff and size of gaps between them is much more
1106 * useful, and that's how we build the strands in our generator.
1107 *
1108 * NVA0 takes this mess to a whole new level by cutting the old strands
1109 * into a few dozen pieces [known as genes], rearranging them randomly,
1110 * and putting them back together to make new strands. Hopefully these
1111 * genes correspond more or less directly to the same PGRAPH subunits
1112 * as in 400040 register.
1113 *
1114 * The most common value in default context is 0, and when the genes
1115 * are separated by 0's, gene bounduaries are quite speculative...
1116 * some of them can be clearly deduced, others can be guessed, and yet
1117 * others won't be resolved without figuring out the real meaning of
1118 * given ctxval. For the same reason, ending point of each strand
1119 * is unknown. Except for strand 0, which is the longest strand and
1120 * its end corresponds to end of the whole xfer.
1121 *
1122 * An unsolved mystery is the seek instruction: it takes an argument
1123 * in bits 8-18, and that argument is clearly the place in strands to
1124 * seek to... but the offsets don't seem to correspond to offsets as
1125 * seen in grctx. Perhaps there's another, real, not randomly-changing
1126 * addressing in strands, and the xfer insn just happens to skip over
1127 * the unused bits? NV10-NV30 PIPE comes to mind...
1128 *
1129 * As far as I know, there's no way to access the xfer areas directly
1130 * without the help of ctxprog.
1131 */
1132
1133static void
1134xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) {
1135 int i;
1136 if (val && ctx->mode == NOUVEAU_GRCTX_VALS)
1137 for (i = 0; i < num; i++)
1138 nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val);
1139 ctx->ctxvals_pos += num << 3;
1140}
1141
1142/* Gene declarations... */
1143
1144static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx);
1145static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx);
1146static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx);
1147static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx);
1148static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx);
1149static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx);
1150static void nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx);
1151static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx);
1152static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx);
1153static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx);
1154static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx);
1155static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx);
1156static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx);
1157static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx);
1158static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx);
1159static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx);
1160static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx);
1161static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx);
1162
1163static void
1164nv50_graph_construct_xfer1(struct nouveau_grctx *ctx)
1165{
1166 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1167 int i;
1168 int offset;
1169 int size = 0;
1170 uint32_t units = nv_rd32 (ctx->dev, 0x1540);
1171
1172 offset = (ctx->ctxvals_pos+0x3f)&~0x3f;
1173 ctx->ctxvals_base = offset;
1174
1175 if (dev_priv->chipset < 0xa0) {
1176 /* Strand 0 */
1177 ctx->ctxvals_pos = offset;
1178 nv50_graph_construct_gene_dispatch(ctx);
1179 nv50_graph_construct_gene_m2mf(ctx);
1180 nv50_graph_construct_gene_unk24xx(ctx);
1181 nv50_graph_construct_gene_clipid(ctx);
1182 nv50_graph_construct_gene_zcull(ctx);
1183 if ((ctx->ctxvals_pos-offset)/8 > size)
1184 size = (ctx->ctxvals_pos-offset)/8;
1185
1186 /* Strand 1 */
1187 ctx->ctxvals_pos = offset + 0x1;
1188 nv50_graph_construct_gene_vfetch(ctx);
1189 nv50_graph_construct_gene_eng2d(ctx);
1190 nv50_graph_construct_gene_csched(ctx);
1191 nv50_graph_construct_gene_ropm1(ctx);
1192 nv50_graph_construct_gene_ropm2(ctx);
1193 if ((ctx->ctxvals_pos-offset)/8 > size)
1194 size = (ctx->ctxvals_pos-offset)/8;
1195
1196 /* Strand 2 */
1197 ctx->ctxvals_pos = offset + 0x2;
1198 nv50_graph_construct_gene_ccache(ctx);
1199 nv50_graph_construct_gene_unk1cxx(ctx);
1200 nv50_graph_construct_gene_strmout(ctx);
1201 nv50_graph_construct_gene_unk14xx(ctx);
1202 nv50_graph_construct_gene_unk10xx(ctx);
1203 nv50_graph_construct_gene_unk34xx(ctx);
1204 if ((ctx->ctxvals_pos-offset)/8 > size)
1205 size = (ctx->ctxvals_pos-offset)/8;
1206
1207 /* Strand 3: per-ROP group state */
1208 ctx->ctxvals_pos = offset + 3;
1209 for (i = 0; i < 6; i++)
1210 if (units & (1 << (i + 16)))
1211 nv50_graph_construct_gene_ropc(ctx);
1212 if ((ctx->ctxvals_pos-offset)/8 > size)
1213 size = (ctx->ctxvals_pos-offset)/8;
1214
1215 /* Strands 4-7: per-TP state */
1216 for (i = 0; i < 4; i++) {
1217 ctx->ctxvals_pos = offset + 4 + i;
1218 if (units & (1 << (2 * i)))
1219 nv50_graph_construct_xfer_tp(ctx);
1220 if (units & (1 << (2 * i + 1)))
1221 nv50_graph_construct_xfer_tp(ctx);
1222 if ((ctx->ctxvals_pos-offset)/8 > size)
1223 size = (ctx->ctxvals_pos-offset)/8;
1224 }
1225 } else {
1226 /* Strand 0 */
1227 ctx->ctxvals_pos = offset;
1228 nv50_graph_construct_gene_dispatch(ctx);
1229 nv50_graph_construct_gene_m2mf(ctx);
1230 nv50_graph_construct_gene_unk34xx(ctx);
1231 nv50_graph_construct_gene_csched(ctx);
1232 nv50_graph_construct_gene_unk1cxx(ctx);
1233 nv50_graph_construct_gene_strmout(ctx);
1234 if ((ctx->ctxvals_pos-offset)/8 > size)
1235 size = (ctx->ctxvals_pos-offset)/8;
1236
1237 /* Strand 1 */
1238 ctx->ctxvals_pos = offset + 1;
1239 nv50_graph_construct_gene_unk10xx(ctx);
1240 if ((ctx->ctxvals_pos-offset)/8 > size)
1241 size = (ctx->ctxvals_pos-offset)/8;
1242
1243 /* Strand 2 */
1244 ctx->ctxvals_pos = offset + 2;
1245 if (dev_priv->chipset == 0xa0)
1246 nv50_graph_construct_gene_unk14xx(ctx);
1247 nv50_graph_construct_gene_unk24xx(ctx);
1248 if ((ctx->ctxvals_pos-offset)/8 > size)
1249 size = (ctx->ctxvals_pos-offset)/8;
1250
1251 /* Strand 3 */
1252 ctx->ctxvals_pos = offset + 3;
1253 nv50_graph_construct_gene_vfetch(ctx);
1254 if ((ctx->ctxvals_pos-offset)/8 > size)
1255 size = (ctx->ctxvals_pos-offset)/8;
1256
1257 /* Strand 4 */
1258 ctx->ctxvals_pos = offset + 4;
1259 nv50_graph_construct_gene_ccache(ctx);
1260 if ((ctx->ctxvals_pos-offset)/8 > size)
1261 size = (ctx->ctxvals_pos-offset)/8;
1262
1263 /* Strand 5 */
1264 ctx->ctxvals_pos = offset + 5;
1265 nv50_graph_construct_gene_ropm2(ctx);
1266 nv50_graph_construct_gene_ropm1(ctx);
1267 /* per-ROP context */
1268 for (i = 0; i < 8; i++)
1269 if (units & (1<<(i+16)))
1270 nv50_graph_construct_gene_ropc(ctx);
1271 if ((ctx->ctxvals_pos-offset)/8 > size)
1272 size = (ctx->ctxvals_pos-offset)/8;
1273
1274 /* Strand 6 */
1275 ctx->ctxvals_pos = offset + 6;
1276 nv50_graph_construct_gene_zcull(ctx);
1277 nv50_graph_construct_gene_clipid(ctx);
1278 nv50_graph_construct_gene_eng2d(ctx);
1279 if (units & (1 << 0))
1280 nv50_graph_construct_xfer_tp(ctx);
1281 if (units & (1 << 1))
1282 nv50_graph_construct_xfer_tp(ctx);
1283 if (units & (1 << 2))
1284 nv50_graph_construct_xfer_tp(ctx);
1285 if (units & (1 << 3))
1286 nv50_graph_construct_xfer_tp(ctx);
1287 if ((ctx->ctxvals_pos-offset)/8 > size)
1288 size = (ctx->ctxvals_pos-offset)/8;
1289
1290 /* Strand 7 */
1291 ctx->ctxvals_pos = offset + 7;
1292 if (dev_priv->chipset == 0xa0) {
1293 if (units & (1 << 4))
1294 nv50_graph_construct_xfer_tp(ctx);
1295 if (units & (1 << 5))
1296 nv50_graph_construct_xfer_tp(ctx);
1297 if (units & (1 << 6))
1298 nv50_graph_construct_xfer_tp(ctx);
1299 if (units & (1 << 7))
1300 nv50_graph_construct_xfer_tp(ctx);
1301 if (units & (1 << 8))
1302 nv50_graph_construct_xfer_tp(ctx);
1303 if (units & (1 << 9))
1304 nv50_graph_construct_xfer_tp(ctx);
1305 } else {
1306 nv50_graph_construct_gene_unk14xx(ctx);
1307 }
1308 if ((ctx->ctxvals_pos-offset)/8 > size)
1309 size = (ctx->ctxvals_pos-offset)/8;
1310 }
1311
1312 ctx->ctxvals_pos = offset + size * 8;
1313 ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f;
1314 cp_lsr (ctx, offset);
1315 cp_out (ctx, CP_SET_XFER_POINTER);
1316 cp_lsr (ctx, size);
1317 cp_out (ctx, CP_SEEK_1);
1318 cp_out (ctx, CP_XFER_1);
1319 cp_wait(ctx, XFER, BUSY);
1320}
1321
1322/*
1323 * non-trivial demagiced parts of ctx init go here
1324 */
1325
1326static void
1327nv50_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
1382static void
1383nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx)
1384{
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 */
1391 xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */
1392 xf_emit (ctx, 1, 0); /* DMA_BUFFER_IN instance >> 4 */
1393 xf_emit (ctx, 1, 0); /* DMA_BUFFER_OUT instance >> 4 */
1394 xf_emit (ctx, 1, 0); /* OFFSET_IN */
1395 xf_emit (ctx, 1, 0); /* OFFSET_OUT */
1396 xf_emit (ctx, 1, 0); /* PITCH_IN */
1397 xf_emit (ctx, 1, 0); /* PITCH_OUT */
1398 xf_emit (ctx, 1, 0); /* LINE_LENGTH */
1399 xf_emit (ctx, 1, 0); /* LINE_COUNT */
1400 xf_emit (ctx, 1, 0x21); /* FORMAT: bits 0-4 INPUT_INC, bits 5-9 OUTPUT_INC */
1401 xf_emit (ctx, 1, 1); /* LINEAR_IN */
1402 xf_emit (ctx, 1, 0x2); /* TILING_MODE_IN: bits 0-2 y tiling, bits 3-5 z tiling */
1403 xf_emit (ctx, 1, 0x100); /* TILING_PITCH_IN */
1404 xf_emit (ctx, 1, 0x100); /* TILING_HEIGHT_IN */
1405 xf_emit (ctx, 1, 1); /* TILING_DEPTH_IN */
1406 xf_emit (ctx, 1, 0); /* TILING_POSITION_IN_Z */
1407 xf_emit (ctx, 1, 0); /* TILING_POSITION_IN */
1408 xf_emit (ctx, 1, 1); /* LINEAR_OUT */
1409 xf_emit (ctx, 1, 0x2); /* TILING_MODE_OUT: bits 0-2 y tiling, bits 3-5 z tiling */
1410 xf_emit (ctx, 1, 0x100); /* TILING_PITCH_OUT */
1411 xf_emit (ctx, 1, 0x100); /* TILING_HEIGHT_OUT */
1412 xf_emit (ctx, 1, 1); /* TILING_DEPTH_OUT */
1413 xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT_Z */
1414 xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT */
1415 xf_emit (ctx, 1, 0); /* OFFSET_IN_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 */
1432}
1433
1434static void
1435nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx)
1436{
1437 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1438 xf_emit(ctx, 2, 0); /* RO */
1439 xf_emit(ctx, 0x800, 0); /* ffffffff */
1440 switch (dev_priv->chipset) {
1441 case 0x50:
1442 case 0x92:
1443 case 0xa0:
1444 xf_emit(ctx, 0x2b, 0);
1445 break;
1446 case 0x84:
1447 xf_emit(ctx, 0x29, 0);
1448 break;
1449 case 0x94:
1450 case 0x96:
1451 case 0xa3:
1452 xf_emit(ctx, 0x27, 0);
1453 break;
1454 case 0x86:
1455 case 0x98:
1456 case 0xa5:
1457 case 0xa8:
1458 case 0xaa:
1459 case 0xac:
1460 case 0xaf:
1461 xf_emit(ctx, 0x25, 0);
1462 break;
1463 }
1464 /* CB bindings, 0x80 of them. first word is address >> 8, second is
1465 * size >> 4 | valid << 24 */
1466 xf_emit(ctx, 0x100, 0); /* ffffffff CB_DEF */
1467 xf_emit(ctx, 1, 0); /* 0000007f CB_ADDR_BUFFER */
1468 xf_emit(ctx, 1, 0); /* 0 */
1469 xf_emit(ctx, 0x30, 0); /* ff SET_PROGRAM_CB */
1470 xf_emit(ctx, 1, 0); /* 3f last SET_PROGRAM_CB */
1471 xf_emit(ctx, 4, 0); /* RO */
1472 xf_emit(ctx, 0x100, 0); /* ffffffff */
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 */
1500}
1501
1502static void
1503nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx)
1504{
1505 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1506 int i;
1507 /* end of area 2 on pre-NVA0, area 1 on NVAx */
1508 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
1509 xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */
1510 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1511 xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */
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
1562static void
1563nv50_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 }
1585}
1586
1587static void
1588nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx)
1589{
1590 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1591 /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */
1592 if (dev_priv->chipset != 0x50) {
1593 xf_emit(ctx, 5, 0); /* ffffffff */
1594 xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */
1595 xf_emit(ctx, 1, 0); /* 00000001 */
1596 xf_emit(ctx, 1, 0); /* 000003ff */
1597 xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */
1598 xf_emit(ctx, 1, 0); /* 00000001 */
1599 xf_emit(ctx, 2, 4); /* 7f, ff */
1600 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
1601 }
1602 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
1603 xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */
1604 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
1605 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1606 xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */
1607 xf_emit(ctx, 1, 0); /* 000000ff VP_CLIP_DISTANCE_ENABLE */
1608 if (dev_priv->chipset != 0x50)
1609 xf_emit(ctx, 1, 0); /* 3ff */
1610 xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1940 */
1611 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */
1612 xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */
1613 xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */
1614 xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */
1615 if (dev_priv->chipset != 0x50)
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 */
1636 else
1637 xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */
1638 xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */
1639 xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */
1640 xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_SCALE: X0, Y0, Z0, X1, Y1, ... */
1641 xf_emit(ctx, 3, 0); /* f, 0, 0 */
1642 xf_emit(ctx, 3, 0); /* ffffffff last VIEWPORT_SCALE? */
1643 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
1644 xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */
1645 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */
1646 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */
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 */
1696}
1697
1698static void
1699nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx)
1700{
1701 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1702 /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */
1703 /* SEEK */
1704 xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */
1705 xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */
1706 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
1707 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
1708 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */
1709 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */
1710 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */
1711 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */
1712 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */
1713 xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */
1714 xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */
1715 xf_emit(ctx, 1, 0); /* ffff0ff3 */
1716 xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */
1717 xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */
1718 xf_emit(ctx, 1, 0); /* 00000001 */
1719 xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */
1720 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
1721 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
1722 xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */
1723 xf_emit(ctx, 1, 0); /* 0000ffff */
1724 xf_emit(ctx, 1, 0); /* 00000001 UNK0FB0 */
1725 xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */
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 */
1757}
1758
1759static void
1760nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx)
1761{
1762 /* middle of strand 0 on pre-NVA0 [after 24xx], middle of area 6 on NVAx */
1763 /* SEEK */
1764 xf_emit(ctx, 1, 0); /* 00000007 UNK0FB4 */
1765 /* SEEK */
1766 xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_HORIZ */
1767 xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_VERT */
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 */
1777}
1778
1779static void
1780nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx)
1781{
1782 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1783 int i;
1784 /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */
1785 /* SEEK */
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 } else {
1807 xf_emit(ctx, 0xc, 0); /* RO */
1808 /* SEEK */
1809 xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */
1810 xf_emit(ctx, 1, 0); /* 1ff */
1811 xf_emit(ctx, 8, 0); /* 0? */
1812
1813 /* SEEK */
1814 xf_emit(ctx, 0xc, 0); /* RO */
1815 /* SEEK */
1816 xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */
1817 xf_emit(ctx, 1, 0); /* 1ff */
1818 xf_emit(ctx, 8, 0); /* 0? */
1819 }
1820 /* SEEK */
1821 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1822 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
1823 xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */
1824 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
1825 if (dev_priv->chipset != 0x50)
1826 xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */
1827 /* SEEK */
1828 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1829 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
1830 xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */
1831 xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */
1832 xf_emit(ctx, 1, 1); /* 00000001 */
1833 /* SEEK */
1834 if (dev_priv->chipset >= 0xa0)
1835 xf_emit(ctx, 2, 4); /* 000000ff */
1836 xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */
1837 xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */
1838 xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */
1839 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
1840 xf_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM_ID */
1841 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1842 xf_emit(ctx, 1, 0); /* 0000000f */
1843 xf_emit(ctx, 1, 1); /* 00000001 */
1844 for (i = 0; i < 10; i++) {
1845 /* SEEK */
1846 xf_emit(ctx, 0x40, 0); /* ffffffff */
1847 xf_emit(ctx, 0x10, 0); /* 3, 0, 0.... */
1848 xf_emit(ctx, 0x10, 0); /* ffffffff */
1849 }
1850 /* SEEK */
1851 xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_CTRL */
1852 xf_emit(ctx, 1, 1); /* 00000001 */
1853 xf_emit(ctx, 1, 0); /* ffffffff */
1854 xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */
1855 xf_emit(ctx, 0x10, 0); /* 00ffffff POINT_COORD_REPLACE_MAP */
1856 xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */
1857 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
1858 if (dev_priv->chipset != 0x50)
1859 xf_emit(ctx, 1, 0); /* 000003ff */
1860}
1861
1862static void
1863nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx)
1864{
1865 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
1866 int acnt = 0x10, rep, i;
1867 /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */
1868 if (IS_NVA3F(dev_priv->chipset))
1869 acnt = 0x20;
1870 /* SEEK */
1871 if (dev_priv->chipset >= 0xa0) {
1872 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */
1873 xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */
1874 }
1875 xf_emit(ctx, 1, 0); /* ffffffff VERTEX_BUFFER_FIRST */
1876 xf_emit(ctx, 1, 0); /* 00000001 PRIMITIVE_RESTART_ENABLE */
1877 xf_emit(ctx, 1, 0); /* 00000001 UNK0DE8 */
1878 xf_emit(ctx, 1, 0); /* ffffffff PRIMITIVE_RESTART_INDEX */
1879 xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */
1880 xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */
1881 xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATR_MASK_UNK0DD0 */
1882 xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */
1883 xf_emit(ctx, 1, 0x20); /* 0000ffff tesla UNK129C */
1884 xf_emit(ctx, 1, 0); /* 000000ff turing UNK370??? */
1885 xf_emit(ctx, 1, 0); /* 0000ffff turing USER_PARAM_COUNT */
1886 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
1887 /* SEEK */
1888 if (IS_NVA3F(dev_priv->chipset))
1889 xf_emit(ctx, 0xb, 0); /* RO */
1890 else if (dev_priv->chipset >= 0xa0)
1891 xf_emit(ctx, 0x9, 0); /* RO */
1892 else
1893 xf_emit(ctx, 0x8, 0); /* RO */
1894 /* SEEK */
1895 xf_emit(ctx, 1, 0); /* 00000001 EDGE_FLAG */
1896 xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */
1897 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1898 xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */
1899 /* SEEK */
1900 xf_emit(ctx, 0xc, 0); /* RO */
1901 /* SEEK */
1902 xf_emit(ctx, 1, 0); /* 7f/ff */
1903 xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */
1904 xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */
1905 xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */
1906 xf_emit(ctx, 1, 4); /* 000001ff UNK1A28 */
1907 xf_emit(ctx, 1, 8); /* 000001ff UNK0DF0 */
1908 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
1909 if (dev_priv->chipset == 0x50)
1910 xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */
1911 else
1912 xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */
1913 if (dev_priv->chipset == 0xa8)
1914 xf_emit(ctx, 1, 0x1e00); /* 7fff */
1915 /* SEEK */
1916 xf_emit(ctx, 0xc, 0); /* RO or close */
1917 /* SEEK */
1918 xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */
1919 xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */
1920 xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */
1921 if (dev_priv->chipset > 0x50 && dev_priv->chipset < 0xa0)
1922 xf_emit(ctx, 2, 0); /* ffffffff */
1923 else
1924 xf_emit(ctx, 1, 0); /* ffffffff */
1925 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0FD8 */
1926 /* SEEK */
1927 if (IS_NVA3F(dev_priv->chipset)) {
1928 xf_emit(ctx, 0x10, 0); /* 0? */
1929 xf_emit(ctx, 2, 0); /* weird... */
1930 xf_emit(ctx, 2, 0); /* RO */
1931 } else {
1932 xf_emit(ctx, 8, 0); /* 0? */
1933 xf_emit(ctx, 1, 0); /* weird... */
1934 xf_emit(ctx, 2, 0); /* RO */
1935 }
1936 /* SEEK */
1937 xf_emit(ctx, 1, 0); /* ffffffff VB_ELEMENT_BASE */
1938 xf_emit(ctx, 1, 0); /* ffffffff UNK1438 */
1939 xf_emit(ctx, acnt, 0); /* 1 tesla UNK1000 */
1940 if (dev_priv->chipset >= 0xa0)
1941 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */
1942 /* SEEK */
1943 xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */
1944 xf_emit(ctx, 1, 0); /* f/1f */
1945 /* SEEK */
1946 xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */
1947 xf_emit(ctx, 1, 0); /* f/1f */
1948 /* SEEK */
1949 xf_emit(ctx, acnt, 0); /* RO */
1950 xf_emit(ctx, 2, 0); /* RO */
1951 /* SEEK */
1952 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK111C? */
1953 xf_emit(ctx, 1, 0); /* RO */
1954 /* SEEK */
1955 xf_emit(ctx, 1, 0); /* 000000ff UNK15F4_ADDRESS_HIGH */
1956 xf_emit(ctx, 1, 0); /* ffffffff UNK15F4_ADDRESS_LOW */
1957 xf_emit(ctx, 1, 0); /* 000000ff UNK0F84_ADDRESS_HIGH */
1958 xf_emit(ctx, 1, 0); /* ffffffff UNK0F84_ADDRESS_LOW */
1959 /* SEEK */
1960 xf_emit(ctx, acnt, 0); /* 00003fff VERTEX_ARRAY_ATTRIB_OFFSET */
1961 xf_emit(ctx, 3, 0); /* f/1f */
1962 /* SEEK */
1963 xf_emit(ctx, acnt, 0); /* 00000fff VERTEX_ARRAY_STRIDE */
1964 xf_emit(ctx, 3, 0); /* f/1f */
1965 /* SEEK */
1966 xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_LOW */
1967 xf_emit(ctx, 3, 0); /* f/1f */
1968 /* SEEK */
1969 xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_ARRAY_HIGH */
1970 xf_emit(ctx, 3, 0); /* f/1f */
1971 /* SEEK */
1972 xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_LIMIT_LOW */
1973 xf_emit(ctx, 3, 0); /* f/1f */
1974 /* SEEK */
1975 xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */
1976 xf_emit(ctx, 3, 0); /* f/1f */
1977 /* SEEK */
1978 if (IS_NVA3F(dev_priv->chipset)) {
1979 xf_emit(ctx, acnt, 0); /* f */
1980 xf_emit(ctx, 3, 0); /* f/1f */
1981 }
1982 /* SEEK */
1983 if (IS_NVA3F(dev_priv->chipset))
1984 xf_emit(ctx, 2, 0); /* RO */
1985 else
1986 xf_emit(ctx, 5, 0); /* RO */
1987 /* SEEK */
1988 xf_emit(ctx, 1, 0); /* ffff DMA_VTXBUF */
1989 /* SEEK */
1990 if (dev_priv->chipset < 0xa0) {
1991 xf_emit(ctx, 0x41, 0); /* RO */
1992 /* SEEK */
1993 xf_emit(ctx, 0x11, 0); /* RO */
1994 } else if (!IS_NVA3F(dev_priv->chipset))
1995 xf_emit(ctx, 0x50, 0); /* RO */
1996 else
1997 xf_emit(ctx, 0x58, 0); /* RO */
1998 /* SEEK */
1999 xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */
2000 xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */
2001 xf_emit(ctx, 1, 1); /* 1 UNK0DEC */
2002 /* SEEK */
2003 xf_emit(ctx, acnt*4, 0); /* ffffffff VTX_ATTR */
2004 xf_emit(ctx, 4, 0); /* f/1f, 0, 0, 0 */
2005 /* SEEK */
2006 if (IS_NVA3F(dev_priv->chipset))
2007 xf_emit(ctx, 0x1d, 0); /* RO */
2008 else
2009 xf_emit(ctx, 0x16, 0); /* RO */
2010 /* SEEK */
2011 xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */
2012 xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */
2013 /* SEEK */
2014 if (dev_priv->chipset < 0xa0)
2015 xf_emit(ctx, 8, 0); /* RO */
2016 else if (IS_NVA3F(dev_priv->chipset))
2017 xf_emit(ctx, 0xc, 0); /* RO */
2018 else
2019 xf_emit(ctx, 7, 0); /* RO */
2020 /* SEEK */
2021 xf_emit(ctx, 0xa, 0); /* RO */
2022 if (dev_priv->chipset == 0xa0)
2023 rep = 0xc;
2024 else
2025 rep = 4;
2026 for (i = 0; i < rep; i++) {
2027 /* SEEK */
2028 if (IS_NVA3F(dev_priv->chipset))
2029 xf_emit(ctx, 0x20, 0); /* ffffffff */
2030 xf_emit(ctx, 0x200, 0); /* ffffffff */
2031 xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */
2032 xf_emit(ctx, 4, 0); /* ffffffff */
2033 }
2034 /* SEEK */
2035 xf_emit(ctx, 1, 0); /* 113/111 */
2036 xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */
2037 xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */
2038 xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATTR_MASK_UNK0DD0 */
2039 xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */
2040 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2041 /* SEEK */
2042 if (IS_NVA3F(dev_priv->chipset))
2043 xf_emit(ctx, 7, 0); /* weird... */
2044 else
2045 xf_emit(ctx, 5, 0); /* weird... */
2046}
2047
2048static void
2049nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx)
2050{
2051 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2052 /* middle of strand 1 on pre-NVA0 [after vfetch], middle of strand 6 on NVAx */
2053 /* SEEK */
2054 xf_emit(ctx, 2, 0); /* 0001ffff CLIP_X, CLIP_Y */
2055 xf_emit(ctx, 2, 0); /* 0000ffff CLIP_W, CLIP_H */
2056 xf_emit(ctx, 1, 0); /* 00000001 CLIP_ENABLE */
2057 if (dev_priv->chipset < 0xa0) {
2058 /* this is useless on everything but the original NV50,
2059 * guess they forgot to nuke it. Or just didn't bother. */
2060 xf_emit(ctx, 2, 0); /* 0000ffff IFC_CLIP_X, Y */
2061 xf_emit(ctx, 2, 1); /* 0000ffff IFC_CLIP_W, H */
2062 xf_emit(ctx, 1, 0); /* 00000001 IFC_CLIP_ENABLE */
2063 }
2064 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2065 xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */
2066 xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */
2067 xf_emit(ctx, 1, 0x11); /* 3f[NV50]/7f[NV84+] DST_FORMAT */
2068 xf_emit(ctx, 1, 0); /* 0001ffff DRAW_POINT_X */
2069 xf_emit(ctx, 1, 8); /* 0000000f DRAW_UNK58C */
2070 xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_X_FRACT */
2071 xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_X_INT */
2072 xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_Y_FRACT */
2073 xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_Y_INT */
2074 xf_emit(ctx, 1, 0); /* 000fffff SIFC_DX_DU_FRACT */
2075 xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DX_DU_INT */
2076 xf_emit(ctx, 1, 0); /* 000fffff SIFC_DY_DV_FRACT */
2077 xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DY_DV_INT */
2078 xf_emit(ctx, 1, 1); /* 0000ffff SIFC_WIDTH */
2079 xf_emit(ctx, 1, 1); /* 0000ffff SIFC_HEIGHT */
2080 xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */
2081 xf_emit(ctx, 1, 2); /* 00000003 SIFC_BITMAP_UNK808 */
2082 xf_emit(ctx, 1, 0); /* 00000003 SIFC_BITMAP_LINE_PACK_MODE */
2083 xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_LSB_FIRST */
2084 xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_ENABLE */
2085 xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_X */
2086 xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_Y */
2087 xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */
2088 xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */
2089 xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */
2090 xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */
2091 xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_W */
2092 xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_H */
2093 xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_X_FRACT */
2094 xf_emit(ctx, 1, 0); /* 0001ffff BLIT_SRC_X_INT */
2095 xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_Y_FRACT */
2096 xf_emit(ctx, 1, 0); /* 00000001 UNK888 */
2097 xf_emit(ctx, 1, 4); /* 0000003f UNK884 */
2098 xf_emit(ctx, 1, 0); /* 00000007 UNK880 */
2099 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK0FB8 */
2100 xf_emit(ctx, 1, 0x15); /* 000000ff tesla UNK128C */
2101 xf_emit(ctx, 2, 0); /* 00000007, ffff0ff3 */
2102 xf_emit(ctx, 1, 0); /* 00000001 UNK260 */
2103 xf_emit(ctx, 1, 0x4444480); /* 1fffffff UNK870 */
2104 /* SEEK */
2105 xf_emit(ctx, 0x10, 0);
2106 /* SEEK */
2107 xf_emit(ctx, 0x27, 0);
2108}
2109
2110static void
2111nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx)
2112{
2113 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2114 /* middle of strand 1 on pre-NVA0 [after eng2d], middle of strand 0 on NVAx */
2115 /* SEEK */
2116 xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY... what is it doing here??? */
2117 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */
2118 xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */
2119 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
2120 xf_emit(ctx, 1, 0); /* 000003ff */
2121 /* SEEK */
2122 xf_emit(ctx, 1, 0); /* ffffffff turing UNK364 */
2123 xf_emit(ctx, 1, 0); /* 0000000f turing UNK36C */
2124 xf_emit(ctx, 1, 0); /* 0000ffff USER_PARAM_COUNT */
2125 xf_emit(ctx, 1, 0x100); /* 00ffffff turing UNK384 */
2126 xf_emit(ctx, 1, 0); /* 0000000f turing UNK2A0 */
2127 xf_emit(ctx, 1, 0); /* 0000ffff GRIDID */
2128 xf_emit(ctx, 1, 0x10001); /* ffffffff GRIDDIM_XY */
2129 xf_emit(ctx, 1, 0); /* ffffffff */
2130 xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */
2131 xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */
2132 xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */
2133 xf_emit(ctx, 1, 1); /* 00000001 LANES32 */
2134 xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */
2135 xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */
2136 /* SEEK */
2137 xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */
2138 switch (dev_priv->chipset) {
2139 case 0x50:
2140 case 0x92:
2141 xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */
2142 xf_emit(ctx, 0x80, 0); /* fff */
2143 xf_emit(ctx, 2, 0); /* ff, fff */
2144 xf_emit(ctx, 0x10*2, 0); /* ffffffff, 1f */
2145 break;
2146 case 0x84:
2147 xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */
2148 xf_emit(ctx, 0x60, 0); /* fff */
2149 xf_emit(ctx, 2, 0); /* ff, fff */
2150 xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */
2151 break;
2152 case 0x94:
2153 case 0x96:
2154 xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */
2155 xf_emit(ctx, 0x40, 0); /* fff */
2156 xf_emit(ctx, 2, 0); /* ff, fff */
2157 xf_emit(ctx, 8*2, 0); /* ffffffff, 1f */
2158 break;
2159 case 0x86:
2160 case 0x98:
2161 xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */
2162 xf_emit(ctx, 0x10, 0); /* fff */
2163 xf_emit(ctx, 2, 0); /* ff, fff */
2164 xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */
2165 break;
2166 case 0xa0:
2167 xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */
2168 xf_emit(ctx, 0xf0, 0); /* fff */
2169 xf_emit(ctx, 2, 0); /* ff, fff */
2170 xf_emit(ctx, 0x1e*2, 0); /* ffffffff, 1f */
2171 break;
2172 case 0xa3:
2173 xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */
2174 xf_emit(ctx, 0x60, 0); /* fff */
2175 xf_emit(ctx, 2, 0); /* ff, fff */
2176 xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */
2177 break;
2178 case 0xa5:
2179 case 0xaf:
2180 xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */
2181 xf_emit(ctx, 0x30, 0); /* fff */
2182 xf_emit(ctx, 2, 0); /* ff, fff */
2183 xf_emit(ctx, 6*2, 0); /* ffffffff, 1f */
2184 break;
2185 case 0xaa:
2186 xf_emit(ctx, 0x12, 0);
2187 break;
2188 case 0xa8:
2189 case 0xac:
2190 xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */
2191 xf_emit(ctx, 0x10, 0); /* fff */
2192 xf_emit(ctx, 2, 0); /* ff, fff */
2193 xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */
2194 break;
2195 }
2196 xf_emit(ctx, 1, 0); /* 0000000f */
2197 xf_emit(ctx, 1, 0); /* 00000000 */
2198 xf_emit(ctx, 1, 0); /* ffffffff */
2199 xf_emit(ctx, 1, 0); /* 0000001f */
2200 xf_emit(ctx, 4, 0); /* ffffffff */
2201 xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */
2202 xf_emit(ctx, 1, 0); /* ffffffff */
2203 xf_emit(ctx, 4, 0); /* ffffffff */
2204 xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */
2205 xf_emit(ctx, 1, 0); /* ffffffff */
2206 xf_emit(ctx, 1, 0); /* 000000ff */
2207}
2208
2209static void
2210nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx)
2211{
2212 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2213 xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */
2214 xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */
2215 xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */
2216 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */
2217 xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */
2218 xf_emit(ctx, 3, 0); /* 00000001 POLYGON_OFFSET_*_ENABLE */
2219 xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */
2220 xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */
2221 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2222 xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */
2223 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */
2224 xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */
2225 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2226 xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */
2227 xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */
2228 xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_UNITS */
2229 xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_FACTOR */
2230 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */
2231 xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */
2232 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */
2233 xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */
2234 xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */
2235 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2236 xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */
2237 xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */
2238 xf_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_LINEAR */
2239 xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */
2240 xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */
2241 xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */
2242 if (IS_NVA3F(dev_priv->chipset))
2243 xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */
2244 else if (dev_priv->chipset >= 0xa0)
2245 xf_emit(ctx, 1, 1); /* 00000001 UNK16B4 */
2246 xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */
2247 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */
2248 xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */
2249 xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */
2250 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */
2251 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2252 xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */
2253 xf_emit(ctx, 1, 5); /* 0000000f UNK1408 */
2254 xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */
2255 xf_emit(ctx, 1, 0); /* ffffffff POINT_SIZE */
2256 xf_emit(ctx, 1, 0); /* 00000001 */
2257 xf_emit(ctx, 1, 0); /* 00000007 tesla UNK0FB4 */
2258 if (dev_priv->chipset != 0x50) {
2259 xf_emit(ctx, 1, 0); /* 3ff */
2260 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */
2261 }
2262 if (IS_NVA3F(dev_priv->chipset))
2263 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */
2264 xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */
2265 xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */
2266 xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */
2267 xf_emit(ctx, 0x20, 0); /* 07ffffff VIEWPORT_HORIZ, then VIEWPORT_VERT. (W&0x3fff)<<13 | (X&0x1fff). */
2268 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK187C */
2269 xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */
2270 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2271 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2272 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */
2273 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */
2274 xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
2275 xf_emit(ctx, 1, 5); /* 0000000f tesla UNK1220 */
2276 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
2277 xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1A20 */
2278 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2279 xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */
2280 xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */
2281 if (dev_priv->chipset != 0x50)
2282 xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */
2283 if (dev_priv->chipset < 0xa0)
2284 xf_emit(ctx, 0x1c, 0); /* RO */
2285 else if (IS_NVA3F(dev_priv->chipset))
2286 xf_emit(ctx, 0x9, 0);
2287 xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */
2288 xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */
2289 xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */
2290 xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */
2291 xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */
2292 xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */
2293 if (dev_priv->chipset != 0x50) {
2294 xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */
2295 xf_emit(ctx, 1, 0); /* 3ff */
2296 }
2297 /* XXX: the following block could belong either to unk1cxx, or
2298 * to STRMOUT. Rather hard to tell. */
2299 if (dev_priv->chipset < 0xa0)
2300 xf_emit(ctx, 0x25, 0);
2301 else
2302 xf_emit(ctx, 0x3b, 0);
2303}
2304
2305static void
2306nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx)
2307{
2308 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2309 xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */
2310 xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */
2311 xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */
2312 if (dev_priv->chipset >= 0xa0) {
2313 xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */
2314 xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */
2315 }
2316 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
2317 xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */
2318 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2319 if (dev_priv->chipset == 0x50)
2320 xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */
2321 else
2322 xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */
2323 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2324 /* SEEK */
2325 xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */
2326 xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */
2327 xf_emit(ctx, 4, 0); /* 000000ff STRMOUT_ADDRESS_HIGH */
2328 xf_emit(ctx, 4, 0); /* ffffffff STRMOUT_ADDRESS_LOW */
2329 xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */
2330 if (dev_priv->chipset >= 0xa0) {
2331 xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */
2332 xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */
2333 }
2334 xf_emit(ctx, 1, 0); /* 0000ffff DMA_STRMOUT */
2335 xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */
2336 xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */
2337 xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW QUERY_COUNTER */
2338 xf_emit(ctx, 2, 0); /* ffffffff */
2339 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2340 /* SEEK */
2341 xf_emit(ctx, 0x20, 0); /* ffffffff STRMOUT_MAP */
2342 xf_emit(ctx, 1, 0); /* 0000000f */
2343 xf_emit(ctx, 1, 0); /* 00000000? */
2344 xf_emit(ctx, 2, 0); /* ffffffff */
2345}
2346
2347static void
2348nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx)
2349{
2350 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2351 xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */
2352 xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */
2353 xf_emit(ctx, 1, 0); /* 00000007 */
2354 xf_emit(ctx, 1, 0); /* 000003ff */
2355 if (IS_NVA3F(dev_priv->chipset))
2356 xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */
2357 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2358}
2359
2360static void
2361nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx)
2362{
2363 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2364 /* SEEK */
2365 xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */
2366 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2367 xf_emit(ctx, 2, 0); /* ffffffff */
2368 xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */
2369 xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */
2370 xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */
2371 xf_emit(ctx, 1, 0); /* 7 */
2372 /* SEEK */
2373 xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */
2374 xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */
2375 xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */
2376 xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */
2377 xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */
2378 xf_emit(ctx, 1, 0); /* 00000001 eng2d UNK260 */
2379 xf_emit(ctx, 1, 0); /* ff/3ff */
2380 xf_emit(ctx, 1, 0); /* 00000007 */
2381 if (IS_NVA3F(dev_priv->chipset))
2382 xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */
2383 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2384}
2385
2386static void
2387nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx)
2388{
2389 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2390 int magic2;
2391 if (dev_priv->chipset == 0x50) {
2392 magic2 = 0x00003e60;
2393 } else if (!IS_NVA3F(dev_priv->chipset)) {
2394 magic2 = 0x001ffe67;
2395 } else {
2396 magic2 = 0x00087e67;
2397 }
2398 xf_emit(ctx, 1, 0); /* f/7 MUTISAMPLE_SAMPLES_LOG2 */
2399 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2400 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */
2401 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */
2402 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */
2403 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */
2404 xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */
2405 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2406 xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */
2407 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2408 xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */
2409 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2410 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2411 if (IS_NVA3F(dev_priv->chipset))
2412 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2413 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */
2414 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */
2415 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */
2416 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */
2417 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2418 if (dev_priv->chipset >= 0xa0 && !IS_NVAAF(dev_priv->chipset))
2419 xf_emit(ctx, 1, 0x15); /* 000000ff */
2420 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */
2421 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */
2422 xf_emit(ctx, 1, 0x10); /* 3ff/ff VIEW_VOLUME_CLIP_CTRL */
2423 xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */
2424 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2425 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2426 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2427 if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) {
2428 xf_emit(ctx, 3, 0); /* ff, ffffffff, ffffffff */
2429 xf_emit(ctx, 1, 4); /* 7 */
2430 xf_emit(ctx, 1, 0x400); /* fffffff */
2431 xf_emit(ctx, 1, 0x300); /* ffff */
2432 xf_emit(ctx, 1, 0x1001); /* 1fff */
2433 if (dev_priv->chipset != 0xa0) {
2434 if (IS_NVA3F(dev_priv->chipset))
2435 xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */
2436 else
2437 xf_emit(ctx, 1, 0x15); /* ff */
2438 }
2439 }
2440 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
2441 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2442 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */
2443 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */
2444 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2445 xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */
2446 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2447 xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */
2448 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2449 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2450 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */
2451 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */
2452 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2453 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */
2454 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */
2455 xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */
2456 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2457 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2458 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2459 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2460 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */
2461 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */
2462 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */
2463 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */
2464 xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */
2465 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2466 xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */
2467 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2468 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2469 xf_emit(ctx, 1, 0); /* 0000000f */
2470 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */
2471 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */
2472 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */
2473 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */
2474 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2475 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */
2476 xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */
2477 xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */
2478 xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */
2479 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2480 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
2481 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */
2482 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */
2483 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */
2484 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */
2485 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */
2486 xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */
2487 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2488 xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */
2489 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2490 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2491 xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */
2492 xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */
2493 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */
2494 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */
2495 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */
2496 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */
2497 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2498 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */
2499 xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */
2500 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2501 xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */
2502 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
2503 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2504 xf_emit(ctx, 2, 0); /* ffff0ff3, ffff */
2505 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */
2506 xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */
2507 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */
2508 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2509 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2510 xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */
2511 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */
2512 if (dev_priv->chipset >= 0xa0) {
2513 xf_emit(ctx, 2, 0);
2514 xf_emit(ctx, 1, 0x1001);
2515 xf_emit(ctx, 0xb, 0);
2516 } else {
2517 xf_emit(ctx, 1, 0); /* 00000007 */
2518 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2519 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
2520 xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */
2521 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2522 }
2523 xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */
2524 xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */
2525 xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */
2526 xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */
2527 xf_emit(ctx, 1, 0x11); /* 3f/7f */
2528 xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */
2529 if (dev_priv->chipset != 0x50) {
2530 xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */
2531 xf_emit(ctx, 1, 0); /* 000000ff */
2532 }
2533 xf_emit(ctx, 1, 0); /* 00000007 OPERATION */
2534 xf_emit(ctx, 1, 0); /* ff/3ff */
2535 xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */
2536 xf_emit(ctx, 2, 1); /* 00000007 BLEND_EQUATION_RGB, ALPHA */
2537 xf_emit(ctx, 1, 1); /* 00000001 UNK133C */
2538 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */
2539 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */
2540 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */
2541 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */
2542 xf_emit(ctx, 1, 0); /* 00000001 */
2543 xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */
2544 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2545 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2546 if (IS_NVA3F(dev_priv->chipset)) {
2547 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK12E4 */
2548 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */
2549 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */
2550 xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */
2551 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */
2552 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */
2553 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */
2554 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */
2555 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */
2556 xf_emit(ctx, 2, 0); /* 00000001 */
2557 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2558 xf_emit(ctx, 1, 0); /* 0000000f */
2559 xf_emit(ctx, 1, 0); /* 00000003 */
2560 xf_emit(ctx, 1, 0); /* ffffffff */
2561 xf_emit(ctx, 2, 0); /* 00000001 */
2562 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2563 xf_emit(ctx, 1, 0); /* 00000001 */
2564 xf_emit(ctx, 1, 0); /* 000003ff */
2565 } else if (dev_priv->chipset >= 0xa0) {
2566 xf_emit(ctx, 2, 0); /* 00000001 */
2567 xf_emit(ctx, 1, 0); /* 00000007 */
2568 xf_emit(ctx, 1, 0); /* 00000003 */
2569 xf_emit(ctx, 1, 0); /* ffffffff */
2570 xf_emit(ctx, 2, 0); /* 00000001 */
2571 } else {
2572 xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */
2573 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1430 */
2574 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2575 }
2576 xf_emit(ctx, 4, 0); /* ffffffff CLEAR_COLOR */
2577 xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR A R G B */
2578 xf_emit(ctx, 1, 0); /* 00000fff eng2d UNK2B0 */
2579 if (dev_priv->chipset >= 0xa0)
2580 xf_emit(ctx, 2, 0); /* 00000001 */
2581 xf_emit(ctx, 1, 0); /* 000003ff */
2582 xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */
2583 xf_emit(ctx, 1, 1); /* 00000001 UNK133C */
2584 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */
2585 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */
2586 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */
2587 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */
2588 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */
2589 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */
2590 xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */
2591 xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */
2592 xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */
2593 if (dev_priv->chipset >= 0xa0)
2594 xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */
2595 if (IS_NVA3F(dev_priv->chipset)) {
2596 xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */
2597 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */
2598 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */
2599 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */
2600 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */
2601 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */
2602 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */
2603 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK15C4 */
2604 xf_emit(ctx, 1, 0); /* 00000001 */
2605 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */
2606 }
2607 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
2608 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2609 xf_emit(ctx, 1, 0); /* 00000007 PATTERN_COLOR_FORMAT */
2610 xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_COLOR */
2611 xf_emit(ctx, 1, 0); /* 00000001 PATTERN_MONO_FORMAT */
2612 xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_BITMAP */
2613 xf_emit(ctx, 1, 0); /* 00000003 PATTERN_SELECT */
2614 xf_emit(ctx, 1, 0); /* 000000ff ROP */
2615 xf_emit(ctx, 1, 0); /* ffffffff BETA1 */
2616 xf_emit(ctx, 1, 0); /* ffffffff BETA4 */
2617 xf_emit(ctx, 1, 0); /* 00000007 OPERATION */
2618 xf_emit(ctx, 0x50, 0); /* 10x ffffff, ffffff, ffffff, ffffff, 3 PATTERN */
2619}
2620
2621static void
2622nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx)
2623{
2624 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2625 int magic3;
2626 switch (dev_priv->chipset) {
2627 case 0x50:
2628 magic3 = 0x1000;
2629 break;
2630 case 0x86:
2631 case 0x98:
2632 case 0xa8:
2633 case 0xaa:
2634 case 0xac:
2635 case 0xaf:
2636 magic3 = 0x1e00;
2637 break;
2638 default:
2639 magic3 = 0;
2640 }
2641 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2642 xf_emit(ctx, 1, 4); /* 7f/ff[NVA0+] VP_REG_ALLOC_RESULT */
2643 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2644 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2645 xf_emit(ctx, 1, 0); /* 111/113[NVA0+] */
2646 if (IS_NVA3F(dev_priv->chipset))
2647 xf_emit(ctx, 0x1f, 0); /* ffffffff */
2648 else if (dev_priv->chipset >= 0xa0)
2649 xf_emit(ctx, 0x0f, 0); /* ffffffff */
2650 else
2651 xf_emit(ctx, 0x10, 0); /* fffffff VP_RESULT_MAP_1 up */
2652 xf_emit(ctx, 2, 0); /* f/1f[NVA3], fffffff/ffffffff[NVA0+] */
2653 xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */
2654 xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */
2655 if (dev_priv->chipset >= 0xa0)
2656 xf_emit(ctx, 1, 0x03020100); /* ffffffff */
2657 else
2658 xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */
2659 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2660 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2661 xf_emit(ctx, 2, 0); /* 111/113, 7f/ff */
2662 xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */
2663 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2664 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2665 xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */
2666 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
2667 xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */
2668 if (magic3)
2669 xf_emit(ctx, 1, magic3); /* 00007fff tesla UNK141C */
2670 xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */
2671 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2672 xf_emit(ctx, 1, 0); /* 111/113 */
2673 xf_emit(ctx, 0x1f, 0); /* ffffffff GP_RESULT_MAP_1 up */
2674 xf_emit(ctx, 1, 0); /* 0000001f */
2675 xf_emit(ctx, 1, 0); /* ffffffff */
2676 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2677 xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */
2678 xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */
2679 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
2680 xf_emit(ctx, 1, 0x03020100); /* ffffffff GP_RESULT_MAP_0 */
2681 xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */
2682 if (magic3)
2683 xf_emit(ctx, 1, magic3); /* 7fff tesla UNK141C */
2684 xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */
2685 xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */
2686 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2687 xf_emit(ctx, 1, 0); /* 111/113 */
2688 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2689 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
2690 xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */
2691 xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */
2692 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2693 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK13A0 */
2694 xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */
2695 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2696 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2697 xf_emit(ctx, 1, 0); /* 111/113 */
2698 if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96)
2699 xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */
2700 else if (dev_priv->chipset < 0xa0)
2701 xf_emit(ctx, 0xa20, 0); /* 4 x (0x280 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */
2702 else if (!IS_NVA3F(dev_priv->chipset))
2703 xf_emit(ctx, 0x210, 0); /* ffffffff */
2704 else
2705 xf_emit(ctx, 0x410, 0); /* ffffffff */
2706 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
2707 xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */
2708 xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */
2709 xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */
2710 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
2711}
2712
2713static void
2714nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx)
2715{
2716 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
2717 int magic1, magic2;
2718 if (dev_priv->chipset == 0x50) {
2719 magic1 = 0x3ff;
2720 magic2 = 0x00003e60;
2721 } else if (!IS_NVA3F(dev_priv->chipset)) {
2722 magic1 = 0x7ff;
2723 magic2 = 0x001ffe67;
2724 } else {
2725 magic1 = 0x7ff;
2726 magic2 = 0x00087e67;
2727 }
2728 xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */
2729 xf_emit(ctx, 1, 0); /* ffffffff ALPHA_TEST_REF */
2730 xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */
2731 if (IS_NVA3F(dev_priv->chipset))
2732 xf_emit(ctx, 1, 1); /* 0000000f UNK16A0 */
2733 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
2734 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2735 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */
2736 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */
2737 xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR */
2738 xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */
2739 xf_emit(ctx, 1, 0); /* 00000001 UNK0FDC */
2740 xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */
2741 xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */
2742 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2743 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2744 xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */
2745 xf_emit(ctx, 1, 0); /* ff[NV50]/3ff[NV84+] */
2746 xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */
2747 xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */
2748 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */
2749 xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */
2750 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2751 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */
2752 xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */
2753 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */
2754 xf_emit(ctx, 1, 0); /* 7 */
2755 xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */
2756 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2757 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2758 xf_emit(ctx, 1, 0); /* ffffffff COLOR_KEY */
2759 xf_emit(ctx, 1, 0); /* 00000001 COLOR_KEY_ENABLE */
2760 xf_emit(ctx, 1, 0); /* 00000007 COLOR_KEY_FORMAT */
2761 xf_emit(ctx, 2, 0); /* ffffffff SIFC_BITMAP_COLOR */
2762 xf_emit(ctx, 1, 1); /* 00000001 SIFC_BITMAP_WRITE_BIT0_ENABLE */
2763 xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */
2764 xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */
2765 if (IS_NVA3F(dev_priv->chipset)) {
2766 xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */
2767 xf_emit(ctx, 1, 0); /* 00000003 */
2768 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1298 */
2769 } else if (dev_priv->chipset >= 0xa0) {
2770 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */
2771 xf_emit(ctx, 1, 0); /* 00000003 */
2772 } else {
2773 xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */
2774 }
2775 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2776 xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */
2777 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */
2778 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */
2779 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */
2780 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */
2781 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */
2782 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */
2783 if (IS_NVA3F(dev_priv->chipset)) {
2784 xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */
2785 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */
2786 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */
2787 xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */
2788 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_RGB */
2789 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_RGB */
2790 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_ALPHA */
2791 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_ALPHA */
2792 xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */
2793 }
2794 xf_emit(ctx, 1, 1); /* 00000001 UNK133C */
2795 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2796 xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */
2797 xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */
2798 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2799 xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */
2800 xf_emit(ctx, 1, 0); /* ff/3ff */
2801 xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */
2802 xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */
2803 xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */
2804 xf_emit(ctx, 1, 0); /* 7 */
2805 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
2806 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2807 xf_emit(ctx, 1, 0); /* 00000007 OPERATION */
2808 xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */
2809 xf_emit(ctx, 1, 0xcf); /* 000000ff DRAW_COLOR_FORMAT */
2810 xf_emit(ctx, 1, 0xcf); /* 000000ff SRC_FORMAT */
2811 if (IS_NVA3F(dev_priv->chipset))
2812 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2813 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2814 xf_emit(ctx, 1, 0); /* 7/f[NVA3] MULTISAMPLE_SAMPLES_LOG2 */
2815 xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */
2816 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */
2817 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */
2818 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */
2819 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */
2820 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */
2821 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */
2822 xf_emit(ctx, 1, 1); /* 00000001 UNK133C */
2823 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2824 xf_emit(ctx, 8, 1); /* 00000001 UNK19E0 */
2825 xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */
2826 xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */
2827 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2828 xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */
2829 xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */
2830 xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */
2831 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2832 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2833 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
2834 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2835 if (IS_NVA3F(dev_priv->chipset))
2836 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2837 if (dev_priv->chipset == 0x50)
2838 xf_emit(ctx, 1, 0); /* ff */
2839 else
2840 xf_emit(ctx, 3, 0); /* 1, 7, 3ff */
2841 xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */
2842 xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */
2843 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2844 xf_emit(ctx, 1, 0); /* 00000007 */
2845 xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */
2846 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2847 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2848 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2849 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
2850 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2851 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2852 xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */
2853 xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */
2854 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2855 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2856 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2857 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2858 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
2859 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2860 xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */
2861 xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */
2862 xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */
2863 xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */
2864 xf_emit(ctx, 1, 0); /* ff/3ff */
2865 xf_emit(ctx, 1, magic1); /* 3ff/7ff tesla UNK0D68 */
2866 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2867 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */
2868 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2869 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2870 xf_emit(ctx, 1, 0); /* 00000007 */
2871 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2872 if (IS_NVA3F(dev_priv->chipset))
2873 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2874 xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */
2875 xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */
2876 xf_emit(ctx, 1, 0); /* 0000ffff DMA_LOCAL */
2877 xf_emit(ctx, 1, 0); /* 0000ffff DMA_STACK */
2878 xf_emit(ctx, 1, 0); /* ff/3ff */
2879 xf_emit(ctx, 1, 0); /* 0000ffff DMA_DST */
2880 xf_emit(ctx, 1, 0); /* 7 */
2881 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
2882 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2883 xf_emit(ctx, 8, 0); /* 000000ff RT_ADDRESS_HIGH */
2884 xf_emit(ctx, 8, 0); /* ffffffff RT_LAYER_STRIDE */
2885 xf_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */
2886 xf_emit(ctx, 8, 8); /* 0000007f RT_TILE_MODE */
2887 xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */
2888 xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */
2889 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2890 xf_emit(ctx, 8, 0x400); /* 0fffffff RT_HORIZ */
2891 xf_emit(ctx, 8, 0x300); /* 0000ffff RT_VERT */
2892 xf_emit(ctx, 1, 1); /* 00001fff RT_ARRAY_MODE */
2893 xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */
2894 xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */
2895 xf_emit(ctx, 1, 0x20); /* 00000fff DST_TILE_MODE */
2896 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
2897 xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */
2898 xf_emit(ctx, 1, 0); /* 000007ff DST_LAYER */
2899 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2900 xf_emit(ctx, 1, 0); /* ffffffff DST_ADDRESS_LOW */
2901 xf_emit(ctx, 1, 0); /* 000000ff DST_ADDRESS_HIGH */
2902 xf_emit(ctx, 1, 0x40); /* 0007ffff DST_PITCH */
2903 xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */
2904 xf_emit(ctx, 1, 0); /* 0000ffff */
2905 xf_emit(ctx, 1, 3); /* 00000003 tesla UNK15AC */
2906 xf_emit(ctx, 1, 0); /* ff/3ff */
2907 xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */
2908 xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */
2909 xf_emit(ctx, 1, 0); /* 00000007 */
2910 if (IS_NVA3F(dev_priv->chipset))
2911 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2912 xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */
2913 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
2914 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
2915 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2916 xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */
2917 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2918 xf_emit(ctx, 1, 0); /* 0000ffff DMA_ZETA */
2919 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2920 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2921 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2922 xf_emit(ctx, 2, 0); /* ffff, ff/3ff */
2923 xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */
2924 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2925 xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */
2926 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */
2927 xf_emit(ctx, 1, 0); /* 00000007 */
2928 xf_emit(ctx, 1, 0); /* ffffffff ZETA_LAYER_STRIDE */
2929 xf_emit(ctx, 1, 0); /* 000000ff ZETA_ADDRESS_HIGH */
2930 xf_emit(ctx, 1, 0); /* ffffffff ZETA_ADDRESS_LOW */
2931 xf_emit(ctx, 1, 4); /* 00000007 ZETA_TILE_MODE */
2932 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2933 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2934 xf_emit(ctx, 1, 0x400); /* 0fffffff ZETA_HORIZ */
2935 xf_emit(ctx, 1, 0x300); /* 0000ffff ZETA_VERT */
2936 xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */
2937 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2938 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
2939 if (IS_NVA3F(dev_priv->chipset))
2940 xf_emit(ctx, 1, 0); /* 00000001 */
2941 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2942 xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */
2943 xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */
2944 xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */
2945 xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */
2946 xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */
2947 xf_emit(ctx, 1, 0); /* ff/3ff */
2948 xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */
2949 xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */
2950 xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */
2951 xf_emit(ctx, 1, 0); /* 7 */
2952 xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */
2953 if (IS_NVA3F(dev_priv->chipset)) {
2954 xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */
2955 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2956 }
2957 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
2958 xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */
2959 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2960 if (dev_priv->chipset >= 0xa0)
2961 xf_emit(ctx, 1, 0x0fac6881); /* fffffff */
2962 xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */
2963 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */
2964 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
2965 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */
2966 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
2967 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */
2968 xf_emit(ctx, 1, 0); /* ff/3ff */
2969 xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */
2970 xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */
2971 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */
2972 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */
2973 xf_emit(ctx, 1, 0); /* 00000007 */
2974 xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */
2975 xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */
2976 xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */
2977 if (IS_NVA3F(dev_priv->chipset)) {
2978 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2979 xf_emit(ctx, 1, 0); /* 0000000f tesla UNK15C8 */
2980 }
2981 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */
2982 if (dev_priv->chipset >= 0xa0) {
2983 xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */
2984 xf_emit(ctx, 1, 0xfac6881); /* fffffff */
2985 xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */
2986 xf_emit(ctx, 1, 4); /* 7 */
2987 xf_emit(ctx, 1, 0); /* 1 */
2988 xf_emit(ctx, 2, 1); /* 1 */
2989 xf_emit(ctx, 2, 0); /* 7, f */
2990 xf_emit(ctx, 1, 1); /* 1 */
2991 xf_emit(ctx, 1, 0); /* 7/f */
2992 if (IS_NVA3F(dev_priv->chipset))
2993 xf_emit(ctx, 0x9, 0); /* 1 */
2994 else
2995 xf_emit(ctx, 0x8, 0); /* 1 */
2996 xf_emit(ctx, 1, 0); /* ffff0ff3 */
2997 xf_emit(ctx, 8, 1); /* 1 */
2998 xf_emit(ctx, 1, 0x11); /* 7f */
2999 xf_emit(ctx, 7, 0); /* 7f */
3000 xf_emit(ctx, 1, 0xfac6881); /* fffffff */
3001 xf_emit(ctx, 1, 0xf); /* f */
3002 xf_emit(ctx, 7, 0); /* f */
3003 xf_emit(ctx, 1, 0x11); /* 7f */
3004 xf_emit(ctx, 1, 1); /* 1 */
3005 xf_emit(ctx, 5, 0); /* 1, 7, 3ff, 3, 7 */
3006 if (IS_NVA3F(dev_priv->chipset)) {
3007 xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */
3008 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
3009 }
3010 }
3011}
3012
3013static void
3014nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx)
3015{
3016 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
3017 xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */
3018 if (dev_priv->chipset != 0x50)
3019 xf_emit(ctx, 1, 0); /* 3 */
3020 xf_emit(ctx, 1, 1); /* 1ffff BLIT_DU_DX_INT */
3021 xf_emit(ctx, 1, 0); /* fffff BLIT_DU_DX_FRACT */
3022 xf_emit(ctx, 1, 1); /* 1ffff BLIT_DV_DY_INT */
3023 xf_emit(ctx, 1, 0); /* fffff BLIT_DV_DY_FRACT */
3024 if (dev_priv->chipset == 0x50)
3025 xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */
3026 else
3027 xf_emit(ctx, 2, 0); /* 3ff, 1 */
3028 xf_emit(ctx, 1, 0x2a712488); /* ffffffff SRC_TIC_0 */
3029 xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_1 */
3030 xf_emit(ctx, 1, 0x4085c000); /* ffffffff SRC_TIC_2 */
3031 xf_emit(ctx, 1, 0x40); /* ffffffff SRC_TIC_3 */
3032 xf_emit(ctx, 1, 0x100); /* ffffffff SRC_TIC_4 */
3033 xf_emit(ctx, 1, 0x10100); /* ffffffff SRC_TIC_5 */
3034 xf_emit(ctx, 1, 0x02800000); /* ffffffff SRC_TIC_6 */
3035 xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_7 */
3036 if (dev_priv->chipset == 0x50) {
3037 xf_emit(ctx, 1, 0); /* 00000001 turing UNK358 */
3038 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */
3039 xf_emit(ctx, 1, 0); /* 00000003 turing UNK37C tesla UNK1690 */
3040 xf_emit(ctx, 1, 0); /* 00000003 BLIT_CONTROL */
3041 xf_emit(ctx, 1, 0); /* 00000001 turing UNK32C tesla UNK0F94 */
3042 } else if (!IS_NVAAF(dev_priv->chipset)) {
3043 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */
3044 xf_emit(ctx, 1, 0); /* 00000003 */
3045 xf_emit(ctx, 1, 0); /* 000003ff */
3046 xf_emit(ctx, 1, 0); /* 00000003 */
3047 xf_emit(ctx, 1, 0); /* 000003ff */
3048 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1664 / turing UNK03E8 */
3049 xf_emit(ctx, 1, 0); /* 00000003 */
3050 xf_emit(ctx, 1, 0); /* 000003ff */
3051 } else {
3052 xf_emit(ctx, 0x6, 0);
3053 }
3054 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */
3055 xf_emit(ctx, 1, 0); /* 0000ffff DMA_TEXTURE */
3056 xf_emit(ctx, 1, 0); /* 0000ffff DMA_SRC */
3057}
3058
3059static void
3060nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx)
3061{
3062 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
3063 xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */
3064 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
3065 xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */
3066 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
3067 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */
3068 xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */
3069 xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */
3070 xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */
3071 xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */
3072 xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */
3073 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK0F98 */
3074 if (IS_NVA3F(dev_priv->chipset))
3075 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
3076 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */
3077 xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */
3078 xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */
3079 xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */
3080 xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */
3081 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
3082 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */
3083 xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */
3084 xf_emit(ctx, 1, 0); /* ffff0ff3 */
3085 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */
3086 xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */
3087 xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */
3088 xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */
3089 xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */
3090 xf_emit(ctx, 1, 0x30201000); /* ffffffff tesla UNK1670 */
3091 xf_emit(ctx, 1, 0x70605040); /* ffffffff tesla UNK1670 */
3092 xf_emit(ctx, 1, 0xb8a89888); /* ffffffff tesla UNK1670 */
3093 xf_emit(ctx, 1, 0xf8e8d8c8); /* ffffffff tesla UNK1670 */
3094 xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */
3095 xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */
3096}
3097
3098static void
3099nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx)
3100{
3101 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
3102 if (dev_priv->chipset < 0xa0) {
3103 nv50_graph_construct_xfer_unk84xx(ctx);
3104 nv50_graph_construct_xfer_tprop(ctx);
3105 nv50_graph_construct_xfer_tex(ctx);
3106 nv50_graph_construct_xfer_unk8cxx(ctx);
3107 } else {
3108 nv50_graph_construct_xfer_tex(ctx);
3109 nv50_graph_construct_xfer_tprop(ctx);
3110 nv50_graph_construct_xfer_unk8cxx(ctx);
3111 nv50_graph_construct_xfer_unk84xx(ctx);
3112 }
3113}
3114
3115static void
3116nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx)
3117{
3118 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
3119 int i, mpcnt = 2;
3120 switch (dev_priv->chipset) {
3121 case 0x98:
3122 case 0xaa:
3123 mpcnt = 1;
3124 break;
3125 case 0x50:
3126 case 0x84:
3127 case 0x86:
3128 case 0x92:
3129 case 0x94:
3130 case 0x96:
3131 case 0xa8:
3132 case 0xac:
3133 mpcnt = 2;
3134 break;
3135 case 0xa0:
3136 case 0xa3:
3137 case 0xa5:
3138 case 0xaf:
3139 mpcnt = 3;
3140 break;
3141 }
3142 for (i = 0; i < mpcnt; i++) {
3143 xf_emit(ctx, 1, 0); /* ff */
3144 xf_emit(ctx, 1, 0x80); /* ffffffff tesla UNK1404 */
3145 xf_emit(ctx, 1, 0x80007004); /* ffffffff tesla UNK12B0 */
3146 xf_emit(ctx, 1, 0x04000400); /* ffffffff */
3147 if (dev_priv->chipset >= 0xa0)
3148 xf_emit(ctx, 1, 0xc0); /* 00007fff tesla UNK152C */
3149 xf_emit(ctx, 1, 0x1000); /* 0000ffff tesla UNK0D60 */
3150 xf_emit(ctx, 1, 0); /* ff/3ff */
3151 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */
3152 if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset == 0xa8 || IS_NVAAF(dev_priv->chipset)) {
3153 xf_emit(ctx, 1, 0xe00); /* 7fff */
3154 xf_emit(ctx, 1, 0x1e00); /* 7fff */
3155 }
3156 xf_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP */
3157 xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */
3158 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
3159 if (dev_priv->chipset == 0x50)
3160 xf_emit(ctx, 2, 0x1000); /* 7fff tesla UNK141C */
3161 xf_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP */
3162 xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */
3163 xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */
3164 xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */
3165 if (IS_NVAAF(dev_priv->chipset))
3166 xf_emit(ctx, 0xb, 0); /* RO */
3167 else if (dev_priv->chipset >= 0xa0)
3168 xf_emit(ctx, 0xc, 0); /* RO */
3169 else
3170 xf_emit(ctx, 0xa, 0); /* RO */
3171 }
3172 xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
3173 xf_emit(ctx, 1, 0); /* ff/3ff */
3174 if (dev_priv->chipset >= 0xa0) {
3175 xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */
3176 }
3177 xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */
3178 xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */
3179 xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */
3180 xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */
3181 xf_emit(ctx, 1, 1); /* 00000001 LANES32 */
3182 xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */
3183 xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */
3184 xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */
3185 xf_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */
3186 xf_emit(ctx, 1, 0x1fe21); /* 1ffff/3ffff[NVA0+] tesla UNk0FAC */
3187 xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */
3188 if (IS_NVA3F(dev_priv->chipset))
3189 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
3190 xf_emit(ctx, 1, 0); /* ff/3ff */
3191 xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */
3192 xf_emit(ctx, 1, 0); /* ff FP_ADDRESS_HIGH */
3193 xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */
3194 xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */
3195 xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */
3196 xf_emit(ctx, 1, 0); /* 000000ff FRAG_COLOR_CLAMP_EN */
3197 xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */
3198 xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */
3199 xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */
3200 xf_emit(ctx, 1, 0); /* 00000007 */
3201 xf_emit(ctx, 1, 0xfac6881); /* 0fffffff RT_CONTROL */
3202 xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */
3203 if (IS_NVA3F(dev_priv->chipset))
3204 xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */
3205 xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */
3206 xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */
3207 xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */
3208 xf_emit(ctx, 1, 4); /* ffffffff tesla UNK1400 */
3209 xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */
3210 xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */
3211 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */
3212 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */
3213 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */
3214 xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */
3215 xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */
3216 xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */
3217 xf_emit(ctx, 1, 1); /* 00000001 UNK133C */
3218 if (IS_NVA3F(dev_priv->chipset)) {
3219 xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */
3220 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */
3221 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */
3222 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */
3223 xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */
3224 xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */
3225 xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */
3226 xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */
3227 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */
3228 xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */
3229 }
3230 xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */
3231 xf_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */
3232 /* XXX: demagic this part some day */
3233 if (dev_priv->chipset == 0x50)
3234 xf_emit(ctx, 0x3a0, 0);
3235 else if (dev_priv->chipset < 0x94)
3236 xf_emit(ctx, 0x3a2, 0);
3237 else if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa)
3238 xf_emit(ctx, 0x39f, 0);
3239 else
3240 xf_emit(ctx, 0x3a3, 0);
3241 xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */
3242 xf_emit(ctx, 1, 0); /* 7 OPERATION */
3243 xf_emit(ctx, 1, 1); /* 1 DST_LINEAR */
3244 xf_emit(ctx, 0x2d, 0);
3245}
3246
3247static void
3248nv50_graph_construct_xfer2(struct nouveau_grctx *ctx)
3249{
3250 struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
3251 int i;
3252 uint32_t offset;
3253 uint32_t units = nv_rd32 (ctx->dev, 0x1540);
3254 int size = 0;
3255
3256 offset = (ctx->ctxvals_pos+0x3f)&~0x3f;
3257
3258 if (dev_priv->chipset < 0xa0) {
3259 for (i = 0; i < 8; i++) {
3260 ctx->ctxvals_pos = offset + i;
3261 /* that little bugger belongs to csched. No idea
3262 * what it's doing here. */
3263 if (i == 0)
3264 xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */
3265 if (units & (1 << i))
3266 nv50_graph_construct_xfer_mpc(ctx);
3267 if ((ctx->ctxvals_pos-offset)/8 > size)
3268 size = (ctx->ctxvals_pos-offset)/8;
3269 }
3270 } else {
3271 /* Strand 0: TPs 0, 1 */
3272 ctx->ctxvals_pos = offset;
3273 /* that little bugger belongs to csched. No idea
3274 * what it's doing here. */
3275 xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */
3276 if (units & (1 << 0))
3277 nv50_graph_construct_xfer_mpc(ctx);
3278 if (units & (1 << 1))
3279 nv50_graph_construct_xfer_mpc(ctx);
3280 if ((ctx->ctxvals_pos-offset)/8 > size)
3281 size = (ctx->ctxvals_pos-offset)/8;
3282
3283 /* Strand 1: TPs 2, 3 */
3284 ctx->ctxvals_pos = offset + 1;
3285 if (units & (1 << 2))
3286 nv50_graph_construct_xfer_mpc(ctx);
3287 if (units & (1 << 3))
3288 nv50_graph_construct_xfer_mpc(ctx);
3289 if ((ctx->ctxvals_pos-offset)/8 > size)
3290 size = (ctx->ctxvals_pos-offset)/8;
3291
3292 /* Strand 2: TPs 4, 5, 6 */
3293 ctx->ctxvals_pos = offset + 2;
3294 if (units & (1 << 4))
3295 nv50_graph_construct_xfer_mpc(ctx);
3296 if (units & (1 << 5))
3297 nv50_graph_construct_xfer_mpc(ctx);
3298 if (units & (1 << 6))
3299 nv50_graph_construct_xfer_mpc(ctx);
3300 if ((ctx->ctxvals_pos-offset)/8 > size)
3301 size = (ctx->ctxvals_pos-offset)/8;
3302
3303 /* Strand 3: TPs 7, 8, 9 */
3304 ctx->ctxvals_pos = offset + 3;
3305 if (units & (1 << 7))
3306 nv50_graph_construct_xfer_mpc(ctx);
3307 if (units & (1 << 8))
3308 nv50_graph_construct_xfer_mpc(ctx);
3309 if (units & (1 << 9))
3310 nv50_graph_construct_xfer_mpc(ctx);
3311 if ((ctx->ctxvals_pos-offset)/8 > size)
3312 size = (ctx->ctxvals_pos-offset)/8;
3313 }
3314 ctx->ctxvals_pos = offset + size * 8;
3315 ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f;
3316 cp_lsr (ctx, offset);
3317 cp_out (ctx, CP_SET_XFER_POINTER);
3318 cp_lsr (ctx, size);
3319 cp_out (ctx, CP_SEEK_2);
3320 cp_out (ctx, CP_XFER_2);
3321 cp_wait(ctx, XFER, BUSY);
3322}
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
new file mode 100644
index 00000000000..a7c12c94a5a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -0,0 +1,428 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28#include "drmP.h"
29#include "drm.h"
30
31#include "nouveau_drv.h"
32#include "nouveau_vm.h"
33
34#define BAR1_VM_BASE 0x0020000000ULL
35#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1)
36#define BAR3_VM_BASE 0x0000000000ULL
37#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3)
38
39struct nv50_instmem_priv {
40 uint32_t save1700[5]; /* 0x1700->0x1710 */
41
42 struct nouveau_gpuobj *bar1_dmaobj;
43 struct nouveau_gpuobj *bar3_dmaobj;
44};
45
46static void
47nv50_channel_del(struct nouveau_channel **pchan)
48{
49 struct nouveau_channel *chan;
50
51 chan = *pchan;
52 *pchan = NULL;
53 if (!chan)
54 return;
55
56 nouveau_gpuobj_ref(NULL, &chan->ramfc);
57 nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
58 nouveau_gpuobj_ref(NULL, &chan->vm_pd);
59 if (drm_mm_initialized(&chan->ramin_heap))
60 drm_mm_takedown(&chan->ramin_heap);
61 nouveau_gpuobj_ref(NULL, &chan->ramin);
62 kfree(chan);
63}
64
65static int
66nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
67 struct nouveau_channel **pchan)
68{
69 struct drm_nouveau_private *dev_priv = dev->dev_private;
70 u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
71 u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200;
72 struct nouveau_channel *chan;
73 int ret, i;
74
75 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
76 if (!chan)
77 return -ENOMEM;
78 chan->dev = dev;
79
80 ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
81 if (ret) {
82 nv50_channel_del(&chan);
83 return ret;
84 }
85
86 ret = drm_mm_init(&chan->ramin_heap, 0x6000, chan->ramin->size);
87 if (ret) {
88 nv50_channel_del(&chan);
89 return ret;
90 }
91
92 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 :
93 chan->ramin->pinst + pgd,
94 chan->ramin->vinst + pgd,
95 0x4000, NVOBJ_FLAG_ZERO_ALLOC,
96 &chan->vm_pd);
97 if (ret) {
98 nv50_channel_del(&chan);
99 return ret;
100 }
101
102 for (i = 0; i < 0x4000; i += 8) {
103 nv_wo32(chan->vm_pd, i + 0, 0x00000000);
104 nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe);
105 }
106
107 ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
108 if (ret) {
109 nv50_channel_del(&chan);
110 return ret;
111 }
112
113 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 :
114 chan->ramin->pinst + fc,
115 chan->ramin->vinst + fc, 0x100,
116 NVOBJ_FLAG_ZERO_ALLOC, &chan->ramfc);
117 if (ret) {
118 nv50_channel_del(&chan);
119 return ret;
120 }
121
122 *pchan = chan;
123 return 0;
124}
125
126int
127nv50_instmem_init(struct drm_device *dev)
128{
129 struct drm_nouveau_private *dev_priv = dev->dev_private;
130 struct nv50_instmem_priv *priv;
131 struct nouveau_channel *chan;
132 struct nouveau_vm *vm;
133 int ret, i;
134 u32 tmp;
135
136 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
137 if (!priv)
138 return -ENOMEM;
139 dev_priv->engine.instmem.priv = priv;
140
141 /* Save state, will restore at takedown. */
142 for (i = 0x1700; i <= 0x1710; i += 4)
143 priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i);
144
145 /* Global PRAMIN heap */
146 ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size);
147 if (ret) {
148 NV_ERROR(dev, "Failed to init RAMIN heap\n");
149 goto error;
150 }
151
152 /* BAR3 */
153 ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE,
154 &dev_priv->bar3_vm);
155 if (ret)
156 goto error;
157
158 ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8,
159 0x1000, NVOBJ_FLAG_DONT_MAP |
160 NVOBJ_FLAG_ZERO_ALLOC,
161 &dev_priv->bar3_vm->pgt[0].obj[0]);
162 if (ret)
163 goto error;
164 dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
165
166 nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
167
168 ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan);
169 if (ret)
170 goto error;
171 dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan;
172
173 ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE,
174 NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM,
175 NV_MEM_TYPE_VM, NV_MEM_COMP_VM,
176 &priv->bar3_dmaobj);
177 if (ret)
178 goto error;
179
180 nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12));
181 nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12));
182 nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4));
183
184 dev_priv->engine.instmem.flush(dev);
185 dev_priv->ramin_available = true;
186
187 tmp = nv_ro32(chan->ramin, 0);
188 nv_wo32(chan->ramin, 0, ~tmp);
189 if (nv_ro32(chan->ramin, 0) != ~tmp) {
190 NV_ERROR(dev, "PRAMIN readback failed\n");
191 ret = -EIO;
192 goto error;
193 }
194 nv_wo32(chan->ramin, 0, tmp);
195
196 /* BAR1 */
197 ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, &vm);
198 if (ret)
199 goto error;
200
201 ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd);
202 if (ret)
203 goto error;
204 nouveau_vm_ref(NULL, &vm, NULL);
205
206 ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE,
207 NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM,
208 NV_MEM_TYPE_VM, NV_MEM_COMP_VM,
209 &priv->bar1_dmaobj);
210 if (ret)
211 goto error;
212
213 nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4));
214 for (i = 0; i < 8; i++)
215 nv_wr32(dev, 0x1900 + (i*4), 0);
216
217 /* Create shared channel VM, space is reserved at the beginning
218 * to catch "NULL pointer" references
219 */
220 ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
221 &dev_priv->chan_vm);
222 if (ret)
223 return ret;
224
225 return 0;
226
227error:
228 nv50_instmem_takedown(dev);
229 return ret;
230}
231
232void
233nv50_instmem_takedown(struct drm_device *dev)
234{
235 struct drm_nouveau_private *dev_priv = dev->dev_private;
236 struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
237 struct nouveau_channel *chan = dev_priv->channels.ptr[0];
238 int i;
239
240 NV_DEBUG(dev, "\n");
241
242 if (!priv)
243 return;
244
245 dev_priv->ramin_available = false;
246
247 nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
248
249 for (i = 0x1700; i <= 0x1710; i += 4)
250 nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]);
251
252 nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj);
253 nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj);
254
255 nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd);
256 dev_priv->channels.ptr[127] = 0;
257 nv50_channel_del(&dev_priv->channels.ptr[0]);
258
259 nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
260 nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
261
262 if (drm_mm_initialized(&dev_priv->ramin_heap))
263 drm_mm_takedown(&dev_priv->ramin_heap);
264
265 dev_priv->engine.instmem.priv = NULL;
266 kfree(priv);
267}
268
269int
270nv50_instmem_suspend(struct drm_device *dev)
271{
272 struct drm_nouveau_private *dev_priv = dev->dev_private;
273
274 dev_priv->ramin_available = false;
275 return 0;
276}
277
278void
279nv50_instmem_resume(struct drm_device *dev)
280{
281 struct drm_nouveau_private *dev_priv = dev->dev_private;
282 struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
283 struct nouveau_channel *chan = dev_priv->channels.ptr[0];
284 int i;
285
286 /* Poke the relevant regs, and pray it works :) */
287 nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12));
288 nv_wr32(dev, NV50_PUNK_UNK1710, 0);
289 nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) |
290 NV50_PUNK_BAR_CFG_BASE_VALID);
291 nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) |
292 NV50_PUNK_BAR1_CTXDMA_VALID);
293 nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) |
294 NV50_PUNK_BAR3_CTXDMA_VALID);
295
296 for (i = 0; i < 8; i++)
297 nv_wr32(dev, 0x1900 + (i*4), 0);
298
299 dev_priv->ramin_available = true;
300}
301
302struct nv50_gpuobj_node {
303 struct nouveau_mem *vram;
304 struct nouveau_vma chan_vma;
305 u32 align;
306};
307
308int
309nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
310 u32 size, u32 align)
311{
312 struct drm_device *dev = gpuobj->dev;
313 struct drm_nouveau_private *dev_priv = dev->dev_private;
314 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
315 struct nv50_gpuobj_node *node = NULL;
316 int ret;
317
318 node = kzalloc(sizeof(*node), GFP_KERNEL);
319 if (!node)
320 return -ENOMEM;
321 node->align = align;
322
323 size = (size + 4095) & ~4095;
324 align = max(align, (u32)4096);
325
326 ret = vram->get(dev, size, align, 0, 0, &node->vram);
327 if (ret) {
328 kfree(node);
329 return ret;
330 }
331
332 gpuobj->vinst = node->vram->offset;
333
334 if (gpuobj->flags & NVOBJ_FLAG_VM) {
335 u32 flags = NV_MEM_ACCESS_RW;
336 if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER))
337 flags |= NV_MEM_ACCESS_SYS;
338
339 ret = nouveau_vm_get(chan->vm, size, 12, flags,
340 &node->chan_vma);
341 if (ret) {
342 vram->put(dev, &node->vram);
343 kfree(node);
344 return ret;
345 }
346
347 nouveau_vm_map(&node->chan_vma, node->vram);
348 gpuobj->linst = node->chan_vma.offset;
349 }
350
351 gpuobj->size = size;
352 gpuobj->node = node;
353 return 0;
354}
355
356void
357nv50_instmem_put(struct nouveau_gpuobj *gpuobj)
358{
359 struct drm_device *dev = gpuobj->dev;
360 struct drm_nouveau_private *dev_priv = dev->dev_private;
361 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
362 struct nv50_gpuobj_node *node;
363
364 node = gpuobj->node;
365 gpuobj->node = NULL;
366
367 if (node->chan_vma.node) {
368 nouveau_vm_unmap(&node->chan_vma);
369 nouveau_vm_put(&node->chan_vma);
370 }
371 vram->put(dev, &node->vram);
372 kfree(node);
373}
374
375int
376nv50_instmem_map(struct nouveau_gpuobj *gpuobj)
377{
378 struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
379 struct nv50_gpuobj_node *node = gpuobj->node;
380 int ret;
381
382 ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12,
383 NV_MEM_ACCESS_RW, &node->vram->bar_vma);
384 if (ret)
385 return ret;
386
387 nouveau_vm_map(&node->vram->bar_vma, node->vram);
388 gpuobj->pinst = node->vram->bar_vma.offset;
389 return 0;
390}
391
392void
393nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj)
394{
395 struct nv50_gpuobj_node *node = gpuobj->node;
396
397 if (node->vram->bar_vma.node) {
398 nouveau_vm_unmap(&node->vram->bar_vma);
399 nouveau_vm_put(&node->vram->bar_vma);
400 }
401}
402
403void
404nv50_instmem_flush(struct drm_device *dev)
405{
406 struct drm_nouveau_private *dev_priv = dev->dev_private;
407 unsigned long flags;
408
409 spin_lock_irqsave(&dev_priv->vm_lock, flags);
410 nv_wr32(dev, 0x00330c, 0x00000001);
411 if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000))
412 NV_ERROR(dev, "PRAMIN flush timeout\n");
413 spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
414}
415
416void
417nv84_instmem_flush(struct drm_device *dev)
418{
419 struct drm_nouveau_private *dev_priv = dev->dev_private;
420 unsigned long flags;
421
422 spin_lock_irqsave(&dev_priv->vm_lock, flags);
423 nv_wr32(dev, 0x070000, 0x00000001);
424 if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000))
425 NV_ERROR(dev, "PRAMIN flush timeout\n");
426 spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
427}
428
diff --git a/drivers/gpu/drm/nouveau/nv50_mc.c b/drivers/gpu/drm/nouveau/nv50_mc.c
new file mode 100644
index 00000000000..e0a9c3faa20
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_mc.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) 2007 Ben Skeggs.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "nouveau_drv.h"
30
31int
32nv50_mc_init(struct drm_device *dev)
33{
34 nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
35 return 0;
36}
37
38void nv50_mc_takedown(struct drm_device *dev)
39{
40}
diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c
new file mode 100644
index 00000000000..b57a2d180ad
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c
@@ -0,0 +1,256 @@
1/*
2 * Copyright 2011 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_ramht.h"
28
29struct nv50_mpeg_engine {
30 struct nouveau_exec_engine base;
31};
32
33static inline u32
34CTX_PTR(struct drm_device *dev, u32 offset)
35{
36 struct drm_nouveau_private *dev_priv = dev->dev_private;
37
38 if (dev_priv->chipset == 0x50)
39 offset += 0x0260;
40 else
41 offset += 0x0060;
42
43 return offset;
44}
45
46static int
47nv50_mpeg_context_new(struct nouveau_channel *chan, int engine)
48{
49 struct drm_device *dev = chan->dev;
50 struct drm_nouveau_private *dev_priv = dev->dev_private;
51 struct nouveau_gpuobj *ramin = chan->ramin;
52 struct nouveau_gpuobj *ctx = NULL;
53 int ret;
54
55 NV_DEBUG(dev, "ch%d\n", chan->id);
56
57 ret = nouveau_gpuobj_new(dev, chan, 128 * 4, 0, NVOBJ_FLAG_ZERO_ALLOC |
58 NVOBJ_FLAG_ZERO_FREE, &ctx);
59 if (ret)
60 return ret;
61
62 nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002);
63 nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->vinst + ctx->size - 1);
64 nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->vinst);
65 nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0);
66 nv_wo32(ramin, CTX_PTR(dev, 0x10), 0);
67 nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000);
68
69 nv_wo32(ctx, 0x70, 0x00801ec1);
70 nv_wo32(ctx, 0x7c, 0x0000037c);
71 dev_priv->engine.instmem.flush(dev);
72
73 chan->engctx[engine] = ctx;
74 return 0;
75}
76
77static void
78nv50_mpeg_context_del(struct nouveau_channel *chan, int engine)
79{
80 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
81 struct nouveau_gpuobj *ctx = chan->engctx[engine];
82 struct drm_device *dev = chan->dev;
83 unsigned long flags;
84 u32 inst, i;
85
86 if (!chan->ramin)
87 return;
88
89 inst = chan->ramin->vinst >> 12;
90 inst |= 0x80000000;
91
92 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
93 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
94 if (nv_rd32(dev, 0x00b318) == inst)
95 nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
96 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
97 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
98
99 for (i = 0x00; i <= 0x14; i += 4)
100 nv_wo32(chan->ramin, CTX_PTR(dev, i), 0x00000000);
101 nouveau_gpuobj_ref(NULL, &ctx);
102 chan->engctx[engine] = NULL;
103}
104
105static int
106nv50_mpeg_object_new(struct nouveau_channel *chan, int engine,
107 u32 handle, u16 class)
108{
109 struct drm_device *dev = chan->dev;
110 struct drm_nouveau_private *dev_priv = dev->dev_private;
111 struct nouveau_gpuobj *obj = NULL;
112 int ret;
113
114 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
115 if (ret)
116 return ret;
117 obj->engine = 2;
118 obj->class = class;
119
120 nv_wo32(obj, 0x00, class);
121 nv_wo32(obj, 0x04, 0x00000000);
122 nv_wo32(obj, 0x08, 0x00000000);
123 nv_wo32(obj, 0x0c, 0x00000000);
124 dev_priv->engine.instmem.flush(dev);
125
126 ret = nouveau_ramht_insert(chan, handle, obj);
127 nouveau_gpuobj_ref(NULL, &obj);
128 return ret;
129}
130
131static void
132nv50_mpeg_tlb_flush(struct drm_device *dev, int engine)
133{
134 nv50_vm_flush_engine(dev, 0x08);
135}
136
137static int
138nv50_mpeg_init(struct drm_device *dev, int engine)
139{
140 nv_wr32(dev, 0x00b32c, 0x00000000);
141 nv_wr32(dev, 0x00b314, 0x00000100);
142 nv_wr32(dev, 0x00b0e0, 0x0000001a);
143
144 nv_wr32(dev, 0x00b220, 0x00000044);
145 nv_wr32(dev, 0x00b300, 0x00801ec1);
146 nv_wr32(dev, 0x00b390, 0x00000000);
147 nv_wr32(dev, 0x00b394, 0x00000000);
148 nv_wr32(dev, 0x00b398, 0x00000000);
149 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
150
151 nv_wr32(dev, 0x00b100, 0xffffffff);
152 nv_wr32(dev, 0x00b140, 0xffffffff);
153
154 if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
155 NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
156 return -EBUSY;
157 }
158
159 return 0;
160}
161
162static int
163nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
164{
165 /*XXX: context save for s/r */
166 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
167 nv_wr32(dev, 0x00b140, 0x00000000);
168 return 0;
169}
170
171static void
172nv50_mpeg_isr(struct drm_device *dev)
173{
174 u32 stat = nv_rd32(dev, 0x00b100);
175 u32 type = nv_rd32(dev, 0x00b230);
176 u32 mthd = nv_rd32(dev, 0x00b234);
177 u32 data = nv_rd32(dev, 0x00b238);
178 u32 show = stat;
179
180 if (stat & 0x01000000) {
181 /* happens on initial binding of the object */
182 if (type == 0x00000020 && mthd == 0x0000) {
183 nv_wr32(dev, 0x00b308, 0x00000100);
184 show &= ~0x01000000;
185 }
186 }
187
188 if (show && nouveau_ratelimit()) {
189 NV_INFO(dev, "PMPEG - 0x%08x 0x%08x 0x%08x 0x%08x\n",
190 stat, type, mthd, data);
191 }
192
193 nv_wr32(dev, 0x00b100, stat);
194 nv_wr32(dev, 0x00b230, 0x00000001);
195 nv50_fb_vm_trap(dev, 1);
196}
197
198static void
199nv50_vpe_isr(struct drm_device *dev)
200{
201 if (nv_rd32(dev, 0x00b100))
202 nv50_mpeg_isr(dev);
203
204 if (nv_rd32(dev, 0x00b800)) {
205 u32 stat = nv_rd32(dev, 0x00b800);
206 NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
207 nv_wr32(dev, 0xb800, stat);
208 }
209}
210
211static void
212nv50_mpeg_destroy(struct drm_device *dev, int engine)
213{
214 struct nv50_mpeg_engine *pmpeg = nv_engine(dev, engine);
215
216 nouveau_irq_unregister(dev, 0);
217
218 NVOBJ_ENGINE_DEL(dev, MPEG);
219 kfree(pmpeg);
220}
221
222int
223nv50_mpeg_create(struct drm_device *dev)
224{
225 struct drm_nouveau_private *dev_priv = dev->dev_private;
226 struct nv50_mpeg_engine *pmpeg;
227
228 pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
229 if (!pmpeg)
230 return -ENOMEM;
231
232 pmpeg->base.destroy = nv50_mpeg_destroy;
233 pmpeg->base.init = nv50_mpeg_init;
234 pmpeg->base.fini = nv50_mpeg_fini;
235 pmpeg->base.context_new = nv50_mpeg_context_new;
236 pmpeg->base.context_del = nv50_mpeg_context_del;
237 pmpeg->base.object_new = nv50_mpeg_object_new;
238 pmpeg->base.tlb_flush = nv50_mpeg_tlb_flush;
239
240 if (dev_priv->chipset == 0x50) {
241 nouveau_irq_register(dev, 0, nv50_vpe_isr);
242 NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
243 NVOBJ_CLASS(dev, 0x3174, MPEG);
244#if 0
245 NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
246 NVOBJ_CLASS(dev, 0x4075, ME);
247#endif
248 } else {
249 nouveau_irq_register(dev, 0, nv50_mpeg_isr);
250 NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
251 NVOBJ_CLASS(dev, 0x8274, MPEG);
252 }
253
254 return 0;
255
256}
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
new file mode 100644
index 00000000000..ffe8b483b7b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -0,0 +1,343 @@
1/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "drmP.h"
28#include "drm_crtc_helper.h"
29
30#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
31#include "nouveau_reg.h"
32#include "nouveau_drv.h"
33#include "nouveau_dma.h"
34#include "nouveau_encoder.h"
35#include "nouveau_connector.h"
36#include "nouveau_crtc.h"
37#include "nv50_display.h"
38
39static void
40nv50_sor_disconnect(struct drm_encoder *encoder)
41{
42 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
43 struct drm_device *dev = encoder->dev;
44 struct nouveau_channel *evo = nv50_display(dev)->master;
45 int ret;
46
47 if (!nv_encoder->crtc)
48 return;
49 nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);
50
51 NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or);
52
53 ret = RING_SPACE(evo, 4);
54 if (ret) {
55 NV_ERROR(dev, "no space while disconnecting SOR\n");
56 return;
57 }
58 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
59 OUT_RING (evo, 0);
60 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
61 OUT_RING (evo, 0);
62
63 nv_encoder->crtc = NULL;
64 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
65}
66
67static void
68nv50_sor_dpms(struct drm_encoder *encoder, int mode)
69{
70 struct drm_device *dev = encoder->dev;
71 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
72 struct drm_encoder *enc;
73 uint32_t val;
74 int or = nv_encoder->or;
75
76 NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode);
77
78 nv_encoder->last_dpms = mode;
79 list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
80 struct nouveau_encoder *nvenc = nouveau_encoder(enc);
81
82 if (nvenc == nv_encoder ||
83 (nvenc->dcb->type != OUTPUT_TMDS &&
84 nvenc->dcb->type != OUTPUT_LVDS &&
85 nvenc->dcb->type != OUTPUT_DP) ||
86 nvenc->dcb->or != nv_encoder->dcb->or)
87 continue;
88
89 if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
90 return;
91 }
92
93 /* wait for it to be done */
94 if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or),
95 NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) {
96 NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or);
97 NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or,
98 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)));
99 }
100
101 val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or));
102
103 if (mode == DRM_MODE_DPMS_ON)
104 val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON;
105 else
106 val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON;
107
108 nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val |
109 NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING);
110 if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or),
111 NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) {
112 NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or);
113 NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or,
114 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or)));
115 }
116
117 if (nv_encoder->dcb->type == OUTPUT_DP) {
118 struct nouveau_i2c_chan *auxch;
119
120 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
121 if (!auxch)
122 return;
123
124 if (mode == DRM_MODE_DPMS_ON) {
125 u8 status = DP_SET_POWER_D0;
126 nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
127 nouveau_dp_link_train(encoder);
128 } else {
129 u8 status = DP_SET_POWER_D3;
130 nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
131 }
132 }
133}
134
135static void
136nv50_sor_save(struct drm_encoder *encoder)
137{
138 NV_ERROR(encoder->dev, "!!\n");
139}
140
141static void
142nv50_sor_restore(struct drm_encoder *encoder)
143{
144 NV_ERROR(encoder->dev, "!!\n");
145}
146
147static bool
148nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
149 struct drm_display_mode *adjusted_mode)
150{
151 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
152 struct nouveau_connector *connector;
153
154 NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);
155
156 connector = nouveau_encoder_connector_get(nv_encoder);
157 if (!connector) {
158 NV_ERROR(encoder->dev, "Encoder has no connector\n");
159 return false;
160 }
161
162 if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
163 connector->native_mode) {
164 int id = adjusted_mode->base.id;
165 *adjusted_mode = *connector->native_mode;
166 adjusted_mode->base.id = id;
167 }
168
169 return true;
170}
171
172static void
173nv50_sor_prepare(struct drm_encoder *encoder)
174{
175}
176
177static void
178nv50_sor_commit(struct drm_encoder *encoder)
179{
180}
181
182static void
183nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
184 struct drm_display_mode *adjusted_mode)
185{
186 struct nouveau_channel *evo = nv50_display(encoder->dev)->master;
187 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
188 struct drm_device *dev = encoder->dev;
189 struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
190 uint32_t mode_ctl = 0;
191 int ret;
192
193 NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n",
194 nv_encoder->or, nv_encoder->dcb->type, crtc->index);
195
196 nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
197
198 switch (nv_encoder->dcb->type) {
199 case OUTPUT_TMDS:
200 if (nv_encoder->dcb->sorconf.link & 1) {
201 if (adjusted_mode->clock < 165000)
202 mode_ctl = 0x0100;
203 else
204 mode_ctl = 0x0500;
205 } else
206 mode_ctl = 0x0200;
207 break;
208 case OUTPUT_DP:
209 mode_ctl |= (nv_encoder->dp.mc_unknown << 16);
210 if (nv_encoder->dcb->sorconf.link & 1)
211 mode_ctl |= 0x00000800;
212 else
213 mode_ctl |= 0x00000900;
214 break;
215 default:
216 break;
217 }
218
219 if (crtc->index == 1)
220 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1;
221 else
222 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0;
223
224 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
225 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC;
226
227 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
228 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
229
230 ret = RING_SPACE(evo, 2);
231 if (ret) {
232 NV_ERROR(dev, "no space while connecting SOR\n");
233 return;
234 }
235 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
236 OUT_RING(evo, mode_ctl);
237
238 nv_encoder->crtc = encoder->crtc;
239}
240
241static struct drm_crtc *
242nv50_sor_crtc_get(struct drm_encoder *encoder)
243{
244 return nouveau_encoder(encoder)->crtc;
245}
246
247static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = {
248 .dpms = nv50_sor_dpms,
249 .save = nv50_sor_save,
250 .restore = nv50_sor_restore,
251 .mode_fixup = nv50_sor_mode_fixup,
252 .prepare = nv50_sor_prepare,
253 .commit = nv50_sor_commit,
254 .mode_set = nv50_sor_mode_set,
255 .get_crtc = nv50_sor_crtc_get,
256 .detect = NULL,
257 .disable = nv50_sor_disconnect
258};
259
260static void
261nv50_sor_destroy(struct drm_encoder *encoder)
262{
263 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
264
265 if (!encoder)
266 return;
267
268 NV_DEBUG_KMS(encoder->dev, "\n");
269
270 drm_encoder_cleanup(encoder);
271
272 kfree(nv_encoder);
273}
274
275static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
276 .destroy = nv50_sor_destroy,
277};
278
279int
280nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
281{
282 struct nouveau_encoder *nv_encoder = NULL;
283 struct drm_device *dev = connector->dev;
284 struct drm_encoder *encoder;
285 int type;
286
287 NV_DEBUG_KMS(dev, "\n");
288
289 switch (entry->type) {
290 case OUTPUT_TMDS:
291 case OUTPUT_DP:
292 type = DRM_MODE_ENCODER_TMDS;
293 break;
294 case OUTPUT_LVDS:
295 type = DRM_MODE_ENCODER_LVDS;
296 break;
297 default:
298 return -EINVAL;
299 }
300
301 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
302 if (!nv_encoder)
303 return -ENOMEM;
304 encoder = to_drm_encoder(nv_encoder);
305
306 nv_encoder->dcb = entry;
307 nv_encoder->or = ffs(entry->or) - 1;
308 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
309
310 drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type);
311 drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs);
312
313 encoder->possible_crtcs = entry->heads;
314 encoder->possible_clones = 0;
315
316 if (nv_encoder->dcb->type == OUTPUT_DP) {
317 int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
318 uint32_t tmp;
319
320 tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
321 if (!tmp)
322 tmp = nv_rd32(dev, 0x610798 + (or * 8));
323
324 switch ((tmp & 0x00000f00) >> 8) {
325 case 8:
326 case 9:
327 nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16;
328 tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
329 nv_encoder->dp.unk0 = tmp & 0x000001fc;
330 tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
331 nv_encoder->dp.unk1 = tmp & 0x010f7f3f;
332 break;
333 default:
334 break;
335 }
336
337 if (!nv_encoder->dp.mc_unknown)
338 nv_encoder->dp.mc_unknown = 5;
339 }
340
341 drm_mode_connector_attach_encoder(connector, encoder);
342 return 0;
343}
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
new file mode 100644
index 00000000000..40b84f22d81
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -0,0 +1,182 @@
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_vm.h"
29
30void
31nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
32 struct nouveau_gpuobj *pgt[2])
33{
34 u64 phys = 0xdeadcafe00000000ULL;
35 u32 coverage = 0;
36
37 if (pgt[0]) {
38 phys = 0x00000003 | pgt[0]->vinst; /* present, 4KiB pages */
39 coverage = (pgt[0]->size >> 3) << 12;
40 } else
41 if (pgt[1]) {
42 phys = 0x00000001 | pgt[1]->vinst; /* present */
43 coverage = (pgt[1]->size >> 3) << 16;
44 }
45
46 if (phys & 1) {
47 if (coverage <= 32 * 1024 * 1024)
48 phys |= 0x60;
49 else if (coverage <= 64 * 1024 * 1024)
50 phys |= 0x40;
51 else if (coverage < 128 * 1024 * 1024)
52 phys |= 0x20;
53 }
54
55 nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys));
56 nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys));
57}
58
59static inline u64
60nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
61{
62 struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private;
63
64 phys |= 1; /* present */
65 phys |= (u64)memtype << 40;
66
67 /* IGPs don't have real VRAM, re-target to stolen system memory */
68 if (target == 0 && dev_priv->vram_sys_base) {
69 phys += dev_priv->vram_sys_base;
70 target = 3;
71 }
72
73 phys |= target << 4;
74
75 if (vma->access & NV_MEM_ACCESS_SYS)
76 phys |= (1 << 6);
77
78 if (!(vma->access & NV_MEM_ACCESS_WO))
79 phys |= (1 << 3);
80
81 return phys;
82}
83
84void
85nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
86 struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
87{
88 u32 comp = (mem->memtype & 0x180) >> 7;
89 u32 block;
90 int i;
91
92 phys = nv50_vm_addr(vma, phys, mem->memtype, 0);
93 pte <<= 3;
94 cnt <<= 3;
95
96 while (cnt) {
97 u32 offset_h = upper_32_bits(phys);
98 u32 offset_l = lower_32_bits(phys);
99
100 for (i = 7; i >= 0; i--) {
101 block = 1 << (i + 3);
102 if (cnt >= block && !(pte & (block - 1)))
103 break;
104 }
105 offset_l |= (i << 7);
106
107 phys += block << (vma->node->type - 3);
108 cnt -= block;
109 if (comp) {
110 u32 tag = mem->tag->start + ((delta >> 16) * comp);
111 offset_h |= (tag << 17);
112 delta += block << (vma->node->type - 3);
113 }
114
115 while (block) {
116 nv_wo32(pgt, pte + 0, offset_l);
117 nv_wo32(pgt, pte + 4, offset_h);
118 pte += 8;
119 block -= 8;
120 }
121 }
122}
123
124void
125nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
126 struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
127{
128 pte <<= 3;
129 while (cnt--) {
130 u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2);
131 nv_wo32(pgt, pte + 0, lower_32_bits(phys));
132 nv_wo32(pgt, pte + 4, upper_32_bits(phys));
133 pte += 8;
134 }
135}
136
137void
138nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
139{
140 pte <<= 3;
141 while (cnt--) {
142 nv_wo32(pgt, pte + 0, 0x00000000);
143 nv_wo32(pgt, pte + 4, 0x00000000);
144 pte += 8;
145 }
146}
147
148void
149nv50_vm_flush(struct nouveau_vm *vm)
150{
151 struct drm_nouveau_private *dev_priv = vm->dev->dev_private;
152 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
153 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
154 int i;
155
156 pinstmem->flush(vm->dev);
157
158 /* BAR */
159 if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) {
160 nv50_vm_flush_engine(vm->dev, 6);
161 return;
162 }
163
164 pfifo->tlb_flush(vm->dev);
165 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
166 if (atomic_read(&vm->engref[i]))
167 dev_priv->eng[i]->tlb_flush(vm->dev, i);
168 }
169}
170
171void
172nv50_vm_flush_engine(struct drm_device *dev, int engine)
173{
174 struct drm_nouveau_private *dev_priv = dev->dev_private;
175 unsigned long flags;
176
177 spin_lock_irqsave(&dev_priv->vm_lock, flags);
178 nv_wr32(dev, 0x100c80, (engine << 16) | 1);
179 if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000))
180 NV_ERROR(dev, "vm flush timeout: engine %d\n", engine);
181 spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
182}
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
new file mode 100644
index 00000000000..af32daecd1e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -0,0 +1,220 @@
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_mm.h"
28
29static int types[0x80] = {
30 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0,
32 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
35 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2,
37 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
38};
39
40bool
41nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
42{
43 int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
44
45 if (likely(type < ARRAY_SIZE(types) && types[type]))
46 return true;
47 return false;
48}
49
50void
51nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
52{
53 struct drm_nouveau_private *dev_priv = dev->dev_private;
54 struct nouveau_mm *mm = dev_priv->engine.vram.mm;
55 struct nouveau_mm_node *this;
56 struct nouveau_mem *mem;
57
58 mem = *pmem;
59 *pmem = NULL;
60 if (unlikely(mem == NULL))
61 return;
62
63 mutex_lock(&mm->mutex);
64 while (!list_empty(&mem->regions)) {
65 this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
66
67 list_del(&this->rl_entry);
68 nouveau_mm_put(mm, this);
69 }
70
71 if (mem->tag) {
72 drm_mm_put_block(mem->tag);
73 mem->tag = NULL;
74 }
75 mutex_unlock(&mm->mutex);
76
77 kfree(mem);
78}
79
80int
81nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
82 u32 memtype, struct nouveau_mem **pmem)
83{
84 struct drm_nouveau_private *dev_priv = dev->dev_private;
85 struct nouveau_mm *mm = dev_priv->engine.vram.mm;
86 struct nouveau_mm_node *r;
87 struct nouveau_mem *mem;
88 int comp = (memtype & 0x300) >> 8;
89 int type = (memtype & 0x07f);
90 int ret;
91
92 if (!types[type])
93 return -EINVAL;
94 size >>= 12;
95 align >>= 12;
96 size_nc >>= 12;
97
98 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
99 if (!mem)
100 return -ENOMEM;
101
102 mutex_lock(&mm->mutex);
103 if (comp) {
104 if (align == 16) {
105 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
106 int n = (size >> 4) * comp;
107
108 mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0);
109 if (mem->tag)
110 mem->tag = drm_mm_get_block(mem->tag, n, 0);
111 }
112
113 if (unlikely(!mem->tag))
114 comp = 0;
115 }
116
117 INIT_LIST_HEAD(&mem->regions);
118 mem->dev = dev_priv->dev;
119 mem->memtype = (comp << 7) | type;
120 mem->size = size;
121
122 do {
123 ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r);
124 if (ret) {
125 mutex_unlock(&mm->mutex);
126 nv50_vram_del(dev, &mem);
127 return ret;
128 }
129
130 list_add_tail(&r->rl_entry, &mem->regions);
131 size -= r->length;
132 } while (size);
133 mutex_unlock(&mm->mutex);
134
135 r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
136 mem->offset = (u64)r->offset << 12;
137 *pmem = mem;
138 return 0;
139}
140
141static u32
142nv50_vram_rblock(struct drm_device *dev)
143{
144 struct drm_nouveau_private *dev_priv = dev->dev_private;
145 int i, parts, colbits, rowbitsa, rowbitsb, banks;
146 u64 rowsize, predicted;
147 u32 r0, r4, rt, ru, rblock_size;
148
149 r0 = nv_rd32(dev, 0x100200);
150 r4 = nv_rd32(dev, 0x100204);
151 rt = nv_rd32(dev, 0x100250);
152 ru = nv_rd32(dev, 0x001540);
153 NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru);
154
155 for (i = 0, parts = 0; i < 8; i++) {
156 if (ru & (0x00010000 << i))
157 parts++;
158 }
159
160 colbits = (r4 & 0x0000f000) >> 12;
161 rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
162 rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
163 banks = ((r4 & 0x01000000) ? 8 : 4);
164
165 rowsize = parts * banks * (1 << colbits) * 8;
166 predicted = rowsize << rowbitsa;
167 if (r0 & 0x00000004)
168 predicted += rowsize << rowbitsb;
169
170 if (predicted != dev_priv->vram_size) {
171 NV_WARN(dev, "memory controller reports %dMiB VRAM\n",
172 (u32)(dev_priv->vram_size >> 20));
173 NV_WARN(dev, "we calculated %dMiB VRAM\n",
174 (u32)(predicted >> 20));
175 }
176
177 rblock_size = rowsize;
178 if (rt & 1)
179 rblock_size *= 3;
180
181 NV_DEBUG(dev, "rblock %d bytes\n", rblock_size);
182 return rblock_size;
183}
184
185int
186nv50_vram_init(struct drm_device *dev)
187{
188 struct drm_nouveau_private *dev_priv = dev->dev_private;
189 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
190 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
191 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
192 u32 rblock, length;
193
194 dev_priv->vram_size = nv_rd32(dev, 0x10020c);
195 dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
196 dev_priv->vram_size &= 0xffffffff00ULL;
197
198 /* IGPs, no funky reordering happens here, they don't have VRAM */
199 if (dev_priv->chipset == 0xaa ||
200 dev_priv->chipset == 0xac ||
201 dev_priv->chipset == 0xaf) {
202 dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
203 rblock = 4096 >> 12;
204 } else {
205 rblock = nv50_vram_rblock(dev) >> 12;
206 }
207
208 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
209
210 return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
211}
212
213void
214nv50_vram_fini(struct drm_device *dev)
215{
216 struct drm_nouveau_private *dev_priv = dev->dev_private;
217 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
218
219 nouveau_mm_fini(&vram->mm);
220}
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
new file mode 100644
index 00000000000..edece9c616e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
@@ -0,0 +1,193 @@
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_util.h"
28#include "nouveau_vm.h"
29#include "nouveau_ramht.h"
30
31struct nv84_crypt_engine {
32 struct nouveau_exec_engine base;
33};
34
35static int
36nv84_crypt_context_new(struct nouveau_channel *chan, int engine)
37{
38 struct drm_device *dev = chan->dev;
39 struct drm_nouveau_private *dev_priv = dev->dev_private;
40 struct nouveau_gpuobj *ramin = chan->ramin;
41 struct nouveau_gpuobj *ctx;
42 int ret;
43
44 NV_DEBUG(dev, "ch%d\n", chan->id);
45
46 ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC |
47 NVOBJ_FLAG_ZERO_FREE, &ctx);
48 if (ret)
49 return ret;
50
51 nv_wo32(ramin, 0xa0, 0x00190000);
52 nv_wo32(ramin, 0xa4, ctx->vinst + ctx->size - 1);
53 nv_wo32(ramin, 0xa8, ctx->vinst);
54 nv_wo32(ramin, 0xac, 0);
55 nv_wo32(ramin, 0xb0, 0);
56 nv_wo32(ramin, 0xb4, 0);
57 dev_priv->engine.instmem.flush(dev);
58
59 atomic_inc(&chan->vm->engref[engine]);
60 chan->engctx[engine] = ctx;
61 return 0;
62}
63
64static void
65nv84_crypt_context_del(struct nouveau_channel *chan, int engine)
66{
67 struct nouveau_gpuobj *ctx = chan->engctx[engine];
68 struct drm_device *dev = chan->dev;
69 u32 inst;
70
71 inst = (chan->ramin->vinst >> 12);
72 inst |= 0x80000000;
73
74 /* mark context as invalid if still on the hardware, not
75 * doing this causes issues the next time PCRYPT is used,
76 * unsurprisingly :)
77 */
78 nv_wr32(dev, 0x10200c, 0x00000000);
79 if (nv_rd32(dev, 0x102188) == inst)
80 nv_mask(dev, 0x102188, 0x80000000, 0x00000000);
81 if (nv_rd32(dev, 0x10218c) == inst)
82 nv_mask(dev, 0x10218c, 0x80000000, 0x00000000);
83 nv_wr32(dev, 0x10200c, 0x00000010);
84
85 nouveau_gpuobj_ref(NULL, &ctx);
86
87 atomic_dec(&chan->vm->engref[engine]);
88 chan->engctx[engine] = NULL;
89}
90
91static int
92nv84_crypt_object_new(struct nouveau_channel *chan, int engine,
93 u32 handle, u16 class)
94{
95 struct drm_device *dev = chan->dev;
96 struct drm_nouveau_private *dev_priv = dev->dev_private;
97 struct nouveau_gpuobj *obj = NULL;
98 int ret;
99
100 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
101 if (ret)
102 return ret;
103 obj->engine = 5;
104 obj->class = class;
105
106 nv_wo32(obj, 0x00, class);
107 dev_priv->engine.instmem.flush(dev);
108
109 ret = nouveau_ramht_insert(chan, handle, obj);
110 nouveau_gpuobj_ref(NULL, &obj);
111 return ret;
112}
113
114static void
115nv84_crypt_tlb_flush(struct drm_device *dev, int engine)
116{
117 nv50_vm_flush_engine(dev, 0x0a);
118}
119
120static void
121nv84_crypt_isr(struct drm_device *dev)
122{
123 u32 stat = nv_rd32(dev, 0x102130);
124 u32 mthd = nv_rd32(dev, 0x102190);
125 u32 data = nv_rd32(dev, 0x102194);
126 u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff;
127 int show = nouveau_ratelimit();
128
129 if (show) {
130 NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n",
131 stat, mthd, data, inst);
132 }
133
134 nv_wr32(dev, 0x102130, stat);
135 nv_wr32(dev, 0x10200c, 0x10);
136
137 nv50_fb_vm_trap(dev, show);
138}
139
140static int
141nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend)
142{
143 nv_wr32(dev, 0x102140, 0x00000000);
144 return 0;
145}
146
147static int
148nv84_crypt_init(struct drm_device *dev, int engine)
149{
150 nv_mask(dev, 0x000200, 0x00004000, 0x00000000);
151 nv_mask(dev, 0x000200, 0x00004000, 0x00004000);
152
153 nv_wr32(dev, 0x102130, 0xffffffff);
154 nv_wr32(dev, 0x102140, 0xffffffbf);
155
156 nv_wr32(dev, 0x10200c, 0x00000010);
157 return 0;
158}
159
160static void
161nv84_crypt_destroy(struct drm_device *dev, int engine)
162{
163 struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine);
164
165 NVOBJ_ENGINE_DEL(dev, CRYPT);
166
167 nouveau_irq_unregister(dev, 14);
168 kfree(pcrypt);
169}
170
171int
172nv84_crypt_create(struct drm_device *dev)
173{
174 struct nv84_crypt_engine *pcrypt;
175
176 pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL);
177 if (!pcrypt)
178 return -ENOMEM;
179
180 pcrypt->base.destroy = nv84_crypt_destroy;
181 pcrypt->base.init = nv84_crypt_init;
182 pcrypt->base.fini = nv84_crypt_fini;
183 pcrypt->base.context_new = nv84_crypt_context_new;
184 pcrypt->base.context_del = nv84_crypt_context_del;
185 pcrypt->base.object_new = nv84_crypt_object_new;
186 pcrypt->base.tlb_flush = nv84_crypt_tlb_flush;
187
188 nouveau_irq_register(dev, 14, nv84_crypt_isr);
189
190 NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base);
191 NVOBJ_CLASS (dev, 0x74c1, CRYPT);
192 return 0;
193}
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c
new file mode 100644
index 00000000000..8f356d58e40
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nva3_copy.c
@@ -0,0 +1,226 @@
1/*
2 * Copyright 2011 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 <linux/firmware.h>
26#include "drmP.h"
27#include "nouveau_drv.h"
28#include "nouveau_util.h"
29#include "nouveau_vm.h"
30#include "nouveau_ramht.h"
31#include "nva3_copy.fuc.h"
32
33struct nva3_copy_engine {
34 struct nouveau_exec_engine base;
35};
36
37static int
38nva3_copy_context_new(struct nouveau_channel *chan, int engine)
39{
40 struct drm_device *dev = chan->dev;
41 struct drm_nouveau_private *dev_priv = dev->dev_private;
42 struct nouveau_gpuobj *ramin = chan->ramin;
43 struct nouveau_gpuobj *ctx = NULL;
44 int ret;
45
46 NV_DEBUG(dev, "ch%d\n", chan->id);
47
48 ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC |
49 NVOBJ_FLAG_ZERO_FREE, &ctx);
50 if (ret)
51 return ret;
52
53 nv_wo32(ramin, 0xc0, 0x00190000);
54 nv_wo32(ramin, 0xc4, ctx->vinst + ctx->size - 1);
55 nv_wo32(ramin, 0xc8, ctx->vinst);
56 nv_wo32(ramin, 0xcc, 0x00000000);
57 nv_wo32(ramin, 0xd0, 0x00000000);
58 nv_wo32(ramin, 0xd4, 0x00000000);
59 dev_priv->engine.instmem.flush(dev);
60
61 atomic_inc(&chan->vm->engref[engine]);
62 chan->engctx[engine] = ctx;
63 return 0;
64}
65
66static int
67nva3_copy_object_new(struct nouveau_channel *chan, int engine,
68 u32 handle, u16 class)
69{
70 struct nouveau_gpuobj *ctx = chan->engctx[engine];
71
72 /* fuc engine doesn't need an object, our ramht code does.. */
73 ctx->engine = 3;
74 ctx->class = class;
75 return nouveau_ramht_insert(chan, handle, ctx);
76}
77
78static void
79nva3_copy_context_del(struct nouveau_channel *chan, int engine)
80{
81 struct nouveau_gpuobj *ctx = chan->engctx[engine];
82 struct drm_device *dev = chan->dev;
83 u32 inst;
84
85 inst = (chan->ramin->vinst >> 12);
86 inst |= 0x40000000;
87
88 /* disable fifo access */
89 nv_wr32(dev, 0x104048, 0x00000000);
90 /* mark channel as unloaded if it's currently active */
91 if (nv_rd32(dev, 0x104050) == inst)
92 nv_mask(dev, 0x104050, 0x40000000, 0x00000000);
93 /* mark next channel as invalid if it's about to be loaded */
94 if (nv_rd32(dev, 0x104054) == inst)
95 nv_mask(dev, 0x104054, 0x40000000, 0x00000000);
96 /* restore fifo access */
97 nv_wr32(dev, 0x104048, 0x00000003);
98
99 for (inst = 0xc0; inst <= 0xd4; inst += 4)
100 nv_wo32(chan->ramin, inst, 0x00000000);
101
102 nouveau_gpuobj_ref(NULL, &ctx);
103
104 atomic_dec(&chan->vm->engref[engine]);
105 chan->engctx[engine] = ctx;
106}
107
108static void
109nva3_copy_tlb_flush(struct drm_device *dev, int engine)
110{
111 nv50_vm_flush_engine(dev, 0x0d);
112}
113
114static int
115nva3_copy_init(struct drm_device *dev, int engine)
116{
117 int i;
118
119 nv_mask(dev, 0x000200, 0x00002000, 0x00000000);
120 nv_mask(dev, 0x000200, 0x00002000, 0x00002000);
121 nv_wr32(dev, 0x104014, 0xffffffff); /* disable all interrupts */
122
123 /* upload ucode */
124 nv_wr32(dev, 0x1041c0, 0x01000000);
125 for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++)
126 nv_wr32(dev, 0x1041c4, nva3_pcopy_data[i]);
127
128 nv_wr32(dev, 0x104180, 0x01000000);
129 for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) {
130 if ((i & 0x3f) == 0)
131 nv_wr32(dev, 0x104188, i >> 6);
132 nv_wr32(dev, 0x104184, nva3_pcopy_code[i]);
133 }
134
135 /* start it running */
136 nv_wr32(dev, 0x10410c, 0x00000000);
137 nv_wr32(dev, 0x104104, 0x00000000); /* ENTRY */
138 nv_wr32(dev, 0x104100, 0x00000002); /* TRIGGER */
139 return 0;
140}
141
142static int
143nva3_copy_fini(struct drm_device *dev, int engine, bool suspend)
144{
145 nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
146
147 /* trigger fuc context unload */
148 nv_wait(dev, 0x104008, 0x0000000c, 0x00000000);
149 nv_mask(dev, 0x104054, 0x40000000, 0x00000000);
150 nv_wr32(dev, 0x104000, 0x00000008);
151 nv_wait(dev, 0x104008, 0x00000008, 0x00000000);
152
153 nv_wr32(dev, 0x104014, 0xffffffff);
154 return 0;
155}
156
157static struct nouveau_enum nva3_copy_isr_error_name[] = {
158 { 0x0001, "ILLEGAL_MTHD" },
159 { 0x0002, "INVALID_ENUM" },
160 { 0x0003, "INVALID_BITFIELD" },
161 {}
162};
163
164static void
165nva3_copy_isr(struct drm_device *dev)
166{
167 u32 dispatch = nv_rd32(dev, 0x10401c);
168 u32 stat = nv_rd32(dev, 0x104008) & dispatch & ~(dispatch >> 16);
169 u32 inst = nv_rd32(dev, 0x104050) & 0x3fffffff;
170 u32 ssta = nv_rd32(dev, 0x104040) & 0x0000ffff;
171 u32 addr = nv_rd32(dev, 0x104040) >> 16;
172 u32 mthd = (addr & 0x07ff) << 2;
173 u32 subc = (addr & 0x3800) >> 11;
174 u32 data = nv_rd32(dev, 0x104044);
175 int chid = nv50_graph_isr_chid(dev, inst);
176
177 if (stat & 0x00000040) {
178 NV_INFO(dev, "PCOPY: DISPATCH_ERROR [");
179 nouveau_enum_print(nva3_copy_isr_error_name, ssta);
180 printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n",
181 chid, inst, subc, mthd, data);
182 nv_wr32(dev, 0x104004, 0x00000040);
183 stat &= ~0x00000040;
184 }
185
186 if (stat) {
187 NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat);
188 nv_wr32(dev, 0x104004, stat);
189 }
190 nv50_fb_vm_trap(dev, 1);
191}
192
193static void
194nva3_copy_destroy(struct drm_device *dev, int engine)
195{
196 struct nva3_copy_engine *pcopy = nv_engine(dev, engine);
197
198 nouveau_irq_unregister(dev, 22);
199
200 NVOBJ_ENGINE_DEL(dev, COPY0);
201 kfree(pcopy);
202}
203
204int
205nva3_copy_create(struct drm_device *dev)
206{
207 struct nva3_copy_engine *pcopy;
208
209 pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL);
210 if (!pcopy)
211 return -ENOMEM;
212
213 pcopy->base.destroy = nva3_copy_destroy;
214 pcopy->base.init = nva3_copy_init;
215 pcopy->base.fini = nva3_copy_fini;
216 pcopy->base.context_new = nva3_copy_context_new;
217 pcopy->base.context_del = nva3_copy_context_del;
218 pcopy->base.object_new = nva3_copy_object_new;
219 pcopy->base.tlb_flush = nva3_copy_tlb_flush;
220
221 nouveau_irq_register(dev, 22, nva3_copy_isr);
222
223 NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base);
224 NVOBJ_CLASS(dev, 0x85b5, COPY0);
225 return 0;
226}
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc b/drivers/gpu/drm/nouveau/nva3_copy.fuc
new file mode 100644
index 00000000000..eaf35f8321e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc
@@ -0,0 +1,870 @@
1/* fuc microcode for copy engine on nva3- chipsets
2 *
3 * Copyright 2011 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the 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) OR AUTHOR(S) 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
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Ben Skeggs
24 */
25
26/* To build for nva3:nvc0
27 * m4 -DNVA3 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nva3_copy.fuc.h
28 *
29 * To build for nvc0-
30 * m4 -DNVC0 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_copy.fuc.h
31 */
32
33ifdef(`NVA3',
34.section nva3_pcopy_data,
35.section nvc0_pcopy_data
36)
37
38ctx_object: .b32 0
39ifdef(`NVA3',
40ctx_dma:
41ctx_dma_query: .b32 0
42ctx_dma_src: .b32 0
43ctx_dma_dst: .b32 0
44,)
45.equ ctx_dma_count 3
46ctx_query_address_high: .b32 0
47ctx_query_address_low: .b32 0
48ctx_query_counter: .b32 0
49ctx_src_address_high: .b32 0
50ctx_src_address_low: .b32 0
51ctx_src_pitch: .b32 0
52ctx_src_tile_mode: .b32 0
53ctx_src_xsize: .b32 0
54ctx_src_ysize: .b32 0
55ctx_src_zsize: .b32 0
56ctx_src_zoff: .b32 0
57ctx_src_xoff: .b32 0
58ctx_src_yoff: .b32 0
59ctx_src_cpp: .b32 0
60ctx_dst_address_high: .b32 0
61ctx_dst_address_low: .b32 0
62ctx_dst_pitch: .b32 0
63ctx_dst_tile_mode: .b32 0
64ctx_dst_xsize: .b32 0
65ctx_dst_ysize: .b32 0
66ctx_dst_zsize: .b32 0
67ctx_dst_zoff: .b32 0
68ctx_dst_xoff: .b32 0
69ctx_dst_yoff: .b32 0
70ctx_dst_cpp: .b32 0
71ctx_format: .b32 0
72ctx_swz_const0: .b32 0
73ctx_swz_const1: .b32 0
74ctx_xcnt: .b32 0
75ctx_ycnt: .b32 0
76.align 256
77
78dispatch_table:
79// mthd 0x0000, NAME
80.b16 0x000 1
81.b32 ctx_object ~0xffffffff
82// mthd 0x0100, NOP
83.b16 0x040 1
84.b32 0x00010000 + cmd_nop ~0xffffffff
85// mthd 0x0140, PM_TRIGGER
86.b16 0x050 1
87.b32 0x00010000 + cmd_pm_trigger ~0xffffffff
88ifdef(`NVA3', `
89// mthd 0x0180-0x018c, DMA_
90.b16 0x060 ctx_dma_count
91dispatch_dma:
92.b32 0x00010000 + cmd_dma ~0xffffffff
93.b32 0x00010000 + cmd_dma ~0xffffffff
94.b32 0x00010000 + cmd_dma ~0xffffffff
95',)
96// mthd 0x0200-0x0218, SRC_TILE
97.b16 0x80 7
98.b32 ctx_src_tile_mode ~0x00000fff
99.b32 ctx_src_xsize ~0x0007ffff
100.b32 ctx_src_ysize ~0x00001fff
101.b32 ctx_src_zsize ~0x000007ff
102.b32 ctx_src_zoff ~0x00000fff
103.b32 ctx_src_xoff ~0x0007ffff
104.b32 ctx_src_yoff ~0x00001fff
105// mthd 0x0220-0x0238, DST_TILE
106.b16 0x88 7
107.b32 ctx_dst_tile_mode ~0x00000fff
108.b32 ctx_dst_xsize ~0x0007ffff
109.b32 ctx_dst_ysize ~0x00001fff
110.b32 ctx_dst_zsize ~0x000007ff
111.b32 ctx_dst_zoff ~0x00000fff
112.b32 ctx_dst_xoff ~0x0007ffff
113.b32 ctx_dst_yoff ~0x00001fff
114// mthd 0x0300-0x0304, EXEC, WRCACHE_FLUSH
115.b16 0xc0 2
116.b32 0x00010000 + cmd_exec ~0xffffffff
117.b32 0x00010000 + cmd_wrcache_flush ~0xffffffff
118// mthd 0x030c-0x0340, various stuff
119.b16 0xc3 14
120.b32 ctx_src_address_high ~0x000000ff
121.b32 ctx_src_address_low ~0xfffffff0
122.b32 ctx_dst_address_high ~0x000000ff
123.b32 ctx_dst_address_low ~0xfffffff0
124.b32 ctx_src_pitch ~0x0007ffff
125.b32 ctx_dst_pitch ~0x0007ffff
126.b32 ctx_xcnt ~0x0000ffff
127.b32 ctx_ycnt ~0x00001fff
128.b32 ctx_format ~0x0333ffff
129.b32 ctx_swz_const0 ~0xffffffff
130.b32 ctx_swz_const1 ~0xffffffff
131.b32 ctx_query_address_high ~0x000000ff
132.b32 ctx_query_address_low ~0xffffffff
133.b32 ctx_query_counter ~0xffffffff
134.b16 0x800 0
135
136ifdef(`NVA3',
137.section nva3_pcopy_code,
138.section nvc0_pcopy_code
139)
140
141main:
142 clear b32 $r0
143 mov $sp $r0
144
145 // setup i0 handler and route fifo and ctxswitch to it
146 mov $r1 ih
147 mov $iv0 $r1
148 mov $r1 0x400
149 movw $r2 0xfff3
150 sethi $r2 0
151 iowr I[$r2 + 0x300] $r2
152
153 // enable interrupts
154 or $r2 0xc
155 iowr I[$r1] $r2
156 bset $flags ie0
157
158 // enable fifo access and context switching
159 mov $r1 0x1200
160 mov $r2 3
161 iowr I[$r1] $r2
162
163 // sleep forever, waking for interrupts
164 bset $flags $p0
165 spin:
166 sleep $p0
167 bra spin
168
169// i0 handler
170ih:
171 iord $r1 I[$r0 + 0x200]
172
173 and $r2 $r1 0x00000008
174 bra e ih_no_chsw
175 call chsw
176 ih_no_chsw:
177 and $r2 $r1 0x00000004
178 bra e ih_no_cmd
179 call dispatch
180
181 ih_no_cmd:
182 and $r1 $r1 0x0000000c
183 iowr I[$r0 + 0x100] $r1
184 iret
185
186// $p1 direction (0 = unload, 1 = load)
187// $r3 channel
188swctx:
189 mov $r4 0x7700
190 mov $xtargets $r4
191ifdef(`NVA3', `
192 // target 7 hardcoded to ctx dma object
193 mov $xdbase $r0
194', ` // NVC0
195 // read SCRATCH3 to decide if we are PCOPY0 or PCOPY1
196 mov $r4 0x2100
197 iord $r4 I[$r4 + 0]
198 and $r4 1
199 shl b32 $r4 4
200 add b32 $r4 0x30
201
202 // channel is in vram
203 mov $r15 0x61c
204 shl b32 $r15 6
205 mov $r5 0x114
206 iowrs I[$r15] $r5
207
208 // read 16-byte PCOPYn info, containing context pointer, from channel
209 shl b32 $r5 $r3 4
210 add b32 $r5 2
211 mov $xdbase $r5
212 mov $r5 $sp
213 // get a chunk of stack space, aligned to 256 byte boundary
214 sub b32 $r5 0x100
215 mov $r6 0xff
216 not b32 $r6
217 and $r5 $r6
218 sethi $r5 0x00020000
219 xdld $r4 $r5
220 xdwait
221 sethi $r5 0
222
223 // set context pointer, from within channel VM
224 mov $r14 0
225 iowrs I[$r15] $r14
226 ld b32 $r4 D[$r5 + 0]
227 shr b32 $r4 8
228 ld b32 $r6 D[$r5 + 4]
229 shl b32 $r6 24
230 or $r4 $r6
231 mov $xdbase $r4
232')
233 // 256-byte context, at start of data segment
234 mov b32 $r4 $r0
235 sethi $r4 0x60000
236
237 // swap!
238 bra $p1 swctx_load
239 xdst $r0 $r4
240 bra swctx_done
241 swctx_load:
242 xdld $r0 $r4
243 swctx_done:
244 xdwait
245 ret
246
247chsw:
248 // read current channel
249 mov $r2 0x1400
250 iord $r3 I[$r2]
251
252 // if it's active, unload it and return
253 xbit $r15 $r3 0x1e
254 bra e chsw_no_unload
255 bclr $flags $p1
256 call swctx
257 bclr $r3 0x1e
258 iowr I[$r2] $r3
259 mov $r4 1
260 iowr I[$r2 + 0x200] $r4
261 ret
262
263 // read next channel
264 chsw_no_unload:
265 iord $r3 I[$r2 + 0x100]
266
267 // is there a channel waiting to be loaded?
268 xbit $r13 $r3 0x1e
269 bra e chsw_finish_load
270 bset $flags $p1
271 call swctx
272ifdef(`NVA3',
273 // load dma objects back into TARGET regs
274 mov $r5 ctx_dma
275 mov $r6 ctx_dma_count
276 chsw_load_ctx_dma:
277 ld b32 $r7 D[$r5 + $r6 * 4]
278 add b32 $r8 $r6 0x180
279 shl b32 $r8 8
280 iowr I[$r8] $r7
281 sub b32 $r6 1
282 bra nc chsw_load_ctx_dma
283,)
284
285 chsw_finish_load:
286 mov $r3 2
287 iowr I[$r2 + 0x200] $r3
288 ret
289
290dispatch:
291 // read incoming fifo command
292 mov $r3 0x1900
293 iord $r2 I[$r3 + 0x100]
294 iord $r3 I[$r3 + 0x000]
295 and $r4 $r2 0x7ff
296 // $r2 will be used to store exception data
297 shl b32 $r2 0x10
298
299 // lookup method in the dispatch table, ILLEGAL_MTHD if not found
300 mov $r5 dispatch_table
301 clear b32 $r6
302 clear b32 $r7
303 dispatch_loop:
304 ld b16 $r6 D[$r5 + 0]
305 ld b16 $r7 D[$r5 + 2]
306 add b32 $r5 4
307 cmpu b32 $r4 $r6
308 bra c dispatch_illegal_mthd
309 add b32 $r7 $r6
310 cmpu b32 $r4 $r7
311 bra c dispatch_valid_mthd
312 sub b32 $r7 $r6
313 shl b32 $r7 3
314 add b32 $r5 $r7
315 bra dispatch_loop
316
317 // ensure no bits set in reserved fields, INVALID_BITFIELD
318 dispatch_valid_mthd:
319 sub b32 $r4 $r6
320 shl b32 $r4 3
321 add b32 $r4 $r5
322 ld b32 $r5 D[$r4 + 4]
323 and $r5 $r3
324 cmpu b32 $r5 0
325 bra ne dispatch_invalid_bitfield
326
327 // depending on dispatch flags: execute method, or save data as state
328 ld b16 $r5 D[$r4 + 0]
329 ld b16 $r6 D[$r4 + 2]
330 cmpu b32 $r6 0
331 bra ne dispatch_cmd
332 st b32 D[$r5] $r3
333 bra dispatch_done
334 dispatch_cmd:
335 bclr $flags $p1
336 call $r5
337 bra $p1 dispatch_error
338 bra dispatch_done
339
340 dispatch_invalid_bitfield:
341 or $r2 2
342 dispatch_illegal_mthd:
343 or $r2 1
344
345 // store exception data in SCRATCH0/SCRATCH1, signal hostirq
346 dispatch_error:
347 mov $r4 0x1000
348 iowr I[$r4 + 0x000] $r2
349 iowr I[$r4 + 0x100] $r3
350 mov $r2 0x40
351 iowr I[$r0] $r2
352 hostirq_wait:
353 iord $r2 I[$r0 + 0x200]
354 and $r2 0x40
355 cmpu b32 $r2 0
356 bra ne hostirq_wait
357
358 dispatch_done:
359 mov $r2 0x1d00
360 mov $r3 1
361 iowr I[$r2] $r3
362 ret
363
364// No-operation
365//
366// Inputs:
367// $r1: irqh state
368// $r2: hostirq state
369// $r3: data
370// $r4: dispatch table entry
371// Outputs:
372// $r1: irqh state
373// $p1: set on error
374// $r2: hostirq state
375// $r3: data
376cmd_nop:
377 ret
378
379// PM_TRIGGER
380//
381// Inputs:
382// $r1: irqh state
383// $r2: hostirq state
384// $r3: data
385// $r4: dispatch table entry
386// Outputs:
387// $r1: irqh state
388// $p1: set on error
389// $r2: hostirq state
390// $r3: data
391cmd_pm_trigger:
392 mov $r2 0x2200
393 clear b32 $r3
394 sethi $r3 0x20000
395 iowr I[$r2] $r3
396 ret
397
398ifdef(`NVA3',
399// SET_DMA_* method handler
400//
401// Inputs:
402// $r1: irqh state
403// $r2: hostirq state
404// $r3: data
405// $r4: dispatch table entry
406// Outputs:
407// $r1: irqh state
408// $p1: set on error
409// $r2: hostirq state
410// $r3: data
411cmd_dma:
412 sub b32 $r4 dispatch_dma
413 shr b32 $r4 1
414 bset $r3 0x1e
415 st b32 D[$r4 + ctx_dma] $r3
416 add b32 $r4 0x600
417 shl b32 $r4 6
418 iowr I[$r4] $r3
419 ret
420,)
421
422// Calculates the hw swizzle mask and adjusts the surface's xcnt to match
423//
424cmd_exec_set_format:
425 // zero out a chunk of the stack to store the swizzle into
426 add $sp -0x10
427 st b32 D[$sp + 0x00] $r0
428 st b32 D[$sp + 0x04] $r0
429 st b32 D[$sp + 0x08] $r0
430 st b32 D[$sp + 0x0c] $r0
431
432 // extract cpp, src_ncomp and dst_ncomp from FORMAT
433 ld b32 $r4 D[$r0 + ctx_format]
434 extr $r5 $r4 16:17
435 add b32 $r5 1
436 extr $r6 $r4 20:21
437 add b32 $r6 1
438 extr $r7 $r4 24:25
439 add b32 $r7 1
440
441 // convert FORMAT swizzle mask to hw swizzle mask
442 bclr $flags $p2
443 clear b32 $r8
444 clear b32 $r9
445 ncomp_loop:
446 and $r10 $r4 0xf
447 shr b32 $r4 4
448 clear b32 $r11
449 bpc_loop:
450 cmpu b8 $r10 4
451 bra nc cmp_c0
452 mulu $r12 $r10 $r5
453 add b32 $r12 $r11
454 bset $flags $p2
455 bra bpc_next
456 cmp_c0:
457 bra ne cmp_c1
458 mov $r12 0x10
459 add b32 $r12 $r11
460 bra bpc_next
461 cmp_c1:
462 cmpu b8 $r10 6
463 bra nc cmp_zero
464 mov $r12 0x14
465 add b32 $r12 $r11
466 bra bpc_next
467 cmp_zero:
468 mov $r12 0x80
469 bpc_next:
470 st b8 D[$sp + $r8] $r12
471 add b32 $r8 1
472 add b32 $r11 1
473 cmpu b32 $r11 $r5
474 bra c bpc_loop
475 add b32 $r9 1
476 cmpu b32 $r9 $r7
477 bra c ncomp_loop
478
479 // SRC_XCNT = (xcnt * src_cpp), or 0 if no src ref in swz (hw will hang)
480 mulu $r6 $r5
481 st b32 D[$r0 + ctx_src_cpp] $r6
482 ld b32 $r8 D[$r0 + ctx_xcnt]
483 mulu $r6 $r8
484 bra $p2 dst_xcnt
485 clear b32 $r6
486
487 dst_xcnt:
488 mulu $r7 $r5
489 st b32 D[$r0 + ctx_dst_cpp] $r7
490 mulu $r7 $r8
491
492 mov $r5 0x810
493 shl b32 $r5 6
494 iowr I[$r5 + 0x000] $r6
495 iowr I[$r5 + 0x100] $r7
496 add b32 $r5 0x800
497 ld b32 $r6 D[$r0 + ctx_dst_cpp]
498 sub b32 $r6 1
499 shl b32 $r6 8
500 ld b32 $r7 D[$r0 + ctx_src_cpp]
501 sub b32 $r7 1
502 or $r6 $r7
503 iowr I[$r5 + 0x000] $r6
504 add b32 $r5 0x100
505 ld b32 $r6 D[$sp + 0x00]
506 iowr I[$r5 + 0x000] $r6
507 ld b32 $r6 D[$sp + 0x04]
508 iowr I[$r5 + 0x100] $r6
509 ld b32 $r6 D[$sp + 0x08]
510 iowr I[$r5 + 0x200] $r6
511 ld b32 $r6 D[$sp + 0x0c]
512 iowr I[$r5 + 0x300] $r6
513 add b32 $r5 0x400
514 ld b32 $r6 D[$r0 + ctx_swz_const0]
515 iowr I[$r5 + 0x000] $r6
516 ld b32 $r6 D[$r0 + ctx_swz_const1]
517 iowr I[$r5 + 0x100] $r6
518 add $sp 0x10
519 ret
520
521// Setup to handle a tiled surface
522//
523// Calculates a number of parameters the hardware requires in order
524// to correctly handle tiling.
525//
526// Offset calculation is performed as follows (Tp/Th/Td from TILE_MODE):
527// nTx = round_up(w * cpp, 1 << Tp) >> Tp
528// nTy = round_up(h, 1 << Th) >> Th
529// Txo = (x * cpp) & ((1 << Tp) - 1)
530// Tx = (x * cpp) >> Tp
531// Tyo = y & ((1 << Th) - 1)
532// Ty = y >> Th
533// Tzo = z & ((1 << Td) - 1)
534// Tz = z >> Td
535//
536// off = (Tzo << Tp << Th) + (Tyo << Tp) + Txo
537// off += ((Tz * nTy * nTx)) + (Ty * nTx) + Tx) << Td << Th << Tp;
538//
539// Inputs:
540// $r4: hw command (0x104800)
541// $r5: ctx offset adjustment for src/dst selection
542// $p2: set if dst surface
543//
544cmd_exec_set_surface_tiled:
545 // translate TILE_MODE into Tp, Th, Td shift values
546 ld b32 $r7 D[$r5 + ctx_src_tile_mode]
547 extr $r9 $r7 8:11
548 extr $r8 $r7 4:7
549ifdef(`NVA3',
550 add b32 $r8 2
551,
552 add b32 $r8 3
553)
554 extr $r7 $r7 0:3
555 cmp b32 $r7 0xe
556 bra ne xtile64
557 mov $r7 4
558 bra xtileok
559 xtile64:
560 xbit $r7 $flags $p2
561 add b32 $r7 17
562 bset $r4 $r7
563 mov $r7 6
564 xtileok:
565
566 // Op = (x * cpp) & ((1 << Tp) - 1)
567 // Tx = (x * cpp) >> Tp
568 ld b32 $r10 D[$r5 + ctx_src_xoff]
569 ld b32 $r11 D[$r5 + ctx_src_cpp]
570 mulu $r10 $r11
571 mov $r11 1
572 shl b32 $r11 $r7
573 sub b32 $r11 1
574 and $r12 $r10 $r11
575 shr b32 $r10 $r7
576
577 // Tyo = y & ((1 << Th) - 1)
578 // Ty = y >> Th
579 ld b32 $r13 D[$r5 + ctx_src_yoff]
580 mov $r14 1
581 shl b32 $r14 $r8
582 sub b32 $r14 1
583 and $r11 $r13 $r14
584 shr b32 $r13 $r8
585
586 // YTILE = ((1 << Th) << 12) | ((1 << Th) - Tyo)
587 add b32 $r14 1
588 shl b32 $r15 $r14 12
589 sub b32 $r14 $r11
590 or $r15 $r14
591 xbit $r6 $flags $p2
592 add b32 $r6 0x208
593 shl b32 $r6 8
594 iowr I[$r6 + 0x000] $r15
595
596 // Op += Tyo << Tp
597 shl b32 $r11 $r7
598 add b32 $r12 $r11
599
600 // nTx = ((w * cpp) + ((1 << Tp) - 1) >> Tp)
601 ld b32 $r15 D[$r5 + ctx_src_xsize]
602 ld b32 $r11 D[$r5 + ctx_src_cpp]
603 mulu $r15 $r11
604 mov $r11 1
605 shl b32 $r11 $r7
606 sub b32 $r11 1
607 add b32 $r15 $r11
608 shr b32 $r15 $r7
609 push $r15
610
611 // nTy = (h + ((1 << Th) - 1)) >> Th
612 ld b32 $r15 D[$r5 + ctx_src_ysize]
613 mov $r11 1
614 shl b32 $r11 $r8
615 sub b32 $r11 1
616 add b32 $r15 $r11
617 shr b32 $r15 $r8
618 push $r15
619
620 // Tys = Tp + Th
621 // CFG_YZ_TILE_SIZE = ((1 << Th) >> 2) << Td
622 add b32 $r7 $r8
623 sub b32 $r8 2
624 mov $r11 1
625 shl b32 $r11 $r8
626 shl b32 $r11 $r9
627
628 // Tzo = z & ((1 << Td) - 1)
629 // Tz = z >> Td
630 // Op += Tzo << Tys
631 // Ts = Tys + Td
632 ld b32 $r8 D[$r5 + ctx_src_zoff]
633 mov $r14 1
634 shl b32 $r14 $r9
635 sub b32 $r14 1
636 and $r15 $r8 $r14
637 shl b32 $r15 $r7
638 add b32 $r12 $r15
639 add b32 $r7 $r9
640 shr b32 $r8 $r9
641
642 // Ot = ((Tz * nTy * nTx) + (Ty * nTx) + Tx) << Ts
643 pop $r15
644 pop $r9
645 mulu $r13 $r9
646 add b32 $r10 $r13
647 mulu $r8 $r9
648 mulu $r8 $r15
649 add b32 $r10 $r8
650 shl b32 $r10 $r7
651
652 // PITCH = (nTx - 1) << Ts
653 sub b32 $r9 1
654 shl b32 $r9 $r7
655 iowr I[$r6 + 0x200] $r9
656
657 // SRC_ADDRESS_LOW = (Ot + Op) & 0xffffffff
658 // CFG_ADDRESS_HIGH |= ((Ot + Op) >> 32) << 16
659 ld b32 $r7 D[$r5 + ctx_src_address_low]
660 ld b32 $r8 D[$r5 + ctx_src_address_high]
661 add b32 $r10 $r12
662 add b32 $r7 $r10
663 adc b32 $r8 0
664 shl b32 $r8 16
665 or $r8 $r11
666 sub b32 $r6 0x600
667 iowr I[$r6 + 0x000] $r7
668 add b32 $r6 0x400
669 iowr I[$r6 + 0x000] $r8
670 ret
671
672// Setup to handle a linear surface
673//
674// Nothing to see here.. Sets ADDRESS and PITCH, pretty non-exciting
675//
676cmd_exec_set_surface_linear:
677 xbit $r6 $flags $p2
678 add b32 $r6 0x202
679 shl b32 $r6 8
680 ld b32 $r7 D[$r5 + ctx_src_address_low]
681 iowr I[$r6 + 0x000] $r7
682 add b32 $r6 0x400
683 ld b32 $r7 D[$r5 + ctx_src_address_high]
684 shl b32 $r7 16
685 iowr I[$r6 + 0x000] $r7
686 add b32 $r6 0x400
687 ld b32 $r7 D[$r5 + ctx_src_pitch]
688 iowr I[$r6 + 0x000] $r7
689 ret
690
691// wait for regs to be available for use
692cmd_exec_wait:
693 push $r0
694 push $r1
695 mov $r0 0x800
696 shl b32 $r0 6
697 loop:
698 iord $r1 I[$r0]
699 and $r1 1
700 bra ne loop
701 pop $r1
702 pop $r0
703 ret
704
705cmd_exec_query:
706 // if QUERY_SHORT not set, write out { -, 0, TIME_LO, TIME_HI }
707 xbit $r4 $r3 13
708 bra ne query_counter
709 call cmd_exec_wait
710 mov $r4 0x80c
711 shl b32 $r4 6
712 ld b32 $r5 D[$r0 + ctx_query_address_low]
713 add b32 $r5 4
714 iowr I[$r4 + 0x000] $r5
715 iowr I[$r4 + 0x100] $r0
716 mov $r5 0xc
717 iowr I[$r4 + 0x200] $r5
718 add b32 $r4 0x400
719 ld b32 $r5 D[$r0 + ctx_query_address_high]
720 shl b32 $r5 16
721 iowr I[$r4 + 0x000] $r5
722 add b32 $r4 0x500
723 mov $r5 0x00000b00
724 sethi $r5 0x00010000
725 iowr I[$r4 + 0x000] $r5
726 mov $r5 0x00004040
727 shl b32 $r5 1
728 sethi $r5 0x80800000
729 iowr I[$r4 + 0x100] $r5
730 mov $r5 0x00001110
731 sethi $r5 0x13120000
732 iowr I[$r4 + 0x200] $r5
733 mov $r5 0x00001514
734 sethi $r5 0x17160000
735 iowr I[$r4 + 0x300] $r5
736 mov $r5 0x00002601
737 sethi $r5 0x00010000
738 mov $r4 0x800
739 shl b32 $r4 6
740 iowr I[$r4 + 0x000] $r5
741
742 // write COUNTER
743 query_counter:
744 call cmd_exec_wait
745 mov $r4 0x80c
746 shl b32 $r4 6
747 ld b32 $r5 D[$r0 + ctx_query_address_low]
748 iowr I[$r4 + 0x000] $r5
749 iowr I[$r4 + 0x100] $r0
750 mov $r5 0x4
751 iowr I[$r4 + 0x200] $r5
752 add b32 $r4 0x400
753 ld b32 $r5 D[$r0 + ctx_query_address_high]
754 shl b32 $r5 16
755 iowr I[$r4 + 0x000] $r5
756 add b32 $r4 0x500
757 mov $r5 0x00000300
758 iowr I[$r4 + 0x000] $r5
759 mov $r5 0x00001110
760 sethi $r5 0x13120000
761 iowr I[$r4 + 0x100] $r5
762 ld b32 $r5 D[$r0 + ctx_query_counter]
763 add b32 $r4 0x500
764 iowr I[$r4 + 0x000] $r5
765 mov $r5 0x00002601
766 sethi $r5 0x00010000
767 mov $r4 0x800
768 shl b32 $r4 6
769 iowr I[$r4 + 0x000] $r5
770 ret
771
772// Execute a copy operation
773//
774// Inputs:
775// $r1: irqh state
776// $r2: hostirq state
777// $r3: data
778// 000002000 QUERY_SHORT
779// 000001000 QUERY
780// 000000100 DST_LINEAR
781// 000000010 SRC_LINEAR
782// 000000001 FORMAT
783// $r4: dispatch table entry
784// Outputs:
785// $r1: irqh state
786// $p1: set on error
787// $r2: hostirq state
788// $r3: data
789cmd_exec:
790 call cmd_exec_wait
791
792 // if format requested, call function to calculate it, otherwise
793 // fill in cpp/xcnt for both surfaces as if (cpp == 1)
794 xbit $r15 $r3 0
795 bra e cmd_exec_no_format
796 call cmd_exec_set_format
797 mov $r4 0x200
798 bra cmd_exec_init_src_surface
799 cmd_exec_no_format:
800 mov $r6 0x810
801 shl b32 $r6 6
802 mov $r7 1
803 st b32 D[$r0 + ctx_src_cpp] $r7
804 st b32 D[$r0 + ctx_dst_cpp] $r7
805 ld b32 $r7 D[$r0 + ctx_xcnt]
806 iowr I[$r6 + 0x000] $r7
807 iowr I[$r6 + 0x100] $r7
808 clear b32 $r4
809
810 cmd_exec_init_src_surface:
811 bclr $flags $p2
812 clear b32 $r5
813 xbit $r15 $r3 4
814 bra e src_tiled
815 call cmd_exec_set_surface_linear
816 bra cmd_exec_init_dst_surface
817 src_tiled:
818 call cmd_exec_set_surface_tiled
819 bset $r4 7
820
821 cmd_exec_init_dst_surface:
822 bset $flags $p2
823 mov $r5 ctx_dst_address_high - ctx_src_address_high
824 xbit $r15 $r3 8
825 bra e dst_tiled
826 call cmd_exec_set_surface_linear
827 bra cmd_exec_kick
828 dst_tiled:
829 call cmd_exec_set_surface_tiled
830 bset $r4 8
831
832 cmd_exec_kick:
833 mov $r5 0x800
834 shl b32 $r5 6
835 ld b32 $r6 D[$r0 + ctx_ycnt]
836 iowr I[$r5 + 0x100] $r6
837 mov $r6 0x0041
838 // SRC_TARGET = 1, DST_TARGET = 2
839 sethi $r6 0x44000000
840 or $r4 $r6
841 iowr I[$r5] $r4
842
843 // if requested, queue up a QUERY write after the copy has completed
844 xbit $r15 $r3 12
845 bra e cmd_exec_done
846 call cmd_exec_query
847
848 cmd_exec_done:
849 ret
850
851// Flush write cache
852//
853// Inputs:
854// $r1: irqh state
855// $r2: hostirq state
856// $r3: data
857// $r4: dispatch table entry
858// Outputs:
859// $r1: irqh state
860// $p1: set on error
861// $r2: hostirq state
862// $r3: data
863cmd_wrcache_flush:
864 mov $r2 0x2200
865 clear b32 $r3
866 sethi $r3 0x10000
867 iowr I[$r2] $r3
868 ret
869
870.align 0x100
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h
new file mode 100644
index 00000000000..2731de22ebe
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h
@@ -0,0 +1,534 @@
1uint32_t nva3_pcopy_data[] = {
2 0x00000000,
3 0x00000000,
4 0x00000000,
5 0x00000000,
6 0x00000000,
7 0x00000000,
8 0x00000000,
9 0x00000000,
10 0x00000000,
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x00000000,
28 0x00000000,
29 0x00000000,
30 0x00000000,
31 0x00000000,
32 0x00000000,
33 0x00000000,
34 0x00000000,
35 0x00000000,
36 0x00000000,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41 0x00000000,
42 0x00000000,
43 0x00000000,
44 0x00000000,
45 0x00000000,
46 0x00000000,
47 0x00000000,
48 0x00000000,
49 0x00000000,
50 0x00000000,
51 0x00000000,
52 0x00000000,
53 0x00000000,
54 0x00000000,
55 0x00000000,
56 0x00000000,
57 0x00000000,
58 0x00000000,
59 0x00000000,
60 0x00000000,
61 0x00000000,
62 0x00000000,
63 0x00000000,
64 0x00000000,
65 0x00000000,
66 0x00010000,
67 0x00000000,
68 0x00000000,
69 0x00010040,
70 0x00010160,
71 0x00000000,
72 0x00010050,
73 0x00010162,
74 0x00000000,
75 0x00030060,
76 0x00010170,
77 0x00000000,
78 0x00010170,
79 0x00000000,
80 0x00010170,
81 0x00000000,
82 0x00070080,
83 0x00000028,
84 0xfffff000,
85 0x0000002c,
86 0xfff80000,
87 0x00000030,
88 0xffffe000,
89 0x00000034,
90 0xfffff800,
91 0x00000038,
92 0xfffff000,
93 0x0000003c,
94 0xfff80000,
95 0x00000040,
96 0xffffe000,
97 0x00070088,
98 0x00000054,
99 0xfffff000,
100 0x00000058,
101 0xfff80000,
102 0x0000005c,
103 0xffffe000,
104 0x00000060,
105 0xfffff800,
106 0x00000064,
107 0xfffff000,
108 0x00000068,
109 0xfff80000,
110 0x0000006c,
111 0xffffe000,
112 0x000200c0,
113 0x00010492,
114 0x00000000,
115 0x0001051b,
116 0x00000000,
117 0x000e00c3,
118 0x0000001c,
119 0xffffff00,
120 0x00000020,
121 0x0000000f,
122 0x00000048,
123 0xffffff00,
124 0x0000004c,
125 0x0000000f,
126 0x00000024,
127 0xfff80000,
128 0x00000050,
129 0xfff80000,
130 0x00000080,
131 0xffff0000,
132 0x00000084,
133 0xffffe000,
134 0x00000074,
135 0xfccc0000,
136 0x00000078,
137 0x00000000,
138 0x0000007c,
139 0x00000000,
140 0x00000010,
141 0xffffff00,
142 0x00000014,
143 0x00000000,
144 0x00000018,
145 0x00000000,
146 0x00000800,
147};
148
149uint32_t nva3_pcopy_code[] = {
150 0x04fe04bd,
151 0x3517f000,
152 0xf10010fe,
153 0xf1040017,
154 0xf0fff327,
155 0x22d00023,
156 0x0c25f0c0,
157 0xf40012d0,
158 0x17f11031,
159 0x27f01200,
160 0x0012d003,
161 0xf40031f4,
162 0x0ef40028,
163 0x8001cffd,
164 0xf40812c4,
165 0x21f4060b,
166 0x0412c472,
167 0xf4060bf4,
168 0x11c4c321,
169 0x4001d00c,
170 0x47f101f8,
171 0x4bfe7700,
172 0x0007fe00,
173 0xf00204b9,
174 0x01f40643,
175 0x0604fa09,
176 0xfa060ef4,
177 0x03f80504,
178 0x27f100f8,
179 0x23cf1400,
180 0x1e3fc800,
181 0xf4170bf4,
182 0x21f40132,
183 0x1e3af052,
184 0xf00023d0,
185 0x24d00147,
186 0xcf00f880,
187 0x3dc84023,
188 0x220bf41e,
189 0xf40131f4,
190 0x57f05221,
191 0x0367f004,
192 0xa07856bc,
193 0xb6018068,
194 0x87d00884,
195 0x0162b600,
196 0xf0f018f4,
197 0x23d00237,
198 0xf100f880,
199 0xcf190037,
200 0x33cf4032,
201 0xff24e400,
202 0x1024b607,
203 0x010057f1,
204 0x74bd64bd,
205 0x58005658,
206 0x50b60157,
207 0x0446b804,
208 0xbb4d08f4,
209 0x47b80076,
210 0x0f08f404,
211 0xb60276bb,
212 0x57bb0374,
213 0xdf0ef400,
214 0xb60246bb,
215 0x45bb0344,
216 0x01459800,
217 0xb00453fd,
218 0x1bf40054,
219 0x00455820,
220 0xb0014658,
221 0x1bf40064,
222 0x00538009,
223 0xf4300ef4,
224 0x55f90132,
225 0xf40c01f4,
226 0x25f0250e,
227 0x0125f002,
228 0x100047f1,
229 0xd00042d0,
230 0x27f04043,
231 0x0002d040,
232 0xf08002cf,
233 0x24b04024,
234 0xf71bf400,
235 0x1d0027f1,
236 0xd00137f0,
237 0x00f80023,
238 0x27f100f8,
239 0x34bd2200,
240 0xd00233f0,
241 0x00f80023,
242 0x012842b7,
243 0xf00145b6,
244 0x43801e39,
245 0x0040b701,
246 0x0644b606,
247 0xf80043d0,
248 0xf030f400,
249 0xb00001b0,
250 0x01b00101,
251 0x0301b002,
252 0xc71d0498,
253 0x50b63045,
254 0x3446c701,
255 0xc70160b6,
256 0x70b63847,
257 0x0232f401,
258 0x94bd84bd,
259 0xb60f4ac4,
260 0xb4bd0445,
261 0xf404a430,
262 0xa5ff0f18,
263 0x00cbbbc0,
264 0xf40231f4,
265 0x1bf4220e,
266 0x10c7f00c,
267 0xf400cbbb,
268 0xa430160e,
269 0x0c18f406,
270 0xbb14c7f0,
271 0x0ef400cb,
272 0x80c7f107,
273 0x01c83800,
274 0xb60180b6,
275 0xb5b801b0,
276 0xc308f404,
277 0xb80190b6,
278 0x08f40497,
279 0x0065fdb2,
280 0x98110680,
281 0x68fd2008,
282 0x0502f400,
283 0x75fd64bd,
284 0x1c078000,
285 0xf10078fd,
286 0xb6081057,
287 0x56d00654,
288 0x4057d000,
289 0x080050b7,
290 0xb61c0698,
291 0x64b60162,
292 0x11079808,
293 0xfd0172b6,
294 0x56d00567,
295 0x0050b700,
296 0x0060b401,
297 0xb40056d0,
298 0x56d00160,
299 0x0260b440,
300 0xb48056d0,
301 0x56d00360,
302 0x0050b7c0,
303 0x1e069804,
304 0x980056d0,
305 0x56d01f06,
306 0x1030f440,
307 0x579800f8,
308 0x6879c70a,
309 0xb66478c7,
310 0x77c70280,
311 0x0e76b060,
312 0xf0091bf4,
313 0x0ef40477,
314 0x027cf00f,
315 0xfd1170b6,
316 0x77f00947,
317 0x0f5a9806,
318 0xfd115b98,
319 0xb7f000ab,
320 0x04b7bb01,
321 0xff01b2b6,
322 0xa7bbc4ab,
323 0x105d9805,
324 0xbb01e7f0,
325 0xe2b604e8,
326 0xb4deff01,
327 0xb605d8bb,
328 0xef9401e0,
329 0x02ebbb0c,
330 0xf005fefd,
331 0x60b7026c,
332 0x64b60208,
333 0x006fd008,
334 0xbb04b7bb,
335 0x5f9800cb,
336 0x115b980b,
337 0xf000fbfd,
338 0xb7bb01b7,
339 0x01b2b604,
340 0xbb00fbbb,
341 0xf0f905f7,
342 0xf00c5f98,
343 0xb8bb01b7,
344 0x01b2b604,
345 0xbb00fbbb,
346 0xf0f905f8,
347 0xb60078bb,
348 0xb7f00282,
349 0x04b8bb01,
350 0x9804b9bb,
351 0xe7f00e58,
352 0x04e9bb01,
353 0xff01e2b6,
354 0xf7bbf48e,
355 0x00cfbb04,
356 0xbb0079bb,
357 0xf0fc0589,
358 0xd9fd90fc,
359 0x00adbb00,
360 0xfd0089fd,
361 0xa8bb008f,
362 0x04a7bb00,
363 0xbb0192b6,
364 0x69d00497,
365 0x08579880,
366 0xbb075898,
367 0x7abb00ac,
368 0x0081b600,
369 0xfd1084b6,
370 0x62b7058b,
371 0x67d00600,
372 0x0060b700,
373 0x0068d004,
374 0x6cf000f8,
375 0x0260b702,
376 0x0864b602,
377 0xd0085798,
378 0x60b70067,
379 0x57980400,
380 0x1074b607,
381 0xb70067d0,
382 0x98040060,
383 0x67d00957,
384 0xf900f800,
385 0xf110f900,
386 0xb6080007,
387 0x01cf0604,
388 0x0114f000,
389 0xfcfa1bf4,
390 0xf800fc10,
391 0x0d34c800,
392 0xf5701bf4,
393 0xf103ab21,
394 0xb6080c47,
395 0x05980644,
396 0x0450b605,
397 0xd00045d0,
398 0x57f04040,
399 0x8045d00c,
400 0x040040b7,
401 0xb6040598,
402 0x45d01054,
403 0x0040b700,
404 0x0057f105,
405 0x0153f00b,
406 0xf10045d0,
407 0xb6404057,
408 0x53f10154,
409 0x45d08080,
410 0x1057f140,
411 0x1253f111,
412 0x8045d013,
413 0x151457f1,
414 0x171653f1,
415 0xf1c045d0,
416 0xf0260157,
417 0x47f10153,
418 0x44b60800,
419 0x0045d006,
420 0x03ab21f5,
421 0x080c47f1,
422 0x980644b6,
423 0x45d00505,
424 0x4040d000,
425 0xd00457f0,
426 0x40b78045,
427 0x05980400,
428 0x1054b604,
429 0xb70045d0,
430 0xf1050040,
431 0xd0030057,
432 0x57f10045,
433 0x53f11110,
434 0x45d01312,
435 0x06059840,
436 0x050040b7,
437 0xf10045d0,
438 0xf0260157,
439 0x47f10153,
440 0x44b60800,
441 0x0045d006,
442 0x21f500f8,
443 0x3fc803ab,
444 0x0e0bf400,
445 0x018921f5,
446 0x020047f1,
447 0xf11e0ef4,
448 0xb6081067,
449 0x77f00664,
450 0x11078001,
451 0x981c0780,
452 0x67d02007,
453 0x4067d000,
454 0x32f444bd,
455 0xc854bd02,
456 0x0bf4043f,
457 0x8221f50a,
458 0x0a0ef403,
459 0x027621f5,
460 0xf40749f0,
461 0x57f00231,
462 0x083fc82c,
463 0xf50a0bf4,
464 0xf4038221,
465 0x21f50a0e,
466 0x49f00276,
467 0x0057f108,
468 0x0654b608,
469 0xd0210698,
470 0x67f04056,
471 0x0063f141,
472 0x0546fd44,
473 0xc80054d0,
474 0x0bf40c3f,
475 0xc521f507,
476 0xf100f803,
477 0xbd220027,
478 0x0133f034,
479 0xf80023d0,
480 0x00000000,
481 0x00000000,
482 0x00000000,
483 0x00000000,
484 0x00000000,
485 0x00000000,
486 0x00000000,
487 0x00000000,
488 0x00000000,
489 0x00000000,
490 0x00000000,
491 0x00000000,
492 0x00000000,
493 0x00000000,
494 0x00000000,
495 0x00000000,
496 0x00000000,
497 0x00000000,
498 0x00000000,
499 0x00000000,
500 0x00000000,
501 0x00000000,
502 0x00000000,
503 0x00000000,
504 0x00000000,
505 0x00000000,
506 0x00000000,
507 0x00000000,
508 0x00000000,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000,
514 0x00000000,
515 0x00000000,
516 0x00000000,
517 0x00000000,
518 0x00000000,
519 0x00000000,
520 0x00000000,
521 0x00000000,
522 0x00000000,
523 0x00000000,
524 0x00000000,
525 0x00000000,
526 0x00000000,
527 0x00000000,
528 0x00000000,
529 0x00000000,
530 0x00000000,
531 0x00000000,
532 0x00000000,
533 0x00000000,
534};
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c
new file mode 100644
index 00000000000..dddf006f6d8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_copy.c
@@ -0,0 +1,243 @@
1/*
2 * Copyright 2011 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 <linux/firmware.h>
26#include "drmP.h"
27#include "nouveau_drv.h"
28#include "nouveau_util.h"
29#include "nouveau_vm.h"
30#include "nouveau_ramht.h"
31#include "nvc0_copy.fuc.h"
32
33struct nvc0_copy_engine {
34 struct nouveau_exec_engine base;
35 u32 irq;
36 u32 pmc;
37 u32 fuc;
38 u32 ctx;
39};
40
41static int
42nvc0_copy_context_new(struct nouveau_channel *chan, int engine)
43{
44 struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine);
45 struct drm_device *dev = chan->dev;
46 struct drm_nouveau_private *dev_priv = dev->dev_private;
47 struct nouveau_gpuobj *ramin = chan->ramin;
48 struct nouveau_gpuobj *ctx = NULL;
49 int ret;
50
51 ret = nouveau_gpuobj_new(dev, chan, 256, 256,
52 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER |
53 NVOBJ_FLAG_ZERO_ALLOC, &ctx);
54 if (ret)
55 return ret;
56
57 nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst));
58 nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst));
59 dev_priv->engine.instmem.flush(dev);
60
61 chan->engctx[engine] = ctx;
62 return 0;
63}
64
65static int
66nvc0_copy_object_new(struct nouveau_channel *chan, int engine,
67 u32 handle, u16 class)
68{
69 return 0;
70}
71
72static void
73nvc0_copy_context_del(struct nouveau_channel *chan, int engine)
74{
75 struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine);
76 struct nouveau_gpuobj *ctx = chan->engctx[engine];
77 struct drm_device *dev = chan->dev;
78 u32 inst;
79
80 inst = (chan->ramin->vinst >> 12);
81 inst |= 0x40000000;
82
83 /* disable fifo access */
84 nv_wr32(dev, pcopy->fuc + 0x048, 0x00000000);
85 /* mark channel as unloaded if it's currently active */
86 if (nv_rd32(dev, pcopy->fuc + 0x050) == inst)
87 nv_mask(dev, pcopy->fuc + 0x050, 0x40000000, 0x00000000);
88 /* mark next channel as invalid if it's about to be loaded */
89 if (nv_rd32(dev, pcopy->fuc + 0x054) == inst)
90 nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000);
91 /* restore fifo access */
92 nv_wr32(dev, pcopy->fuc + 0x048, 0x00000003);
93
94 nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000);
95 nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000);
96 nouveau_gpuobj_ref(NULL, &ctx);
97
98 chan->engctx[engine] = ctx;
99}
100
101static int
102nvc0_copy_init(struct drm_device *dev, int engine)
103{
104 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
105 int i;
106
107 nv_mask(dev, 0x000200, pcopy->pmc, 0x00000000);
108 nv_mask(dev, 0x000200, pcopy->pmc, pcopy->pmc);
109 nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff);
110
111 nv_wr32(dev, pcopy->fuc + 0x1c0, 0x01000000);
112 for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++)
113 nv_wr32(dev, pcopy->fuc + 0x1c4, nvc0_pcopy_data[i]);
114
115 nv_wr32(dev, pcopy->fuc + 0x180, 0x01000000);
116 for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) {
117 if ((i & 0x3f) == 0)
118 nv_wr32(dev, pcopy->fuc + 0x188, i >> 6);
119 nv_wr32(dev, pcopy->fuc + 0x184, nvc0_pcopy_code[i]);
120 }
121
122 nv_wr32(dev, pcopy->fuc + 0x084, engine - NVOBJ_ENGINE_COPY0);
123 nv_wr32(dev, pcopy->fuc + 0x10c, 0x00000000);
124 nv_wr32(dev, pcopy->fuc + 0x104, 0x00000000); /* ENTRY */
125 nv_wr32(dev, pcopy->fuc + 0x100, 0x00000002); /* TRIGGER */
126 return 0;
127}
128
129static int
130nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend)
131{
132 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
133
134 nv_mask(dev, pcopy->fuc + 0x048, 0x00000003, 0x00000000);
135
136 /* trigger fuc context unload */
137 nv_wait(dev, pcopy->fuc + 0x008, 0x0000000c, 0x00000000);
138 nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000);
139 nv_wr32(dev, pcopy->fuc + 0x000, 0x00000008);
140 nv_wait(dev, pcopy->fuc + 0x008, 0x00000008, 0x00000000);
141
142 nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff);
143 return 0;
144}
145
146static struct nouveau_enum nvc0_copy_isr_error_name[] = {
147 { 0x0001, "ILLEGAL_MTHD" },
148 { 0x0002, "INVALID_ENUM" },
149 { 0x0003, "INVALID_BITFIELD" },
150 {}
151};
152
153static void
154nvc0_copy_isr(struct drm_device *dev, int engine)
155{
156 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
157 u32 disp = nv_rd32(dev, pcopy->fuc + 0x01c);
158 u32 stat = nv_rd32(dev, pcopy->fuc + 0x008) & disp & ~(disp >> 16);
159 u64 inst = (u64)(nv_rd32(dev, pcopy->fuc + 0x050) & 0x0fffffff) << 12;
160 u32 chid = nvc0_graph_isr_chid(dev, inst);
161 u32 ssta = nv_rd32(dev, pcopy->fuc + 0x040) & 0x0000ffff;
162 u32 addr = nv_rd32(dev, pcopy->fuc + 0x040) >> 16;
163 u32 mthd = (addr & 0x07ff) << 2;
164 u32 subc = (addr & 0x3800) >> 11;
165 u32 data = nv_rd32(dev, pcopy->fuc + 0x044);
166
167 if (stat & 0x00000040) {
168 NV_INFO(dev, "PCOPY: DISPATCH_ERROR [");
169 nouveau_enum_print(nvc0_copy_isr_error_name, ssta);
170 printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n",
171 chid, inst, subc, mthd, data);
172 nv_wr32(dev, pcopy->fuc + 0x004, 0x00000040);
173 stat &= ~0x00000040;
174 }
175
176 if (stat) {
177 NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat);
178 nv_wr32(dev, pcopy->fuc + 0x004, stat);
179 }
180}
181
182static void
183nvc0_copy_isr_0(struct drm_device *dev)
184{
185 nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY0);
186}
187
188static void
189nvc0_copy_isr_1(struct drm_device *dev)
190{
191 nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY1);
192}
193
194static void
195nvc0_copy_destroy(struct drm_device *dev, int engine)
196{
197 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
198
199 nouveau_irq_unregister(dev, pcopy->irq);
200
201 if (engine == NVOBJ_ENGINE_COPY0)
202 NVOBJ_ENGINE_DEL(dev, COPY0);
203 else
204 NVOBJ_ENGINE_DEL(dev, COPY1);
205 kfree(pcopy);
206}
207
208int
209nvc0_copy_create(struct drm_device *dev, int engine)
210{
211 struct nvc0_copy_engine *pcopy;
212
213 pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL);
214 if (!pcopy)
215 return -ENOMEM;
216
217 pcopy->base.destroy = nvc0_copy_destroy;
218 pcopy->base.init = nvc0_copy_init;
219 pcopy->base.fini = nvc0_copy_fini;
220 pcopy->base.context_new = nvc0_copy_context_new;
221 pcopy->base.context_del = nvc0_copy_context_del;
222 pcopy->base.object_new = nvc0_copy_object_new;
223
224 if (engine == 0) {
225 pcopy->irq = 5;
226 pcopy->pmc = 0x00000040;
227 pcopy->fuc = 0x104000;
228 pcopy->ctx = 0x0230;
229 nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_0);
230 NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base);
231 NVOBJ_CLASS(dev, 0x90b5, COPY0);
232 } else {
233 pcopy->irq = 6;
234 pcopy->pmc = 0x00000080;
235 pcopy->fuc = 0x105000;
236 pcopy->ctx = 0x0240;
237 nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_1);
238 NVOBJ_ENGINE_ADD(dev, COPY1, &pcopy->base);
239 NVOBJ_CLASS(dev, 0x90b8, COPY1);
240 }
241
242 return 0;
243}
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h
new file mode 100644
index 00000000000..419903880e9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h
@@ -0,0 +1,527 @@
1uint32_t nvc0_pcopy_data[] = {
2 0x00000000,
3 0x00000000,
4 0x00000000,
5 0x00000000,
6 0x00000000,
7 0x00000000,
8 0x00000000,
9 0x00000000,
10 0x00000000,
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x00000000,
28 0x00000000,
29 0x00000000,
30 0x00000000,
31 0x00000000,
32 0x00000000,
33 0x00000000,
34 0x00000000,
35 0x00000000,
36 0x00000000,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41 0x00000000,
42 0x00000000,
43 0x00000000,
44 0x00000000,
45 0x00000000,
46 0x00000000,
47 0x00000000,
48 0x00000000,
49 0x00000000,
50 0x00000000,
51 0x00000000,
52 0x00000000,
53 0x00000000,
54 0x00000000,
55 0x00000000,
56 0x00000000,
57 0x00000000,
58 0x00000000,
59 0x00000000,
60 0x00000000,
61 0x00000000,
62 0x00000000,
63 0x00000000,
64 0x00000000,
65 0x00000000,
66 0x00010000,
67 0x00000000,
68 0x00000000,
69 0x00010040,
70 0x0001019f,
71 0x00000000,
72 0x00010050,
73 0x000101a1,
74 0x00000000,
75 0x00070080,
76 0x0000001c,
77 0xfffff000,
78 0x00000020,
79 0xfff80000,
80 0x00000024,
81 0xffffe000,
82 0x00000028,
83 0xfffff800,
84 0x0000002c,
85 0xfffff000,
86 0x00000030,
87 0xfff80000,
88 0x00000034,
89 0xffffe000,
90 0x00070088,
91 0x00000048,
92 0xfffff000,
93 0x0000004c,
94 0xfff80000,
95 0x00000050,
96 0xffffe000,
97 0x00000054,
98 0xfffff800,
99 0x00000058,
100 0xfffff000,
101 0x0000005c,
102 0xfff80000,
103 0x00000060,
104 0xffffe000,
105 0x000200c0,
106 0x000104b8,
107 0x00000000,
108 0x00010541,
109 0x00000000,
110 0x000e00c3,
111 0x00000010,
112 0xffffff00,
113 0x00000014,
114 0x0000000f,
115 0x0000003c,
116 0xffffff00,
117 0x00000040,
118 0x0000000f,
119 0x00000018,
120 0xfff80000,
121 0x00000044,
122 0xfff80000,
123 0x00000074,
124 0xffff0000,
125 0x00000078,
126 0xffffe000,
127 0x00000068,
128 0xfccc0000,
129 0x0000006c,
130 0x00000000,
131 0x00000070,
132 0x00000000,
133 0x00000004,
134 0xffffff00,
135 0x00000008,
136 0x00000000,
137 0x0000000c,
138 0x00000000,
139 0x00000800,
140};
141
142uint32_t nvc0_pcopy_code[] = {
143 0x04fe04bd,
144 0x3517f000,
145 0xf10010fe,
146 0xf1040017,
147 0xf0fff327,
148 0x22d00023,
149 0x0c25f0c0,
150 0xf40012d0,
151 0x17f11031,
152 0x27f01200,
153 0x0012d003,
154 0xf40031f4,
155 0x0ef40028,
156 0x8001cffd,
157 0xf40812c4,
158 0x21f4060b,
159 0x0412c4ca,
160 0xf5070bf4,
161 0xc4010221,
162 0x01d00c11,
163 0xf101f840,
164 0xfe770047,
165 0x47f1004b,
166 0x44cf2100,
167 0x0144f000,
168 0xb60444b6,
169 0xf7f13040,
170 0xf4b6061c,
171 0x1457f106,
172 0x00f5d101,
173 0xb6043594,
174 0x57fe0250,
175 0x0145fe00,
176 0x010052b7,
177 0x00ff67f1,
178 0x56fd60bd,
179 0x0253f004,
180 0xf80545fa,
181 0x0053f003,
182 0xd100e7f0,
183 0x549800fe,
184 0x0845b600,
185 0xb6015698,
186 0x46fd1864,
187 0x0047fe05,
188 0xf00204b9,
189 0x01f40643,
190 0x0604fa09,
191 0xfa060ef4,
192 0x03f80504,
193 0x27f100f8,
194 0x23cf1400,
195 0x1e3fc800,
196 0xf4170bf4,
197 0x21f40132,
198 0x1e3af053,
199 0xf00023d0,
200 0x24d00147,
201 0xcf00f880,
202 0x3dc84023,
203 0x090bf41e,
204 0xf40131f4,
205 0x37f05321,
206 0x8023d002,
207 0x37f100f8,
208 0x32cf1900,
209 0x0033cf40,
210 0x07ff24e4,
211 0xf11024b6,
212 0xbd010057,
213 0x5874bd64,
214 0x57580056,
215 0x0450b601,
216 0xf40446b8,
217 0x76bb4d08,
218 0x0447b800,
219 0xbb0f08f4,
220 0x74b60276,
221 0x0057bb03,
222 0xbbdf0ef4,
223 0x44b60246,
224 0x0045bb03,
225 0xfd014598,
226 0x54b00453,
227 0x201bf400,
228 0x58004558,
229 0x64b00146,
230 0x091bf400,
231 0xf4005380,
232 0x32f4300e,
233 0xf455f901,
234 0x0ef40c01,
235 0x0225f025,
236 0xf10125f0,
237 0xd0100047,
238 0x43d00042,
239 0x4027f040,
240 0xcf0002d0,
241 0x24f08002,
242 0x0024b040,
243 0xf1f71bf4,
244 0xf01d0027,
245 0x23d00137,
246 0xf800f800,
247 0x0027f100,
248 0xf034bd22,
249 0x23d00233,
250 0xf400f800,
251 0x01b0f030,
252 0x0101b000,
253 0xb00201b0,
254 0x04980301,
255 0x3045c71a,
256 0xc70150b6,
257 0x60b63446,
258 0x3847c701,
259 0xf40170b6,
260 0x84bd0232,
261 0x4ac494bd,
262 0x0445b60f,
263 0xa430b4bd,
264 0x0f18f404,
265 0xbbc0a5ff,
266 0x31f400cb,
267 0x220ef402,
268 0xf00c1bf4,
269 0xcbbb10c7,
270 0x160ef400,
271 0xf406a430,
272 0xc7f00c18,
273 0x00cbbb14,
274 0xf1070ef4,
275 0x380080c7,
276 0x80b601c8,
277 0x01b0b601,
278 0xf404b5b8,
279 0x90b6c308,
280 0x0497b801,
281 0xfdb208f4,
282 0x06800065,
283 0x1d08980e,
284 0xf40068fd,
285 0x64bd0502,
286 0x800075fd,
287 0x78fd1907,
288 0x1057f100,
289 0x0654b608,
290 0xd00056d0,
291 0x50b74057,
292 0x06980800,
293 0x0162b619,
294 0x980864b6,
295 0x72b60e07,
296 0x0567fd01,
297 0xb70056d0,
298 0xb4010050,
299 0x56d00060,
300 0x0160b400,
301 0xb44056d0,
302 0x56d00260,
303 0x0360b480,
304 0xb7c056d0,
305 0x98040050,
306 0x56d01b06,
307 0x1c069800,
308 0xf44056d0,
309 0x00f81030,
310 0xc7075798,
311 0x78c76879,
312 0x0380b664,
313 0xb06077c7,
314 0x1bf40e76,
315 0x0477f009,
316 0xf00f0ef4,
317 0x70b6027c,
318 0x0947fd11,
319 0x980677f0,
320 0x5b980c5a,
321 0x00abfd0e,
322 0xbb01b7f0,
323 0xb2b604b7,
324 0xc4abff01,
325 0x9805a7bb,
326 0xe7f00d5d,
327 0x04e8bb01,
328 0xff01e2b6,
329 0xd8bbb4de,
330 0x01e0b605,
331 0xbb0cef94,
332 0xfefd02eb,
333 0x026cf005,
334 0x020860b7,
335 0xd00864b6,
336 0xb7bb006f,
337 0x00cbbb04,
338 0x98085f98,
339 0xfbfd0e5b,
340 0x01b7f000,
341 0xb604b7bb,
342 0xfbbb01b2,
343 0x05f7bb00,
344 0x5f98f0f9,
345 0x01b7f009,
346 0xb604b8bb,
347 0xfbbb01b2,
348 0x05f8bb00,
349 0x78bbf0f9,
350 0x0282b600,
351 0xbb01b7f0,
352 0xb9bb04b8,
353 0x0b589804,
354 0xbb01e7f0,
355 0xe2b604e9,
356 0xf48eff01,
357 0xbb04f7bb,
358 0x79bb00cf,
359 0x0589bb00,
360 0x90fcf0fc,
361 0xbb00d9fd,
362 0x89fd00ad,
363 0x008ffd00,
364 0xbb00a8bb,
365 0x92b604a7,
366 0x0497bb01,
367 0x988069d0,
368 0x58980557,
369 0x00acbb04,
370 0xb6007abb,
371 0x84b60081,
372 0x058bfd10,
373 0x060062b7,
374 0xb70067d0,
375 0xd0040060,
376 0x00f80068,
377 0xb7026cf0,
378 0xb6020260,
379 0x57980864,
380 0x0067d005,
381 0x040060b7,
382 0xb6045798,
383 0x67d01074,
384 0x0060b700,
385 0x06579804,
386 0xf80067d0,
387 0xf900f900,
388 0x0007f110,
389 0x0604b608,
390 0xf00001cf,
391 0x1bf40114,
392 0xfc10fcfa,
393 0xc800f800,
394 0x1bf40d34,
395 0xd121f570,
396 0x0c47f103,
397 0x0644b608,
398 0xb6020598,
399 0x45d00450,
400 0x4040d000,
401 0xd00c57f0,
402 0x40b78045,
403 0x05980400,
404 0x1054b601,
405 0xb70045d0,
406 0xf1050040,
407 0xf00b0057,
408 0x45d00153,
409 0x4057f100,
410 0x0154b640,
411 0x808053f1,
412 0xf14045d0,
413 0xf1111057,
414 0xd0131253,
415 0x57f18045,
416 0x53f11514,
417 0x45d01716,
418 0x0157f1c0,
419 0x0153f026,
420 0x080047f1,
421 0xd00644b6,
422 0x21f50045,
423 0x47f103d1,
424 0x44b6080c,
425 0x02059806,
426 0xd00045d0,
427 0x57f04040,
428 0x8045d004,
429 0x040040b7,
430 0xb6010598,
431 0x45d01054,
432 0x0040b700,
433 0x0057f105,
434 0x0045d003,
435 0x111057f1,
436 0x131253f1,
437 0x984045d0,
438 0x40b70305,
439 0x45d00500,
440 0x0157f100,
441 0x0153f026,
442 0x080047f1,
443 0xd00644b6,
444 0x00f80045,
445 0x03d121f5,
446 0xf4003fc8,
447 0x21f50e0b,
448 0x47f101af,
449 0x0ef40200,
450 0x1067f11e,
451 0x0664b608,
452 0x800177f0,
453 0x07800e07,
454 0x1d079819,
455 0xd00067d0,
456 0x44bd4067,
457 0xbd0232f4,
458 0x043fc854,
459 0xf50a0bf4,
460 0xf403a821,
461 0x21f50a0e,
462 0x49f0029c,
463 0x0231f407,
464 0xc82c57f0,
465 0x0bf4083f,
466 0xa821f50a,
467 0x0a0ef403,
468 0x029c21f5,
469 0xf10849f0,
470 0xb6080057,
471 0x06980654,
472 0x4056d01e,
473 0xf14167f0,
474 0xfd440063,
475 0x54d00546,
476 0x0c3fc800,
477 0xf5070bf4,
478 0xf803eb21,
479 0x0027f100,
480 0xf034bd22,
481 0x23d00133,
482 0x0000f800,
483 0x00000000,
484 0x00000000,
485 0x00000000,
486 0x00000000,
487 0x00000000,
488 0x00000000,
489 0x00000000,
490 0x00000000,
491 0x00000000,
492 0x00000000,
493 0x00000000,
494 0x00000000,
495 0x00000000,
496 0x00000000,
497 0x00000000,
498 0x00000000,
499 0x00000000,
500 0x00000000,
501 0x00000000,
502 0x00000000,
503 0x00000000,
504 0x00000000,
505 0x00000000,
506 0x00000000,
507 0x00000000,
508 0x00000000,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000,
514 0x00000000,
515 0x00000000,
516 0x00000000,
517 0x00000000,
518 0x00000000,
519 0x00000000,
520 0x00000000,
521 0x00000000,
522 0x00000000,
523 0x00000000,
524 0x00000000,
525 0x00000000,
526 0x00000000,
527};
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
new file mode 100644
index 00000000000..08e6b118f02
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -0,0 +1,102 @@
1/*
2 * Copyright 2011 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 "drm.h"
27#include "nouveau_drv.h"
28#include "nouveau_drm.h"
29
30struct nvc0_fb_priv {
31 struct page *r100c10_page;
32 dma_addr_t r100c10;
33};
34
35static void
36nvc0_fb_destroy(struct drm_device *dev)
37{
38 struct drm_nouveau_private *dev_priv = dev->dev_private;
39 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
40 struct nvc0_fb_priv *priv = pfb->priv;
41
42 if (priv->r100c10_page) {
43 pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
44 PCI_DMA_BIDIRECTIONAL);
45 __free_page(priv->r100c10_page);
46 }
47
48 kfree(priv);
49 pfb->priv = NULL;
50}
51
52static int
53nvc0_fb_create(struct drm_device *dev)
54{
55 struct drm_nouveau_private *dev_priv = dev->dev_private;
56 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
57 struct nvc0_fb_priv *priv;
58
59 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
60 if (!priv)
61 return -ENOMEM;
62 pfb->priv = priv;
63
64 priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
65 if (!priv->r100c10_page) {
66 nvc0_fb_destroy(dev);
67 return -ENOMEM;
68 }
69
70 priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0,
71 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
72 if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) {
73 nvc0_fb_destroy(dev);
74 return -EFAULT;
75 }
76
77 return 0;
78}
79
80int
81nvc0_fb_init(struct drm_device *dev)
82{
83 struct drm_nouveau_private *dev_priv = dev->dev_private;
84 struct nvc0_fb_priv *priv;
85 int ret;
86
87 if (!dev_priv->engine.fb.priv) {
88 ret = nvc0_fb_create(dev);
89 if (ret)
90 return ret;
91 }
92 priv = dev_priv->engine.fb.priv;
93
94 nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
95 return 0;
96}
97
98void
99nvc0_fb_takedown(struct drm_device *dev)
100{
101 nvc0_fb_destroy(dev);
102}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
new file mode 100644
index 00000000000..6f9f341c3e8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -0,0 +1,508 @@
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_mm.h"
29
30static void nvc0_fifo_isr(struct drm_device *);
31
32struct nvc0_fifo_priv {
33 struct nouveau_gpuobj *playlist[2];
34 int cur_playlist;
35 struct nouveau_vma user_vma;
36 int spoon_nr;
37};
38
39struct nvc0_fifo_chan {
40 struct nouveau_gpuobj *user;
41 struct nouveau_gpuobj *ramfc;
42};
43
44static void
45nvc0_fifo_playlist_update(struct drm_device *dev)
46{
47 struct drm_nouveau_private *dev_priv = dev->dev_private;
48 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
49 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
50 struct nvc0_fifo_priv *priv = pfifo->priv;
51 struct nouveau_gpuobj *cur;
52 int i, p;
53
54 cur = priv->playlist[priv->cur_playlist];
55 priv->cur_playlist = !priv->cur_playlist;
56
57 for (i = 0, p = 0; i < 128; i++) {
58 if (!(nv_rd32(dev, 0x3004 + (i * 8)) & 1))
59 continue;
60 nv_wo32(cur, p + 0, i);
61 nv_wo32(cur, p + 4, 0x00000004);
62 p += 8;
63 }
64 pinstmem->flush(dev);
65
66 nv_wr32(dev, 0x002270, cur->vinst >> 12);
67 nv_wr32(dev, 0x002274, 0x01f00000 | (p >> 3));
68 if (!nv_wait(dev, 0x00227c, 0x00100000, 0x00000000))
69 NV_ERROR(dev, "PFIFO - playlist update failed\n");
70}
71
72void
73nvc0_fifo_disable(struct drm_device *dev)
74{
75}
76
77void
78nvc0_fifo_enable(struct drm_device *dev)
79{
80}
81
82bool
83nvc0_fifo_reassign(struct drm_device *dev, bool enable)
84{
85 return false;
86}
87
88bool
89nvc0_fifo_cache_pull(struct drm_device *dev, bool enable)
90{
91 return false;
92}
93
94int
95nvc0_fifo_channel_id(struct drm_device *dev)
96{
97 return 127;
98}
99
100int
101nvc0_fifo_create_context(struct nouveau_channel *chan)
102{
103 struct drm_device *dev = chan->dev;
104 struct drm_nouveau_private *dev_priv = dev->dev_private;
105 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
106 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
107 struct nvc0_fifo_priv *priv = pfifo->priv;
108 struct nvc0_fifo_chan *fifoch;
109 u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
110 int ret;
111
112 chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL);
113 if (!chan->fifo_priv)
114 return -ENOMEM;
115 fifoch = chan->fifo_priv;
116
117 /* allocate vram for control regs, map into polling area */
118 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000,
119 NVOBJ_FLAG_ZERO_ALLOC, &fifoch->user);
120 if (ret)
121 goto error;
122
123 nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000,
124 *(struct nouveau_mem **)fifoch->user->node);
125
126 chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) +
127 priv->user_vma.offset + (chan->id * 0x1000),
128 PAGE_SIZE);
129 if (!chan->user) {
130 ret = -ENOMEM;
131 goto error;
132 }
133
134 /* ramfc */
135 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst,
136 chan->ramin->vinst, 0x100,
137 NVOBJ_FLAG_ZERO_ALLOC, &fifoch->ramfc);
138 if (ret)
139 goto error;
140
141 nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(fifoch->user->vinst));
142 nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(fifoch->user->vinst));
143 nv_wo32(fifoch->ramfc, 0x10, 0x0000face);
144 nv_wo32(fifoch->ramfc, 0x30, 0xfffff902);
145 nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt));
146 nv_wo32(fifoch->ramfc, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 |
147 upper_32_bits(ib_virt));
148 nv_wo32(fifoch->ramfc, 0x54, 0x00000002);
149 nv_wo32(fifoch->ramfc, 0x84, 0x20400000);
150 nv_wo32(fifoch->ramfc, 0x94, 0x30000001);
151 nv_wo32(fifoch->ramfc, 0x9c, 0x00000100);
152 nv_wo32(fifoch->ramfc, 0xa4, 0x1f1f1f1f);
153 nv_wo32(fifoch->ramfc, 0xa8, 0x1f1f1f1f);
154 nv_wo32(fifoch->ramfc, 0xac, 0x0000001f);
155 nv_wo32(fifoch->ramfc, 0xb8, 0xf8000000);
156 nv_wo32(fifoch->ramfc, 0xf8, 0x10003080); /* 0x002310 */
157 nv_wo32(fifoch->ramfc, 0xfc, 0x10000010); /* 0x002350 */
158 pinstmem->flush(dev);
159
160 nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 |
161 (chan->ramin->vinst >> 12));
162 nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001);
163 nvc0_fifo_playlist_update(dev);
164 return 0;
165
166error:
167 pfifo->destroy_context(chan);
168 return ret;
169}
170
171void
172nvc0_fifo_destroy_context(struct nouveau_channel *chan)
173{
174 struct drm_device *dev = chan->dev;
175 struct nvc0_fifo_chan *fifoch;
176
177 nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000);
178 nv_wr32(dev, 0x002634, chan->id);
179 if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id))
180 NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634));
181
182 nvc0_fifo_playlist_update(dev);
183
184 nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000);
185
186 if (chan->user) {
187 iounmap(chan->user);
188 chan->user = NULL;
189 }
190
191 fifoch = chan->fifo_priv;
192 chan->fifo_priv = NULL;
193 if (!fifoch)
194 return;
195
196 nouveau_gpuobj_ref(NULL, &fifoch->ramfc);
197 nouveau_gpuobj_ref(NULL, &fifoch->user);
198 kfree(fifoch);
199}
200
201int
202nvc0_fifo_load_context(struct nouveau_channel *chan)
203{
204 return 0;
205}
206
207int
208nvc0_fifo_unload_context(struct drm_device *dev)
209{
210 int i;
211
212 for (i = 0; i < 128; i++) {
213 if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1))
214 continue;
215
216 nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000);
217 nv_wr32(dev, 0x002634, i);
218 if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
219 NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
220 i, nv_rd32(dev, 0x002634));
221 return -EBUSY;
222 }
223 }
224
225 return 0;
226}
227
228static void
229nvc0_fifo_destroy(struct drm_device *dev)
230{
231 struct drm_nouveau_private *dev_priv = dev->dev_private;
232 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
233 struct nvc0_fifo_priv *priv;
234
235 priv = pfifo->priv;
236 if (!priv)
237 return;
238
239 nouveau_vm_put(&priv->user_vma);
240 nouveau_gpuobj_ref(NULL, &priv->playlist[1]);
241 nouveau_gpuobj_ref(NULL, &priv->playlist[0]);
242 kfree(priv);
243}
244
245void
246nvc0_fifo_takedown(struct drm_device *dev)
247{
248 nv_wr32(dev, 0x002140, 0x00000000);
249 nvc0_fifo_destroy(dev);
250}
251
252static int
253nvc0_fifo_create(struct drm_device *dev)
254{
255 struct drm_nouveau_private *dev_priv = dev->dev_private;
256 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
257 struct nvc0_fifo_priv *priv;
258 int ret;
259
260 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
261 if (!priv)
262 return -ENOMEM;
263 pfifo->priv = priv;
264
265 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0,
266 &priv->playlist[0]);
267 if (ret)
268 goto error;
269
270 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0,
271 &priv->playlist[1]);
272 if (ret)
273 goto error;
274
275 ret = nouveau_vm_get(dev_priv->bar1_vm, pfifo->channels * 0x1000,
276 12, NV_MEM_ACCESS_RW, &priv->user_vma);
277 if (ret)
278 goto error;
279
280 nouveau_irq_register(dev, 8, nvc0_fifo_isr);
281 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
282 return 0;
283
284error:
285 nvc0_fifo_destroy(dev);
286 return ret;
287}
288
289int
290nvc0_fifo_init(struct drm_device *dev)
291{
292 struct drm_nouveau_private *dev_priv = dev->dev_private;
293 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
294 struct nouveau_channel *chan;
295 struct nvc0_fifo_priv *priv;
296 int ret, i;
297
298 if (!pfifo->priv) {
299 ret = nvc0_fifo_create(dev);
300 if (ret)
301 return ret;
302 }
303 priv = pfifo->priv;
304
305 /* reset PFIFO, enable all available PSUBFIFO areas */
306 nv_mask(dev, 0x000200, 0x00000100, 0x00000000);
307 nv_mask(dev, 0x000200, 0x00000100, 0x00000100);
308 nv_wr32(dev, 0x000204, 0xffffffff);
309 nv_wr32(dev, 0x002204, 0xffffffff);
310
311 priv->spoon_nr = hweight32(nv_rd32(dev, 0x002204));
312 NV_DEBUG(dev, "PFIFO: %d subfifo(s)\n", priv->spoon_nr);
313
314 /* assign engines to subfifos */
315 if (priv->spoon_nr >= 3) {
316 nv_wr32(dev, 0x002208, ~(1 << 0)); /* PGRAPH */
317 nv_wr32(dev, 0x00220c, ~(1 << 1)); /* PVP */
318 nv_wr32(dev, 0x002210, ~(1 << 1)); /* PPP */
319 nv_wr32(dev, 0x002214, ~(1 << 1)); /* PBSP */
320 nv_wr32(dev, 0x002218, ~(1 << 2)); /* PCE0 */
321 nv_wr32(dev, 0x00221c, ~(1 << 1)); /* PCE1 */
322 }
323
324 /* PSUBFIFO[n] */
325 for (i = 0; i < 3; i++) {
326 nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
327 nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
328 nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */
329 }
330
331 nv_mask(dev, 0x002200, 0x00000001, 0x00000001);
332 nv_wr32(dev, 0x002254, 0x10000000 | priv->user_vma.offset >> 12);
333
334 nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
335 nv_wr32(dev, 0x002100, 0xffffffff);
336 nv_wr32(dev, 0x002140, 0xbfffffff);
337
338 /* restore PFIFO context table */
339 for (i = 0; i < 128; i++) {
340 chan = dev_priv->channels.ptr[i];
341 if (!chan || !chan->fifo_priv)
342 continue;
343
344 nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 |
345 (chan->ramin->vinst >> 12));
346 nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001);
347 }
348 nvc0_fifo_playlist_update(dev);
349
350 return 0;
351}
352
353struct nouveau_enum nvc0_fifo_fault_unit[] = {
354 { 0x00, "PGRAPH" },
355 { 0x03, "PEEPHOLE" },
356 { 0x04, "BAR1" },
357 { 0x05, "BAR3" },
358 { 0x07, "PFIFO" },
359 { 0x10, "PBSP" },
360 { 0x11, "PPPP" },
361 { 0x13, "PCOUNTER" },
362 { 0x14, "PVP" },
363 { 0x15, "PCOPY0" },
364 { 0x16, "PCOPY1" },
365 { 0x17, "PDAEMON" },
366 {}
367};
368
369struct nouveau_enum nvc0_fifo_fault_reason[] = {
370 { 0x00, "PT_NOT_PRESENT" },
371 { 0x01, "PT_TOO_SHORT" },
372 { 0x02, "PAGE_NOT_PRESENT" },
373 { 0x03, "VM_LIMIT_EXCEEDED" },
374 { 0x04, "NO_CHANNEL" },
375 { 0x05, "PAGE_SYSTEM_ONLY" },
376 { 0x06, "PAGE_READ_ONLY" },
377 { 0x0a, "COMPRESSED_SYSRAM" },
378 { 0x0c, "INVALID_STORAGE_TYPE" },
379 {}
380};
381
382struct nouveau_enum nvc0_fifo_fault_hubclient[] = {
383 { 0x01, "PCOPY0" },
384 { 0x02, "PCOPY1" },
385 { 0x04, "DISPATCH" },
386 { 0x05, "CTXCTL" },
387 { 0x06, "PFIFO" },
388 { 0x07, "BAR_READ" },
389 { 0x08, "BAR_WRITE" },
390 { 0x0b, "PVP" },
391 { 0x0c, "PPPP" },
392 { 0x0d, "PBSP" },
393 { 0x11, "PCOUNTER" },
394 { 0x12, "PDAEMON" },
395 { 0x14, "CCACHE" },
396 { 0x15, "CCACHE_POST" },
397 {}
398};
399
400struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
401 { 0x01, "TEX" },
402 { 0x0c, "ESETUP" },
403 { 0x0e, "CTXCTL" },
404 { 0x0f, "PROP" },
405 {}
406};
407
408struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = {
409/* { 0x00008000, "" } seen with null ib push */
410 { 0x00200000, "ILLEGAL_MTHD" },
411 { 0x00800000, "EMPTY_SUBC" },
412 {}
413};
414
415static void
416nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit)
417{
418 u32 inst = nv_rd32(dev, 0x2800 + (unit * 0x10));
419 u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10));
420 u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10));
421 u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10));
422 u32 client = (stat & 0x00001f00) >> 8;
423
424 NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [",
425 (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo);
426 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
427 printk("] from ");
428 nouveau_enum_print(nvc0_fifo_fault_unit, unit);
429 if (stat & 0x00000040) {
430 printk("/");
431 nouveau_enum_print(nvc0_fifo_fault_hubclient, client);
432 } else {
433 printk("/GPC%d/", (stat & 0x1f000000) >> 24);
434 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client);
435 }
436 printk(" on channel 0x%010llx\n", (u64)inst << 12);
437}
438
439static void
440nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
441{
442 u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000));
443 u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000));
444 u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000));
445 u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;
446 u32 subc = (addr & 0x00070000);
447 u32 mthd = (addr & 0x00003ffc);
448
449 NV_INFO(dev, "PSUBFIFO %d:", unit);
450 nouveau_bitfield_print(nvc0_fifo_subfifo_intr, stat);
451 NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n",
452 unit, chid, subc, mthd, data);
453
454 nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008);
455 nv_wr32(dev, 0x040108 + (unit * 0x2000), stat);
456}
457
458static void
459nvc0_fifo_isr(struct drm_device *dev)
460{
461 u32 stat = nv_rd32(dev, 0x002100);
462
463 if (stat & 0x00000100) {
464 NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
465 nv_wr32(dev, 0x002100, 0x00000100);
466 stat &= ~0x00000100;
467 }
468
469 if (stat & 0x10000000) {
470 u32 units = nv_rd32(dev, 0x00259c);
471 u32 u = units;
472
473 while (u) {
474 int i = ffs(u) - 1;
475 nvc0_fifo_isr_vm_fault(dev, i);
476 u &= ~(1 << i);
477 }
478
479 nv_wr32(dev, 0x00259c, units);
480 stat &= ~0x10000000;
481 }
482
483 if (stat & 0x20000000) {
484 u32 units = nv_rd32(dev, 0x0025a0);
485 u32 u = units;
486
487 while (u) {
488 int i = ffs(u) - 1;
489 nvc0_fifo_isr_subfifo_intr(dev, i);
490 u &= ~(1 << i);
491 }
492
493 nv_wr32(dev, 0x0025a0, units);
494 stat &= ~0x20000000;
495 }
496
497 if (stat & 0x40000000) {
498 NV_INFO(dev, "PFIFO: unknown status 0x40000000\n");
499 nv_mask(dev, 0x002a00, 0x00000000, 0x00000000);
500 stat &= ~0x40000000;
501 }
502
503 if (stat) {
504 NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat);
505 nv_wr32(dev, 0x002100, stat);
506 nv_wr32(dev, 0x002140, 0);
507 }
508}
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
new file mode 100644
index 00000000000..5b2f6f42046
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
@@ -0,0 +1,908 @@
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 <linux/firmware.h>
26
27#include "drmP.h"
28
29#include "nouveau_drv.h"
30#include "nouveau_mm.h"
31
32#include "nvc0_graph.h"
33#include "nvc0_grhub.fuc.h"
34#include "nvc0_grgpc.fuc.h"
35
36static void
37nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base)
38{
39 NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base,
40 nv_rd32(dev, base + 0x400));
41 NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
42 nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804),
43 nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c));
44 NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
45 nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814),
46 nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c));
47}
48
49static void
50nvc0_graph_ctxctl_debug(struct drm_device *dev)
51{
52 u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff;
53 u32 gpc;
54
55 nvc0_graph_ctxctl_debug_unit(dev, 0x409000);
56 for (gpc = 0; gpc < gpcnr; gpc++)
57 nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000));
58}
59
60static int
61nvc0_graph_load_context(struct nouveau_channel *chan)
62{
63 struct drm_device *dev = chan->dev;
64
65 nv_wr32(dev, 0x409840, 0x00000030);
66 nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
67 nv_wr32(dev, 0x409504, 0x00000003);
68 if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010))
69 NV_ERROR(dev, "PGRAPH: load_ctx timeout\n");
70
71 return 0;
72}
73
74static int
75nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan)
76{
77 nv_wr32(dev, 0x409840, 0x00000003);
78 nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12);
79 nv_wr32(dev, 0x409504, 0x00000009);
80 if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) {
81 NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n");
82 return -EBUSY;
83 }
84
85 return 0;
86}
87
88static int
89nvc0_graph_construct_context(struct nouveau_channel *chan)
90{
91 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
92 struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
93 struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
94 struct drm_device *dev = chan->dev;
95 int ret, i;
96 u32 *ctx;
97
98 ctx = kmalloc(priv->grctx_size, GFP_KERNEL);
99 if (!ctx)
100 return -ENOMEM;
101
102 if (!nouveau_ctxfw) {
103 nv_wr32(dev, 0x409840, 0x80000000);
104 nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
105 nv_wr32(dev, 0x409504, 0x00000001);
106 if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
107 NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n");
108 nvc0_graph_ctxctl_debug(dev);
109 ret = -EBUSY;
110 goto err;
111 }
112 } else {
113 nvc0_graph_load_context(chan);
114
115 nv_wo32(grch->grctx, 0x1c, 1);
116 nv_wo32(grch->grctx, 0x20, 0);
117 nv_wo32(grch->grctx, 0x28, 0);
118 nv_wo32(grch->grctx, 0x2c, 0);
119 dev_priv->engine.instmem.flush(dev);
120 }
121
122 ret = nvc0_grctx_generate(chan);
123 if (ret)
124 goto err;
125
126 if (!nouveau_ctxfw) {
127 nv_wr32(dev, 0x409840, 0x80000000);
128 nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
129 nv_wr32(dev, 0x409504, 0x00000002);
130 if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
131 NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n");
132 nvc0_graph_ctxctl_debug(dev);
133 ret = -EBUSY;
134 goto err;
135 }
136 } else {
137 ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
138 if (ret)
139 goto err;
140 }
141
142 for (i = 0; i < priv->grctx_size; i += 4)
143 ctx[i / 4] = nv_ro32(grch->grctx, i);
144
145 priv->grctx_vals = ctx;
146 return 0;
147
148err:
149 kfree(ctx);
150 return ret;
151}
152
153static int
154nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
155{
156 struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
157 struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
158 struct drm_device *dev = chan->dev;
159 int i = 0, gpc, tp, ret;
160 u32 magic;
161
162 ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
163 &grch->unk408004);
164 if (ret)
165 return ret;
166
167 ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM,
168 &grch->unk40800c);
169 if (ret)
170 return ret;
171
172 ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096,
173 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER,
174 &grch->unk418810);
175 if (ret)
176 return ret;
177
178 ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM,
179 &grch->mmio);
180 if (ret)
181 return ret;
182
183
184 nv_wo32(grch->mmio, i++ * 4, 0x00408004);
185 nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
186 nv_wo32(grch->mmio, i++ * 4, 0x00408008);
187 nv_wo32(grch->mmio, i++ * 4, 0x80000018);
188
189 nv_wo32(grch->mmio, i++ * 4, 0x0040800c);
190 nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
191 nv_wo32(grch->mmio, i++ * 4, 0x00408010);
192 nv_wo32(grch->mmio, i++ * 4, 0x80000000);
193
194 nv_wo32(grch->mmio, i++ * 4, 0x00418810);
195 nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12);
196 nv_wo32(grch->mmio, i++ * 4, 0x00419848);
197 nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12);
198
199 nv_wo32(grch->mmio, i++ * 4, 0x00419004);
200 nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
201 nv_wo32(grch->mmio, i++ * 4, 0x00419008);
202 nv_wo32(grch->mmio, i++ * 4, 0x00000000);
203
204 nv_wo32(grch->mmio, i++ * 4, 0x00418808);
205 nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
206 nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
207 nv_wo32(grch->mmio, i++ * 4, 0x80000018);
208
209 magic = 0x02180000;
210 nv_wo32(grch->mmio, i++ * 4, 0x00405830);
211 nv_wo32(grch->mmio, i++ * 4, magic);
212 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
213 for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
214 u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
215 nv_wo32(grch->mmio, i++ * 4, reg);
216 nv_wo32(grch->mmio, i++ * 4, magic);
217 }
218 }
219
220 grch->mmio_nr = i / 2;
221 return 0;
222}
223
224static int
225nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
226{
227 struct drm_device *dev = chan->dev;
228 struct drm_nouveau_private *dev_priv = dev->dev_private;
229 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
230 struct nvc0_graph_priv *priv = nv_engine(dev, engine);
231 struct nvc0_graph_chan *grch;
232 struct nouveau_gpuobj *grctx;
233 int ret, i;
234
235 grch = kzalloc(sizeof(*grch), GFP_KERNEL);
236 if (!grch)
237 return -ENOMEM;
238 chan->engctx[NVOBJ_ENGINE_GR] = grch;
239
240 ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256,
241 NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC,
242 &grch->grctx);
243 if (ret)
244 goto error;
245 grctx = grch->grctx;
246
247 ret = nvc0_graph_create_context_mmio_list(chan);
248 if (ret)
249 goto error;
250
251 nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4);
252 nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst));
253 pinstmem->flush(dev);
254
255 if (!priv->grctx_vals) {
256 ret = nvc0_graph_construct_context(chan);
257 if (ret)
258 goto error;
259 }
260
261 for (i = 0; i < priv->grctx_size; i += 4)
262 nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
263
264 if (!nouveau_ctxfw) {
265 nv_wo32(grctx, 0x00, grch->mmio_nr);
266 nv_wo32(grctx, 0x04, grch->mmio->linst >> 8);
267 } else {
268 nv_wo32(grctx, 0xf4, 0);
269 nv_wo32(grctx, 0xf8, 0);
270 nv_wo32(grctx, 0x10, grch->mmio_nr);
271 nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst));
272 nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst));
273 nv_wo32(grctx, 0x1c, 1);
274 nv_wo32(grctx, 0x20, 0);
275 nv_wo32(grctx, 0x28, 0);
276 nv_wo32(grctx, 0x2c, 0);
277 }
278 pinstmem->flush(dev);
279 return 0;
280
281error:
282 priv->base.context_del(chan, engine);
283 return ret;
284}
285
286static void
287nvc0_graph_context_del(struct nouveau_channel *chan, int engine)
288{
289 struct nvc0_graph_chan *grch = chan->engctx[engine];
290
291 nouveau_gpuobj_ref(NULL, &grch->mmio);
292 nouveau_gpuobj_ref(NULL, &grch->unk418810);
293 nouveau_gpuobj_ref(NULL, &grch->unk40800c);
294 nouveau_gpuobj_ref(NULL, &grch->unk408004);
295 nouveau_gpuobj_ref(NULL, &grch->grctx);
296 chan->engctx[engine] = NULL;
297}
298
299static int
300nvc0_graph_object_new(struct nouveau_channel *chan, int engine,
301 u32 handle, u16 class)
302{
303 return 0;
304}
305
306static int
307nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend)
308{
309 return 0;
310}
311
312static int
313nvc0_graph_mthd_page_flip(struct nouveau_channel *chan,
314 u32 class, u32 mthd, u32 data)
315{
316 nouveau_finish_page_flip(chan, NULL);
317 return 0;
318}
319
320static void
321nvc0_graph_init_obj418880(struct drm_device *dev)
322{
323 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
324 int i;
325
326 nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000);
327 nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000);
328 for (i = 0; i < 4; i++)
329 nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
330 nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8);
331 nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8);
332}
333
334static void
335nvc0_graph_init_regs(struct drm_device *dev)
336{
337 nv_wr32(dev, 0x400080, 0x003083c2);
338 nv_wr32(dev, 0x400088, 0x00006fe7);
339 nv_wr32(dev, 0x40008c, 0x00000000);
340 nv_wr32(dev, 0x400090, 0x00000030);
341 nv_wr32(dev, 0x40013c, 0x013901f7);
342 nv_wr32(dev, 0x400140, 0x00000100);
343 nv_wr32(dev, 0x400144, 0x00000000);
344 nv_wr32(dev, 0x400148, 0x00000110);
345 nv_wr32(dev, 0x400138, 0x00000000);
346 nv_wr32(dev, 0x400130, 0x00000000);
347 nv_wr32(dev, 0x400134, 0x00000000);
348 nv_wr32(dev, 0x400124, 0x00000002);
349}
350
351static void
352nvc0_graph_init_gpc_0(struct drm_device *dev)
353{
354 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
355 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total);
356 u32 data[TP_MAX / 8];
357 u8 tpnr[GPC_MAX];
358 int i, gpc, tpc;
359
360 /*
361 * TP ROP UNKVAL(magic_not_rop_nr)
362 * 450: 4/0/0/0 2 3
363 * 460: 3/4/0/0 4 1
364 * 465: 3/4/4/0 4 7
365 * 470: 3/3/4/4 5 5
366 * 480: 3/4/4/4 6 6
367 */
368
369 memset(data, 0x00, sizeof(data));
370 memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
371 for (i = 0, gpc = -1; i < priv->tp_total; i++) {
372 do {
373 gpc = (gpc + 1) % priv->gpc_nr;
374 } while (!tpnr[gpc]);
375 tpc = priv->tp_nr[gpc] - tpnr[gpc]--;
376
377 data[i / 8] |= tpc << ((i % 8) * 4);
378 }
379
380 nv_wr32(dev, GPC_BCAST(0x0980), data[0]);
381 nv_wr32(dev, GPC_BCAST(0x0984), data[1]);
382 nv_wr32(dev, GPC_BCAST(0x0988), data[2]);
383 nv_wr32(dev, GPC_BCAST(0x098c), data[3]);
384
385 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
386 nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
387 priv->tp_nr[gpc]);
388 nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total);
389 nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918);
390 }
391
392 nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
393 nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
394}
395
396static void
397nvc0_graph_init_units(struct drm_device *dev)
398{
399 nv_wr32(dev, 0x409c24, 0x000f0000);
400 nv_wr32(dev, 0x404000, 0xc0000000); /* DISPATCH */
401 nv_wr32(dev, 0x404600, 0xc0000000); /* M2MF */
402 nv_wr32(dev, 0x408030, 0xc0000000);
403 nv_wr32(dev, 0x40601c, 0xc0000000);
404 nv_wr32(dev, 0x404490, 0xc0000000); /* MACRO */
405 nv_wr32(dev, 0x406018, 0xc0000000);
406 nv_wr32(dev, 0x405840, 0xc0000000);
407 nv_wr32(dev, 0x405844, 0x00ffffff);
408 nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008);
409 nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000);
410}
411
412static void
413nvc0_graph_init_gpc_1(struct drm_device *dev)
414{
415 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
416 int gpc, tp;
417
418 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
419 nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000);
420 nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000);
421 nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000);
422 nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000);
423 for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
424 nv_wr32(dev, TP_UNIT(gpc, tp, 0x508), 0xffffffff);
425 nv_wr32(dev, TP_UNIT(gpc, tp, 0x50c), 0xffffffff);
426 nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000);
427 nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000);
428 nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000);
429 nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe);
430 nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f);
431 }
432 nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
433 nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
434 }
435}
436
437static void
438nvc0_graph_init_rop(struct drm_device *dev)
439{
440 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
441 int rop;
442
443 for (rop = 0; rop < priv->rop_nr; rop++) {
444 nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000);
445 nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000);
446 nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff);
447 nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff);
448 }
449}
450
451static void
452nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base,
453 struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data)
454{
455 int i;
456
457 nv_wr32(dev, fuc_base + 0x01c0, 0x01000000);
458 for (i = 0; i < data->size / 4; i++)
459 nv_wr32(dev, fuc_base + 0x01c4, data->data[i]);
460
461 nv_wr32(dev, fuc_base + 0x0180, 0x01000000);
462 for (i = 0; i < code->size / 4; i++) {
463 if ((i & 0x3f) == 0)
464 nv_wr32(dev, fuc_base + 0x0188, i >> 6);
465 nv_wr32(dev, fuc_base + 0x0184, code->data[i]);
466 }
467}
468
469static int
470nvc0_graph_init_ctxctl(struct drm_device *dev)
471{
472 struct drm_nouveau_private *dev_priv = dev->dev_private;
473 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
474 u32 r000260;
475 int i;
476
477 if (!nouveau_ctxfw) {
478 /* load HUB microcode */
479 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
480 nv_wr32(dev, 0x4091c0, 0x01000000);
481 for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++)
482 nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]);
483
484 nv_wr32(dev, 0x409180, 0x01000000);
485 for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) {
486 if ((i & 0x3f) == 0)
487 nv_wr32(dev, 0x409188, i >> 6);
488 nv_wr32(dev, 0x409184, nvc0_grhub_code[i]);
489 }
490
491 /* load GPC microcode */
492 nv_wr32(dev, 0x41a1c0, 0x01000000);
493 for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++)
494 nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]);
495
496 nv_wr32(dev, 0x41a180, 0x01000000);
497 for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) {
498 if ((i & 0x3f) == 0)
499 nv_wr32(dev, 0x41a188, i >> 6);
500 nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]);
501 }
502 nv_wr32(dev, 0x000260, r000260);
503
504 /* start HUB ucode running, it'll init the GPCs */
505 nv_wr32(dev, 0x409800, dev_priv->chipset);
506 nv_wr32(dev, 0x40910c, 0x00000000);
507 nv_wr32(dev, 0x409100, 0x00000002);
508 if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
509 NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n");
510 nvc0_graph_ctxctl_debug(dev);
511 return -EBUSY;
512 }
513
514 priv->grctx_size = nv_rd32(dev, 0x409804);
515 return 0;
516 }
517
518 /* load fuc microcode */
519 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
520 nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d);
521 nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
522 nv_wr32(dev, 0x000260, r000260);
523
524 /* start both of them running */
525 nv_wr32(dev, 0x409840, 0xffffffff);
526 nv_wr32(dev, 0x41a10c, 0x00000000);
527 nv_wr32(dev, 0x40910c, 0x00000000);
528 nv_wr32(dev, 0x41a100, 0x00000002);
529 nv_wr32(dev, 0x409100, 0x00000002);
530 if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001))
531 NV_INFO(dev, "0x409800 wait failed\n");
532
533 nv_wr32(dev, 0x409840, 0xffffffff);
534 nv_wr32(dev, 0x409500, 0x7fffffff);
535 nv_wr32(dev, 0x409504, 0x00000021);
536
537 nv_wr32(dev, 0x409840, 0xffffffff);
538 nv_wr32(dev, 0x409500, 0x00000000);
539 nv_wr32(dev, 0x409504, 0x00000010);
540 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
541 NV_ERROR(dev, "fuc09 req 0x10 timeout\n");
542 return -EBUSY;
543 }
544 priv->grctx_size = nv_rd32(dev, 0x409800);
545
546 nv_wr32(dev, 0x409840, 0xffffffff);
547 nv_wr32(dev, 0x409500, 0x00000000);
548 nv_wr32(dev, 0x409504, 0x00000016);
549 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
550 NV_ERROR(dev, "fuc09 req 0x16 timeout\n");
551 return -EBUSY;
552 }
553
554 nv_wr32(dev, 0x409840, 0xffffffff);
555 nv_wr32(dev, 0x409500, 0x00000000);
556 nv_wr32(dev, 0x409504, 0x00000025);
557 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
558 NV_ERROR(dev, "fuc09 req 0x25 timeout\n");
559 return -EBUSY;
560 }
561
562 return 0;
563}
564
565static int
566nvc0_graph_init(struct drm_device *dev, int engine)
567{
568 int ret;
569
570 nv_mask(dev, 0x000200, 0x18001000, 0x00000000);
571 nv_mask(dev, 0x000200, 0x18001000, 0x18001000);
572
573 nvc0_graph_init_obj418880(dev);
574 nvc0_graph_init_regs(dev);
575 /*nvc0_graph_init_unitplemented_magics(dev);*/
576 nvc0_graph_init_gpc_0(dev);
577 /*nvc0_graph_init_unitplemented_c242(dev);*/
578
579 nv_wr32(dev, 0x400500, 0x00010001);
580 nv_wr32(dev, 0x400100, 0xffffffff);
581 nv_wr32(dev, 0x40013c, 0xffffffff);
582
583 nvc0_graph_init_units(dev);
584 nvc0_graph_init_gpc_1(dev);
585 nvc0_graph_init_rop(dev);
586
587 nv_wr32(dev, 0x400108, 0xffffffff);
588 nv_wr32(dev, 0x400138, 0xffffffff);
589 nv_wr32(dev, 0x400118, 0xffffffff);
590 nv_wr32(dev, 0x400130, 0xffffffff);
591 nv_wr32(dev, 0x40011c, 0xffffffff);
592 nv_wr32(dev, 0x400134, 0xffffffff);
593 nv_wr32(dev, 0x400054, 0x34ce3464);
594
595 ret = nvc0_graph_init_ctxctl(dev);
596 if (ret)
597 return ret;
598
599 return 0;
600}
601
602int
603nvc0_graph_isr_chid(struct drm_device *dev, u64 inst)
604{
605 struct drm_nouveau_private *dev_priv = dev->dev_private;
606 struct nouveau_channel *chan;
607 unsigned long flags;
608 int i;
609
610 spin_lock_irqsave(&dev_priv->channels.lock, flags);
611 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
612 chan = dev_priv->channels.ptr[i];
613 if (!chan || !chan->ramin)
614 continue;
615
616 if (inst == chan->ramin->vinst)
617 break;
618 }
619 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
620 return i;
621}
622
623static void
624nvc0_graph_ctxctl_isr(struct drm_device *dev)
625{
626 u32 ustat = nv_rd32(dev, 0x409c18);
627
628 if (ustat & 0x00000001)
629 NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n");
630 if (ustat & 0x00080000)
631 NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n");
632 if (ustat & ~0x00080001)
633 NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat);
634
635 nvc0_graph_ctxctl_debug(dev);
636 nv_wr32(dev, 0x409c20, ustat);
637}
638
639static void
640nvc0_graph_isr(struct drm_device *dev)
641{
642 u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
643 u32 chid = nvc0_graph_isr_chid(dev, inst);
644 u32 stat = nv_rd32(dev, 0x400100);
645 u32 addr = nv_rd32(dev, 0x400704);
646 u32 mthd = (addr & 0x00003ffc);
647 u32 subc = (addr & 0x00070000) >> 16;
648 u32 data = nv_rd32(dev, 0x400708);
649 u32 code = nv_rd32(dev, 0x400110);
650 u32 class = nv_rd32(dev, 0x404200 + (subc * 4));
651
652 if (stat & 0x00000010) {
653 if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) {
654 NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] "
655 "subc %d class 0x%04x mthd 0x%04x "
656 "data 0x%08x\n",
657 chid, inst, subc, class, mthd, data);
658 }
659 nv_wr32(dev, 0x400100, 0x00000010);
660 stat &= ~0x00000010;
661 }
662
663 if (stat & 0x00000020) {
664 NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d "
665 "class 0x%04x mthd 0x%04x data 0x%08x\n",
666 chid, inst, subc, class, mthd, data);
667 nv_wr32(dev, 0x400100, 0x00000020);
668 stat &= ~0x00000020;
669 }
670
671 if (stat & 0x00100000) {
672 NV_INFO(dev, "PGRAPH: DATA_ERROR [");
673 nouveau_enum_print(nv50_data_error_names, code);
674 printk("] ch %d [0x%010llx] subc %d class 0x%04x "
675 "mthd 0x%04x data 0x%08x\n",
676 chid, inst, subc, class, mthd, data);
677 nv_wr32(dev, 0x400100, 0x00100000);
678 stat &= ~0x00100000;
679 }
680
681 if (stat & 0x00200000) {
682 u32 trap = nv_rd32(dev, 0x400108);
683 NV_INFO(dev, "PGRAPH: TRAP ch %d status 0x%08x\n", chid, trap);
684 nv_wr32(dev, 0x400108, trap);
685 nv_wr32(dev, 0x400100, 0x00200000);
686 stat &= ~0x00200000;
687 }
688
689 if (stat & 0x00080000) {
690 nvc0_graph_ctxctl_isr(dev);
691 nv_wr32(dev, 0x400100, 0x00080000);
692 stat &= ~0x00080000;
693 }
694
695 if (stat) {
696 NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat);
697 nv_wr32(dev, 0x400100, stat);
698 }
699
700 nv_wr32(dev, 0x400500, 0x00010001);
701}
702
703static void
704nvc0_runk140_isr(struct drm_device *dev)
705{
706 u32 units = nv_rd32(dev, 0x00017c) & 0x1f;
707
708 while (units) {
709 u32 unit = ffs(units) - 1;
710 u32 reg = 0x140000 + unit * 0x2000;
711 u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
712 u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
713
714 NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
715 units &= ~(1 << unit);
716 }
717}
718
719static int
720nvc0_graph_create_fw(struct drm_device *dev, const char *fwname,
721 struct nvc0_graph_fuc *fuc)
722{
723 struct drm_nouveau_private *dev_priv = dev->dev_private;
724 const struct firmware *fw;
725 char f[32];
726 int ret;
727
728 snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname);
729 ret = request_firmware(&fw, f, &dev->pdev->dev);
730 if (ret) {
731 snprintf(f, sizeof(f), "nouveau/%s", fwname);
732 ret = request_firmware(&fw, f, &dev->pdev->dev);
733 if (ret) {
734 NV_ERROR(dev, "failed to load %s\n", fwname);
735 return ret;
736 }
737 }
738
739 fuc->size = fw->size;
740 fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
741 release_firmware(fw);
742 return (fuc->data != NULL) ? 0 : -ENOMEM;
743}
744
745static void
746nvc0_graph_destroy_fw(struct nvc0_graph_fuc *fuc)
747{
748 if (fuc->data) {
749 kfree(fuc->data);
750 fuc->data = NULL;
751 }
752}
753
754static void
755nvc0_graph_destroy(struct drm_device *dev, int engine)
756{
757 struct nvc0_graph_priv *priv = nv_engine(dev, engine);
758
759 if (nouveau_ctxfw) {
760 nvc0_graph_destroy_fw(&priv->fuc409c);
761 nvc0_graph_destroy_fw(&priv->fuc409d);
762 nvc0_graph_destroy_fw(&priv->fuc41ac);
763 nvc0_graph_destroy_fw(&priv->fuc41ad);
764 }
765
766 nouveau_irq_unregister(dev, 12);
767 nouveau_irq_unregister(dev, 25);
768
769 nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
770 nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
771
772 if (priv->grctx_vals)
773 kfree(priv->grctx_vals);
774
775 NVOBJ_ENGINE_DEL(dev, GR);
776 kfree(priv);
777}
778
779int
780nvc0_graph_create(struct drm_device *dev)
781{
782 struct drm_nouveau_private *dev_priv = dev->dev_private;
783 struct nvc0_graph_priv *priv;
784 int ret, gpc, i;
785 u32 fermi;
786
787 fermi = nvc0_graph_class(dev);
788 if (!fermi) {
789 NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
790 return 0;
791 }
792
793 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
794 if (!priv)
795 return -ENOMEM;
796
797 priv->base.destroy = nvc0_graph_destroy;
798 priv->base.init = nvc0_graph_init;
799 priv->base.fini = nvc0_graph_fini;
800 priv->base.context_new = nvc0_graph_context_new;
801 priv->base.context_del = nvc0_graph_context_del;
802 priv->base.object_new = nvc0_graph_object_new;
803
804 NVOBJ_ENGINE_ADD(dev, GR, &priv->base);
805 nouveau_irq_register(dev, 12, nvc0_graph_isr);
806 nouveau_irq_register(dev, 25, nvc0_runk140_isr);
807
808 if (nouveau_ctxfw) {
809 NV_INFO(dev, "PGRAPH: using external firmware\n");
810 if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
811 nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
812 nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
813 nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
814 ret = 0;
815 goto error;
816 }
817 }
818
819 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
820 if (ret)
821 goto error;
822
823 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8);
824 if (ret)
825 goto error;
826
827 for (i = 0; i < 0x1000; i += 4) {
828 nv_wo32(priv->unk4188b4, i, 0x00000010);
829 nv_wo32(priv->unk4188b8, i, 0x00000010);
830 }
831
832 priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f;
833 priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16;
834 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
835 priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608));
836 priv->tp_total += priv->tp_nr[gpc];
837 }
838
839 /*XXX: these need figuring out... */
840 switch (dev_priv->chipset) {
841 case 0xc0:
842 if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
843 priv->magic_not_rop_nr = 0x07;
844 } else
845 if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
846 priv->magic_not_rop_nr = 0x05;
847 } else
848 if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
849 priv->magic_not_rop_nr = 0x06;
850 }
851 break;
852 case 0xc3: /* 450, 4/0/0/0, 2 */
853 priv->magic_not_rop_nr = 0x03;
854 break;
855 case 0xc4: /* 460, 3/4/0/0, 4 */
856 priv->magic_not_rop_nr = 0x01;
857 break;
858 case 0xc1: /* 2/0/0/0, 1 */
859 priv->magic_not_rop_nr = 0x01;
860 break;
861 case 0xc8: /* 4/4/3/4, 5 */
862 priv->magic_not_rop_nr = 0x06;
863 break;
864 case 0xce: /* 4/4/0/0, 4 */
865 priv->magic_not_rop_nr = 0x03;
866 break;
867 }
868
869 if (!priv->magic_not_rop_nr) {
870 NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n",
871 priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2],
872 priv->tp_nr[3], priv->rop_nr);
873 /* use 0xc3's values... */
874 priv->magic_not_rop_nr = 0x03;
875 }
876
877 NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
878 NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
879 NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
880 NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
881 if (fermi >= 0x9197)
882 NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */
883 if (fermi >= 0x9297)
884 NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */
885 NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
886 return 0;
887
888error:
889 nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR);
890 return ret;
891}
892
893MODULE_FIRMWARE("nouveau/nvc0_fuc409c");
894MODULE_FIRMWARE("nouveau/nvc0_fuc409d");
895MODULE_FIRMWARE("nouveau/nvc0_fuc41ac");
896MODULE_FIRMWARE("nouveau/nvc0_fuc41ad");
897MODULE_FIRMWARE("nouveau/nvc3_fuc409c");
898MODULE_FIRMWARE("nouveau/nvc3_fuc409d");
899MODULE_FIRMWARE("nouveau/nvc3_fuc41ac");
900MODULE_FIRMWARE("nouveau/nvc3_fuc41ad");
901MODULE_FIRMWARE("nouveau/nvc4_fuc409c");
902MODULE_FIRMWARE("nouveau/nvc4_fuc409d");
903MODULE_FIRMWARE("nouveau/nvc4_fuc41ac");
904MODULE_FIRMWARE("nouveau/nvc4_fuc41ad");
905MODULE_FIRMWARE("nouveau/fuc409c");
906MODULE_FIRMWARE("nouveau/fuc409d");
907MODULE_FIRMWARE("nouveau/fuc41ac");
908MODULE_FIRMWARE("nouveau/fuc41ad");
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.fuc b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
new file mode 100644
index 00000000000..2a4b6dc8f9d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
@@ -0,0 +1,400 @@
1/* fuc microcode util functions for nvc0 PGRAPH
2 *
3 * Copyright 2011 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the 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) OR AUTHOR(S) 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
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Ben Skeggs
24 */
25
26define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)')
27define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))')
28
29ifdef(`include_code', `
30// Error codes
31define(`E_BAD_COMMAND', 0x01)
32define(`E_CMD_OVERFLOW', 0x02)
33
34// Util macros to help with debugging ucode hangs etc
35define(`T_WAIT', 0)
36define(`T_MMCTX', 1)
37define(`T_STRWAIT', 2)
38define(`T_STRINIT', 3)
39define(`T_AUTO', 4)
40define(`T_CHAN', 5)
41define(`T_LOAD', 6)
42define(`T_SAVE', 7)
43define(`T_LCHAN', 8)
44define(`T_LCTXH', 9)
45
46define(`trace_set', `
47 mov $r8 0x83c
48 shl b32 $r8 6
49 clear b32 $r9
50 bset $r9 $1
51 iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7]
52')
53
54define(`trace_clr', `
55 mov $r8 0x85c
56 shl b32 $r8 6
57 clear b32 $r9
58 bset $r9 $1
59 iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7]
60')
61
62// queue_put - add request to queue
63//
64// In : $r13 queue pointer
65// $r14 command
66// $r15 data
67//
68queue_put:
69 // make sure we have space..
70 ld b32 $r8 D[$r13 + 0x0] // GET
71 ld b32 $r9 D[$r13 + 0x4] // PUT
72 xor $r8 8
73 cmpu b32 $r8 $r9
74 bra ne queue_put_next
75 mov $r15 E_CMD_OVERFLOW
76 call error
77 ret
78
79 // store cmd/data on queue
80 queue_put_next:
81 and $r8 $r9 7
82 shl b32 $r8 3
83 add b32 $r8 $r13
84 add b32 $r8 8
85 st b32 D[$r8 + 0x0] $r14
86 st b32 D[$r8 + 0x4] $r15
87
88 // update PUT
89 add b32 $r9 1
90 and $r9 0xf
91 st b32 D[$r13 + 0x4] $r9
92 ret
93
94// queue_get - fetch request from queue
95//
96// In : $r13 queue pointer
97//
98// Out: $p1 clear on success (data available)
99// $r14 command
100// $r15 data
101//
102queue_get:
103 bset $flags $p1
104 ld b32 $r8 D[$r13 + 0x0] // GET
105 ld b32 $r9 D[$r13 + 0x4] // PUT
106 cmpu b32 $r8 $r9
107 bra e queue_get_done
108 // fetch first cmd/data pair
109 and $r9 $r8 7
110 shl b32 $r9 3
111 add b32 $r9 $r13
112 add b32 $r9 8
113 ld b32 $r14 D[$r9 + 0x0]
114 ld b32 $r15 D[$r9 + 0x4]
115
116 // update GET
117 add b32 $r8 1
118 and $r8 0xf
119 st b32 D[$r13 + 0x0] $r8
120 bclr $flags $p1
121queue_get_done:
122 ret
123
124// nv_rd32 - read 32-bit value from nv register
125//
126// In : $r14 register
127// Out: $r15 value
128//
129nv_rd32:
130 mov $r11 0x728
131 shl b32 $r11 6
132 mov b32 $r12 $r14
133 bset $r12 31 // MMIO_CTRL_PENDING
134 iowr I[$r11 + 0x000] $r12 // MMIO_CTRL
135 nv_rd32_wait:
136 iord $r12 I[$r11 + 0x000]
137 xbit $r12 $r12 31
138 bra ne nv_rd32_wait
139 mov $r10 6 // DONE_MMIO_RD
140 call wait_doneo
141 iord $r15 I[$r11 + 0x100] // MMIO_RDVAL
142 ret
143
144// nv_wr32 - write 32-bit value to nv register
145//
146// In : $r14 register
147// $r15 value
148//
149nv_wr32:
150 mov $r11 0x728
151 shl b32 $r11 6
152 iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL
153 mov b32 $r12 $r14
154 bset $r12 31 // MMIO_CTRL_PENDING
155 bset $r12 30 // MMIO_CTRL_WRITE
156 iowr I[$r11 + 0x000] $r12 // MMIO_CTRL
157 nv_wr32_wait:
158 iord $r12 I[$r11 + 0x000]
159 xbit $r12 $r12 31
160 bra ne nv_wr32_wait
161 ret
162
163// (re)set watchdog timer
164//
165// In : $r15 timeout
166//
167watchdog_reset:
168 mov $r8 0x430
169 shl b32 $r8 6
170 bset $r15 31
171 iowr I[$r8 + 0x000] $r15
172 ret
173
174// clear watchdog timer
175watchdog_clear:
176 mov $r8 0x430
177 shl b32 $r8 6
178 iowr I[$r8 + 0x000] $r0
179 ret
180
181// wait_done{z,o} - wait on FUC_DONE bit to become clear/set
182//
183// In : $r10 bit to wait on
184//
185define(`wait_done', `
186$1:
187 trace_set(T_WAIT);
188 mov $r8 0x818
189 shl b32 $r8 6
190 iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit
191 wait_done_$1:
192 mov $r8 0x400
193 shl b32 $r8 6
194 iord $r8 I[$r8 + 0x000] // DONE
195 xbit $r8 $r8 $r10
196 bra $2 wait_done_$1
197 trace_clr(T_WAIT)
198 ret
199')
200wait_done(wait_donez, ne)
201wait_done(wait_doneo, e)
202
203// mmctx_size - determine size of a mmio list transfer
204//
205// In : $r14 mmio list head
206// $r15 mmio list tail
207// Out: $r15 transfer size (in bytes)
208//
209mmctx_size:
210 clear b32 $r9
211 nv_mmctx_size_loop:
212 ld b32 $r8 D[$r14]
213 shr b32 $r8 26
214 add b32 $r8 1
215 shl b32 $r8 2
216 add b32 $r9 $r8
217 add b32 $r14 4
218 cmpu b32 $r14 $r15
219 bra ne nv_mmctx_size_loop
220 mov b32 $r15 $r9
221 ret
222
223// mmctx_xfer - execute a list of mmio transfers
224//
225// In : $r10 flags
226// bit 0: direction (0 = save, 1 = load)
227// bit 1: set if first transfer
228// bit 2: set if last transfer
229// $r11 base
230// $r12 mmio list head
231// $r13 mmio list tail
232// $r14 multi_stride
233// $r15 multi_mask
234//
235mmctx_xfer:
236 trace_set(T_MMCTX)
237 mov $r8 0x710
238 shl b32 $r8 6
239 clear b32 $r9
240 or $r11 $r11
241 bra e mmctx_base_disabled
242 iowr I[$r8 + 0x000] $r11 // MMCTX_BASE
243 bset $r9 0 // BASE_EN
244 mmctx_base_disabled:
245 or $r14 $r14
246 bra e mmctx_multi_disabled
247 iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE
248 iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK
249 bset $r9 1 // MULTI_EN
250 mmctx_multi_disabled:
251 add b32 $r8 0x100
252
253 xbit $r11 $r10 0
254 shl b32 $r11 16 // DIR
255 bset $r11 12 // QLIMIT = 0x10
256 xbit $r14 $r10 1
257 shl b32 $r14 17
258 or $r11 $r14 // START_TRIGGER
259 iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL
260
261 // loop over the mmio list, and send requests to the hw
262 mmctx_exec_loop:
263 // wait for space in mmctx queue
264 mmctx_wait_free:
265 iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
266 and $r14 0x1f
267 bra e mmctx_wait_free
268
269 // queue up an entry
270 ld b32 $r14 D[$r12]
271 or $r14 $r9
272 iowr I[$r8 + 0x300] $r14
273 add b32 $r12 4
274 cmpu b32 $r12 $r13
275 bra ne mmctx_exec_loop
276
277 xbit $r11 $r10 2
278 bra ne mmctx_stop
279 // wait for queue to empty
280 mmctx_fini_wait:
281 iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
282 and $r11 0x1f
283 cmpu b32 $r11 0x10
284 bra ne mmctx_fini_wait
285 mov $r10 2 // DONE_MMCTX
286 call wait_donez
287 bra mmctx_done
288 mmctx_stop:
289 xbit $r11 $r10 0
290 shl b32 $r11 16 // DIR
291 bset $r11 12 // QLIMIT = 0x10
292 bset $r11 18 // STOP_TRIGGER
293 iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL
294 mmctx_stop_wait:
295 // wait for STOP_TRIGGER to clear
296 iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
297 xbit $r11 $r11 18
298 bra ne mmctx_stop_wait
299 mmctx_done:
300 trace_clr(T_MMCTX)
301 ret
302
303// Wait for DONE_STRAND
304//
305strand_wait:
306 push $r10
307 mov $r10 2
308 call wait_donez
309 pop $r10
310 ret
311
312// unknown - call before issuing strand commands
313//
314strand_pre:
315 mov $r8 0x4afc
316 sethi $r8 0x20000
317 mov $r9 0xc
318 iowr I[$r8] $r9
319 call strand_wait
320 ret
321
322// unknown - call after issuing strand commands
323//
324strand_post:
325 mov $r8 0x4afc
326 sethi $r8 0x20000
327 mov $r9 0xd
328 iowr I[$r8] $r9
329 call strand_wait
330 ret
331
332// Selects strand set?!
333//
334// In: $r14 id
335//
336strand_set:
337 mov $r10 0x4ffc
338 sethi $r10 0x20000
339 sub b32 $r11 $r10 0x500
340 mov $r12 0xf
341 iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf
342 mov $r12 0xb
343 iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb
344 call strand_wait
345 iowr I[$r10 + 0x000] $r14 // 0x93c = <id>
346 mov $r12 0xa
347 iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa
348 call strand_wait
349 ret
350
351// Initialise strand context data
352//
353// In : $r15 context base
354// Out: $r15 context size (in bytes)
355//
356// Strandset(?) 3 hardcoded currently
357//
358strand_ctx_init:
359 trace_set(T_STRINIT)
360 call strand_pre
361 mov $r14 3
362 call strand_set
363 mov $r10 0x46fc
364 sethi $r10 0x20000
365 add b32 $r11 $r10 0x400
366 iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0
367 mov $r12 1
368 iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE
369 call strand_wait
370 sub b32 $r12 $r0 1
371 iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff
372 mov $r12 2
373 iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT
374 call strand_wait
375 call strand_post
376
377 // read the size of each strand, poke the context offset of
378 // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
379 // about it later then.
380 mov $r8 0x880
381 shl b32 $r8 6
382 iord $r9 I[$r8 + 0x000] // STRANDS
383 add b32 $r8 0x2200
384 shr b32 $r14 $r15 8
385 ctx_init_strand_loop:
386 iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE
387 iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE
388 iord $r10 I[$r8 + 0x200] // STRAND_SIZE
389 shr b32 $r10 6
390 add b32 $r10 1
391 add b32 $r14 $r10
392 add b32 $r8 4
393 sub b32 $r9 1
394 bra ne ctx_init_strand_loop
395
396 shl b32 $r14 8
397 sub b32 $r15 $r14 $r15
398 trace_clr(T_STRINIT)
399 ret
400')
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h
new file mode 100644
index 00000000000..55689e99728
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h
@@ -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#ifndef __NVC0_GRAPH_H__
26#define __NVC0_GRAPH_H__
27
28#define GPC_MAX 4
29#define TP_MAX 32
30
31#define ROP_BCAST(r) (0x408800 + (r))
32#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r))
33#define GPC_BCAST(r) (0x418000 + (r))
34#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r))
35#define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))
36
37struct nvc0_graph_fuc {
38 u32 *data;
39 u32 size;
40};
41
42struct nvc0_graph_priv {
43 struct nouveau_exec_engine base;
44
45 struct nvc0_graph_fuc fuc409c;
46 struct nvc0_graph_fuc fuc409d;
47 struct nvc0_graph_fuc fuc41ac;
48 struct nvc0_graph_fuc fuc41ad;
49
50 u8 gpc_nr;
51 u8 rop_nr;
52 u8 tp_nr[GPC_MAX];
53 u8 tp_total;
54
55 u32 grctx_size;
56 u32 *grctx_vals;
57 struct nouveau_gpuobj *unk4188b4;
58 struct nouveau_gpuobj *unk4188b8;
59
60 u8 magic_not_rop_nr;
61};
62
63struct nvc0_graph_chan {
64 struct nouveau_gpuobj *grctx;
65 struct nouveau_gpuobj *unk408004; /* 0x418810 too */
66 struct nouveau_gpuobj *unk40800c; /* 0x419004 too */
67 struct nouveau_gpuobj *unk418810; /* 0x419848 too */
68 struct nouveau_gpuobj *mmio;
69 int mmio_nr;
70};
71
72int nvc0_grctx_generate(struct nouveau_channel *);
73
74/* nvc0_graph.c uses this also to determine supported chipsets */
75static inline u32
76nvc0_graph_class(struct drm_device *dev)
77{
78 struct drm_nouveau_private *dev_priv = dev->dev_private;
79
80 switch (dev_priv->chipset) {
81 case 0xc0:
82 case 0xc3:
83 case 0xc4:
84 case 0xce: /* guess, mmio trace shows only 0x9097 state */
85 return 0x9097;
86 case 0xc1:
87 return 0x9197;
88 case 0xc8:
89 return 0x9297;
90 default:
91 return 0;
92 }
93}
94
95#endif
diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c
new file mode 100644
index 00000000000..31018eaf527
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c
@@ -0,0 +1,2807 @@
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_mm.h"
28#include "nvc0_graph.h"
29
30static void
31nv_icmd(struct drm_device *dev, u32 icmd, u32 data)
32{
33 nv_wr32(dev, 0x400204, data);
34 nv_wr32(dev, 0x400200, icmd);
35 while (nv_rd32(dev, 0x400700) & 2) {}
36}
37
38static void
39nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data)
40{
41 nv_wr32(dev, 0x40448c, data);
42 nv_wr32(dev, 0x404488, 0x80000000 | (mthd << 14) | class);
43}
44
45static void
46nvc0_grctx_generate_9097(struct drm_device *dev)
47{
48 u32 fermi = nvc0_graph_class(dev);
49 u32 mthd;
50
51 nv_mthd(dev, 0x9097, 0x0800, 0x00000000);
52 nv_mthd(dev, 0x9097, 0x0840, 0x00000000);
53 nv_mthd(dev, 0x9097, 0x0880, 0x00000000);
54 nv_mthd(dev, 0x9097, 0x08c0, 0x00000000);
55 nv_mthd(dev, 0x9097, 0x0900, 0x00000000);
56 nv_mthd(dev, 0x9097, 0x0940, 0x00000000);
57 nv_mthd(dev, 0x9097, 0x0980, 0x00000000);
58 nv_mthd(dev, 0x9097, 0x09c0, 0x00000000);
59 nv_mthd(dev, 0x9097, 0x0804, 0x00000000);
60 nv_mthd(dev, 0x9097, 0x0844, 0x00000000);
61 nv_mthd(dev, 0x9097, 0x0884, 0x00000000);
62 nv_mthd(dev, 0x9097, 0x08c4, 0x00000000);
63 nv_mthd(dev, 0x9097, 0x0904, 0x00000000);
64 nv_mthd(dev, 0x9097, 0x0944, 0x00000000);
65 nv_mthd(dev, 0x9097, 0x0984, 0x00000000);
66 nv_mthd(dev, 0x9097, 0x09c4, 0x00000000);
67 nv_mthd(dev, 0x9097, 0x0808, 0x00000400);
68 nv_mthd(dev, 0x9097, 0x0848, 0x00000400);
69 nv_mthd(dev, 0x9097, 0x0888, 0x00000400);
70 nv_mthd(dev, 0x9097, 0x08c8, 0x00000400);
71 nv_mthd(dev, 0x9097, 0x0908, 0x00000400);
72 nv_mthd(dev, 0x9097, 0x0948, 0x00000400);
73 nv_mthd(dev, 0x9097, 0x0988, 0x00000400);
74 nv_mthd(dev, 0x9097, 0x09c8, 0x00000400);
75 nv_mthd(dev, 0x9097, 0x080c, 0x00000300);
76 nv_mthd(dev, 0x9097, 0x084c, 0x00000300);
77 nv_mthd(dev, 0x9097, 0x088c, 0x00000300);
78 nv_mthd(dev, 0x9097, 0x08cc, 0x00000300);
79 nv_mthd(dev, 0x9097, 0x090c, 0x00000300);
80 nv_mthd(dev, 0x9097, 0x094c, 0x00000300);
81 nv_mthd(dev, 0x9097, 0x098c, 0x00000300);
82 nv_mthd(dev, 0x9097, 0x09cc, 0x00000300);
83 nv_mthd(dev, 0x9097, 0x0810, 0x000000cf);
84 nv_mthd(dev, 0x9097, 0x0850, 0x00000000);
85 nv_mthd(dev, 0x9097, 0x0890, 0x00000000);
86 nv_mthd(dev, 0x9097, 0x08d0, 0x00000000);
87 nv_mthd(dev, 0x9097, 0x0910, 0x00000000);
88 nv_mthd(dev, 0x9097, 0x0950, 0x00000000);
89 nv_mthd(dev, 0x9097, 0x0990, 0x00000000);
90 nv_mthd(dev, 0x9097, 0x09d0, 0x00000000);
91 nv_mthd(dev, 0x9097, 0x0814, 0x00000040);
92 nv_mthd(dev, 0x9097, 0x0854, 0x00000040);
93 nv_mthd(dev, 0x9097, 0x0894, 0x00000040);
94 nv_mthd(dev, 0x9097, 0x08d4, 0x00000040);
95 nv_mthd(dev, 0x9097, 0x0914, 0x00000040);
96 nv_mthd(dev, 0x9097, 0x0954, 0x00000040);
97 nv_mthd(dev, 0x9097, 0x0994, 0x00000040);
98 nv_mthd(dev, 0x9097, 0x09d4, 0x00000040);
99 nv_mthd(dev, 0x9097, 0x0818, 0x00000001);
100 nv_mthd(dev, 0x9097, 0x0858, 0x00000001);
101 nv_mthd(dev, 0x9097, 0x0898, 0x00000001);
102 nv_mthd(dev, 0x9097, 0x08d8, 0x00000001);
103 nv_mthd(dev, 0x9097, 0x0918, 0x00000001);
104 nv_mthd(dev, 0x9097, 0x0958, 0x00000001);
105 nv_mthd(dev, 0x9097, 0x0998, 0x00000001);
106 nv_mthd(dev, 0x9097, 0x09d8, 0x00000001);
107 nv_mthd(dev, 0x9097, 0x081c, 0x00000000);
108 nv_mthd(dev, 0x9097, 0x085c, 0x00000000);
109 nv_mthd(dev, 0x9097, 0x089c, 0x00000000);
110 nv_mthd(dev, 0x9097, 0x08dc, 0x00000000);
111 nv_mthd(dev, 0x9097, 0x091c, 0x00000000);
112 nv_mthd(dev, 0x9097, 0x095c, 0x00000000);
113 nv_mthd(dev, 0x9097, 0x099c, 0x00000000);
114 nv_mthd(dev, 0x9097, 0x09dc, 0x00000000);
115 nv_mthd(dev, 0x9097, 0x0820, 0x00000000);
116 nv_mthd(dev, 0x9097, 0x0860, 0x00000000);
117 nv_mthd(dev, 0x9097, 0x08a0, 0x00000000);
118 nv_mthd(dev, 0x9097, 0x08e0, 0x00000000);
119 nv_mthd(dev, 0x9097, 0x0920, 0x00000000);
120 nv_mthd(dev, 0x9097, 0x0960, 0x00000000);
121 nv_mthd(dev, 0x9097, 0x09a0, 0x00000000);
122 nv_mthd(dev, 0x9097, 0x09e0, 0x00000000);
123 nv_mthd(dev, 0x9097, 0x2700, 0x00000000);
124 nv_mthd(dev, 0x9097, 0x2720, 0x00000000);
125 nv_mthd(dev, 0x9097, 0x2740, 0x00000000);
126 nv_mthd(dev, 0x9097, 0x2760, 0x00000000);
127 nv_mthd(dev, 0x9097, 0x2780, 0x00000000);
128 nv_mthd(dev, 0x9097, 0x27a0, 0x00000000);
129 nv_mthd(dev, 0x9097, 0x27c0, 0x00000000);
130 nv_mthd(dev, 0x9097, 0x27e0, 0x00000000);
131 nv_mthd(dev, 0x9097, 0x2704, 0x00000000);
132 nv_mthd(dev, 0x9097, 0x2724, 0x00000000);
133 nv_mthd(dev, 0x9097, 0x2744, 0x00000000);
134 nv_mthd(dev, 0x9097, 0x2764, 0x00000000);
135 nv_mthd(dev, 0x9097, 0x2784, 0x00000000);
136 nv_mthd(dev, 0x9097, 0x27a4, 0x00000000);
137 nv_mthd(dev, 0x9097, 0x27c4, 0x00000000);
138 nv_mthd(dev, 0x9097, 0x27e4, 0x00000000);
139 nv_mthd(dev, 0x9097, 0x2708, 0x00000000);
140 nv_mthd(dev, 0x9097, 0x2728, 0x00000000);
141 nv_mthd(dev, 0x9097, 0x2748, 0x00000000);
142 nv_mthd(dev, 0x9097, 0x2768, 0x00000000);
143 nv_mthd(dev, 0x9097, 0x2788, 0x00000000);
144 nv_mthd(dev, 0x9097, 0x27a8, 0x00000000);
145 nv_mthd(dev, 0x9097, 0x27c8, 0x00000000);
146 nv_mthd(dev, 0x9097, 0x27e8, 0x00000000);
147 nv_mthd(dev, 0x9097, 0x270c, 0x00000000);
148 nv_mthd(dev, 0x9097, 0x272c, 0x00000000);
149 nv_mthd(dev, 0x9097, 0x274c, 0x00000000);
150 nv_mthd(dev, 0x9097, 0x276c, 0x00000000);
151 nv_mthd(dev, 0x9097, 0x278c, 0x00000000);
152 nv_mthd(dev, 0x9097, 0x27ac, 0x00000000);
153 nv_mthd(dev, 0x9097, 0x27cc, 0x00000000);
154 nv_mthd(dev, 0x9097, 0x27ec, 0x00000000);
155 nv_mthd(dev, 0x9097, 0x2710, 0x00014000);
156 nv_mthd(dev, 0x9097, 0x2730, 0x00014000);
157 nv_mthd(dev, 0x9097, 0x2750, 0x00014000);
158 nv_mthd(dev, 0x9097, 0x2770, 0x00014000);
159 nv_mthd(dev, 0x9097, 0x2790, 0x00014000);
160 nv_mthd(dev, 0x9097, 0x27b0, 0x00014000);
161 nv_mthd(dev, 0x9097, 0x27d0, 0x00014000);
162 nv_mthd(dev, 0x9097, 0x27f0, 0x00014000);
163 nv_mthd(dev, 0x9097, 0x2714, 0x00000040);
164 nv_mthd(dev, 0x9097, 0x2734, 0x00000040);
165 nv_mthd(dev, 0x9097, 0x2754, 0x00000040);
166 nv_mthd(dev, 0x9097, 0x2774, 0x00000040);
167 nv_mthd(dev, 0x9097, 0x2794, 0x00000040);
168 nv_mthd(dev, 0x9097, 0x27b4, 0x00000040);
169 nv_mthd(dev, 0x9097, 0x27d4, 0x00000040);
170 nv_mthd(dev, 0x9097, 0x27f4, 0x00000040);
171 nv_mthd(dev, 0x9097, 0x1c00, 0x00000000);
172 nv_mthd(dev, 0x9097, 0x1c10, 0x00000000);
173 nv_mthd(dev, 0x9097, 0x1c20, 0x00000000);
174 nv_mthd(dev, 0x9097, 0x1c30, 0x00000000);
175 nv_mthd(dev, 0x9097, 0x1c40, 0x00000000);
176 nv_mthd(dev, 0x9097, 0x1c50, 0x00000000);
177 nv_mthd(dev, 0x9097, 0x1c60, 0x00000000);
178 nv_mthd(dev, 0x9097, 0x1c70, 0x00000000);
179 nv_mthd(dev, 0x9097, 0x1c80, 0x00000000);
180 nv_mthd(dev, 0x9097, 0x1c90, 0x00000000);
181 nv_mthd(dev, 0x9097, 0x1ca0, 0x00000000);
182 nv_mthd(dev, 0x9097, 0x1cb0, 0x00000000);
183 nv_mthd(dev, 0x9097, 0x1cc0, 0x00000000);
184 nv_mthd(dev, 0x9097, 0x1cd0, 0x00000000);
185 nv_mthd(dev, 0x9097, 0x1ce0, 0x00000000);
186 nv_mthd(dev, 0x9097, 0x1cf0, 0x00000000);
187 nv_mthd(dev, 0x9097, 0x1c04, 0x00000000);
188 nv_mthd(dev, 0x9097, 0x1c14, 0x00000000);
189 nv_mthd(dev, 0x9097, 0x1c24, 0x00000000);
190 nv_mthd(dev, 0x9097, 0x1c34, 0x00000000);
191 nv_mthd(dev, 0x9097, 0x1c44, 0x00000000);
192 nv_mthd(dev, 0x9097, 0x1c54, 0x00000000);
193 nv_mthd(dev, 0x9097, 0x1c64, 0x00000000);
194 nv_mthd(dev, 0x9097, 0x1c74, 0x00000000);
195 nv_mthd(dev, 0x9097, 0x1c84, 0x00000000);
196 nv_mthd(dev, 0x9097, 0x1c94, 0x00000000);
197 nv_mthd(dev, 0x9097, 0x1ca4, 0x00000000);
198 nv_mthd(dev, 0x9097, 0x1cb4, 0x00000000);
199 nv_mthd(dev, 0x9097, 0x1cc4, 0x00000000);
200 nv_mthd(dev, 0x9097, 0x1cd4, 0x00000000);
201 nv_mthd(dev, 0x9097, 0x1ce4, 0x00000000);
202 nv_mthd(dev, 0x9097, 0x1cf4, 0x00000000);
203 nv_mthd(dev, 0x9097, 0x1c08, 0x00000000);
204 nv_mthd(dev, 0x9097, 0x1c18, 0x00000000);
205 nv_mthd(dev, 0x9097, 0x1c28, 0x00000000);
206 nv_mthd(dev, 0x9097, 0x1c38, 0x00000000);
207 nv_mthd(dev, 0x9097, 0x1c48, 0x00000000);
208 nv_mthd(dev, 0x9097, 0x1c58, 0x00000000);
209 nv_mthd(dev, 0x9097, 0x1c68, 0x00000000);
210 nv_mthd(dev, 0x9097, 0x1c78, 0x00000000);
211 nv_mthd(dev, 0x9097, 0x1c88, 0x00000000);
212 nv_mthd(dev, 0x9097, 0x1c98, 0x00000000);
213 nv_mthd(dev, 0x9097, 0x1ca8, 0x00000000);
214 nv_mthd(dev, 0x9097, 0x1cb8, 0x00000000);
215 nv_mthd(dev, 0x9097, 0x1cc8, 0x00000000);
216 nv_mthd(dev, 0x9097, 0x1cd8, 0x00000000);
217 nv_mthd(dev, 0x9097, 0x1ce8, 0x00000000);
218 nv_mthd(dev, 0x9097, 0x1cf8, 0x00000000);
219 nv_mthd(dev, 0x9097, 0x1c0c, 0x00000000);
220 nv_mthd(dev, 0x9097, 0x1c1c, 0x00000000);
221 nv_mthd(dev, 0x9097, 0x1c2c, 0x00000000);
222 nv_mthd(dev, 0x9097, 0x1c3c, 0x00000000);
223 nv_mthd(dev, 0x9097, 0x1c4c, 0x00000000);
224 nv_mthd(dev, 0x9097, 0x1c5c, 0x00000000);
225 nv_mthd(dev, 0x9097, 0x1c6c, 0x00000000);
226 nv_mthd(dev, 0x9097, 0x1c7c, 0x00000000);
227 nv_mthd(dev, 0x9097, 0x1c8c, 0x00000000);
228 nv_mthd(dev, 0x9097, 0x1c9c, 0x00000000);
229 nv_mthd(dev, 0x9097, 0x1cac, 0x00000000);
230 nv_mthd(dev, 0x9097, 0x1cbc, 0x00000000);
231 nv_mthd(dev, 0x9097, 0x1ccc, 0x00000000);
232 nv_mthd(dev, 0x9097, 0x1cdc, 0x00000000);
233 nv_mthd(dev, 0x9097, 0x1cec, 0x00000000);
234 nv_mthd(dev, 0x9097, 0x1cfc, 0x00000000);
235 nv_mthd(dev, 0x9097, 0x1d00, 0x00000000);
236 nv_mthd(dev, 0x9097, 0x1d10, 0x00000000);
237 nv_mthd(dev, 0x9097, 0x1d20, 0x00000000);
238 nv_mthd(dev, 0x9097, 0x1d30, 0x00000000);
239 nv_mthd(dev, 0x9097, 0x1d40, 0x00000000);
240 nv_mthd(dev, 0x9097, 0x1d50, 0x00000000);
241 nv_mthd(dev, 0x9097, 0x1d60, 0x00000000);
242 nv_mthd(dev, 0x9097, 0x1d70, 0x00000000);
243 nv_mthd(dev, 0x9097, 0x1d80, 0x00000000);
244 nv_mthd(dev, 0x9097, 0x1d90, 0x00000000);
245 nv_mthd(dev, 0x9097, 0x1da0, 0x00000000);
246 nv_mthd(dev, 0x9097, 0x1db0, 0x00000000);
247 nv_mthd(dev, 0x9097, 0x1dc0, 0x00000000);
248 nv_mthd(dev, 0x9097, 0x1dd0, 0x00000000);
249 nv_mthd(dev, 0x9097, 0x1de0, 0x00000000);
250 nv_mthd(dev, 0x9097, 0x1df0, 0x00000000);
251 nv_mthd(dev, 0x9097, 0x1d04, 0x00000000);
252 nv_mthd(dev, 0x9097, 0x1d14, 0x00000000);
253 nv_mthd(dev, 0x9097, 0x1d24, 0x00000000);
254 nv_mthd(dev, 0x9097, 0x1d34, 0x00000000);
255 nv_mthd(dev, 0x9097, 0x1d44, 0x00000000);
256 nv_mthd(dev, 0x9097, 0x1d54, 0x00000000);
257 nv_mthd(dev, 0x9097, 0x1d64, 0x00000000);
258 nv_mthd(dev, 0x9097, 0x1d74, 0x00000000);
259 nv_mthd(dev, 0x9097, 0x1d84, 0x00000000);
260 nv_mthd(dev, 0x9097, 0x1d94, 0x00000000);
261 nv_mthd(dev, 0x9097, 0x1da4, 0x00000000);
262 nv_mthd(dev, 0x9097, 0x1db4, 0x00000000);
263 nv_mthd(dev, 0x9097, 0x1dc4, 0x00000000);
264 nv_mthd(dev, 0x9097, 0x1dd4, 0x00000000);
265 nv_mthd(dev, 0x9097, 0x1de4, 0x00000000);
266 nv_mthd(dev, 0x9097, 0x1df4, 0x00000000);
267 nv_mthd(dev, 0x9097, 0x1d08, 0x00000000);
268 nv_mthd(dev, 0x9097, 0x1d18, 0x00000000);
269 nv_mthd(dev, 0x9097, 0x1d28, 0x00000000);
270 nv_mthd(dev, 0x9097, 0x1d38, 0x00000000);
271 nv_mthd(dev, 0x9097, 0x1d48, 0x00000000);
272 nv_mthd(dev, 0x9097, 0x1d58, 0x00000000);
273 nv_mthd(dev, 0x9097, 0x1d68, 0x00000000);
274 nv_mthd(dev, 0x9097, 0x1d78, 0x00000000);
275 nv_mthd(dev, 0x9097, 0x1d88, 0x00000000);
276 nv_mthd(dev, 0x9097, 0x1d98, 0x00000000);
277 nv_mthd(dev, 0x9097, 0x1da8, 0x00000000);
278 nv_mthd(dev, 0x9097, 0x1db8, 0x00000000);
279 nv_mthd(dev, 0x9097, 0x1dc8, 0x00000000);
280 nv_mthd(dev, 0x9097, 0x1dd8, 0x00000000);
281 nv_mthd(dev, 0x9097, 0x1de8, 0x00000000);
282 nv_mthd(dev, 0x9097, 0x1df8, 0x00000000);
283 nv_mthd(dev, 0x9097, 0x1d0c, 0x00000000);
284 nv_mthd(dev, 0x9097, 0x1d1c, 0x00000000);
285 nv_mthd(dev, 0x9097, 0x1d2c, 0x00000000);
286 nv_mthd(dev, 0x9097, 0x1d3c, 0x00000000);
287 nv_mthd(dev, 0x9097, 0x1d4c, 0x00000000);
288 nv_mthd(dev, 0x9097, 0x1d5c, 0x00000000);
289 nv_mthd(dev, 0x9097, 0x1d6c, 0x00000000);
290 nv_mthd(dev, 0x9097, 0x1d7c, 0x00000000);
291 nv_mthd(dev, 0x9097, 0x1d8c, 0x00000000);
292 nv_mthd(dev, 0x9097, 0x1d9c, 0x00000000);
293 nv_mthd(dev, 0x9097, 0x1dac, 0x00000000);
294 nv_mthd(dev, 0x9097, 0x1dbc, 0x00000000);
295 nv_mthd(dev, 0x9097, 0x1dcc, 0x00000000);
296 nv_mthd(dev, 0x9097, 0x1ddc, 0x00000000);
297 nv_mthd(dev, 0x9097, 0x1dec, 0x00000000);
298 nv_mthd(dev, 0x9097, 0x1dfc, 0x00000000);
299 nv_mthd(dev, 0x9097, 0x1f00, 0x00000000);
300 nv_mthd(dev, 0x9097, 0x1f08, 0x00000000);
301 nv_mthd(dev, 0x9097, 0x1f10, 0x00000000);
302 nv_mthd(dev, 0x9097, 0x1f18, 0x00000000);
303 nv_mthd(dev, 0x9097, 0x1f20, 0x00000000);
304 nv_mthd(dev, 0x9097, 0x1f28, 0x00000000);
305 nv_mthd(dev, 0x9097, 0x1f30, 0x00000000);
306 nv_mthd(dev, 0x9097, 0x1f38, 0x00000000);
307 nv_mthd(dev, 0x9097, 0x1f40, 0x00000000);
308 nv_mthd(dev, 0x9097, 0x1f48, 0x00000000);
309 nv_mthd(dev, 0x9097, 0x1f50, 0x00000000);
310 nv_mthd(dev, 0x9097, 0x1f58, 0x00000000);
311 nv_mthd(dev, 0x9097, 0x1f60, 0x00000000);
312 nv_mthd(dev, 0x9097, 0x1f68, 0x00000000);
313 nv_mthd(dev, 0x9097, 0x1f70, 0x00000000);
314 nv_mthd(dev, 0x9097, 0x1f78, 0x00000000);
315 nv_mthd(dev, 0x9097, 0x1f04, 0x00000000);
316 nv_mthd(dev, 0x9097, 0x1f0c, 0x00000000);
317 nv_mthd(dev, 0x9097, 0x1f14, 0x00000000);
318 nv_mthd(dev, 0x9097, 0x1f1c, 0x00000000);
319 nv_mthd(dev, 0x9097, 0x1f24, 0x00000000);
320 nv_mthd(dev, 0x9097, 0x1f2c, 0x00000000);
321 nv_mthd(dev, 0x9097, 0x1f34, 0x00000000);
322 nv_mthd(dev, 0x9097, 0x1f3c, 0x00000000);
323 nv_mthd(dev, 0x9097, 0x1f44, 0x00000000);
324 nv_mthd(dev, 0x9097, 0x1f4c, 0x00000000);
325 nv_mthd(dev, 0x9097, 0x1f54, 0x00000000);
326 nv_mthd(dev, 0x9097, 0x1f5c, 0x00000000);
327 nv_mthd(dev, 0x9097, 0x1f64, 0x00000000);
328 nv_mthd(dev, 0x9097, 0x1f6c, 0x00000000);
329 nv_mthd(dev, 0x9097, 0x1f74, 0x00000000);
330 nv_mthd(dev, 0x9097, 0x1f7c, 0x00000000);
331 nv_mthd(dev, 0x9097, 0x1f80, 0x00000000);
332 nv_mthd(dev, 0x9097, 0x1f88, 0x00000000);
333 nv_mthd(dev, 0x9097, 0x1f90, 0x00000000);
334 nv_mthd(dev, 0x9097, 0x1f98, 0x00000000);
335 nv_mthd(dev, 0x9097, 0x1fa0, 0x00000000);
336 nv_mthd(dev, 0x9097, 0x1fa8, 0x00000000);
337 nv_mthd(dev, 0x9097, 0x1fb0, 0x00000000);
338 nv_mthd(dev, 0x9097, 0x1fb8, 0x00000000);
339 nv_mthd(dev, 0x9097, 0x1fc0, 0x00000000);
340 nv_mthd(dev, 0x9097, 0x1fc8, 0x00000000);
341 nv_mthd(dev, 0x9097, 0x1fd0, 0x00000000);
342 nv_mthd(dev, 0x9097, 0x1fd8, 0x00000000);
343 nv_mthd(dev, 0x9097, 0x1fe0, 0x00000000);
344 nv_mthd(dev, 0x9097, 0x1fe8, 0x00000000);
345 nv_mthd(dev, 0x9097, 0x1ff0, 0x00000000);
346 nv_mthd(dev, 0x9097, 0x1ff8, 0x00000000);
347 nv_mthd(dev, 0x9097, 0x1f84, 0x00000000);
348 nv_mthd(dev, 0x9097, 0x1f8c, 0x00000000);
349 nv_mthd(dev, 0x9097, 0x1f94, 0x00000000);
350 nv_mthd(dev, 0x9097, 0x1f9c, 0x00000000);
351 nv_mthd(dev, 0x9097, 0x1fa4, 0x00000000);
352 nv_mthd(dev, 0x9097, 0x1fac, 0x00000000);
353 nv_mthd(dev, 0x9097, 0x1fb4, 0x00000000);
354 nv_mthd(dev, 0x9097, 0x1fbc, 0x00000000);
355 nv_mthd(dev, 0x9097, 0x1fc4, 0x00000000);
356 nv_mthd(dev, 0x9097, 0x1fcc, 0x00000000);
357 nv_mthd(dev, 0x9097, 0x1fd4, 0x00000000);
358 nv_mthd(dev, 0x9097, 0x1fdc, 0x00000000);
359 nv_mthd(dev, 0x9097, 0x1fe4, 0x00000000);
360 nv_mthd(dev, 0x9097, 0x1fec, 0x00000000);
361 nv_mthd(dev, 0x9097, 0x1ff4, 0x00000000);
362 nv_mthd(dev, 0x9097, 0x1ffc, 0x00000000);
363 nv_mthd(dev, 0x9097, 0x2200, 0x00000022);
364 nv_mthd(dev, 0x9097, 0x2210, 0x00000022);
365 nv_mthd(dev, 0x9097, 0x2220, 0x00000022);
366 nv_mthd(dev, 0x9097, 0x2230, 0x00000022);
367 nv_mthd(dev, 0x9097, 0x2240, 0x00000022);
368 nv_mthd(dev, 0x9097, 0x2000, 0x00000000);
369 nv_mthd(dev, 0x9097, 0x2040, 0x00000011);
370 nv_mthd(dev, 0x9097, 0x2080, 0x00000020);
371 nv_mthd(dev, 0x9097, 0x20c0, 0x00000030);
372 nv_mthd(dev, 0x9097, 0x2100, 0x00000040);
373 nv_mthd(dev, 0x9097, 0x2140, 0x00000051);
374 nv_mthd(dev, 0x9097, 0x200c, 0x00000001);
375 nv_mthd(dev, 0x9097, 0x204c, 0x00000001);
376 nv_mthd(dev, 0x9097, 0x208c, 0x00000001);
377 nv_mthd(dev, 0x9097, 0x20cc, 0x00000001);
378 nv_mthd(dev, 0x9097, 0x210c, 0x00000001);
379 nv_mthd(dev, 0x9097, 0x214c, 0x00000001);
380 nv_mthd(dev, 0x9097, 0x2010, 0x00000000);
381 nv_mthd(dev, 0x9097, 0x2050, 0x00000000);
382 nv_mthd(dev, 0x9097, 0x2090, 0x00000001);
383 nv_mthd(dev, 0x9097, 0x20d0, 0x00000002);
384 nv_mthd(dev, 0x9097, 0x2110, 0x00000003);
385 nv_mthd(dev, 0x9097, 0x2150, 0x00000004);
386 nv_mthd(dev, 0x9097, 0x0380, 0x00000000);
387 nv_mthd(dev, 0x9097, 0x03a0, 0x00000000);
388 nv_mthd(dev, 0x9097, 0x03c0, 0x00000000);
389 nv_mthd(dev, 0x9097, 0x03e0, 0x00000000);
390 nv_mthd(dev, 0x9097, 0x0384, 0x00000000);
391 nv_mthd(dev, 0x9097, 0x03a4, 0x00000000);
392 nv_mthd(dev, 0x9097, 0x03c4, 0x00000000);
393 nv_mthd(dev, 0x9097, 0x03e4, 0x00000000);
394 nv_mthd(dev, 0x9097, 0x0388, 0x00000000);
395 nv_mthd(dev, 0x9097, 0x03a8, 0x00000000);
396 nv_mthd(dev, 0x9097, 0x03c8, 0x00000000);
397 nv_mthd(dev, 0x9097, 0x03e8, 0x00000000);
398 nv_mthd(dev, 0x9097, 0x038c, 0x00000000);
399 nv_mthd(dev, 0x9097, 0x03ac, 0x00000000);
400 nv_mthd(dev, 0x9097, 0x03cc, 0x00000000);
401 nv_mthd(dev, 0x9097, 0x03ec, 0x00000000);
402 nv_mthd(dev, 0x9097, 0x0700, 0x00000000);
403 nv_mthd(dev, 0x9097, 0x0710, 0x00000000);
404 nv_mthd(dev, 0x9097, 0x0720, 0x00000000);
405 nv_mthd(dev, 0x9097, 0x0730, 0x00000000);
406 nv_mthd(dev, 0x9097, 0x0704, 0x00000000);
407 nv_mthd(dev, 0x9097, 0x0714, 0x00000000);
408 nv_mthd(dev, 0x9097, 0x0724, 0x00000000);
409 nv_mthd(dev, 0x9097, 0x0734, 0x00000000);
410 nv_mthd(dev, 0x9097, 0x0708, 0x00000000);
411 nv_mthd(dev, 0x9097, 0x0718, 0x00000000);
412 nv_mthd(dev, 0x9097, 0x0728, 0x00000000);
413 nv_mthd(dev, 0x9097, 0x0738, 0x00000000);
414 nv_mthd(dev, 0x9097, 0x2800, 0x00000000);
415 nv_mthd(dev, 0x9097, 0x2804, 0x00000000);
416 nv_mthd(dev, 0x9097, 0x2808, 0x00000000);
417 nv_mthd(dev, 0x9097, 0x280c, 0x00000000);
418 nv_mthd(dev, 0x9097, 0x2810, 0x00000000);
419 nv_mthd(dev, 0x9097, 0x2814, 0x00000000);
420 nv_mthd(dev, 0x9097, 0x2818, 0x00000000);
421 nv_mthd(dev, 0x9097, 0x281c, 0x00000000);
422 nv_mthd(dev, 0x9097, 0x2820, 0x00000000);
423 nv_mthd(dev, 0x9097, 0x2824, 0x00000000);
424 nv_mthd(dev, 0x9097, 0x2828, 0x00000000);
425 nv_mthd(dev, 0x9097, 0x282c, 0x00000000);
426 nv_mthd(dev, 0x9097, 0x2830, 0x00000000);
427 nv_mthd(dev, 0x9097, 0x2834, 0x00000000);
428 nv_mthd(dev, 0x9097, 0x2838, 0x00000000);
429 nv_mthd(dev, 0x9097, 0x283c, 0x00000000);
430 nv_mthd(dev, 0x9097, 0x2840, 0x00000000);
431 nv_mthd(dev, 0x9097, 0x2844, 0x00000000);
432 nv_mthd(dev, 0x9097, 0x2848, 0x00000000);
433 nv_mthd(dev, 0x9097, 0x284c, 0x00000000);
434 nv_mthd(dev, 0x9097, 0x2850, 0x00000000);
435 nv_mthd(dev, 0x9097, 0x2854, 0x00000000);
436 nv_mthd(dev, 0x9097, 0x2858, 0x00000000);
437 nv_mthd(dev, 0x9097, 0x285c, 0x00000000);
438 nv_mthd(dev, 0x9097, 0x2860, 0x00000000);
439 nv_mthd(dev, 0x9097, 0x2864, 0x00000000);
440 nv_mthd(dev, 0x9097, 0x2868, 0x00000000);
441 nv_mthd(dev, 0x9097, 0x286c, 0x00000000);
442 nv_mthd(dev, 0x9097, 0x2870, 0x00000000);
443 nv_mthd(dev, 0x9097, 0x2874, 0x00000000);
444 nv_mthd(dev, 0x9097, 0x2878, 0x00000000);
445 nv_mthd(dev, 0x9097, 0x287c, 0x00000000);
446 nv_mthd(dev, 0x9097, 0x2880, 0x00000000);
447 nv_mthd(dev, 0x9097, 0x2884, 0x00000000);
448 nv_mthd(dev, 0x9097, 0x2888, 0x00000000);
449 nv_mthd(dev, 0x9097, 0x288c, 0x00000000);
450 nv_mthd(dev, 0x9097, 0x2890, 0x00000000);
451 nv_mthd(dev, 0x9097, 0x2894, 0x00000000);
452 nv_mthd(dev, 0x9097, 0x2898, 0x00000000);
453 nv_mthd(dev, 0x9097, 0x289c, 0x00000000);
454 nv_mthd(dev, 0x9097, 0x28a0, 0x00000000);
455 nv_mthd(dev, 0x9097, 0x28a4, 0x00000000);
456 nv_mthd(dev, 0x9097, 0x28a8, 0x00000000);
457 nv_mthd(dev, 0x9097, 0x28ac, 0x00000000);
458 nv_mthd(dev, 0x9097, 0x28b0, 0x00000000);
459 nv_mthd(dev, 0x9097, 0x28b4, 0x00000000);
460 nv_mthd(dev, 0x9097, 0x28b8, 0x00000000);
461 nv_mthd(dev, 0x9097, 0x28bc, 0x00000000);
462 nv_mthd(dev, 0x9097, 0x28c0, 0x00000000);
463 nv_mthd(dev, 0x9097, 0x28c4, 0x00000000);
464 nv_mthd(dev, 0x9097, 0x28c8, 0x00000000);
465 nv_mthd(dev, 0x9097, 0x28cc, 0x00000000);
466 nv_mthd(dev, 0x9097, 0x28d0, 0x00000000);
467 nv_mthd(dev, 0x9097, 0x28d4, 0x00000000);
468 nv_mthd(dev, 0x9097, 0x28d8, 0x00000000);
469 nv_mthd(dev, 0x9097, 0x28dc, 0x00000000);
470 nv_mthd(dev, 0x9097, 0x28e0, 0x00000000);
471 nv_mthd(dev, 0x9097, 0x28e4, 0x00000000);
472 nv_mthd(dev, 0x9097, 0x28e8, 0x00000000);
473 nv_mthd(dev, 0x9097, 0x28ec, 0x00000000);
474 nv_mthd(dev, 0x9097, 0x28f0, 0x00000000);
475 nv_mthd(dev, 0x9097, 0x28f4, 0x00000000);
476 nv_mthd(dev, 0x9097, 0x28f8, 0x00000000);
477 nv_mthd(dev, 0x9097, 0x28fc, 0x00000000);
478 nv_mthd(dev, 0x9097, 0x2900, 0x00000000);
479 nv_mthd(dev, 0x9097, 0x2904, 0x00000000);
480 nv_mthd(dev, 0x9097, 0x2908, 0x00000000);
481 nv_mthd(dev, 0x9097, 0x290c, 0x00000000);
482 nv_mthd(dev, 0x9097, 0x2910, 0x00000000);
483 nv_mthd(dev, 0x9097, 0x2914, 0x00000000);
484 nv_mthd(dev, 0x9097, 0x2918, 0x00000000);
485 nv_mthd(dev, 0x9097, 0x291c, 0x00000000);
486 nv_mthd(dev, 0x9097, 0x2920, 0x00000000);
487 nv_mthd(dev, 0x9097, 0x2924, 0x00000000);
488 nv_mthd(dev, 0x9097, 0x2928, 0x00000000);
489 nv_mthd(dev, 0x9097, 0x292c, 0x00000000);
490 nv_mthd(dev, 0x9097, 0x2930, 0x00000000);
491 nv_mthd(dev, 0x9097, 0x2934, 0x00000000);
492 nv_mthd(dev, 0x9097, 0x2938, 0x00000000);
493 nv_mthd(dev, 0x9097, 0x293c, 0x00000000);
494 nv_mthd(dev, 0x9097, 0x2940, 0x00000000);
495 nv_mthd(dev, 0x9097, 0x2944, 0x00000000);
496 nv_mthd(dev, 0x9097, 0x2948, 0x00000000);
497 nv_mthd(dev, 0x9097, 0x294c, 0x00000000);
498 nv_mthd(dev, 0x9097, 0x2950, 0x00000000);
499 nv_mthd(dev, 0x9097, 0x2954, 0x00000000);
500 nv_mthd(dev, 0x9097, 0x2958, 0x00000000);
501 nv_mthd(dev, 0x9097, 0x295c, 0x00000000);
502 nv_mthd(dev, 0x9097, 0x2960, 0x00000000);
503 nv_mthd(dev, 0x9097, 0x2964, 0x00000000);
504 nv_mthd(dev, 0x9097, 0x2968, 0x00000000);
505 nv_mthd(dev, 0x9097, 0x296c, 0x00000000);
506 nv_mthd(dev, 0x9097, 0x2970, 0x00000000);
507 nv_mthd(dev, 0x9097, 0x2974, 0x00000000);
508 nv_mthd(dev, 0x9097, 0x2978, 0x00000000);
509 nv_mthd(dev, 0x9097, 0x297c, 0x00000000);
510 nv_mthd(dev, 0x9097, 0x2980, 0x00000000);
511 nv_mthd(dev, 0x9097, 0x2984, 0x00000000);
512 nv_mthd(dev, 0x9097, 0x2988, 0x00000000);
513 nv_mthd(dev, 0x9097, 0x298c, 0x00000000);
514 nv_mthd(dev, 0x9097, 0x2990, 0x00000000);
515 nv_mthd(dev, 0x9097, 0x2994, 0x00000000);
516 nv_mthd(dev, 0x9097, 0x2998, 0x00000000);
517 nv_mthd(dev, 0x9097, 0x299c, 0x00000000);
518 nv_mthd(dev, 0x9097, 0x29a0, 0x00000000);
519 nv_mthd(dev, 0x9097, 0x29a4, 0x00000000);
520 nv_mthd(dev, 0x9097, 0x29a8, 0x00000000);
521 nv_mthd(dev, 0x9097, 0x29ac, 0x00000000);
522 nv_mthd(dev, 0x9097, 0x29b0, 0x00000000);
523 nv_mthd(dev, 0x9097, 0x29b4, 0x00000000);
524 nv_mthd(dev, 0x9097, 0x29b8, 0x00000000);
525 nv_mthd(dev, 0x9097, 0x29bc, 0x00000000);
526 nv_mthd(dev, 0x9097, 0x29c0, 0x00000000);
527 nv_mthd(dev, 0x9097, 0x29c4, 0x00000000);
528 nv_mthd(dev, 0x9097, 0x29c8, 0x00000000);
529 nv_mthd(dev, 0x9097, 0x29cc, 0x00000000);
530 nv_mthd(dev, 0x9097, 0x29d0, 0x00000000);
531 nv_mthd(dev, 0x9097, 0x29d4, 0x00000000);
532 nv_mthd(dev, 0x9097, 0x29d8, 0x00000000);
533 nv_mthd(dev, 0x9097, 0x29dc, 0x00000000);
534 nv_mthd(dev, 0x9097, 0x29e0, 0x00000000);
535 nv_mthd(dev, 0x9097, 0x29e4, 0x00000000);
536 nv_mthd(dev, 0x9097, 0x29e8, 0x00000000);
537 nv_mthd(dev, 0x9097, 0x29ec, 0x00000000);
538 nv_mthd(dev, 0x9097, 0x29f0, 0x00000000);
539 nv_mthd(dev, 0x9097, 0x29f4, 0x00000000);
540 nv_mthd(dev, 0x9097, 0x29f8, 0x00000000);
541 nv_mthd(dev, 0x9097, 0x29fc, 0x00000000);
542 nv_mthd(dev, 0x9097, 0x0a00, 0x00000000);
543 nv_mthd(dev, 0x9097, 0x0a20, 0x00000000);
544 nv_mthd(dev, 0x9097, 0x0a40, 0x00000000);
545 nv_mthd(dev, 0x9097, 0x0a60, 0x00000000);
546 nv_mthd(dev, 0x9097, 0x0a80, 0x00000000);
547 nv_mthd(dev, 0x9097, 0x0aa0, 0x00000000);
548 nv_mthd(dev, 0x9097, 0x0ac0, 0x00000000);
549 nv_mthd(dev, 0x9097, 0x0ae0, 0x00000000);
550 nv_mthd(dev, 0x9097, 0x0b00, 0x00000000);
551 nv_mthd(dev, 0x9097, 0x0b20, 0x00000000);
552 nv_mthd(dev, 0x9097, 0x0b40, 0x00000000);
553 nv_mthd(dev, 0x9097, 0x0b60, 0x00000000);
554 nv_mthd(dev, 0x9097, 0x0b80, 0x00000000);
555 nv_mthd(dev, 0x9097, 0x0ba0, 0x00000000);
556 nv_mthd(dev, 0x9097, 0x0bc0, 0x00000000);
557 nv_mthd(dev, 0x9097, 0x0be0, 0x00000000);
558 nv_mthd(dev, 0x9097, 0x0a04, 0x00000000);
559 nv_mthd(dev, 0x9097, 0x0a24, 0x00000000);
560 nv_mthd(dev, 0x9097, 0x0a44, 0x00000000);
561 nv_mthd(dev, 0x9097, 0x0a64, 0x00000000);
562 nv_mthd(dev, 0x9097, 0x0a84, 0x00000000);
563 nv_mthd(dev, 0x9097, 0x0aa4, 0x00000000);
564 nv_mthd(dev, 0x9097, 0x0ac4, 0x00000000);
565 nv_mthd(dev, 0x9097, 0x0ae4, 0x00000000);
566 nv_mthd(dev, 0x9097, 0x0b04, 0x00000000);
567 nv_mthd(dev, 0x9097, 0x0b24, 0x00000000);
568 nv_mthd(dev, 0x9097, 0x0b44, 0x00000000);
569 nv_mthd(dev, 0x9097, 0x0b64, 0x00000000);
570 nv_mthd(dev, 0x9097, 0x0b84, 0x00000000);
571 nv_mthd(dev, 0x9097, 0x0ba4, 0x00000000);
572 nv_mthd(dev, 0x9097, 0x0bc4, 0x00000000);
573 nv_mthd(dev, 0x9097, 0x0be4, 0x00000000);
574 nv_mthd(dev, 0x9097, 0x0a08, 0x00000000);
575 nv_mthd(dev, 0x9097, 0x0a28, 0x00000000);
576 nv_mthd(dev, 0x9097, 0x0a48, 0x00000000);
577 nv_mthd(dev, 0x9097, 0x0a68, 0x00000000);
578 nv_mthd(dev, 0x9097, 0x0a88, 0x00000000);
579 nv_mthd(dev, 0x9097, 0x0aa8, 0x00000000);
580 nv_mthd(dev, 0x9097, 0x0ac8, 0x00000000);
581 nv_mthd(dev, 0x9097, 0x0ae8, 0x00000000);
582 nv_mthd(dev, 0x9097, 0x0b08, 0x00000000);
583 nv_mthd(dev, 0x9097, 0x0b28, 0x00000000);
584 nv_mthd(dev, 0x9097, 0x0b48, 0x00000000);
585 nv_mthd(dev, 0x9097, 0x0b68, 0x00000000);
586 nv_mthd(dev, 0x9097, 0x0b88, 0x00000000);
587 nv_mthd(dev, 0x9097, 0x0ba8, 0x00000000);
588 nv_mthd(dev, 0x9097, 0x0bc8, 0x00000000);
589 nv_mthd(dev, 0x9097, 0x0be8, 0x00000000);
590 nv_mthd(dev, 0x9097, 0x0a0c, 0x00000000);
591 nv_mthd(dev, 0x9097, 0x0a2c, 0x00000000);
592 nv_mthd(dev, 0x9097, 0x0a4c, 0x00000000);
593 nv_mthd(dev, 0x9097, 0x0a6c, 0x00000000);
594 nv_mthd(dev, 0x9097, 0x0a8c, 0x00000000);
595 nv_mthd(dev, 0x9097, 0x0aac, 0x00000000);
596 nv_mthd(dev, 0x9097, 0x0acc, 0x00000000);
597 nv_mthd(dev, 0x9097, 0x0aec, 0x00000000);
598 nv_mthd(dev, 0x9097, 0x0b0c, 0x00000000);
599 nv_mthd(dev, 0x9097, 0x0b2c, 0x00000000);
600 nv_mthd(dev, 0x9097, 0x0b4c, 0x00000000);
601 nv_mthd(dev, 0x9097, 0x0b6c, 0x00000000);
602 nv_mthd(dev, 0x9097, 0x0b8c, 0x00000000);
603 nv_mthd(dev, 0x9097, 0x0bac, 0x00000000);
604 nv_mthd(dev, 0x9097, 0x0bcc, 0x00000000);
605 nv_mthd(dev, 0x9097, 0x0bec, 0x00000000);
606 nv_mthd(dev, 0x9097, 0x0a10, 0x00000000);
607 nv_mthd(dev, 0x9097, 0x0a30, 0x00000000);
608 nv_mthd(dev, 0x9097, 0x0a50, 0x00000000);
609 nv_mthd(dev, 0x9097, 0x0a70, 0x00000000);
610 nv_mthd(dev, 0x9097, 0x0a90, 0x00000000);
611 nv_mthd(dev, 0x9097, 0x0ab0, 0x00000000);
612 nv_mthd(dev, 0x9097, 0x0ad0, 0x00000000);
613 nv_mthd(dev, 0x9097, 0x0af0, 0x00000000);
614 nv_mthd(dev, 0x9097, 0x0b10, 0x00000000);
615 nv_mthd(dev, 0x9097, 0x0b30, 0x00000000);
616 nv_mthd(dev, 0x9097, 0x0b50, 0x00000000);
617 nv_mthd(dev, 0x9097, 0x0b70, 0x00000000);
618 nv_mthd(dev, 0x9097, 0x0b90, 0x00000000);
619 nv_mthd(dev, 0x9097, 0x0bb0, 0x00000000);
620 nv_mthd(dev, 0x9097, 0x0bd0, 0x00000000);
621 nv_mthd(dev, 0x9097, 0x0bf0, 0x00000000);
622 nv_mthd(dev, 0x9097, 0x0a14, 0x00000000);
623 nv_mthd(dev, 0x9097, 0x0a34, 0x00000000);
624 nv_mthd(dev, 0x9097, 0x0a54, 0x00000000);
625 nv_mthd(dev, 0x9097, 0x0a74, 0x00000000);
626 nv_mthd(dev, 0x9097, 0x0a94, 0x00000000);
627 nv_mthd(dev, 0x9097, 0x0ab4, 0x00000000);
628 nv_mthd(dev, 0x9097, 0x0ad4, 0x00000000);
629 nv_mthd(dev, 0x9097, 0x0af4, 0x00000000);
630 nv_mthd(dev, 0x9097, 0x0b14, 0x00000000);
631 nv_mthd(dev, 0x9097, 0x0b34, 0x00000000);
632 nv_mthd(dev, 0x9097, 0x0b54, 0x00000000);
633 nv_mthd(dev, 0x9097, 0x0b74, 0x00000000);
634 nv_mthd(dev, 0x9097, 0x0b94, 0x00000000);
635 nv_mthd(dev, 0x9097, 0x0bb4, 0x00000000);
636 nv_mthd(dev, 0x9097, 0x0bd4, 0x00000000);
637 nv_mthd(dev, 0x9097, 0x0bf4, 0x00000000);
638 nv_mthd(dev, 0x9097, 0x0c00, 0x00000000);
639 nv_mthd(dev, 0x9097, 0x0c10, 0x00000000);
640 nv_mthd(dev, 0x9097, 0x0c20, 0x00000000);
641 nv_mthd(dev, 0x9097, 0x0c30, 0x00000000);
642 nv_mthd(dev, 0x9097, 0x0c40, 0x00000000);
643 nv_mthd(dev, 0x9097, 0x0c50, 0x00000000);
644 nv_mthd(dev, 0x9097, 0x0c60, 0x00000000);
645 nv_mthd(dev, 0x9097, 0x0c70, 0x00000000);
646 nv_mthd(dev, 0x9097, 0x0c80, 0x00000000);
647 nv_mthd(dev, 0x9097, 0x0c90, 0x00000000);
648 nv_mthd(dev, 0x9097, 0x0ca0, 0x00000000);
649 nv_mthd(dev, 0x9097, 0x0cb0, 0x00000000);
650 nv_mthd(dev, 0x9097, 0x0cc0, 0x00000000);
651 nv_mthd(dev, 0x9097, 0x0cd0, 0x00000000);
652 nv_mthd(dev, 0x9097, 0x0ce0, 0x00000000);
653 nv_mthd(dev, 0x9097, 0x0cf0, 0x00000000);
654 nv_mthd(dev, 0x9097, 0x0c04, 0x00000000);
655 nv_mthd(dev, 0x9097, 0x0c14, 0x00000000);
656 nv_mthd(dev, 0x9097, 0x0c24, 0x00000000);
657 nv_mthd(dev, 0x9097, 0x0c34, 0x00000000);
658 nv_mthd(dev, 0x9097, 0x0c44, 0x00000000);
659 nv_mthd(dev, 0x9097, 0x0c54, 0x00000000);
660 nv_mthd(dev, 0x9097, 0x0c64, 0x00000000);
661 nv_mthd(dev, 0x9097, 0x0c74, 0x00000000);
662 nv_mthd(dev, 0x9097, 0x0c84, 0x00000000);
663 nv_mthd(dev, 0x9097, 0x0c94, 0x00000000);
664 nv_mthd(dev, 0x9097, 0x0ca4, 0x00000000);
665 nv_mthd(dev, 0x9097, 0x0cb4, 0x00000000);
666 nv_mthd(dev, 0x9097, 0x0cc4, 0x00000000);
667 nv_mthd(dev, 0x9097, 0x0cd4, 0x00000000);
668 nv_mthd(dev, 0x9097, 0x0ce4, 0x00000000);
669 nv_mthd(dev, 0x9097, 0x0cf4, 0x00000000);
670 nv_mthd(dev, 0x9097, 0x0c08, 0x00000000);
671 nv_mthd(dev, 0x9097, 0x0c18, 0x00000000);
672 nv_mthd(dev, 0x9097, 0x0c28, 0x00000000);
673 nv_mthd(dev, 0x9097, 0x0c38, 0x00000000);
674 nv_mthd(dev, 0x9097, 0x0c48, 0x00000000);
675 nv_mthd(dev, 0x9097, 0x0c58, 0x00000000);
676 nv_mthd(dev, 0x9097, 0x0c68, 0x00000000);
677 nv_mthd(dev, 0x9097, 0x0c78, 0x00000000);
678 nv_mthd(dev, 0x9097, 0x0c88, 0x00000000);
679 nv_mthd(dev, 0x9097, 0x0c98, 0x00000000);
680 nv_mthd(dev, 0x9097, 0x0ca8, 0x00000000);
681 nv_mthd(dev, 0x9097, 0x0cb8, 0x00000000);
682 nv_mthd(dev, 0x9097, 0x0cc8, 0x00000000);
683 nv_mthd(dev, 0x9097, 0x0cd8, 0x00000000);
684 nv_mthd(dev, 0x9097, 0x0ce8, 0x00000000);
685 nv_mthd(dev, 0x9097, 0x0cf8, 0x00000000);
686 nv_mthd(dev, 0x9097, 0x0c0c, 0x3f800000);
687 nv_mthd(dev, 0x9097, 0x0c1c, 0x3f800000);
688 nv_mthd(dev, 0x9097, 0x0c2c, 0x3f800000);
689 nv_mthd(dev, 0x9097, 0x0c3c, 0x3f800000);
690 nv_mthd(dev, 0x9097, 0x0c4c, 0x3f800000);
691 nv_mthd(dev, 0x9097, 0x0c5c, 0x3f800000);
692 nv_mthd(dev, 0x9097, 0x0c6c, 0x3f800000);
693 nv_mthd(dev, 0x9097, 0x0c7c, 0x3f800000);
694 nv_mthd(dev, 0x9097, 0x0c8c, 0x3f800000);
695 nv_mthd(dev, 0x9097, 0x0c9c, 0x3f800000);
696 nv_mthd(dev, 0x9097, 0x0cac, 0x3f800000);
697 nv_mthd(dev, 0x9097, 0x0cbc, 0x3f800000);
698 nv_mthd(dev, 0x9097, 0x0ccc, 0x3f800000);
699 nv_mthd(dev, 0x9097, 0x0cdc, 0x3f800000);
700 nv_mthd(dev, 0x9097, 0x0cec, 0x3f800000);
701 nv_mthd(dev, 0x9097, 0x0cfc, 0x3f800000);
702 nv_mthd(dev, 0x9097, 0x0d00, 0xffff0000);
703 nv_mthd(dev, 0x9097, 0x0d08, 0xffff0000);
704 nv_mthd(dev, 0x9097, 0x0d10, 0xffff0000);
705 nv_mthd(dev, 0x9097, 0x0d18, 0xffff0000);
706 nv_mthd(dev, 0x9097, 0x0d20, 0xffff0000);
707 nv_mthd(dev, 0x9097, 0x0d28, 0xffff0000);
708 nv_mthd(dev, 0x9097, 0x0d30, 0xffff0000);
709 nv_mthd(dev, 0x9097, 0x0d38, 0xffff0000);
710 nv_mthd(dev, 0x9097, 0x0d04, 0xffff0000);
711 nv_mthd(dev, 0x9097, 0x0d0c, 0xffff0000);
712 nv_mthd(dev, 0x9097, 0x0d14, 0xffff0000);
713 nv_mthd(dev, 0x9097, 0x0d1c, 0xffff0000);
714 nv_mthd(dev, 0x9097, 0x0d24, 0xffff0000);
715 nv_mthd(dev, 0x9097, 0x0d2c, 0xffff0000);
716 nv_mthd(dev, 0x9097, 0x0d34, 0xffff0000);
717 nv_mthd(dev, 0x9097, 0x0d3c, 0xffff0000);
718 nv_mthd(dev, 0x9097, 0x0e00, 0x00000000);
719 nv_mthd(dev, 0x9097, 0x0e10, 0x00000000);
720 nv_mthd(dev, 0x9097, 0x0e20, 0x00000000);
721 nv_mthd(dev, 0x9097, 0x0e30, 0x00000000);
722 nv_mthd(dev, 0x9097, 0x0e40, 0x00000000);
723 nv_mthd(dev, 0x9097, 0x0e50, 0x00000000);
724 nv_mthd(dev, 0x9097, 0x0e60, 0x00000000);
725 nv_mthd(dev, 0x9097, 0x0e70, 0x00000000);
726 nv_mthd(dev, 0x9097, 0x0e80, 0x00000000);
727 nv_mthd(dev, 0x9097, 0x0e90, 0x00000000);
728 nv_mthd(dev, 0x9097, 0x0ea0, 0x00000000);
729 nv_mthd(dev, 0x9097, 0x0eb0, 0x00000000);
730 nv_mthd(dev, 0x9097, 0x0ec0, 0x00000000);
731 nv_mthd(dev, 0x9097, 0x0ed0, 0x00000000);
732 nv_mthd(dev, 0x9097, 0x0ee0, 0x00000000);
733 nv_mthd(dev, 0x9097, 0x0ef0, 0x00000000);
734 nv_mthd(dev, 0x9097, 0x0e04, 0xffff0000);
735 nv_mthd(dev, 0x9097, 0x0e14, 0xffff0000);
736 nv_mthd(dev, 0x9097, 0x0e24, 0xffff0000);
737 nv_mthd(dev, 0x9097, 0x0e34, 0xffff0000);
738 nv_mthd(dev, 0x9097, 0x0e44, 0xffff0000);
739 nv_mthd(dev, 0x9097, 0x0e54, 0xffff0000);
740 nv_mthd(dev, 0x9097, 0x0e64, 0xffff0000);
741 nv_mthd(dev, 0x9097, 0x0e74, 0xffff0000);
742 nv_mthd(dev, 0x9097, 0x0e84, 0xffff0000);
743 nv_mthd(dev, 0x9097, 0x0e94, 0xffff0000);
744 nv_mthd(dev, 0x9097, 0x0ea4, 0xffff0000);
745 nv_mthd(dev, 0x9097, 0x0eb4, 0xffff0000);
746 nv_mthd(dev, 0x9097, 0x0ec4, 0xffff0000);
747 nv_mthd(dev, 0x9097, 0x0ed4, 0xffff0000);
748 nv_mthd(dev, 0x9097, 0x0ee4, 0xffff0000);
749 nv_mthd(dev, 0x9097, 0x0ef4, 0xffff0000);
750 nv_mthd(dev, 0x9097, 0x0e08, 0xffff0000);
751 nv_mthd(dev, 0x9097, 0x0e18, 0xffff0000);
752 nv_mthd(dev, 0x9097, 0x0e28, 0xffff0000);
753 nv_mthd(dev, 0x9097, 0x0e38, 0xffff0000);
754 nv_mthd(dev, 0x9097, 0x0e48, 0xffff0000);
755 nv_mthd(dev, 0x9097, 0x0e58, 0xffff0000);
756 nv_mthd(dev, 0x9097, 0x0e68, 0xffff0000);
757 nv_mthd(dev, 0x9097, 0x0e78, 0xffff0000);
758 nv_mthd(dev, 0x9097, 0x0e88, 0xffff0000);
759 nv_mthd(dev, 0x9097, 0x0e98, 0xffff0000);
760 nv_mthd(dev, 0x9097, 0x0ea8, 0xffff0000);
761 nv_mthd(dev, 0x9097, 0x0eb8, 0xffff0000);
762 nv_mthd(dev, 0x9097, 0x0ec8, 0xffff0000);
763 nv_mthd(dev, 0x9097, 0x0ed8, 0xffff0000);
764 nv_mthd(dev, 0x9097, 0x0ee8, 0xffff0000);
765 nv_mthd(dev, 0x9097, 0x0ef8, 0xffff0000);
766 nv_mthd(dev, 0x9097, 0x0d40, 0x00000000);
767 nv_mthd(dev, 0x9097, 0x0d48, 0x00000000);
768 nv_mthd(dev, 0x9097, 0x0d50, 0x00000000);
769 nv_mthd(dev, 0x9097, 0x0d58, 0x00000000);
770 nv_mthd(dev, 0x9097, 0x0d44, 0x00000000);
771 nv_mthd(dev, 0x9097, 0x0d4c, 0x00000000);
772 nv_mthd(dev, 0x9097, 0x0d54, 0x00000000);
773 nv_mthd(dev, 0x9097, 0x0d5c, 0x00000000);
774 nv_mthd(dev, 0x9097, 0x1e00, 0x00000001);
775 nv_mthd(dev, 0x9097, 0x1e20, 0x00000001);
776 nv_mthd(dev, 0x9097, 0x1e40, 0x00000001);
777 nv_mthd(dev, 0x9097, 0x1e60, 0x00000001);
778 nv_mthd(dev, 0x9097, 0x1e80, 0x00000001);
779 nv_mthd(dev, 0x9097, 0x1ea0, 0x00000001);
780 nv_mthd(dev, 0x9097, 0x1ec0, 0x00000001);
781 nv_mthd(dev, 0x9097, 0x1ee0, 0x00000001);
782 nv_mthd(dev, 0x9097, 0x1e04, 0x00000001);
783 nv_mthd(dev, 0x9097, 0x1e24, 0x00000001);
784 nv_mthd(dev, 0x9097, 0x1e44, 0x00000001);
785 nv_mthd(dev, 0x9097, 0x1e64, 0x00000001);
786 nv_mthd(dev, 0x9097, 0x1e84, 0x00000001);
787 nv_mthd(dev, 0x9097, 0x1ea4, 0x00000001);
788 nv_mthd(dev, 0x9097, 0x1ec4, 0x00000001);
789 nv_mthd(dev, 0x9097, 0x1ee4, 0x00000001);
790 nv_mthd(dev, 0x9097, 0x1e08, 0x00000002);
791 nv_mthd(dev, 0x9097, 0x1e28, 0x00000002);
792 nv_mthd(dev, 0x9097, 0x1e48, 0x00000002);
793 nv_mthd(dev, 0x9097, 0x1e68, 0x00000002);
794 nv_mthd(dev, 0x9097, 0x1e88, 0x00000002);
795 nv_mthd(dev, 0x9097, 0x1ea8, 0x00000002);
796 nv_mthd(dev, 0x9097, 0x1ec8, 0x00000002);
797 nv_mthd(dev, 0x9097, 0x1ee8, 0x00000002);
798 nv_mthd(dev, 0x9097, 0x1e0c, 0x00000001);
799 nv_mthd(dev, 0x9097, 0x1e2c, 0x00000001);
800 nv_mthd(dev, 0x9097, 0x1e4c, 0x00000001);
801 nv_mthd(dev, 0x9097, 0x1e6c, 0x00000001);
802 nv_mthd(dev, 0x9097, 0x1e8c, 0x00000001);
803 nv_mthd(dev, 0x9097, 0x1eac, 0x00000001);
804 nv_mthd(dev, 0x9097, 0x1ecc, 0x00000001);
805 nv_mthd(dev, 0x9097, 0x1eec, 0x00000001);
806 nv_mthd(dev, 0x9097, 0x1e10, 0x00000001);
807 nv_mthd(dev, 0x9097, 0x1e30, 0x00000001);
808 nv_mthd(dev, 0x9097, 0x1e50, 0x00000001);
809 nv_mthd(dev, 0x9097, 0x1e70, 0x00000001);
810 nv_mthd(dev, 0x9097, 0x1e90, 0x00000001);
811 nv_mthd(dev, 0x9097, 0x1eb0, 0x00000001);
812 nv_mthd(dev, 0x9097, 0x1ed0, 0x00000001);
813 nv_mthd(dev, 0x9097, 0x1ef0, 0x00000001);
814 nv_mthd(dev, 0x9097, 0x1e14, 0x00000002);
815 nv_mthd(dev, 0x9097, 0x1e34, 0x00000002);
816 nv_mthd(dev, 0x9097, 0x1e54, 0x00000002);
817 nv_mthd(dev, 0x9097, 0x1e74, 0x00000002);
818 nv_mthd(dev, 0x9097, 0x1e94, 0x00000002);
819 nv_mthd(dev, 0x9097, 0x1eb4, 0x00000002);
820 nv_mthd(dev, 0x9097, 0x1ed4, 0x00000002);
821 nv_mthd(dev, 0x9097, 0x1ef4, 0x00000002);
822 nv_mthd(dev, 0x9097, 0x1e18, 0x00000001);
823 nv_mthd(dev, 0x9097, 0x1e38, 0x00000001);
824 nv_mthd(dev, 0x9097, 0x1e58, 0x00000001);
825 nv_mthd(dev, 0x9097, 0x1e78, 0x00000001);
826 nv_mthd(dev, 0x9097, 0x1e98, 0x00000001);
827 nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001);
828 nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001);
829 nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001);
830 if (fermi == 0x9097) {
831 for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
832 nv_mthd(dev, 0x9097, mthd, 0x00000000);
833 }
834 nv_mthd(dev, 0x9097, 0x030c, 0x00000001);
835 nv_mthd(dev, 0x9097, 0x1944, 0x00000000);
836 nv_mthd(dev, 0x9097, 0x1514, 0x00000000);
837 nv_mthd(dev, 0x9097, 0x0d68, 0x0000ffff);
838 nv_mthd(dev, 0x9097, 0x121c, 0x0fac6881);
839 nv_mthd(dev, 0x9097, 0x0fac, 0x00000001);
840 nv_mthd(dev, 0x9097, 0x1538, 0x00000001);
841 nv_mthd(dev, 0x9097, 0x0fe0, 0x00000000);
842 nv_mthd(dev, 0x9097, 0x0fe4, 0x00000000);
843 nv_mthd(dev, 0x9097, 0x0fe8, 0x00000014);
844 nv_mthd(dev, 0x9097, 0x0fec, 0x00000040);
845 nv_mthd(dev, 0x9097, 0x0ff0, 0x00000000);
846 nv_mthd(dev, 0x9097, 0x179c, 0x00000000);
847 nv_mthd(dev, 0x9097, 0x1228, 0x00000400);
848 nv_mthd(dev, 0x9097, 0x122c, 0x00000300);
849 nv_mthd(dev, 0x9097, 0x1230, 0x00010001);
850 nv_mthd(dev, 0x9097, 0x07f8, 0x00000000);
851 nv_mthd(dev, 0x9097, 0x15b4, 0x00000001);
852 nv_mthd(dev, 0x9097, 0x15cc, 0x00000000);
853 nv_mthd(dev, 0x9097, 0x1534, 0x00000000);
854 nv_mthd(dev, 0x9097, 0x0fb0, 0x00000000);
855 nv_mthd(dev, 0x9097, 0x15d0, 0x00000000);
856 nv_mthd(dev, 0x9097, 0x153c, 0x00000000);
857 nv_mthd(dev, 0x9097, 0x16b4, 0x00000003);
858 nv_mthd(dev, 0x9097, 0x0fbc, 0x0000ffff);
859 nv_mthd(dev, 0x9097, 0x0fc0, 0x0000ffff);
860 nv_mthd(dev, 0x9097, 0x0fc4, 0x0000ffff);
861 nv_mthd(dev, 0x9097, 0x0fc8, 0x0000ffff);
862 nv_mthd(dev, 0x9097, 0x0df8, 0x00000000);
863 nv_mthd(dev, 0x9097, 0x0dfc, 0x00000000);
864 nv_mthd(dev, 0x9097, 0x1948, 0x00000000);
865 nv_mthd(dev, 0x9097, 0x1970, 0x00000001);
866 nv_mthd(dev, 0x9097, 0x161c, 0x000009f0);
867 nv_mthd(dev, 0x9097, 0x0dcc, 0x00000010);
868 nv_mthd(dev, 0x9097, 0x163c, 0x00000000);
869 nv_mthd(dev, 0x9097, 0x15e4, 0x00000000);
870 nv_mthd(dev, 0x9097, 0x1160, 0x25e00040);
871 nv_mthd(dev, 0x9097, 0x1164, 0x25e00040);
872 nv_mthd(dev, 0x9097, 0x1168, 0x25e00040);
873 nv_mthd(dev, 0x9097, 0x116c, 0x25e00040);
874 nv_mthd(dev, 0x9097, 0x1170, 0x25e00040);
875 nv_mthd(dev, 0x9097, 0x1174, 0x25e00040);
876 nv_mthd(dev, 0x9097, 0x1178, 0x25e00040);
877 nv_mthd(dev, 0x9097, 0x117c, 0x25e00040);
878 nv_mthd(dev, 0x9097, 0x1180, 0x25e00040);
879 nv_mthd(dev, 0x9097, 0x1184, 0x25e00040);
880 nv_mthd(dev, 0x9097, 0x1188, 0x25e00040);
881 nv_mthd(dev, 0x9097, 0x118c, 0x25e00040);
882 nv_mthd(dev, 0x9097, 0x1190, 0x25e00040);
883 nv_mthd(dev, 0x9097, 0x1194, 0x25e00040);
884 nv_mthd(dev, 0x9097, 0x1198, 0x25e00040);
885 nv_mthd(dev, 0x9097, 0x119c, 0x25e00040);
886 nv_mthd(dev, 0x9097, 0x11a0, 0x25e00040);
887 nv_mthd(dev, 0x9097, 0x11a4, 0x25e00040);
888 nv_mthd(dev, 0x9097, 0x11a8, 0x25e00040);
889 nv_mthd(dev, 0x9097, 0x11ac, 0x25e00040);
890 nv_mthd(dev, 0x9097, 0x11b0, 0x25e00040);
891 nv_mthd(dev, 0x9097, 0x11b4, 0x25e00040);
892 nv_mthd(dev, 0x9097, 0x11b8, 0x25e00040);
893 nv_mthd(dev, 0x9097, 0x11bc, 0x25e00040);
894 nv_mthd(dev, 0x9097, 0x11c0, 0x25e00040);
895 nv_mthd(dev, 0x9097, 0x11c4, 0x25e00040);
896 nv_mthd(dev, 0x9097, 0x11c8, 0x25e00040);
897 nv_mthd(dev, 0x9097, 0x11cc, 0x25e00040);
898 nv_mthd(dev, 0x9097, 0x11d0, 0x25e00040);
899 nv_mthd(dev, 0x9097, 0x11d4, 0x25e00040);
900 nv_mthd(dev, 0x9097, 0x11d8, 0x25e00040);
901 nv_mthd(dev, 0x9097, 0x11dc, 0x25e00040);
902 nv_mthd(dev, 0x9097, 0x1880, 0x00000000);
903 nv_mthd(dev, 0x9097, 0x1884, 0x00000000);
904 nv_mthd(dev, 0x9097, 0x1888, 0x00000000);
905 nv_mthd(dev, 0x9097, 0x188c, 0x00000000);
906 nv_mthd(dev, 0x9097, 0x1890, 0x00000000);
907 nv_mthd(dev, 0x9097, 0x1894, 0x00000000);
908 nv_mthd(dev, 0x9097, 0x1898, 0x00000000);
909 nv_mthd(dev, 0x9097, 0x189c, 0x00000000);
910 nv_mthd(dev, 0x9097, 0x18a0, 0x00000000);
911 nv_mthd(dev, 0x9097, 0x18a4, 0x00000000);
912 nv_mthd(dev, 0x9097, 0x18a8, 0x00000000);
913 nv_mthd(dev, 0x9097, 0x18ac, 0x00000000);
914 nv_mthd(dev, 0x9097, 0x18b0, 0x00000000);
915 nv_mthd(dev, 0x9097, 0x18b4, 0x00000000);
916 nv_mthd(dev, 0x9097, 0x18b8, 0x00000000);
917 nv_mthd(dev, 0x9097, 0x18bc, 0x00000000);
918 nv_mthd(dev, 0x9097, 0x18c0, 0x00000000);
919 nv_mthd(dev, 0x9097, 0x18c4, 0x00000000);
920 nv_mthd(dev, 0x9097, 0x18c8, 0x00000000);
921 nv_mthd(dev, 0x9097, 0x18cc, 0x00000000);
922 nv_mthd(dev, 0x9097, 0x18d0, 0x00000000);
923 nv_mthd(dev, 0x9097, 0x18d4, 0x00000000);
924 nv_mthd(dev, 0x9097, 0x18d8, 0x00000000);
925 nv_mthd(dev, 0x9097, 0x18dc, 0x00000000);
926 nv_mthd(dev, 0x9097, 0x18e0, 0x00000000);
927 nv_mthd(dev, 0x9097, 0x18e4, 0x00000000);
928 nv_mthd(dev, 0x9097, 0x18e8, 0x00000000);
929 nv_mthd(dev, 0x9097, 0x18ec, 0x00000000);
930 nv_mthd(dev, 0x9097, 0x18f0, 0x00000000);
931 nv_mthd(dev, 0x9097, 0x18f4, 0x00000000);
932 nv_mthd(dev, 0x9097, 0x18f8, 0x00000000);
933 nv_mthd(dev, 0x9097, 0x18fc, 0x00000000);
934 nv_mthd(dev, 0x9097, 0x0f84, 0x00000000);
935 nv_mthd(dev, 0x9097, 0x0f88, 0x00000000);
936 nv_mthd(dev, 0x9097, 0x17c8, 0x00000000);
937 nv_mthd(dev, 0x9097, 0x17cc, 0x00000000);
938 nv_mthd(dev, 0x9097, 0x17d0, 0x000000ff);
939 nv_mthd(dev, 0x9097, 0x17d4, 0xffffffff);
940 nv_mthd(dev, 0x9097, 0x17d8, 0x00000002);
941 nv_mthd(dev, 0x9097, 0x17dc, 0x00000000);
942 nv_mthd(dev, 0x9097, 0x15f4, 0x00000000);
943 nv_mthd(dev, 0x9097, 0x15f8, 0x00000000);
944 nv_mthd(dev, 0x9097, 0x1434, 0x00000000);
945 nv_mthd(dev, 0x9097, 0x1438, 0x00000000);
946 nv_mthd(dev, 0x9097, 0x0d74, 0x00000000);
947 nv_mthd(dev, 0x9097, 0x0dec, 0x00000001);
948 nv_mthd(dev, 0x9097, 0x13a4, 0x00000000);
949 nv_mthd(dev, 0x9097, 0x1318, 0x00000001);
950 nv_mthd(dev, 0x9097, 0x1644, 0x00000000);
951 nv_mthd(dev, 0x9097, 0x0748, 0x00000000);
952 nv_mthd(dev, 0x9097, 0x0de8, 0x00000000);
953 nv_mthd(dev, 0x9097, 0x1648, 0x00000000);
954 nv_mthd(dev, 0x9097, 0x12a4, 0x00000000);
955 nv_mthd(dev, 0x9097, 0x1120, 0x00000000);
956 nv_mthd(dev, 0x9097, 0x1124, 0x00000000);
957 nv_mthd(dev, 0x9097, 0x1128, 0x00000000);
958 nv_mthd(dev, 0x9097, 0x112c, 0x00000000);
959 nv_mthd(dev, 0x9097, 0x1118, 0x00000000);
960 nv_mthd(dev, 0x9097, 0x164c, 0x00000000);
961 nv_mthd(dev, 0x9097, 0x1658, 0x00000000);
962 nv_mthd(dev, 0x9097, 0x1910, 0x00000290);
963 nv_mthd(dev, 0x9097, 0x1518, 0x00000000);
964 nv_mthd(dev, 0x9097, 0x165c, 0x00000001);
965 nv_mthd(dev, 0x9097, 0x1520, 0x00000000);
966 nv_mthd(dev, 0x9097, 0x1604, 0x00000000);
967 nv_mthd(dev, 0x9097, 0x1570, 0x00000000);
968 nv_mthd(dev, 0x9097, 0x13b0, 0x3f800000);
969 nv_mthd(dev, 0x9097, 0x13b4, 0x3f800000);
970 nv_mthd(dev, 0x9097, 0x020c, 0x00000000);
971 nv_mthd(dev, 0x9097, 0x1670, 0x30201000);
972 nv_mthd(dev, 0x9097, 0x1674, 0x70605040);
973 nv_mthd(dev, 0x9097, 0x1678, 0xb8a89888);
974 nv_mthd(dev, 0x9097, 0x167c, 0xf8e8d8c8);
975 nv_mthd(dev, 0x9097, 0x166c, 0x00000000);
976 nv_mthd(dev, 0x9097, 0x1680, 0x00ffff00);
977 nv_mthd(dev, 0x9097, 0x12d0, 0x00000003);
978 nv_mthd(dev, 0x9097, 0x12d4, 0x00000002);
979 nv_mthd(dev, 0x9097, 0x1684, 0x00000000);
980 nv_mthd(dev, 0x9097, 0x1688, 0x00000000);
981 nv_mthd(dev, 0x9097, 0x0dac, 0x00001b02);
982 nv_mthd(dev, 0x9097, 0x0db0, 0x00001b02);
983 nv_mthd(dev, 0x9097, 0x0db4, 0x00000000);
984 nv_mthd(dev, 0x9097, 0x168c, 0x00000000);
985 nv_mthd(dev, 0x9097, 0x15bc, 0x00000000);
986 nv_mthd(dev, 0x9097, 0x156c, 0x00000000);
987 nv_mthd(dev, 0x9097, 0x187c, 0x00000000);
988 nv_mthd(dev, 0x9097, 0x1110, 0x00000001);
989 nv_mthd(dev, 0x9097, 0x0dc0, 0x00000000);
990 nv_mthd(dev, 0x9097, 0x0dc4, 0x00000000);
991 nv_mthd(dev, 0x9097, 0x0dc8, 0x00000000);
992 nv_mthd(dev, 0x9097, 0x1234, 0x00000000);
993 nv_mthd(dev, 0x9097, 0x1690, 0x00000000);
994 nv_mthd(dev, 0x9097, 0x12ac, 0x00000001);
995 nv_mthd(dev, 0x9097, 0x02c4, 0x00000000);
996 nv_mthd(dev, 0x9097, 0x0790, 0x00000000);
997 nv_mthd(dev, 0x9097, 0x0794, 0x00000000);
998 nv_mthd(dev, 0x9097, 0x0798, 0x00000000);
999 nv_mthd(dev, 0x9097, 0x079c, 0x00000000);
1000 nv_mthd(dev, 0x9097, 0x07a0, 0x00000000);
1001 nv_mthd(dev, 0x9097, 0x077c, 0x00000000);
1002 nv_mthd(dev, 0x9097, 0x1000, 0x00000010);
1003 nv_mthd(dev, 0x9097, 0x10fc, 0x00000000);
1004 nv_mthd(dev, 0x9097, 0x1290, 0x00000000);
1005 nv_mthd(dev, 0x9097, 0x0218, 0x00000010);
1006 nv_mthd(dev, 0x9097, 0x12d8, 0x00000000);
1007 nv_mthd(dev, 0x9097, 0x12dc, 0x00000010);
1008 nv_mthd(dev, 0x9097, 0x0d94, 0x00000001);
1009 nv_mthd(dev, 0x9097, 0x155c, 0x00000000);
1010 nv_mthd(dev, 0x9097, 0x1560, 0x00000000);
1011 nv_mthd(dev, 0x9097, 0x1564, 0x00001fff);
1012 nv_mthd(dev, 0x9097, 0x1574, 0x00000000);
1013 nv_mthd(dev, 0x9097, 0x1578, 0x00000000);
1014 nv_mthd(dev, 0x9097, 0x157c, 0x003fffff);
1015 nv_mthd(dev, 0x9097, 0x1354, 0x00000000);
1016 nv_mthd(dev, 0x9097, 0x1664, 0x00000000);
1017 nv_mthd(dev, 0x9097, 0x1610, 0x00000012);
1018 nv_mthd(dev, 0x9097, 0x1608, 0x00000000);
1019 nv_mthd(dev, 0x9097, 0x160c, 0x00000000);
1020 nv_mthd(dev, 0x9097, 0x162c, 0x00000003);
1021 nv_mthd(dev, 0x9097, 0x0210, 0x00000000);
1022 nv_mthd(dev, 0x9097, 0x0320, 0x00000000);
1023 nv_mthd(dev, 0x9097, 0x0324, 0x3f800000);
1024 nv_mthd(dev, 0x9097, 0x0328, 0x3f800000);
1025 nv_mthd(dev, 0x9097, 0x032c, 0x3f800000);
1026 nv_mthd(dev, 0x9097, 0x0330, 0x3f800000);
1027 nv_mthd(dev, 0x9097, 0x0334, 0x3f800000);
1028 nv_mthd(dev, 0x9097, 0x0338, 0x3f800000);
1029 nv_mthd(dev, 0x9097, 0x0750, 0x00000000);
1030 nv_mthd(dev, 0x9097, 0x0760, 0x39291909);
1031 nv_mthd(dev, 0x9097, 0x0764, 0x79695949);
1032 nv_mthd(dev, 0x9097, 0x0768, 0xb9a99989);
1033 nv_mthd(dev, 0x9097, 0x076c, 0xf9e9d9c9);
1034 nv_mthd(dev, 0x9097, 0x0770, 0x30201000);
1035 nv_mthd(dev, 0x9097, 0x0774, 0x70605040);
1036 nv_mthd(dev, 0x9097, 0x0778, 0x00009080);
1037 nv_mthd(dev, 0x9097, 0x0780, 0x39291909);
1038 nv_mthd(dev, 0x9097, 0x0784, 0x79695949);
1039 nv_mthd(dev, 0x9097, 0x0788, 0xb9a99989);
1040 nv_mthd(dev, 0x9097, 0x078c, 0xf9e9d9c9);
1041 nv_mthd(dev, 0x9097, 0x07d0, 0x30201000);
1042 nv_mthd(dev, 0x9097, 0x07d4, 0x70605040);
1043 nv_mthd(dev, 0x9097, 0x07d8, 0x00009080);
1044 nv_mthd(dev, 0x9097, 0x037c, 0x00000001);
1045 nv_mthd(dev, 0x9097, 0x0740, 0x00000000);
1046 nv_mthd(dev, 0x9097, 0x0744, 0x00000000);
1047 nv_mthd(dev, 0x9097, 0x2600, 0x00000000);
1048 nv_mthd(dev, 0x9097, 0x1918, 0x00000000);
1049 nv_mthd(dev, 0x9097, 0x191c, 0x00000900);
1050 nv_mthd(dev, 0x9097, 0x1920, 0x00000405);
1051 nv_mthd(dev, 0x9097, 0x1308, 0x00000001);
1052 nv_mthd(dev, 0x9097, 0x1924, 0x00000000);
1053 nv_mthd(dev, 0x9097, 0x13ac, 0x00000000);
1054 nv_mthd(dev, 0x9097, 0x192c, 0x00000001);
1055 nv_mthd(dev, 0x9097, 0x193c, 0x00002c1c);
1056 nv_mthd(dev, 0x9097, 0x0d7c, 0x00000000);
1057 nv_mthd(dev, 0x9097, 0x0f8c, 0x00000000);
1058 nv_mthd(dev, 0x9097, 0x02c0, 0x00000001);
1059 nv_mthd(dev, 0x9097, 0x1510, 0x00000000);
1060 nv_mthd(dev, 0x9097, 0x1940, 0x00000000);
1061 nv_mthd(dev, 0x9097, 0x0ff4, 0x00000000);
1062 nv_mthd(dev, 0x9097, 0x0ff8, 0x00000000);
1063 nv_mthd(dev, 0x9097, 0x194c, 0x00000000);
1064 nv_mthd(dev, 0x9097, 0x1950, 0x00000000);
1065 nv_mthd(dev, 0x9097, 0x1968, 0x00000000);
1066 nv_mthd(dev, 0x9097, 0x1590, 0x0000003f);
1067 nv_mthd(dev, 0x9097, 0x07e8, 0x00000000);
1068 nv_mthd(dev, 0x9097, 0x07ec, 0x00000000);
1069 nv_mthd(dev, 0x9097, 0x07f0, 0x00000000);
1070 nv_mthd(dev, 0x9097, 0x07f4, 0x00000000);
1071 nv_mthd(dev, 0x9097, 0x196c, 0x00000011);
1072 nv_mthd(dev, 0x9097, 0x197c, 0x00000000);
1073 nv_mthd(dev, 0x9097, 0x0fcc, 0x00000000);
1074 nv_mthd(dev, 0x9097, 0x0fd0, 0x00000000);
1075 nv_mthd(dev, 0x9097, 0x02d8, 0x00000040);
1076 nv_mthd(dev, 0x9097, 0x1980, 0x00000080);
1077 nv_mthd(dev, 0x9097, 0x1504, 0x00000080);
1078 nv_mthd(dev, 0x9097, 0x1984, 0x00000000);
1079 nv_mthd(dev, 0x9097, 0x0300, 0x00000001);
1080 nv_mthd(dev, 0x9097, 0x13a8, 0x00000000);
1081 nv_mthd(dev, 0x9097, 0x12ec, 0x00000000);
1082 nv_mthd(dev, 0x9097, 0x1310, 0x00000000);
1083 nv_mthd(dev, 0x9097, 0x1314, 0x00000001);
1084 nv_mthd(dev, 0x9097, 0x1380, 0x00000000);
1085 nv_mthd(dev, 0x9097, 0x1384, 0x00000001);
1086 nv_mthd(dev, 0x9097, 0x1388, 0x00000001);
1087 nv_mthd(dev, 0x9097, 0x138c, 0x00000001);
1088 nv_mthd(dev, 0x9097, 0x1390, 0x00000001);
1089 nv_mthd(dev, 0x9097, 0x1394, 0x00000000);
1090 nv_mthd(dev, 0x9097, 0x139c, 0x00000000);
1091 nv_mthd(dev, 0x9097, 0x1398, 0x00000000);
1092 nv_mthd(dev, 0x9097, 0x1594, 0x00000000);
1093 nv_mthd(dev, 0x9097, 0x1598, 0x00000001);
1094 nv_mthd(dev, 0x9097, 0x159c, 0x00000001);
1095 nv_mthd(dev, 0x9097, 0x15a0, 0x00000001);
1096 nv_mthd(dev, 0x9097, 0x15a4, 0x00000001);
1097 nv_mthd(dev, 0x9097, 0x0f54, 0x00000000);
1098 nv_mthd(dev, 0x9097, 0x0f58, 0x00000000);
1099 nv_mthd(dev, 0x9097, 0x0f5c, 0x00000000);
1100 nv_mthd(dev, 0x9097, 0x19bc, 0x00000000);
1101 nv_mthd(dev, 0x9097, 0x0f9c, 0x00000000);
1102 nv_mthd(dev, 0x9097, 0x0fa0, 0x00000000);
1103 nv_mthd(dev, 0x9097, 0x12cc, 0x00000000);
1104 nv_mthd(dev, 0x9097, 0x12e8, 0x00000000);
1105 nv_mthd(dev, 0x9097, 0x130c, 0x00000001);
1106 nv_mthd(dev, 0x9097, 0x1360, 0x00000000);
1107 nv_mthd(dev, 0x9097, 0x1364, 0x00000000);
1108 nv_mthd(dev, 0x9097, 0x1368, 0x00000000);
1109 nv_mthd(dev, 0x9097, 0x136c, 0x00000000);
1110 nv_mthd(dev, 0x9097, 0x1370, 0x00000000);
1111 nv_mthd(dev, 0x9097, 0x1374, 0x00000000);
1112 nv_mthd(dev, 0x9097, 0x1378, 0x00000000);
1113 nv_mthd(dev, 0x9097, 0x137c, 0x00000000);
1114 nv_mthd(dev, 0x9097, 0x133c, 0x00000001);
1115 nv_mthd(dev, 0x9097, 0x1340, 0x00000001);
1116 nv_mthd(dev, 0x9097, 0x1344, 0x00000002);
1117 nv_mthd(dev, 0x9097, 0x1348, 0x00000001);
1118 nv_mthd(dev, 0x9097, 0x134c, 0x00000001);
1119 nv_mthd(dev, 0x9097, 0x1350, 0x00000002);
1120 nv_mthd(dev, 0x9097, 0x1358, 0x00000001);
1121 nv_mthd(dev, 0x9097, 0x12e4, 0x00000000);
1122 nv_mthd(dev, 0x9097, 0x131c, 0x00000000);
1123 nv_mthd(dev, 0x9097, 0x1320, 0x00000000);
1124 nv_mthd(dev, 0x9097, 0x1324, 0x00000000);
1125 nv_mthd(dev, 0x9097, 0x1328, 0x00000000);
1126 nv_mthd(dev, 0x9097, 0x19c0, 0x00000000);
1127 nv_mthd(dev, 0x9097, 0x1140, 0x00000000);
1128 nv_mthd(dev, 0x9097, 0x19c4, 0x00000000);
1129 nv_mthd(dev, 0x9097, 0x19c8, 0x00001500);
1130 nv_mthd(dev, 0x9097, 0x135c, 0x00000000);
1131 nv_mthd(dev, 0x9097, 0x0f90, 0x00000000);
1132 nv_mthd(dev, 0x9097, 0x19e0, 0x00000001);
1133 nv_mthd(dev, 0x9097, 0x19e4, 0x00000001);
1134 nv_mthd(dev, 0x9097, 0x19e8, 0x00000001);
1135 nv_mthd(dev, 0x9097, 0x19ec, 0x00000001);
1136 nv_mthd(dev, 0x9097, 0x19f0, 0x00000001);
1137 nv_mthd(dev, 0x9097, 0x19f4, 0x00000001);
1138 nv_mthd(dev, 0x9097, 0x19f8, 0x00000001);
1139 nv_mthd(dev, 0x9097, 0x19fc, 0x00000001);
1140 nv_mthd(dev, 0x9097, 0x19cc, 0x00000001);
1141 nv_mthd(dev, 0x9097, 0x15b8, 0x00000000);
1142 nv_mthd(dev, 0x9097, 0x1a00, 0x00001111);
1143 nv_mthd(dev, 0x9097, 0x1a04, 0x00000000);
1144 nv_mthd(dev, 0x9097, 0x1a08, 0x00000000);
1145 nv_mthd(dev, 0x9097, 0x1a0c, 0x00000000);
1146 nv_mthd(dev, 0x9097, 0x1a10, 0x00000000);
1147 nv_mthd(dev, 0x9097, 0x1a14, 0x00000000);
1148 nv_mthd(dev, 0x9097, 0x1a18, 0x00000000);
1149 nv_mthd(dev, 0x9097, 0x1a1c, 0x00000000);
1150 nv_mthd(dev, 0x9097, 0x0d6c, 0xffff0000);
1151 nv_mthd(dev, 0x9097, 0x0d70, 0xffff0000);
1152 nv_mthd(dev, 0x9097, 0x10f8, 0x00001010);
1153 nv_mthd(dev, 0x9097, 0x0d80, 0x00000000);
1154 nv_mthd(dev, 0x9097, 0x0d84, 0x00000000);
1155 nv_mthd(dev, 0x9097, 0x0d88, 0x00000000);
1156 nv_mthd(dev, 0x9097, 0x0d8c, 0x00000000);
1157 nv_mthd(dev, 0x9097, 0x0d90, 0x00000000);
1158 nv_mthd(dev, 0x9097, 0x0da0, 0x00000000);
1159 nv_mthd(dev, 0x9097, 0x1508, 0x80000000);
1160 nv_mthd(dev, 0x9097, 0x150c, 0x40000000);
1161 nv_mthd(dev, 0x9097, 0x1668, 0x00000000);
1162 nv_mthd(dev, 0x9097, 0x0318, 0x00000008);
1163 nv_mthd(dev, 0x9097, 0x031c, 0x00000008);
1164 nv_mthd(dev, 0x9097, 0x0d9c, 0x00000001);
1165 nv_mthd(dev, 0x9097, 0x07dc, 0x00000000);
1166 nv_mthd(dev, 0x9097, 0x074c, 0x00000055);
1167 nv_mthd(dev, 0x9097, 0x1420, 0x00000003);
1168 nv_mthd(dev, 0x9097, 0x17bc, 0x00000000);
1169 nv_mthd(dev, 0x9097, 0x17c0, 0x00000000);
1170 nv_mthd(dev, 0x9097, 0x17c4, 0x00000001);
1171 nv_mthd(dev, 0x9097, 0x1008, 0x00000008);
1172 nv_mthd(dev, 0x9097, 0x100c, 0x00000040);
1173 nv_mthd(dev, 0x9097, 0x1010, 0x0000012c);
1174 nv_mthd(dev, 0x9097, 0x0d60, 0x00000040);
1175 nv_mthd(dev, 0x9097, 0x075c, 0x00000003);
1176 nv_mthd(dev, 0x9097, 0x1018, 0x00000020);
1177 nv_mthd(dev, 0x9097, 0x101c, 0x00000001);
1178 nv_mthd(dev, 0x9097, 0x1020, 0x00000020);
1179 nv_mthd(dev, 0x9097, 0x1024, 0x00000001);
1180 nv_mthd(dev, 0x9097, 0x1444, 0x00000000);
1181 nv_mthd(dev, 0x9097, 0x1448, 0x00000000);
1182 nv_mthd(dev, 0x9097, 0x144c, 0x00000000);
1183 nv_mthd(dev, 0x9097, 0x0360, 0x20164010);
1184 nv_mthd(dev, 0x9097, 0x0364, 0x00000020);
1185 nv_mthd(dev, 0x9097, 0x0368, 0x00000000);
1186 nv_mthd(dev, 0x9097, 0x0de4, 0x00000000);
1187 nv_mthd(dev, 0x9097, 0x0204, 0x00000006);
1188 nv_mthd(dev, 0x9097, 0x0208, 0x00000000);
1189 nv_mthd(dev, 0x9097, 0x02cc, 0x003fffff);
1190 nv_mthd(dev, 0x9097, 0x02d0, 0x00000c48);
1191 nv_mthd(dev, 0x9097, 0x1220, 0x00000005);
1192 nv_mthd(dev, 0x9097, 0x0fdc, 0x00000000);
1193 nv_mthd(dev, 0x9097, 0x0f98, 0x00300008);
1194 nv_mthd(dev, 0x9097, 0x1284, 0x04000080);
1195 nv_mthd(dev, 0x9097, 0x1450, 0x00300008);
1196 nv_mthd(dev, 0x9097, 0x1454, 0x04000080);
1197 nv_mthd(dev, 0x9097, 0x0214, 0x00000000);
1198 /* in trace, right after 0x90c0, not here */
1199 nv_mthd(dev, 0x9097, 0x3410, 0x80002006);
1200}
1201
1202static void
1203nvc0_grctx_generate_9197(struct drm_device *dev)
1204{
1205 u32 fermi = nvc0_graph_class(dev);
1206 u32 mthd;
1207
1208 if (fermi == 0x9197) {
1209 for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
1210 nv_mthd(dev, 0x9197, mthd, 0x00000000);
1211 }
1212 nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001);
1213}
1214
1215static void
1216nvc0_grctx_generate_9297(struct drm_device *dev)
1217{
1218 u32 fermi = nvc0_graph_class(dev);
1219 u32 mthd;
1220
1221 if (fermi == 0x9297) {
1222 for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
1223 nv_mthd(dev, 0x9297, mthd, 0x00000000);
1224 }
1225 nv_mthd(dev, 0x9297, 0x036c, 0x00000000);
1226 nv_mthd(dev, 0x9297, 0x0370, 0x00000000);
1227 nv_mthd(dev, 0x9297, 0x07a4, 0x00000000);
1228 nv_mthd(dev, 0x9297, 0x07a8, 0x00000000);
1229 nv_mthd(dev, 0x9297, 0x0374, 0x00000000);
1230 nv_mthd(dev, 0x9297, 0x0378, 0x00000020);
1231}
1232
1233static void
1234nvc0_grctx_generate_902d(struct drm_device *dev)
1235{
1236 nv_mthd(dev, 0x902d, 0x0200, 0x000000cf);
1237 nv_mthd(dev, 0x902d, 0x0204, 0x00000001);
1238 nv_mthd(dev, 0x902d, 0x0208, 0x00000020);
1239 nv_mthd(dev, 0x902d, 0x020c, 0x00000001);
1240 nv_mthd(dev, 0x902d, 0x0210, 0x00000000);
1241 nv_mthd(dev, 0x902d, 0x0214, 0x00000080);
1242 nv_mthd(dev, 0x902d, 0x0218, 0x00000100);
1243 nv_mthd(dev, 0x902d, 0x021c, 0x00000100);
1244 nv_mthd(dev, 0x902d, 0x0220, 0x00000000);
1245 nv_mthd(dev, 0x902d, 0x0224, 0x00000000);
1246 nv_mthd(dev, 0x902d, 0x0230, 0x000000cf);
1247 nv_mthd(dev, 0x902d, 0x0234, 0x00000001);
1248 nv_mthd(dev, 0x902d, 0x0238, 0x00000020);
1249 nv_mthd(dev, 0x902d, 0x023c, 0x00000001);
1250 nv_mthd(dev, 0x902d, 0x0244, 0x00000080);
1251 nv_mthd(dev, 0x902d, 0x0248, 0x00000100);
1252 nv_mthd(dev, 0x902d, 0x024c, 0x00000100);
1253}
1254
1255static void
1256nvc0_grctx_generate_9039(struct drm_device *dev)
1257{
1258 nv_mthd(dev, 0x9039, 0x030c, 0x00000000);
1259 nv_mthd(dev, 0x9039, 0x0310, 0x00000000);
1260 nv_mthd(dev, 0x9039, 0x0314, 0x00000000);
1261 nv_mthd(dev, 0x9039, 0x0320, 0x00000000);
1262 nv_mthd(dev, 0x9039, 0x0238, 0x00000000);
1263 nv_mthd(dev, 0x9039, 0x023c, 0x00000000);
1264 nv_mthd(dev, 0x9039, 0x0318, 0x00000000);
1265 nv_mthd(dev, 0x9039, 0x031c, 0x00000000);
1266}
1267
1268static void
1269nvc0_grctx_generate_90c0(struct drm_device *dev)
1270{
1271 nv_mthd(dev, 0x90c0, 0x270c, 0x00000000);
1272 nv_mthd(dev, 0x90c0, 0x272c, 0x00000000);
1273 nv_mthd(dev, 0x90c0, 0x274c, 0x00000000);
1274 nv_mthd(dev, 0x90c0, 0x276c, 0x00000000);
1275 nv_mthd(dev, 0x90c0, 0x278c, 0x00000000);
1276 nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000);
1277 nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000);
1278 nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000);
1279 nv_mthd(dev, 0x90c0, 0x030c, 0x00000001);
1280 nv_mthd(dev, 0x90c0, 0x1944, 0x00000000);
1281 nv_mthd(dev, 0x90c0, 0x0758, 0x00000100);
1282 nv_mthd(dev, 0x90c0, 0x02c4, 0x00000000);
1283 nv_mthd(dev, 0x90c0, 0x0790, 0x00000000);
1284 nv_mthd(dev, 0x90c0, 0x0794, 0x00000000);
1285 nv_mthd(dev, 0x90c0, 0x0798, 0x00000000);
1286 nv_mthd(dev, 0x90c0, 0x079c, 0x00000000);
1287 nv_mthd(dev, 0x90c0, 0x07a0, 0x00000000);
1288 nv_mthd(dev, 0x90c0, 0x077c, 0x00000000);
1289 nv_mthd(dev, 0x90c0, 0x0204, 0x00000000);
1290 nv_mthd(dev, 0x90c0, 0x0208, 0x00000000);
1291 nv_mthd(dev, 0x90c0, 0x020c, 0x00000000);
1292 nv_mthd(dev, 0x90c0, 0x0214, 0x00000000);
1293 nv_mthd(dev, 0x90c0, 0x024c, 0x00000000);
1294 nv_mthd(dev, 0x90c0, 0x0d94, 0x00000001);
1295 nv_mthd(dev, 0x90c0, 0x1608, 0x00000000);
1296 nv_mthd(dev, 0x90c0, 0x160c, 0x00000000);
1297 nv_mthd(dev, 0x90c0, 0x1664, 0x00000000);
1298}
1299
1300static void
1301nvc0_grctx_generate_dispatch(struct drm_device *dev)
1302{
1303 int i;
1304
1305 nv_wr32(dev, 0x404004, 0x00000000);
1306 nv_wr32(dev, 0x404008, 0x00000000);
1307 nv_wr32(dev, 0x40400c, 0x00000000);
1308 nv_wr32(dev, 0x404010, 0x00000000);
1309 nv_wr32(dev, 0x404014, 0x00000000);
1310 nv_wr32(dev, 0x404018, 0x00000000);
1311 nv_wr32(dev, 0x40401c, 0x00000000);
1312 nv_wr32(dev, 0x404020, 0x00000000);
1313 nv_wr32(dev, 0x404024, 0x00000000);
1314 nv_wr32(dev, 0x404028, 0x00000000);
1315 nv_wr32(dev, 0x40402c, 0x00000000);
1316 nv_wr32(dev, 0x404044, 0x00000000);
1317 nv_wr32(dev, 0x404094, 0x00000000);
1318 nv_wr32(dev, 0x404098, 0x00000000);
1319 nv_wr32(dev, 0x40409c, 0x00000000);
1320 nv_wr32(dev, 0x4040a0, 0x00000000);
1321 nv_wr32(dev, 0x4040a4, 0x00000000);
1322 nv_wr32(dev, 0x4040a8, 0x00000000);
1323 nv_wr32(dev, 0x4040ac, 0x00000000);
1324 nv_wr32(dev, 0x4040b0, 0x00000000);
1325 nv_wr32(dev, 0x4040b4, 0x00000000);
1326 nv_wr32(dev, 0x4040b8, 0x00000000);
1327 nv_wr32(dev, 0x4040bc, 0x00000000);
1328 nv_wr32(dev, 0x4040c0, 0x00000000);
1329 nv_wr32(dev, 0x4040c4, 0x00000000);
1330 nv_wr32(dev, 0x4040c8, 0xf0000087);
1331 nv_wr32(dev, 0x4040d4, 0x00000000);
1332 nv_wr32(dev, 0x4040d8, 0x00000000);
1333 nv_wr32(dev, 0x4040dc, 0x00000000);
1334 nv_wr32(dev, 0x4040e0, 0x00000000);
1335 nv_wr32(dev, 0x4040e4, 0x00000000);
1336 nv_wr32(dev, 0x4040e8, 0x00001000);
1337 nv_wr32(dev, 0x4040f8, 0x00000000);
1338 nv_wr32(dev, 0x404130, 0x00000000);
1339 nv_wr32(dev, 0x404134, 0x00000000);
1340 nv_wr32(dev, 0x404138, 0x20000040);
1341 nv_wr32(dev, 0x404150, 0x0000002e);
1342 nv_wr32(dev, 0x404154, 0x00000400);
1343 nv_wr32(dev, 0x404158, 0x00000200);
1344 nv_wr32(dev, 0x404164, 0x00000055);
1345 nv_wr32(dev, 0x404168, 0x00000000);
1346 nv_wr32(dev, 0x404174, 0x00000000);
1347 nv_wr32(dev, 0x404178, 0x00000000);
1348 nv_wr32(dev, 0x40417c, 0x00000000);
1349 for (i = 0; i < 8; i++)
1350 nv_wr32(dev, 0x404200 + (i * 4), 0x00000000); /* subc */
1351}
1352
1353static void
1354nvc0_grctx_generate_macro(struct drm_device *dev)
1355{
1356 nv_wr32(dev, 0x404404, 0x00000000);
1357 nv_wr32(dev, 0x404408, 0x00000000);
1358 nv_wr32(dev, 0x40440c, 0x00000000);
1359 nv_wr32(dev, 0x404410, 0x00000000);
1360 nv_wr32(dev, 0x404414, 0x00000000);
1361 nv_wr32(dev, 0x404418, 0x00000000);
1362 nv_wr32(dev, 0x40441c, 0x00000000);
1363 nv_wr32(dev, 0x404420, 0x00000000);
1364 nv_wr32(dev, 0x404424, 0x00000000);
1365 nv_wr32(dev, 0x404428, 0x00000000);
1366 nv_wr32(dev, 0x40442c, 0x00000000);
1367 nv_wr32(dev, 0x404430, 0x00000000);
1368 nv_wr32(dev, 0x404434, 0x00000000);
1369 nv_wr32(dev, 0x404438, 0x00000000);
1370 nv_wr32(dev, 0x404460, 0x00000000);
1371 nv_wr32(dev, 0x404464, 0x00000000);
1372 nv_wr32(dev, 0x404468, 0x00ffffff);
1373 nv_wr32(dev, 0x40446c, 0x00000000);
1374 nv_wr32(dev, 0x404480, 0x00000001);
1375 nv_wr32(dev, 0x404498, 0x00000001);
1376}
1377
1378static void
1379nvc0_grctx_generate_m2mf(struct drm_device *dev)
1380{
1381 nv_wr32(dev, 0x404604, 0x00000015);
1382 nv_wr32(dev, 0x404608, 0x00000000);
1383 nv_wr32(dev, 0x40460c, 0x00002e00);
1384 nv_wr32(dev, 0x404610, 0x00000100);
1385 nv_wr32(dev, 0x404618, 0x00000000);
1386 nv_wr32(dev, 0x40461c, 0x00000000);
1387 nv_wr32(dev, 0x404620, 0x00000000);
1388 nv_wr32(dev, 0x404624, 0x00000000);
1389 nv_wr32(dev, 0x404628, 0x00000000);
1390 nv_wr32(dev, 0x40462c, 0x00000000);
1391 nv_wr32(dev, 0x404630, 0x00000000);
1392 nv_wr32(dev, 0x404634, 0x00000000);
1393 nv_wr32(dev, 0x404638, 0x00000004);
1394 nv_wr32(dev, 0x40463c, 0x00000000);
1395 nv_wr32(dev, 0x404640, 0x00000000);
1396 nv_wr32(dev, 0x404644, 0x00000000);
1397 nv_wr32(dev, 0x404648, 0x00000000);
1398 nv_wr32(dev, 0x40464c, 0x00000000);
1399 nv_wr32(dev, 0x404650, 0x00000000);
1400 nv_wr32(dev, 0x404654, 0x00000000);
1401 nv_wr32(dev, 0x404658, 0x00000000);
1402 nv_wr32(dev, 0x40465c, 0x007f0100);
1403 nv_wr32(dev, 0x404660, 0x00000000);
1404 nv_wr32(dev, 0x404664, 0x00000000);
1405 nv_wr32(dev, 0x404668, 0x00000000);
1406 nv_wr32(dev, 0x40466c, 0x00000000);
1407 nv_wr32(dev, 0x404670, 0x00000000);
1408 nv_wr32(dev, 0x404674, 0x00000000);
1409 nv_wr32(dev, 0x404678, 0x00000000);
1410 nv_wr32(dev, 0x40467c, 0x00000002);
1411 nv_wr32(dev, 0x404680, 0x00000000);
1412 nv_wr32(dev, 0x404684, 0x00000000);
1413 nv_wr32(dev, 0x404688, 0x00000000);
1414 nv_wr32(dev, 0x40468c, 0x00000000);
1415 nv_wr32(dev, 0x404690, 0x00000000);
1416 nv_wr32(dev, 0x404694, 0x00000000);
1417 nv_wr32(dev, 0x404698, 0x00000000);
1418 nv_wr32(dev, 0x40469c, 0x00000000);
1419 nv_wr32(dev, 0x4046a0, 0x007f0080);
1420 nv_wr32(dev, 0x4046a4, 0x00000000);
1421 nv_wr32(dev, 0x4046a8, 0x00000000);
1422 nv_wr32(dev, 0x4046ac, 0x00000000);
1423 nv_wr32(dev, 0x4046b0, 0x00000000);
1424 nv_wr32(dev, 0x4046b4, 0x00000000);
1425 nv_wr32(dev, 0x4046b8, 0x00000000);
1426 nv_wr32(dev, 0x4046bc, 0x00000000);
1427 nv_wr32(dev, 0x4046c0, 0x00000000);
1428 nv_wr32(dev, 0x4046c4, 0x00000000);
1429 nv_wr32(dev, 0x4046c8, 0x00000000);
1430 nv_wr32(dev, 0x4046cc, 0x00000000);
1431 nv_wr32(dev, 0x4046d0, 0x00000000);
1432 nv_wr32(dev, 0x4046d4, 0x00000000);
1433 nv_wr32(dev, 0x4046d8, 0x00000000);
1434 nv_wr32(dev, 0x4046dc, 0x00000000);
1435 nv_wr32(dev, 0x4046e0, 0x00000000);
1436 nv_wr32(dev, 0x4046e4, 0x00000000);
1437 nv_wr32(dev, 0x4046e8, 0x00000000);
1438 nv_wr32(dev, 0x4046f0, 0x00000000);
1439 nv_wr32(dev, 0x4046f4, 0x00000000);
1440}
1441
1442static void
1443nvc0_grctx_generate_unk47xx(struct drm_device *dev)
1444{
1445 nv_wr32(dev, 0x404700, 0x00000000);
1446 nv_wr32(dev, 0x404704, 0x00000000);
1447 nv_wr32(dev, 0x404708, 0x00000000);
1448 nv_wr32(dev, 0x40470c, 0x00000000);
1449 nv_wr32(dev, 0x404710, 0x00000000);
1450 nv_wr32(dev, 0x404714, 0x00000000);
1451 nv_wr32(dev, 0x404718, 0x00000000);
1452 nv_wr32(dev, 0x40471c, 0x00000000);
1453 nv_wr32(dev, 0x404720, 0x00000000);
1454 nv_wr32(dev, 0x404724, 0x00000000);
1455 nv_wr32(dev, 0x404728, 0x00000000);
1456 nv_wr32(dev, 0x40472c, 0x00000000);
1457 nv_wr32(dev, 0x404730, 0x00000000);
1458 nv_wr32(dev, 0x404734, 0x00000100);
1459 nv_wr32(dev, 0x404738, 0x00000000);
1460 nv_wr32(dev, 0x40473c, 0x00000000);
1461 nv_wr32(dev, 0x404740, 0x00000000);
1462 nv_wr32(dev, 0x404744, 0x00000000);
1463 nv_wr32(dev, 0x404748, 0x00000000);
1464 nv_wr32(dev, 0x40474c, 0x00000000);
1465 nv_wr32(dev, 0x404750, 0x00000000);
1466 nv_wr32(dev, 0x404754, 0x00000000);
1467}
1468
1469static void
1470nvc0_grctx_generate_shaders(struct drm_device *dev)
1471{
1472 struct drm_nouveau_private *dev_priv = dev->dev_private;
1473
1474 if (dev_priv->chipset != 0xc1) {
1475 nv_wr32(dev, 0x405800, 0x078000bf);
1476 nv_wr32(dev, 0x405830, 0x02180000);
1477 } else {
1478 nv_wr32(dev, 0x405800, 0x0f8000bf);
1479 nv_wr32(dev, 0x405830, 0x02180218);
1480 }
1481 nv_wr32(dev, 0x405834, 0x00000000);
1482 nv_wr32(dev, 0x405838, 0x00000000);
1483 nv_wr32(dev, 0x405854, 0x00000000);
1484 nv_wr32(dev, 0x405870, 0x00000001);
1485 nv_wr32(dev, 0x405874, 0x00000001);
1486 nv_wr32(dev, 0x405878, 0x00000001);
1487 nv_wr32(dev, 0x40587c, 0x00000001);
1488 nv_wr32(dev, 0x405a00, 0x00000000);
1489 nv_wr32(dev, 0x405a04, 0x00000000);
1490 nv_wr32(dev, 0x405a18, 0x00000000);
1491}
1492
1493static void
1494nvc0_grctx_generate_unk60xx(struct drm_device *dev)
1495{
1496 nv_wr32(dev, 0x406020, 0x000103c1);
1497 nv_wr32(dev, 0x406028, 0x00000001);
1498 nv_wr32(dev, 0x40602c, 0x00000001);
1499 nv_wr32(dev, 0x406030, 0x00000001);
1500 nv_wr32(dev, 0x406034, 0x00000001);
1501}
1502
1503static void
1504nvc0_grctx_generate_unk64xx(struct drm_device *dev)
1505{
1506 struct drm_nouveau_private *dev_priv = dev->dev_private;
1507
1508 nv_wr32(dev, 0x4064a8, 0x00000000);
1509 nv_wr32(dev, 0x4064ac, 0x00003fff);
1510 nv_wr32(dev, 0x4064b4, 0x00000000);
1511 nv_wr32(dev, 0x4064b8, 0x00000000);
1512 if (dev_priv->chipset == 0xc1) {
1513 nv_wr32(dev, 0x4064c0, 0x80140078);
1514 nv_wr32(dev, 0x4064c4, 0x0086ffff);
1515 }
1516}
1517
1518static void
1519nvc0_grctx_generate_tpbus(struct drm_device *dev)
1520{
1521 nv_wr32(dev, 0x407804, 0x00000023);
1522 nv_wr32(dev, 0x40780c, 0x0a418820);
1523 nv_wr32(dev, 0x407810, 0x062080e6);
1524 nv_wr32(dev, 0x407814, 0x020398a4);
1525 nv_wr32(dev, 0x407818, 0x0e629062);
1526 nv_wr32(dev, 0x40781c, 0x0a418820);
1527 nv_wr32(dev, 0x407820, 0x000000e6);
1528 nv_wr32(dev, 0x4078bc, 0x00000103);
1529}
1530
1531static void
1532nvc0_grctx_generate_ccache(struct drm_device *dev)
1533{
1534 nv_wr32(dev, 0x408000, 0x00000000);
1535 nv_wr32(dev, 0x408004, 0x00000000);
1536 nv_wr32(dev, 0x408008, 0x00000018);
1537 nv_wr32(dev, 0x40800c, 0x00000000);
1538 nv_wr32(dev, 0x408010, 0x00000000);
1539 nv_wr32(dev, 0x408014, 0x00000069);
1540 nv_wr32(dev, 0x408018, 0xe100e100);
1541 nv_wr32(dev, 0x408064, 0x00000000);
1542}
1543
1544static void
1545nvc0_grctx_generate_rop(struct drm_device *dev)
1546{
1547 struct drm_nouveau_private *dev_priv = dev->dev_private;
1548 int chipset = dev_priv->chipset;
1549
1550 /* ROPC_BROADCAST */
1551 nv_wr32(dev, 0x408800, 0x02802a3c);
1552 nv_wr32(dev, 0x408804, 0x00000040);
1553 nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005);
1554 nv_wr32(dev, 0x408900, 0x3080b801);
1555 nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001);
1556 nv_wr32(dev, 0x408908, 0x00c80929);
1557 nv_wr32(dev, 0x40890c, 0x00000000);
1558 nv_wr32(dev, 0x408980, 0x0000011d);
1559}
1560
1561static void
1562nvc0_grctx_generate_gpc(struct drm_device *dev)
1563{
1564 struct drm_nouveau_private *dev_priv = dev->dev_private;
1565 int chipset = dev_priv->chipset;
1566 int i;
1567
1568 /* GPC_BROADCAST */
1569 nv_wr32(dev, 0x418380, 0x00000016);
1570 nv_wr32(dev, 0x418400, 0x38004e00);
1571 nv_wr32(dev, 0x418404, 0x71e0ffff);
1572 nv_wr32(dev, 0x418408, 0x00000000);
1573 nv_wr32(dev, 0x41840c, 0x00001008);
1574 nv_wr32(dev, 0x418410, 0x0fff0fff);
1575 nv_wr32(dev, 0x418414, 0x00200fff);
1576 nv_wr32(dev, 0x418450, 0x00000000);
1577 nv_wr32(dev, 0x418454, 0x00000000);
1578 nv_wr32(dev, 0x418458, 0x00000000);
1579 nv_wr32(dev, 0x41845c, 0x00000000);
1580 nv_wr32(dev, 0x418460, 0x00000000);
1581 nv_wr32(dev, 0x418464, 0x00000000);
1582 nv_wr32(dev, 0x418468, 0x00000001);
1583 nv_wr32(dev, 0x41846c, 0x00000000);
1584 nv_wr32(dev, 0x418470, 0x00000000);
1585 nv_wr32(dev, 0x418600, 0x0000001f);
1586 nv_wr32(dev, 0x418684, 0x0000000f);
1587 nv_wr32(dev, 0x418700, 0x00000002);
1588 nv_wr32(dev, 0x418704, 0x00000080);
1589 nv_wr32(dev, 0x418708, 0x00000000);
1590 nv_wr32(dev, 0x41870c, 0x07c80000);
1591 nv_wr32(dev, 0x418710, 0x00000000);
1592 nv_wr32(dev, 0x418800, 0x0006860a);
1593 nv_wr32(dev, 0x418808, 0x00000000);
1594 nv_wr32(dev, 0x41880c, 0x00000000);
1595 nv_wr32(dev, 0x418810, 0x00000000);
1596 nv_wr32(dev, 0x418828, 0x00008442);
1597 nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001);
1598 nv_wr32(dev, 0x4188d8, 0x00000008);
1599 nv_wr32(dev, 0x4188e0, 0x01000000);
1600 nv_wr32(dev, 0x4188e8, 0x00000000);
1601 nv_wr32(dev, 0x4188ec, 0x00000000);
1602 nv_wr32(dev, 0x4188f0, 0x00000000);
1603 nv_wr32(dev, 0x4188f4, 0x00000000);
1604 nv_wr32(dev, 0x4188f8, 0x00000000);
1605 nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018);
1606 nv_wr32(dev, 0x41891c, 0x00ff00ff);
1607 nv_wr32(dev, 0x418924, 0x00000000);
1608 nv_wr32(dev, 0x418928, 0x00ffff00);
1609 nv_wr32(dev, 0x41892c, 0x0000ff00);
1610 for (i = 0; i < 8; i++) {
1611 nv_wr32(dev, 0x418a00 + (i * 0x20), 0x00000000);
1612 nv_wr32(dev, 0x418a04 + (i * 0x20), 0x00000000);
1613 nv_wr32(dev, 0x418a08 + (i * 0x20), 0x00000000);
1614 nv_wr32(dev, 0x418a0c + (i * 0x20), 0x00010000);
1615 nv_wr32(dev, 0x418a10 + (i * 0x20), 0x00000000);
1616 nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000);
1617 nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000);
1618 }
1619 nv_wr32(dev, 0x418b00, 0x00000000);
1620 nv_wr32(dev, 0x418b08, 0x0a418820);
1621 nv_wr32(dev, 0x418b0c, 0x062080e6);
1622 nv_wr32(dev, 0x418b10, 0x020398a4);
1623 nv_wr32(dev, 0x418b14, 0x0e629062);
1624 nv_wr32(dev, 0x418b18, 0x0a418820);
1625 nv_wr32(dev, 0x418b1c, 0x000000e6);
1626 nv_wr32(dev, 0x418bb8, 0x00000103);
1627 nv_wr32(dev, 0x418c08, 0x00000001);
1628 nv_wr32(dev, 0x418c10, 0x00000000);
1629 nv_wr32(dev, 0x418c14, 0x00000000);
1630 nv_wr32(dev, 0x418c18, 0x00000000);
1631 nv_wr32(dev, 0x418c1c, 0x00000000);
1632 nv_wr32(dev, 0x418c20, 0x00000000);
1633 nv_wr32(dev, 0x418c24, 0x00000000);
1634 nv_wr32(dev, 0x418c28, 0x00000000);
1635 nv_wr32(dev, 0x418c2c, 0x00000000);
1636 if (chipset == 0xc1)
1637 nv_wr32(dev, 0x418c6c, 0x00000001);
1638 nv_wr32(dev, 0x418c80, 0x20200004);
1639 nv_wr32(dev, 0x418c8c, 0x00000001);
1640 nv_wr32(dev, 0x419000, 0x00000780);
1641 nv_wr32(dev, 0x419004, 0x00000000);
1642 nv_wr32(dev, 0x419008, 0x00000000);
1643 nv_wr32(dev, 0x419014, 0x00000004);
1644}
1645
1646static void
1647nvc0_grctx_generate_tp(struct drm_device *dev)
1648{
1649 struct drm_nouveau_private *dev_priv = dev->dev_private;
1650 int chipset = dev_priv->chipset;
1651
1652 /* GPC_BROADCAST.TP_BROADCAST */
1653 nv_wr32(dev, 0x419818, 0x00000000);
1654 nv_wr32(dev, 0x41983c, 0x00038bc7);
1655 nv_wr32(dev, 0x419848, 0x00000000);
1656 nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129);
1657 nv_wr32(dev, 0x419888, 0x00000000);
1658 nv_wr32(dev, 0x419a00, 0x000001f0);
1659 nv_wr32(dev, 0x419a04, 0x00000001);
1660 nv_wr32(dev, 0x419a08, 0x00000023);
1661 nv_wr32(dev, 0x419a0c, 0x00020000);
1662 nv_wr32(dev, 0x419a10, 0x00000000);
1663 nv_wr32(dev, 0x419a14, 0x00000200);
1664 nv_wr32(dev, 0x419a1c, 0x00000000);
1665 nv_wr32(dev, 0x419a20, 0x00000800);
1666 if (chipset != 0xc0 && chipset != 0xc8)
1667 nv_wr32(dev, 0x00419ac4, 0x0007f440);
1668 nv_wr32(dev, 0x419b00, 0x0a418820);
1669 nv_wr32(dev, 0x419b04, 0x062080e6);
1670 nv_wr32(dev, 0x419b08, 0x020398a4);
1671 nv_wr32(dev, 0x419b0c, 0x0e629062);
1672 nv_wr32(dev, 0x419b10, 0x0a418820);
1673 nv_wr32(dev, 0x419b14, 0x000000e6);
1674 nv_wr32(dev, 0x419bd0, 0x00900103);
1675 nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001);
1676 nv_wr32(dev, 0x419be4, 0x00000000);
1677 nv_wr32(dev, 0x419c00, 0x00000002);
1678 nv_wr32(dev, 0x419c04, 0x00000006);
1679 nv_wr32(dev, 0x419c08, 0x00000002);
1680 nv_wr32(dev, 0x419c20, 0x00000000);
1681 nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
1682 nv_wr32(dev, 0x419ce8, 0x00000000);
1683 nv_wr32(dev, 0x419cf4, 0x00000183);
1684 nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
1685 nv_wr32(dev, 0x419d24, 0x00001fff);
1686 if (chipset == 0xc1)
1687 nv_wr32(dev, 0x419d44, 0x02180218);
1688 nv_wr32(dev, 0x419e04, 0x00000000);
1689 nv_wr32(dev, 0x419e08, 0x00000000);
1690 nv_wr32(dev, 0x419e0c, 0x00000000);
1691 nv_wr32(dev, 0x419e10, 0x00000002);
1692 nv_wr32(dev, 0x419e44, 0x001beff2);
1693 nv_wr32(dev, 0x419e48, 0x00000000);
1694 nv_wr32(dev, 0x419e4c, 0x0000000f);
1695 nv_wr32(dev, 0x419e50, 0x00000000);
1696 nv_wr32(dev, 0x419e54, 0x00000000);
1697 nv_wr32(dev, 0x419e58, 0x00000000);
1698 nv_wr32(dev, 0x419e5c, 0x00000000);
1699 nv_wr32(dev, 0x419e60, 0x00000000);
1700 nv_wr32(dev, 0x419e64, 0x00000000);
1701 nv_wr32(dev, 0x419e68, 0x00000000);
1702 nv_wr32(dev, 0x419e6c, 0x00000000);
1703 nv_wr32(dev, 0x419e70, 0x00000000);
1704 nv_wr32(dev, 0x419e74, 0x00000000);
1705 nv_wr32(dev, 0x419e78, 0x00000000);
1706 nv_wr32(dev, 0x419e7c, 0x00000000);
1707 nv_wr32(dev, 0x419e80, 0x00000000);
1708 nv_wr32(dev, 0x419e84, 0x00000000);
1709 nv_wr32(dev, 0x419e88, 0x00000000);
1710 nv_wr32(dev, 0x419e8c, 0x00000000);
1711 nv_wr32(dev, 0x419e90, 0x00000000);
1712 nv_wr32(dev, 0x419e98, 0x00000000);
1713 if (chipset != 0xc0 && chipset != 0xc8)
1714 nv_wr32(dev, 0x419ee0, 0x00011110);
1715 nv_wr32(dev, 0x419f50, 0x00000000);
1716 nv_wr32(dev, 0x419f54, 0x00000000);
1717 if (chipset != 0xc0 && chipset != 0xc8)
1718 nv_wr32(dev, 0x419f58, 0x00000000);
1719}
1720
1721int
1722nvc0_grctx_generate(struct nouveau_channel *chan)
1723{
1724 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
1725 struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
1726 struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
1727 struct drm_device *dev = chan->dev;
1728 int i, gpc, tp, id;
1729 u32 fermi = nvc0_graph_class(dev);
1730 u32 r000260, tmp;
1731
1732 r000260 = nv_rd32(dev, 0x000260);
1733 nv_wr32(dev, 0x000260, r000260 & ~1);
1734 nv_wr32(dev, 0x400208, 0x00000000);
1735
1736 nvc0_grctx_generate_dispatch(dev);
1737 nvc0_grctx_generate_macro(dev);
1738 nvc0_grctx_generate_m2mf(dev);
1739 nvc0_grctx_generate_unk47xx(dev);
1740 nvc0_grctx_generate_shaders(dev);
1741 nvc0_grctx_generate_unk60xx(dev);
1742 nvc0_grctx_generate_unk64xx(dev);
1743 nvc0_grctx_generate_tpbus(dev);
1744 nvc0_grctx_generate_ccache(dev);
1745 nvc0_grctx_generate_rop(dev);
1746 nvc0_grctx_generate_gpc(dev);
1747 nvc0_grctx_generate_tp(dev);
1748
1749 nv_wr32(dev, 0x404154, 0x00000000);
1750
1751 /* fuc "mmio list" writes */
1752 for (i = 0; i < grch->mmio_nr * 8; i += 8) {
1753 u32 reg = nv_ro32(grch->mmio, i + 0);
1754 nv_wr32(dev, reg, nv_ro32(grch->mmio, i + 4));
1755 }
1756
1757 for (tp = 0, id = 0; tp < 4; tp++) {
1758 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
1759 if (tp < priv->tp_nr[gpc]) {
1760 nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id);
1761 nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id);
1762 nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id);
1763 nv_wr32(dev, TP_UNIT(gpc, tp, 0x088), id);
1764 id++;
1765 }
1766
1767 nv_wr32(dev, GPC_UNIT(gpc, 0x0c08), priv->tp_nr[gpc]);
1768 nv_wr32(dev, GPC_UNIT(gpc, 0x0c8c), priv->tp_nr[gpc]);
1769 }
1770 }
1771
1772 tmp = 0;
1773 for (i = 0; i < priv->gpc_nr; i++)
1774 tmp |= priv->tp_nr[i] << (i * 4);
1775 nv_wr32(dev, 0x406028, tmp);
1776 nv_wr32(dev, 0x405870, tmp);
1777
1778 nv_wr32(dev, 0x40602c, 0x00000000);
1779 nv_wr32(dev, 0x405874, 0x00000000);
1780 nv_wr32(dev, 0x406030, 0x00000000);
1781 nv_wr32(dev, 0x405878, 0x00000000);
1782 nv_wr32(dev, 0x406034, 0x00000000);
1783 nv_wr32(dev, 0x40587c, 0x00000000);
1784
1785 if (1) {
1786 const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0,
1787 16, 0, 0, 0, 0, 0, 8, 0 };
1788 u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
1789 u8 tpnr[GPC_MAX];
1790 u8 data[TP_MAX];
1791
1792 memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
1793 memset(data, 0x1f, sizeof(data));
1794
1795 gpc = -1;
1796 for (tp = 0; tp < priv->tp_total; tp++) {
1797 do {
1798 gpc = (gpc + 1) % priv->gpc_nr;
1799 } while (!tpnr[gpc]);
1800 tpnr[gpc]--;
1801 data[tp] = gpc;
1802 }
1803
1804 for (i = 0; i < max / 4; i++)
1805 nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]);
1806 }
1807
1808 if (1) {
1809 u32 data[6] = {}, data2[2] = {};
1810 u8 tpnr[GPC_MAX];
1811 u8 shift, ntpcv;
1812
1813 /* calculate first set of magics */
1814 memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
1815
1816 for (tp = 0; tp < priv->tp_total; tp++) {
1817 do {
1818 gpc = (gpc + 1) % priv->gpc_nr;
1819 } while (!tpnr[gpc]);
1820 tpnr[gpc]--;
1821
1822 data[tp / 6] |= gpc << ((tp % 6) * 5);
1823 }
1824
1825 for (; tp < 32; tp++)
1826 data[tp / 6] |= 7 << ((tp % 6) * 5);
1827
1828 /* and the second... */
1829 shift = 0;
1830 ntpcv = priv->tp_total;
1831 while (!(ntpcv & (1 << 4))) {
1832 ntpcv <<= 1;
1833 shift++;
1834 }
1835
1836 data2[0] = (ntpcv << 16);
1837 data2[0] |= (shift << 21);
1838 data2[0] |= (((1 << (0 + 5)) % ntpcv) << 24);
1839 for (i = 1; i < 7; i++)
1840 data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5);
1841
1842 /* GPC_BROADCAST */
1843 nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) |
1844 priv->magic_not_rop_nr);
1845 for (i = 0; i < 6; i++)
1846 nv_wr32(dev, 0x418b08 + (i * 4), data[i]);
1847
1848 /* GPC_BROADCAST.TP_BROADCAST */
1849 nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) |
1850 priv->magic_not_rop_nr |
1851 data2[0]);
1852 nv_wr32(dev, 0x419be4, data2[1]);
1853 for (i = 0; i < 6; i++)
1854 nv_wr32(dev, 0x419b00 + (i * 4), data[i]);
1855
1856 /* UNK78xx */
1857 nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) |
1858 priv->magic_not_rop_nr);
1859 for (i = 0; i < 6; i++)
1860 nv_wr32(dev, 0x40780c + (i * 4), data[i]);
1861 }
1862
1863 if (1) {
1864 u32 tp_mask = 0, tp_set = 0;
1865 u8 tpnr[GPC_MAX];
1866
1867 memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
1868 for (gpc = 0; gpc < priv->gpc_nr; gpc++)
1869 tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
1870
1871 gpc = -1;
1872 for (i = 0, gpc = -1; i < 32; i++) {
1873 int ltp = i * (priv->tp_total - 1) / 32;
1874
1875 do {
1876 gpc = (gpc + 1) % priv->gpc_nr;
1877 } while (!tpnr[gpc]);
1878 tp = priv->tp_nr[gpc] - tpnr[gpc]--;
1879
1880 tp_set |= 1 << ((gpc * 8) + tp);
1881
1882 do {
1883 nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
1884 tp_set ^= tp_mask;
1885 nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
1886 tp_set ^= tp_mask;
1887 } while (ltp == (++i * (priv->tp_total - 1) / 32));
1888 i--;
1889 }
1890 }
1891
1892 nv_wr32(dev, 0x400208, 0x80000000);
1893
1894 nv_icmd(dev, 0x00001000, 0x00000004);
1895 nv_icmd(dev, 0x000000a9, 0x0000ffff);
1896 nv_icmd(dev, 0x00000038, 0x0fac6881);
1897 nv_icmd(dev, 0x0000003d, 0x00000001);
1898 nv_icmd(dev, 0x000000e8, 0x00000400);
1899 nv_icmd(dev, 0x000000e9, 0x00000400);
1900 nv_icmd(dev, 0x000000ea, 0x00000400);
1901 nv_icmd(dev, 0x000000eb, 0x00000400);
1902 nv_icmd(dev, 0x000000ec, 0x00000400);
1903 nv_icmd(dev, 0x000000ed, 0x00000400);
1904 nv_icmd(dev, 0x000000ee, 0x00000400);
1905 nv_icmd(dev, 0x000000ef, 0x00000400);
1906 nv_icmd(dev, 0x00000078, 0x00000300);
1907 nv_icmd(dev, 0x00000079, 0x00000300);
1908 nv_icmd(dev, 0x0000007a, 0x00000300);
1909 nv_icmd(dev, 0x0000007b, 0x00000300);
1910 nv_icmd(dev, 0x0000007c, 0x00000300);
1911 nv_icmd(dev, 0x0000007d, 0x00000300);
1912 nv_icmd(dev, 0x0000007e, 0x00000300);
1913 nv_icmd(dev, 0x0000007f, 0x00000300);
1914 nv_icmd(dev, 0x00000050, 0x00000011);
1915 nv_icmd(dev, 0x00000058, 0x00000008);
1916 nv_icmd(dev, 0x00000059, 0x00000008);
1917 nv_icmd(dev, 0x0000005a, 0x00000008);
1918 nv_icmd(dev, 0x0000005b, 0x00000008);
1919 nv_icmd(dev, 0x0000005c, 0x00000008);
1920 nv_icmd(dev, 0x0000005d, 0x00000008);
1921 nv_icmd(dev, 0x0000005e, 0x00000008);
1922 nv_icmd(dev, 0x0000005f, 0x00000008);
1923 nv_icmd(dev, 0x00000208, 0x00000001);
1924 nv_icmd(dev, 0x00000209, 0x00000001);
1925 nv_icmd(dev, 0x0000020a, 0x00000001);
1926 nv_icmd(dev, 0x0000020b, 0x00000001);
1927 nv_icmd(dev, 0x0000020c, 0x00000001);
1928 nv_icmd(dev, 0x0000020d, 0x00000001);
1929 nv_icmd(dev, 0x0000020e, 0x00000001);
1930 nv_icmd(dev, 0x0000020f, 0x00000001);
1931 nv_icmd(dev, 0x00000081, 0x00000001);
1932 nv_icmd(dev, 0x00000085, 0x00000004);
1933 nv_icmd(dev, 0x00000088, 0x00000400);
1934 nv_icmd(dev, 0x00000090, 0x00000300);
1935 nv_icmd(dev, 0x00000098, 0x00001001);
1936 nv_icmd(dev, 0x000000e3, 0x00000001);
1937 nv_icmd(dev, 0x000000da, 0x00000001);
1938 nv_icmd(dev, 0x000000f8, 0x00000003);
1939 nv_icmd(dev, 0x000000fa, 0x00000001);
1940 nv_icmd(dev, 0x0000009f, 0x0000ffff);
1941 nv_icmd(dev, 0x000000a0, 0x0000ffff);
1942 nv_icmd(dev, 0x000000a1, 0x0000ffff);
1943 nv_icmd(dev, 0x000000a2, 0x0000ffff);
1944 nv_icmd(dev, 0x000000b1, 0x00000001);
1945 nv_icmd(dev, 0x000000b2, 0x00000000);
1946 nv_icmd(dev, 0x000000b3, 0x00000000);
1947 nv_icmd(dev, 0x000000b4, 0x00000000);
1948 nv_icmd(dev, 0x000000b5, 0x00000000);
1949 nv_icmd(dev, 0x000000b6, 0x00000000);
1950 nv_icmd(dev, 0x000000b7, 0x00000000);
1951 nv_icmd(dev, 0x000000b8, 0x00000000);
1952 nv_icmd(dev, 0x000000b9, 0x00000000);
1953 nv_icmd(dev, 0x000000ba, 0x00000000);
1954 nv_icmd(dev, 0x000000bb, 0x00000000);
1955 nv_icmd(dev, 0x000000bc, 0x00000000);
1956 nv_icmd(dev, 0x000000bd, 0x00000000);
1957 nv_icmd(dev, 0x000000be, 0x00000000);
1958 nv_icmd(dev, 0x000000bf, 0x00000000);
1959 nv_icmd(dev, 0x000000c0, 0x00000000);
1960 nv_icmd(dev, 0x000000c1, 0x00000000);
1961 nv_icmd(dev, 0x000000c2, 0x00000000);
1962 nv_icmd(dev, 0x000000c3, 0x00000000);
1963 nv_icmd(dev, 0x000000c4, 0x00000000);
1964 nv_icmd(dev, 0x000000c5, 0x00000000);
1965 nv_icmd(dev, 0x000000c6, 0x00000000);
1966 nv_icmd(dev, 0x000000c7, 0x00000000);
1967 nv_icmd(dev, 0x000000c8, 0x00000000);
1968 nv_icmd(dev, 0x000000c9, 0x00000000);
1969 nv_icmd(dev, 0x000000ca, 0x00000000);
1970 nv_icmd(dev, 0x000000cb, 0x00000000);
1971 nv_icmd(dev, 0x000000cc, 0x00000000);
1972 nv_icmd(dev, 0x000000cd, 0x00000000);
1973 nv_icmd(dev, 0x000000ce, 0x00000000);
1974 nv_icmd(dev, 0x000000cf, 0x00000000);
1975 nv_icmd(dev, 0x000000d0, 0x00000000);
1976 nv_icmd(dev, 0x000000d1, 0x00000000);
1977 nv_icmd(dev, 0x000000d2, 0x00000000);
1978 nv_icmd(dev, 0x000000d3, 0x00000000);
1979 nv_icmd(dev, 0x000000d4, 0x00000000);
1980 nv_icmd(dev, 0x000000d5, 0x00000000);
1981 nv_icmd(dev, 0x000000d6, 0x00000000);
1982 nv_icmd(dev, 0x000000d7, 0x00000000);
1983 nv_icmd(dev, 0x000000d8, 0x00000000);
1984 nv_icmd(dev, 0x000000d9, 0x00000000);
1985 nv_icmd(dev, 0x00000210, 0x00000040);
1986 nv_icmd(dev, 0x00000211, 0x00000040);
1987 nv_icmd(dev, 0x00000212, 0x00000040);
1988 nv_icmd(dev, 0x00000213, 0x00000040);
1989 nv_icmd(dev, 0x00000214, 0x00000040);
1990 nv_icmd(dev, 0x00000215, 0x00000040);
1991 nv_icmd(dev, 0x00000216, 0x00000040);
1992 nv_icmd(dev, 0x00000217, 0x00000040);
1993 nv_icmd(dev, 0x00000218, 0x0000c080);
1994 nv_icmd(dev, 0x00000219, 0x0000c080);
1995 nv_icmd(dev, 0x0000021a, 0x0000c080);
1996 nv_icmd(dev, 0x0000021b, 0x0000c080);
1997 nv_icmd(dev, 0x0000021c, 0x0000c080);
1998 nv_icmd(dev, 0x0000021d, 0x0000c080);
1999 nv_icmd(dev, 0x0000021e, 0x0000c080);
2000 nv_icmd(dev, 0x0000021f, 0x0000c080);
2001 nv_icmd(dev, 0x000000ad, 0x0000013e);
2002 nv_icmd(dev, 0x000000e1, 0x00000010);
2003 nv_icmd(dev, 0x00000290, 0x00000000);
2004 nv_icmd(dev, 0x00000291, 0x00000000);
2005 nv_icmd(dev, 0x00000292, 0x00000000);
2006 nv_icmd(dev, 0x00000293, 0x00000000);
2007 nv_icmd(dev, 0x00000294, 0x00000000);
2008 nv_icmd(dev, 0x00000295, 0x00000000);
2009 nv_icmd(dev, 0x00000296, 0x00000000);
2010 nv_icmd(dev, 0x00000297, 0x00000000);
2011 nv_icmd(dev, 0x00000298, 0x00000000);
2012 nv_icmd(dev, 0x00000299, 0x00000000);
2013 nv_icmd(dev, 0x0000029a, 0x00000000);
2014 nv_icmd(dev, 0x0000029b, 0x00000000);
2015 nv_icmd(dev, 0x0000029c, 0x00000000);
2016 nv_icmd(dev, 0x0000029d, 0x00000000);
2017 nv_icmd(dev, 0x0000029e, 0x00000000);
2018 nv_icmd(dev, 0x0000029f, 0x00000000);
2019 nv_icmd(dev, 0x000003b0, 0x00000000);
2020 nv_icmd(dev, 0x000003b1, 0x00000000);
2021 nv_icmd(dev, 0x000003b2, 0x00000000);
2022 nv_icmd(dev, 0x000003b3, 0x00000000);
2023 nv_icmd(dev, 0x000003b4, 0x00000000);
2024 nv_icmd(dev, 0x000003b5, 0x00000000);
2025 nv_icmd(dev, 0x000003b6, 0x00000000);
2026 nv_icmd(dev, 0x000003b7, 0x00000000);
2027 nv_icmd(dev, 0x000003b8, 0x00000000);
2028 nv_icmd(dev, 0x000003b9, 0x00000000);
2029 nv_icmd(dev, 0x000003ba, 0x00000000);
2030 nv_icmd(dev, 0x000003bb, 0x00000000);
2031 nv_icmd(dev, 0x000003bc, 0x00000000);
2032 nv_icmd(dev, 0x000003bd, 0x00000000);
2033 nv_icmd(dev, 0x000003be, 0x00000000);
2034 nv_icmd(dev, 0x000003bf, 0x00000000);
2035 nv_icmd(dev, 0x000002a0, 0x00000000);
2036 nv_icmd(dev, 0x000002a1, 0x00000000);
2037 nv_icmd(dev, 0x000002a2, 0x00000000);
2038 nv_icmd(dev, 0x000002a3, 0x00000000);
2039 nv_icmd(dev, 0x000002a4, 0x00000000);
2040 nv_icmd(dev, 0x000002a5, 0x00000000);
2041 nv_icmd(dev, 0x000002a6, 0x00000000);
2042 nv_icmd(dev, 0x000002a7, 0x00000000);
2043 nv_icmd(dev, 0x000002a8, 0x00000000);
2044 nv_icmd(dev, 0x000002a9, 0x00000000);
2045 nv_icmd(dev, 0x000002aa, 0x00000000);
2046 nv_icmd(dev, 0x000002ab, 0x00000000);
2047 nv_icmd(dev, 0x000002ac, 0x00000000);
2048 nv_icmd(dev, 0x000002ad, 0x00000000);
2049 nv_icmd(dev, 0x000002ae, 0x00000000);
2050 nv_icmd(dev, 0x000002af, 0x00000000);
2051 nv_icmd(dev, 0x00000420, 0x00000000);
2052 nv_icmd(dev, 0x00000421, 0x00000000);
2053 nv_icmd(dev, 0x00000422, 0x00000000);
2054 nv_icmd(dev, 0x00000423, 0x00000000);
2055 nv_icmd(dev, 0x00000424, 0x00000000);
2056 nv_icmd(dev, 0x00000425, 0x00000000);
2057 nv_icmd(dev, 0x00000426, 0x00000000);
2058 nv_icmd(dev, 0x00000427, 0x00000000);
2059 nv_icmd(dev, 0x00000428, 0x00000000);
2060 nv_icmd(dev, 0x00000429, 0x00000000);
2061 nv_icmd(dev, 0x0000042a, 0x00000000);
2062 nv_icmd(dev, 0x0000042b, 0x00000000);
2063 nv_icmd(dev, 0x0000042c, 0x00000000);
2064 nv_icmd(dev, 0x0000042d, 0x00000000);
2065 nv_icmd(dev, 0x0000042e, 0x00000000);
2066 nv_icmd(dev, 0x0000042f, 0x00000000);
2067 nv_icmd(dev, 0x000002b0, 0x00000000);
2068 nv_icmd(dev, 0x000002b1, 0x00000000);
2069 nv_icmd(dev, 0x000002b2, 0x00000000);
2070 nv_icmd(dev, 0x000002b3, 0x00000000);
2071 nv_icmd(dev, 0x000002b4, 0x00000000);
2072 nv_icmd(dev, 0x000002b5, 0x00000000);
2073 nv_icmd(dev, 0x000002b6, 0x00000000);
2074 nv_icmd(dev, 0x000002b7, 0x00000000);
2075 nv_icmd(dev, 0x000002b8, 0x00000000);
2076 nv_icmd(dev, 0x000002b9, 0x00000000);
2077 nv_icmd(dev, 0x000002ba, 0x00000000);
2078 nv_icmd(dev, 0x000002bb, 0x00000000);
2079 nv_icmd(dev, 0x000002bc, 0x00000000);
2080 nv_icmd(dev, 0x000002bd, 0x00000000);
2081 nv_icmd(dev, 0x000002be, 0x00000000);
2082 nv_icmd(dev, 0x000002bf, 0x00000000);
2083 nv_icmd(dev, 0x00000430, 0x00000000);
2084 nv_icmd(dev, 0x00000431, 0x00000000);
2085 nv_icmd(dev, 0x00000432, 0x00000000);
2086 nv_icmd(dev, 0x00000433, 0x00000000);
2087 nv_icmd(dev, 0x00000434, 0x00000000);
2088 nv_icmd(dev, 0x00000435, 0x00000000);
2089 nv_icmd(dev, 0x00000436, 0x00000000);
2090 nv_icmd(dev, 0x00000437, 0x00000000);
2091 nv_icmd(dev, 0x00000438, 0x00000000);
2092 nv_icmd(dev, 0x00000439, 0x00000000);
2093 nv_icmd(dev, 0x0000043a, 0x00000000);
2094 nv_icmd(dev, 0x0000043b, 0x00000000);
2095 nv_icmd(dev, 0x0000043c, 0x00000000);
2096 nv_icmd(dev, 0x0000043d, 0x00000000);
2097 nv_icmd(dev, 0x0000043e, 0x00000000);
2098 nv_icmd(dev, 0x0000043f, 0x00000000);
2099 nv_icmd(dev, 0x000002c0, 0x00000000);
2100 nv_icmd(dev, 0x000002c1, 0x00000000);
2101 nv_icmd(dev, 0x000002c2, 0x00000000);
2102 nv_icmd(dev, 0x000002c3, 0x00000000);
2103 nv_icmd(dev, 0x000002c4, 0x00000000);
2104 nv_icmd(dev, 0x000002c5, 0x00000000);
2105 nv_icmd(dev, 0x000002c6, 0x00000000);
2106 nv_icmd(dev, 0x000002c7, 0x00000000);
2107 nv_icmd(dev, 0x000002c8, 0x00000000);
2108 nv_icmd(dev, 0x000002c9, 0x00000000);
2109 nv_icmd(dev, 0x000002ca, 0x00000000);
2110 nv_icmd(dev, 0x000002cb, 0x00000000);
2111 nv_icmd(dev, 0x000002cc, 0x00000000);
2112 nv_icmd(dev, 0x000002cd, 0x00000000);
2113 nv_icmd(dev, 0x000002ce, 0x00000000);
2114 nv_icmd(dev, 0x000002cf, 0x00000000);
2115 nv_icmd(dev, 0x000004d0, 0x00000000);
2116 nv_icmd(dev, 0x000004d1, 0x00000000);
2117 nv_icmd(dev, 0x000004d2, 0x00000000);
2118 nv_icmd(dev, 0x000004d3, 0x00000000);
2119 nv_icmd(dev, 0x000004d4, 0x00000000);
2120 nv_icmd(dev, 0x000004d5, 0x00000000);
2121 nv_icmd(dev, 0x000004d6, 0x00000000);
2122 nv_icmd(dev, 0x000004d7, 0x00000000);
2123 nv_icmd(dev, 0x000004d8, 0x00000000);
2124 nv_icmd(dev, 0x000004d9, 0x00000000);
2125 nv_icmd(dev, 0x000004da, 0x00000000);
2126 nv_icmd(dev, 0x000004db, 0x00000000);
2127 nv_icmd(dev, 0x000004dc, 0x00000000);
2128 nv_icmd(dev, 0x000004dd, 0x00000000);
2129 nv_icmd(dev, 0x000004de, 0x00000000);
2130 nv_icmd(dev, 0x000004df, 0x00000000);
2131 nv_icmd(dev, 0x00000720, 0x00000000);
2132 nv_icmd(dev, 0x00000721, 0x00000000);
2133 nv_icmd(dev, 0x00000722, 0x00000000);
2134 nv_icmd(dev, 0x00000723, 0x00000000);
2135 nv_icmd(dev, 0x00000724, 0x00000000);
2136 nv_icmd(dev, 0x00000725, 0x00000000);
2137 nv_icmd(dev, 0x00000726, 0x00000000);
2138 nv_icmd(dev, 0x00000727, 0x00000000);
2139 nv_icmd(dev, 0x00000728, 0x00000000);
2140 nv_icmd(dev, 0x00000729, 0x00000000);
2141 nv_icmd(dev, 0x0000072a, 0x00000000);
2142 nv_icmd(dev, 0x0000072b, 0x00000000);
2143 nv_icmd(dev, 0x0000072c, 0x00000000);
2144 nv_icmd(dev, 0x0000072d, 0x00000000);
2145 nv_icmd(dev, 0x0000072e, 0x00000000);
2146 nv_icmd(dev, 0x0000072f, 0x00000000);
2147 nv_icmd(dev, 0x000008c0, 0x00000000);
2148 nv_icmd(dev, 0x000008c1, 0x00000000);
2149 nv_icmd(dev, 0x000008c2, 0x00000000);
2150 nv_icmd(dev, 0x000008c3, 0x00000000);
2151 nv_icmd(dev, 0x000008c4, 0x00000000);
2152 nv_icmd(dev, 0x000008c5, 0x00000000);
2153 nv_icmd(dev, 0x000008c6, 0x00000000);
2154 nv_icmd(dev, 0x000008c7, 0x00000000);
2155 nv_icmd(dev, 0x000008c8, 0x00000000);
2156 nv_icmd(dev, 0x000008c9, 0x00000000);
2157 nv_icmd(dev, 0x000008ca, 0x00000000);
2158 nv_icmd(dev, 0x000008cb, 0x00000000);
2159 nv_icmd(dev, 0x000008cc, 0x00000000);
2160 nv_icmd(dev, 0x000008cd, 0x00000000);
2161 nv_icmd(dev, 0x000008ce, 0x00000000);
2162 nv_icmd(dev, 0x000008cf, 0x00000000);
2163 nv_icmd(dev, 0x00000890, 0x00000000);
2164 nv_icmd(dev, 0x00000891, 0x00000000);
2165 nv_icmd(dev, 0x00000892, 0x00000000);
2166 nv_icmd(dev, 0x00000893, 0x00000000);
2167 nv_icmd(dev, 0x00000894, 0x00000000);
2168 nv_icmd(dev, 0x00000895, 0x00000000);
2169 nv_icmd(dev, 0x00000896, 0x00000000);
2170 nv_icmd(dev, 0x00000897, 0x00000000);
2171 nv_icmd(dev, 0x00000898, 0x00000000);
2172 nv_icmd(dev, 0x00000899, 0x00000000);
2173 nv_icmd(dev, 0x0000089a, 0x00000000);
2174 nv_icmd(dev, 0x0000089b, 0x00000000);
2175 nv_icmd(dev, 0x0000089c, 0x00000000);
2176 nv_icmd(dev, 0x0000089d, 0x00000000);
2177 nv_icmd(dev, 0x0000089e, 0x00000000);
2178 nv_icmd(dev, 0x0000089f, 0x00000000);
2179 nv_icmd(dev, 0x000008e0, 0x00000000);
2180 nv_icmd(dev, 0x000008e1, 0x00000000);
2181 nv_icmd(dev, 0x000008e2, 0x00000000);
2182 nv_icmd(dev, 0x000008e3, 0x00000000);
2183 nv_icmd(dev, 0x000008e4, 0x00000000);
2184 nv_icmd(dev, 0x000008e5, 0x00000000);
2185 nv_icmd(dev, 0x000008e6, 0x00000000);
2186 nv_icmd(dev, 0x000008e7, 0x00000000);
2187 nv_icmd(dev, 0x000008e8, 0x00000000);
2188 nv_icmd(dev, 0x000008e9, 0x00000000);
2189 nv_icmd(dev, 0x000008ea, 0x00000000);
2190 nv_icmd(dev, 0x000008eb, 0x00000000);
2191 nv_icmd(dev, 0x000008ec, 0x00000000);
2192 nv_icmd(dev, 0x000008ed, 0x00000000);
2193 nv_icmd(dev, 0x000008ee, 0x00000000);
2194 nv_icmd(dev, 0x000008ef, 0x00000000);
2195 nv_icmd(dev, 0x000008a0, 0x00000000);
2196 nv_icmd(dev, 0x000008a1, 0x00000000);
2197 nv_icmd(dev, 0x000008a2, 0x00000000);
2198 nv_icmd(dev, 0x000008a3, 0x00000000);
2199 nv_icmd(dev, 0x000008a4, 0x00000000);
2200 nv_icmd(dev, 0x000008a5, 0x00000000);
2201 nv_icmd(dev, 0x000008a6, 0x00000000);
2202 nv_icmd(dev, 0x000008a7, 0x00000000);
2203 nv_icmd(dev, 0x000008a8, 0x00000000);
2204 nv_icmd(dev, 0x000008a9, 0x00000000);
2205 nv_icmd(dev, 0x000008aa, 0x00000000);
2206 nv_icmd(dev, 0x000008ab, 0x00000000);
2207 nv_icmd(dev, 0x000008ac, 0x00000000);
2208 nv_icmd(dev, 0x000008ad, 0x00000000);
2209 nv_icmd(dev, 0x000008ae, 0x00000000);
2210 nv_icmd(dev, 0x000008af, 0x00000000);
2211 nv_icmd(dev, 0x000008f0, 0x00000000);
2212 nv_icmd(dev, 0x000008f1, 0x00000000);
2213 nv_icmd(dev, 0x000008f2, 0x00000000);
2214 nv_icmd(dev, 0x000008f3, 0x00000000);
2215 nv_icmd(dev, 0x000008f4, 0x00000000);
2216 nv_icmd(dev, 0x000008f5, 0x00000000);
2217 nv_icmd(dev, 0x000008f6, 0x00000000);
2218 nv_icmd(dev, 0x000008f7, 0x00000000);
2219 nv_icmd(dev, 0x000008f8, 0x00000000);
2220 nv_icmd(dev, 0x000008f9, 0x00000000);
2221 nv_icmd(dev, 0x000008fa, 0x00000000);
2222 nv_icmd(dev, 0x000008fb, 0x00000000);
2223 nv_icmd(dev, 0x000008fc, 0x00000000);
2224 nv_icmd(dev, 0x000008fd, 0x00000000);
2225 nv_icmd(dev, 0x000008fe, 0x00000000);
2226 nv_icmd(dev, 0x000008ff, 0x00000000);
2227 nv_icmd(dev, 0x0000094c, 0x000000ff);
2228 nv_icmd(dev, 0x0000094d, 0xffffffff);
2229 nv_icmd(dev, 0x0000094e, 0x00000002);
2230 nv_icmd(dev, 0x000002ec, 0x00000001);
2231 nv_icmd(dev, 0x00000303, 0x00000001);
2232 nv_icmd(dev, 0x000002e6, 0x00000001);
2233 nv_icmd(dev, 0x00000466, 0x00000052);
2234 nv_icmd(dev, 0x00000301, 0x3f800000);
2235 nv_icmd(dev, 0x00000304, 0x30201000);
2236 nv_icmd(dev, 0x00000305, 0x70605040);
2237 nv_icmd(dev, 0x00000306, 0xb8a89888);
2238 nv_icmd(dev, 0x00000307, 0xf8e8d8c8);
2239 nv_icmd(dev, 0x0000030a, 0x00ffff00);
2240 nv_icmd(dev, 0x0000030b, 0x0000001a);
2241 nv_icmd(dev, 0x0000030c, 0x00000001);
2242 nv_icmd(dev, 0x00000318, 0x00000001);
2243 nv_icmd(dev, 0x00000340, 0x00000000);
2244 nv_icmd(dev, 0x00000375, 0x00000001);
2245 nv_icmd(dev, 0x00000351, 0x00000100);
2246 nv_icmd(dev, 0x0000037d, 0x00000006);
2247 nv_icmd(dev, 0x000003a0, 0x00000002);
2248 nv_icmd(dev, 0x000003aa, 0x00000001);
2249 nv_icmd(dev, 0x000003a9, 0x00000001);
2250 nv_icmd(dev, 0x00000380, 0x00000001);
2251 nv_icmd(dev, 0x00000360, 0x00000040);
2252 nv_icmd(dev, 0x00000366, 0x00000000);
2253 nv_icmd(dev, 0x00000367, 0x00000000);
2254 nv_icmd(dev, 0x00000368, 0x00001fff);
2255 nv_icmd(dev, 0x00000370, 0x00000000);
2256 nv_icmd(dev, 0x00000371, 0x00000000);
2257 nv_icmd(dev, 0x00000372, 0x003fffff);
2258 nv_icmd(dev, 0x0000037a, 0x00000012);
2259 nv_icmd(dev, 0x000005e0, 0x00000022);
2260 nv_icmd(dev, 0x000005e1, 0x00000022);
2261 nv_icmd(dev, 0x000005e2, 0x00000022);
2262 nv_icmd(dev, 0x000005e3, 0x00000022);
2263 nv_icmd(dev, 0x000005e4, 0x00000022);
2264 nv_icmd(dev, 0x00000619, 0x00000003);
2265 nv_icmd(dev, 0x00000811, 0x00000003);
2266 nv_icmd(dev, 0x00000812, 0x00000004);
2267 nv_icmd(dev, 0x00000813, 0x00000006);
2268 nv_icmd(dev, 0x00000814, 0x00000008);
2269 nv_icmd(dev, 0x00000815, 0x0000000b);
2270 nv_icmd(dev, 0x00000800, 0x00000001);
2271 nv_icmd(dev, 0x00000801, 0x00000001);
2272 nv_icmd(dev, 0x00000802, 0x00000001);
2273 nv_icmd(dev, 0x00000803, 0x00000001);
2274 nv_icmd(dev, 0x00000804, 0x00000001);
2275 nv_icmd(dev, 0x00000805, 0x00000001);
2276 nv_icmd(dev, 0x00000632, 0x00000001);
2277 nv_icmd(dev, 0x00000633, 0x00000002);
2278 nv_icmd(dev, 0x00000634, 0x00000003);
2279 nv_icmd(dev, 0x00000635, 0x00000004);
2280 nv_icmd(dev, 0x00000654, 0x3f800000);
2281 nv_icmd(dev, 0x00000657, 0x3f800000);
2282 nv_icmd(dev, 0x00000655, 0x3f800000);
2283 nv_icmd(dev, 0x00000656, 0x3f800000);
2284 nv_icmd(dev, 0x000006cd, 0x3f800000);
2285 nv_icmd(dev, 0x000007f5, 0x3f800000);
2286 nv_icmd(dev, 0x000007dc, 0x39291909);
2287 nv_icmd(dev, 0x000007dd, 0x79695949);
2288 nv_icmd(dev, 0x000007de, 0xb9a99989);
2289 nv_icmd(dev, 0x000007df, 0xf9e9d9c9);
2290 nv_icmd(dev, 0x000007e8, 0x00003210);
2291 nv_icmd(dev, 0x000007e9, 0x00007654);
2292 nv_icmd(dev, 0x000007ea, 0x00000098);
2293 nv_icmd(dev, 0x000007ec, 0x39291909);
2294 nv_icmd(dev, 0x000007ed, 0x79695949);
2295 nv_icmd(dev, 0x000007ee, 0xb9a99989);
2296 nv_icmd(dev, 0x000007ef, 0xf9e9d9c9);
2297 nv_icmd(dev, 0x000007f0, 0x00003210);
2298 nv_icmd(dev, 0x000007f1, 0x00007654);
2299 nv_icmd(dev, 0x000007f2, 0x00000098);
2300 nv_icmd(dev, 0x000005a5, 0x00000001);
2301 nv_icmd(dev, 0x00000980, 0x00000000);
2302 nv_icmd(dev, 0x00000981, 0x00000000);
2303 nv_icmd(dev, 0x00000982, 0x00000000);
2304 nv_icmd(dev, 0x00000983, 0x00000000);
2305 nv_icmd(dev, 0x00000984, 0x00000000);
2306 nv_icmd(dev, 0x00000985, 0x00000000);
2307 nv_icmd(dev, 0x00000986, 0x00000000);
2308 nv_icmd(dev, 0x00000987, 0x00000000);
2309 nv_icmd(dev, 0x00000988, 0x00000000);
2310 nv_icmd(dev, 0x00000989, 0x00000000);
2311 nv_icmd(dev, 0x0000098a, 0x00000000);
2312 nv_icmd(dev, 0x0000098b, 0x00000000);
2313 nv_icmd(dev, 0x0000098c, 0x00000000);
2314 nv_icmd(dev, 0x0000098d, 0x00000000);
2315 nv_icmd(dev, 0x0000098e, 0x00000000);
2316 nv_icmd(dev, 0x0000098f, 0x00000000);
2317 nv_icmd(dev, 0x00000990, 0x00000000);
2318 nv_icmd(dev, 0x00000991, 0x00000000);
2319 nv_icmd(dev, 0x00000992, 0x00000000);
2320 nv_icmd(dev, 0x00000993, 0x00000000);
2321 nv_icmd(dev, 0x00000994, 0x00000000);
2322 nv_icmd(dev, 0x00000995, 0x00000000);
2323 nv_icmd(dev, 0x00000996, 0x00000000);
2324 nv_icmd(dev, 0x00000997, 0x00000000);
2325 nv_icmd(dev, 0x00000998, 0x00000000);
2326 nv_icmd(dev, 0x00000999, 0x00000000);
2327 nv_icmd(dev, 0x0000099a, 0x00000000);
2328 nv_icmd(dev, 0x0000099b, 0x00000000);
2329 nv_icmd(dev, 0x0000099c, 0x00000000);
2330 nv_icmd(dev, 0x0000099d, 0x00000000);
2331 nv_icmd(dev, 0x0000099e, 0x00000000);
2332 nv_icmd(dev, 0x0000099f, 0x00000000);
2333 nv_icmd(dev, 0x000009a0, 0x00000000);
2334 nv_icmd(dev, 0x000009a1, 0x00000000);
2335 nv_icmd(dev, 0x000009a2, 0x00000000);
2336 nv_icmd(dev, 0x000009a3, 0x00000000);
2337 nv_icmd(dev, 0x000009a4, 0x00000000);
2338 nv_icmd(dev, 0x000009a5, 0x00000000);
2339 nv_icmd(dev, 0x000009a6, 0x00000000);
2340 nv_icmd(dev, 0x000009a7, 0x00000000);
2341 nv_icmd(dev, 0x000009a8, 0x00000000);
2342 nv_icmd(dev, 0x000009a9, 0x00000000);
2343 nv_icmd(dev, 0x000009aa, 0x00000000);
2344 nv_icmd(dev, 0x000009ab, 0x00000000);
2345 nv_icmd(dev, 0x000009ac, 0x00000000);
2346 nv_icmd(dev, 0x000009ad, 0x00000000);
2347 nv_icmd(dev, 0x000009ae, 0x00000000);
2348 nv_icmd(dev, 0x000009af, 0x00000000);
2349 nv_icmd(dev, 0x000009b0, 0x00000000);
2350 nv_icmd(dev, 0x000009b1, 0x00000000);
2351 nv_icmd(dev, 0x000009b2, 0x00000000);
2352 nv_icmd(dev, 0x000009b3, 0x00000000);
2353 nv_icmd(dev, 0x000009b4, 0x00000000);
2354 nv_icmd(dev, 0x000009b5, 0x00000000);
2355 nv_icmd(dev, 0x000009b6, 0x00000000);
2356 nv_icmd(dev, 0x000009b7, 0x00000000);
2357 nv_icmd(dev, 0x000009b8, 0x00000000);
2358 nv_icmd(dev, 0x000009b9, 0x00000000);
2359 nv_icmd(dev, 0x000009ba, 0x00000000);
2360 nv_icmd(dev, 0x000009bb, 0x00000000);
2361 nv_icmd(dev, 0x000009bc, 0x00000000);
2362 nv_icmd(dev, 0x000009bd, 0x00000000);
2363 nv_icmd(dev, 0x000009be, 0x00000000);
2364 nv_icmd(dev, 0x000009bf, 0x00000000);
2365 nv_icmd(dev, 0x000009c0, 0x00000000);
2366 nv_icmd(dev, 0x000009c1, 0x00000000);
2367 nv_icmd(dev, 0x000009c2, 0x00000000);
2368 nv_icmd(dev, 0x000009c3, 0x00000000);
2369 nv_icmd(dev, 0x000009c4, 0x00000000);
2370 nv_icmd(dev, 0x000009c5, 0x00000000);
2371 nv_icmd(dev, 0x000009c6, 0x00000000);
2372 nv_icmd(dev, 0x000009c7, 0x00000000);
2373 nv_icmd(dev, 0x000009c8, 0x00000000);
2374 nv_icmd(dev, 0x000009c9, 0x00000000);
2375 nv_icmd(dev, 0x000009ca, 0x00000000);
2376 nv_icmd(dev, 0x000009cb, 0x00000000);
2377 nv_icmd(dev, 0x000009cc, 0x00000000);
2378 nv_icmd(dev, 0x000009cd, 0x00000000);
2379 nv_icmd(dev, 0x000009ce, 0x00000000);
2380 nv_icmd(dev, 0x000009cf, 0x00000000);
2381 nv_icmd(dev, 0x000009d0, 0x00000000);
2382 nv_icmd(dev, 0x000009d1, 0x00000000);
2383 nv_icmd(dev, 0x000009d2, 0x00000000);
2384 nv_icmd(dev, 0x000009d3, 0x00000000);
2385 nv_icmd(dev, 0x000009d4, 0x00000000);
2386 nv_icmd(dev, 0x000009d5, 0x00000000);
2387 nv_icmd(dev, 0x000009d6, 0x00000000);
2388 nv_icmd(dev, 0x000009d7, 0x00000000);
2389 nv_icmd(dev, 0x000009d8, 0x00000000);
2390 nv_icmd(dev, 0x000009d9, 0x00000000);
2391 nv_icmd(dev, 0x000009da, 0x00000000);
2392 nv_icmd(dev, 0x000009db, 0x00000000);
2393 nv_icmd(dev, 0x000009dc, 0x00000000);
2394 nv_icmd(dev, 0x000009dd, 0x00000000);
2395 nv_icmd(dev, 0x000009de, 0x00000000);
2396 nv_icmd(dev, 0x000009df, 0x00000000);
2397 nv_icmd(dev, 0x000009e0, 0x00000000);
2398 nv_icmd(dev, 0x000009e1, 0x00000000);
2399 nv_icmd(dev, 0x000009e2, 0x00000000);
2400 nv_icmd(dev, 0x000009e3, 0x00000000);
2401 nv_icmd(dev, 0x000009e4, 0x00000000);
2402 nv_icmd(dev, 0x000009e5, 0x00000000);
2403 nv_icmd(dev, 0x000009e6, 0x00000000);
2404 nv_icmd(dev, 0x000009e7, 0x00000000);
2405 nv_icmd(dev, 0x000009e8, 0x00000000);
2406 nv_icmd(dev, 0x000009e9, 0x00000000);
2407 nv_icmd(dev, 0x000009ea, 0x00000000);
2408 nv_icmd(dev, 0x000009eb, 0x00000000);
2409 nv_icmd(dev, 0x000009ec, 0x00000000);
2410 nv_icmd(dev, 0x000009ed, 0x00000000);
2411 nv_icmd(dev, 0x000009ee, 0x00000000);
2412 nv_icmd(dev, 0x000009ef, 0x00000000);
2413 nv_icmd(dev, 0x000009f0, 0x00000000);
2414 nv_icmd(dev, 0x000009f1, 0x00000000);
2415 nv_icmd(dev, 0x000009f2, 0x00000000);
2416 nv_icmd(dev, 0x000009f3, 0x00000000);
2417 nv_icmd(dev, 0x000009f4, 0x00000000);
2418 nv_icmd(dev, 0x000009f5, 0x00000000);
2419 nv_icmd(dev, 0x000009f6, 0x00000000);
2420 nv_icmd(dev, 0x000009f7, 0x00000000);
2421 nv_icmd(dev, 0x000009f8, 0x00000000);
2422 nv_icmd(dev, 0x000009f9, 0x00000000);
2423 nv_icmd(dev, 0x000009fa, 0x00000000);
2424 nv_icmd(dev, 0x000009fb, 0x00000000);
2425 nv_icmd(dev, 0x000009fc, 0x00000000);
2426 nv_icmd(dev, 0x000009fd, 0x00000000);
2427 nv_icmd(dev, 0x000009fe, 0x00000000);
2428 nv_icmd(dev, 0x000009ff, 0x00000000);
2429 nv_icmd(dev, 0x00000468, 0x00000004);
2430 nv_icmd(dev, 0x0000046c, 0x00000001);
2431 nv_icmd(dev, 0x00000470, 0x00000000);
2432 nv_icmd(dev, 0x00000471, 0x00000000);
2433 nv_icmd(dev, 0x00000472, 0x00000000);
2434 nv_icmd(dev, 0x00000473, 0x00000000);
2435 nv_icmd(dev, 0x00000474, 0x00000000);
2436 nv_icmd(dev, 0x00000475, 0x00000000);
2437 nv_icmd(dev, 0x00000476, 0x00000000);
2438 nv_icmd(dev, 0x00000477, 0x00000000);
2439 nv_icmd(dev, 0x00000478, 0x00000000);
2440 nv_icmd(dev, 0x00000479, 0x00000000);
2441 nv_icmd(dev, 0x0000047a, 0x00000000);
2442 nv_icmd(dev, 0x0000047b, 0x00000000);
2443 nv_icmd(dev, 0x0000047c, 0x00000000);
2444 nv_icmd(dev, 0x0000047d, 0x00000000);
2445 nv_icmd(dev, 0x0000047e, 0x00000000);
2446 nv_icmd(dev, 0x0000047f, 0x00000000);
2447 nv_icmd(dev, 0x00000480, 0x00000000);
2448 nv_icmd(dev, 0x00000481, 0x00000000);
2449 nv_icmd(dev, 0x00000482, 0x00000000);
2450 nv_icmd(dev, 0x00000483, 0x00000000);
2451 nv_icmd(dev, 0x00000484, 0x00000000);
2452 nv_icmd(dev, 0x00000485, 0x00000000);
2453 nv_icmd(dev, 0x00000486, 0x00000000);
2454 nv_icmd(dev, 0x00000487, 0x00000000);
2455 nv_icmd(dev, 0x00000488, 0x00000000);
2456 nv_icmd(dev, 0x00000489, 0x00000000);
2457 nv_icmd(dev, 0x0000048a, 0x00000000);
2458 nv_icmd(dev, 0x0000048b, 0x00000000);
2459 nv_icmd(dev, 0x0000048c, 0x00000000);
2460 nv_icmd(dev, 0x0000048d, 0x00000000);
2461 nv_icmd(dev, 0x0000048e, 0x00000000);
2462 nv_icmd(dev, 0x0000048f, 0x00000000);
2463 nv_icmd(dev, 0x00000490, 0x00000000);
2464 nv_icmd(dev, 0x00000491, 0x00000000);
2465 nv_icmd(dev, 0x00000492, 0x00000000);
2466 nv_icmd(dev, 0x00000493, 0x00000000);
2467 nv_icmd(dev, 0x00000494, 0x00000000);
2468 nv_icmd(dev, 0x00000495, 0x00000000);
2469 nv_icmd(dev, 0x00000496, 0x00000000);
2470 nv_icmd(dev, 0x00000497, 0x00000000);
2471 nv_icmd(dev, 0x00000498, 0x00000000);
2472 nv_icmd(dev, 0x00000499, 0x00000000);
2473 nv_icmd(dev, 0x0000049a, 0x00000000);
2474 nv_icmd(dev, 0x0000049b, 0x00000000);
2475 nv_icmd(dev, 0x0000049c, 0x00000000);
2476 nv_icmd(dev, 0x0000049d, 0x00000000);
2477 nv_icmd(dev, 0x0000049e, 0x00000000);
2478 nv_icmd(dev, 0x0000049f, 0x00000000);
2479 nv_icmd(dev, 0x000004a0, 0x00000000);
2480 nv_icmd(dev, 0x000004a1, 0x00000000);
2481 nv_icmd(dev, 0x000004a2, 0x00000000);
2482 nv_icmd(dev, 0x000004a3, 0x00000000);
2483 nv_icmd(dev, 0x000004a4, 0x00000000);
2484 nv_icmd(dev, 0x000004a5, 0x00000000);
2485 nv_icmd(dev, 0x000004a6, 0x00000000);
2486 nv_icmd(dev, 0x000004a7, 0x00000000);
2487 nv_icmd(dev, 0x000004a8, 0x00000000);
2488 nv_icmd(dev, 0x000004a9, 0x00000000);
2489 nv_icmd(dev, 0x000004aa, 0x00000000);
2490 nv_icmd(dev, 0x000004ab, 0x00000000);
2491 nv_icmd(dev, 0x000004ac, 0x00000000);
2492 nv_icmd(dev, 0x000004ad, 0x00000000);
2493 nv_icmd(dev, 0x000004ae, 0x00000000);
2494 nv_icmd(dev, 0x000004af, 0x00000000);
2495 nv_icmd(dev, 0x000004b0, 0x00000000);
2496 nv_icmd(dev, 0x000004b1, 0x00000000);
2497 nv_icmd(dev, 0x000004b2, 0x00000000);
2498 nv_icmd(dev, 0x000004b3, 0x00000000);
2499 nv_icmd(dev, 0x000004b4, 0x00000000);
2500 nv_icmd(dev, 0x000004b5, 0x00000000);
2501 nv_icmd(dev, 0x000004b6, 0x00000000);
2502 nv_icmd(dev, 0x000004b7, 0x00000000);
2503 nv_icmd(dev, 0x000004b8, 0x00000000);
2504 nv_icmd(dev, 0x000004b9, 0x00000000);
2505 nv_icmd(dev, 0x000004ba, 0x00000000);
2506 nv_icmd(dev, 0x000004bb, 0x00000000);
2507 nv_icmd(dev, 0x000004bc, 0x00000000);
2508 nv_icmd(dev, 0x000004bd, 0x00000000);
2509 nv_icmd(dev, 0x000004be, 0x00000000);
2510 nv_icmd(dev, 0x000004bf, 0x00000000);
2511 nv_icmd(dev, 0x000004c0, 0x00000000);
2512 nv_icmd(dev, 0x000004c1, 0x00000000);
2513 nv_icmd(dev, 0x000004c2, 0x00000000);
2514 nv_icmd(dev, 0x000004c3, 0x00000000);
2515 nv_icmd(dev, 0x000004c4, 0x00000000);
2516 nv_icmd(dev, 0x000004c5, 0x00000000);
2517 nv_icmd(dev, 0x000004c6, 0x00000000);
2518 nv_icmd(dev, 0x000004c7, 0x00000000);
2519 nv_icmd(dev, 0x000004c8, 0x00000000);
2520 nv_icmd(dev, 0x000004c9, 0x00000000);
2521 nv_icmd(dev, 0x000004ca, 0x00000000);
2522 nv_icmd(dev, 0x000004cb, 0x00000000);
2523 nv_icmd(dev, 0x000004cc, 0x00000000);
2524 nv_icmd(dev, 0x000004cd, 0x00000000);
2525 nv_icmd(dev, 0x000004ce, 0x00000000);
2526 nv_icmd(dev, 0x000004cf, 0x00000000);
2527 nv_icmd(dev, 0x00000510, 0x3f800000);
2528 nv_icmd(dev, 0x00000511, 0x3f800000);
2529 nv_icmd(dev, 0x00000512, 0x3f800000);
2530 nv_icmd(dev, 0x00000513, 0x3f800000);
2531 nv_icmd(dev, 0x00000514, 0x3f800000);
2532 nv_icmd(dev, 0x00000515, 0x3f800000);
2533 nv_icmd(dev, 0x00000516, 0x3f800000);
2534 nv_icmd(dev, 0x00000517, 0x3f800000);
2535 nv_icmd(dev, 0x00000518, 0x3f800000);
2536 nv_icmd(dev, 0x00000519, 0x3f800000);
2537 nv_icmd(dev, 0x0000051a, 0x3f800000);
2538 nv_icmd(dev, 0x0000051b, 0x3f800000);
2539 nv_icmd(dev, 0x0000051c, 0x3f800000);
2540 nv_icmd(dev, 0x0000051d, 0x3f800000);
2541 nv_icmd(dev, 0x0000051e, 0x3f800000);
2542 nv_icmd(dev, 0x0000051f, 0x3f800000);
2543 nv_icmd(dev, 0x00000520, 0x000002b6);
2544 nv_icmd(dev, 0x00000529, 0x00000001);
2545 nv_icmd(dev, 0x00000530, 0xffff0000);
2546 nv_icmd(dev, 0x00000531, 0xffff0000);
2547 nv_icmd(dev, 0x00000532, 0xffff0000);
2548 nv_icmd(dev, 0x00000533, 0xffff0000);
2549 nv_icmd(dev, 0x00000534, 0xffff0000);
2550 nv_icmd(dev, 0x00000535, 0xffff0000);
2551 nv_icmd(dev, 0x00000536, 0xffff0000);
2552 nv_icmd(dev, 0x00000537, 0xffff0000);
2553 nv_icmd(dev, 0x00000538, 0xffff0000);
2554 nv_icmd(dev, 0x00000539, 0xffff0000);
2555 nv_icmd(dev, 0x0000053a, 0xffff0000);
2556 nv_icmd(dev, 0x0000053b, 0xffff0000);
2557 nv_icmd(dev, 0x0000053c, 0xffff0000);
2558 nv_icmd(dev, 0x0000053d, 0xffff0000);
2559 nv_icmd(dev, 0x0000053e, 0xffff0000);
2560 nv_icmd(dev, 0x0000053f, 0xffff0000);
2561 nv_icmd(dev, 0x00000585, 0x0000003f);
2562 nv_icmd(dev, 0x00000576, 0x00000003);
2563 if (dev_priv->chipset == 0xc1)
2564 nv_icmd(dev, 0x0000057b, 0x00000059);
2565 nv_icmd(dev, 0x00000586, 0x00000040);
2566 nv_icmd(dev, 0x00000582, 0x00000080);
2567 nv_icmd(dev, 0x00000583, 0x00000080);
2568 nv_icmd(dev, 0x000005c2, 0x00000001);
2569 nv_icmd(dev, 0x00000638, 0x00000001);
2570 nv_icmd(dev, 0x00000639, 0x00000001);
2571 nv_icmd(dev, 0x0000063a, 0x00000002);
2572 nv_icmd(dev, 0x0000063b, 0x00000001);
2573 nv_icmd(dev, 0x0000063c, 0x00000001);
2574 nv_icmd(dev, 0x0000063d, 0x00000002);
2575 nv_icmd(dev, 0x0000063e, 0x00000001);
2576 nv_icmd(dev, 0x000008b8, 0x00000001);
2577 nv_icmd(dev, 0x000008b9, 0x00000001);
2578 nv_icmd(dev, 0x000008ba, 0x00000001);
2579 nv_icmd(dev, 0x000008bb, 0x00000001);
2580 nv_icmd(dev, 0x000008bc, 0x00000001);
2581 nv_icmd(dev, 0x000008bd, 0x00000001);
2582 nv_icmd(dev, 0x000008be, 0x00000001);
2583 nv_icmd(dev, 0x000008bf, 0x00000001);
2584 nv_icmd(dev, 0x00000900, 0x00000001);
2585 nv_icmd(dev, 0x00000901, 0x00000001);
2586 nv_icmd(dev, 0x00000902, 0x00000001);
2587 nv_icmd(dev, 0x00000903, 0x00000001);
2588 nv_icmd(dev, 0x00000904, 0x00000001);
2589 nv_icmd(dev, 0x00000905, 0x00000001);
2590 nv_icmd(dev, 0x00000906, 0x00000001);
2591 nv_icmd(dev, 0x00000907, 0x00000001);
2592 nv_icmd(dev, 0x00000908, 0x00000002);
2593 nv_icmd(dev, 0x00000909, 0x00000002);
2594 nv_icmd(dev, 0x0000090a, 0x00000002);
2595 nv_icmd(dev, 0x0000090b, 0x00000002);
2596 nv_icmd(dev, 0x0000090c, 0x00000002);
2597 nv_icmd(dev, 0x0000090d, 0x00000002);
2598 nv_icmd(dev, 0x0000090e, 0x00000002);
2599 nv_icmd(dev, 0x0000090f, 0x00000002);
2600 nv_icmd(dev, 0x00000910, 0x00000001);
2601 nv_icmd(dev, 0x00000911, 0x00000001);
2602 nv_icmd(dev, 0x00000912, 0x00000001);
2603 nv_icmd(dev, 0x00000913, 0x00000001);
2604 nv_icmd(dev, 0x00000914, 0x00000001);
2605 nv_icmd(dev, 0x00000915, 0x00000001);
2606 nv_icmd(dev, 0x00000916, 0x00000001);
2607 nv_icmd(dev, 0x00000917, 0x00000001);
2608 nv_icmd(dev, 0x00000918, 0x00000001);
2609 nv_icmd(dev, 0x00000919, 0x00000001);
2610 nv_icmd(dev, 0x0000091a, 0x00000001);
2611 nv_icmd(dev, 0x0000091b, 0x00000001);
2612 nv_icmd(dev, 0x0000091c, 0x00000001);
2613 nv_icmd(dev, 0x0000091d, 0x00000001);
2614 nv_icmd(dev, 0x0000091e, 0x00000001);
2615 nv_icmd(dev, 0x0000091f, 0x00000001);
2616 nv_icmd(dev, 0x00000920, 0x00000002);
2617 nv_icmd(dev, 0x00000921, 0x00000002);
2618 nv_icmd(dev, 0x00000922, 0x00000002);
2619 nv_icmd(dev, 0x00000923, 0x00000002);
2620 nv_icmd(dev, 0x00000924, 0x00000002);
2621 nv_icmd(dev, 0x00000925, 0x00000002);
2622 nv_icmd(dev, 0x00000926, 0x00000002);
2623 nv_icmd(dev, 0x00000927, 0x00000002);
2624 nv_icmd(dev, 0x00000928, 0x00000001);
2625 nv_icmd(dev, 0x00000929, 0x00000001);
2626 nv_icmd(dev, 0x0000092a, 0x00000001);
2627 nv_icmd(dev, 0x0000092b, 0x00000001);
2628 nv_icmd(dev, 0x0000092c, 0x00000001);
2629 nv_icmd(dev, 0x0000092d, 0x00000001);
2630 nv_icmd(dev, 0x0000092e, 0x00000001);
2631 nv_icmd(dev, 0x0000092f, 0x00000001);
2632 nv_icmd(dev, 0x00000648, 0x00000001);
2633 nv_icmd(dev, 0x00000649, 0x00000001);
2634 nv_icmd(dev, 0x0000064a, 0x00000001);
2635 nv_icmd(dev, 0x0000064b, 0x00000001);
2636 nv_icmd(dev, 0x0000064c, 0x00000001);
2637 nv_icmd(dev, 0x0000064d, 0x00000001);
2638 nv_icmd(dev, 0x0000064e, 0x00000001);
2639 nv_icmd(dev, 0x0000064f, 0x00000001);
2640 nv_icmd(dev, 0x00000650, 0x00000001);
2641 nv_icmd(dev, 0x00000658, 0x0000000f);
2642 nv_icmd(dev, 0x000007ff, 0x0000000a);
2643 nv_icmd(dev, 0x0000066a, 0x40000000);
2644 nv_icmd(dev, 0x0000066b, 0x10000000);
2645 nv_icmd(dev, 0x0000066c, 0xffff0000);
2646 nv_icmd(dev, 0x0000066d, 0xffff0000);
2647 nv_icmd(dev, 0x000007af, 0x00000008);
2648 nv_icmd(dev, 0x000007b0, 0x00000008);
2649 nv_icmd(dev, 0x000007f6, 0x00000001);
2650 nv_icmd(dev, 0x000006b2, 0x00000055);
2651 nv_icmd(dev, 0x000007ad, 0x00000003);
2652 nv_icmd(dev, 0x00000937, 0x00000001);
2653 nv_icmd(dev, 0x00000971, 0x00000008);
2654 nv_icmd(dev, 0x00000972, 0x00000040);
2655 nv_icmd(dev, 0x00000973, 0x0000012c);
2656 nv_icmd(dev, 0x0000097c, 0x00000040);
2657 nv_icmd(dev, 0x00000979, 0x00000003);
2658 nv_icmd(dev, 0x00000975, 0x00000020);
2659 nv_icmd(dev, 0x00000976, 0x00000001);
2660 nv_icmd(dev, 0x00000977, 0x00000020);
2661 nv_icmd(dev, 0x00000978, 0x00000001);
2662 nv_icmd(dev, 0x00000957, 0x00000003);
2663 nv_icmd(dev, 0x0000095e, 0x20164010);
2664 nv_icmd(dev, 0x0000095f, 0x00000020);
2665 nv_icmd(dev, 0x00000683, 0x00000006);
2666 nv_icmd(dev, 0x00000685, 0x003fffff);
2667 nv_icmd(dev, 0x00000687, 0x00000c48);
2668 nv_icmd(dev, 0x000006a0, 0x00000005);
2669 nv_icmd(dev, 0x00000840, 0x00300008);
2670 nv_icmd(dev, 0x00000841, 0x04000080);
2671 nv_icmd(dev, 0x00000842, 0x00300008);
2672 nv_icmd(dev, 0x00000843, 0x04000080);
2673 nv_icmd(dev, 0x00000818, 0x00000000);
2674 nv_icmd(dev, 0x00000819, 0x00000000);
2675 nv_icmd(dev, 0x0000081a, 0x00000000);
2676 nv_icmd(dev, 0x0000081b, 0x00000000);
2677 nv_icmd(dev, 0x0000081c, 0x00000000);
2678 nv_icmd(dev, 0x0000081d, 0x00000000);
2679 nv_icmd(dev, 0x0000081e, 0x00000000);
2680 nv_icmd(dev, 0x0000081f, 0x00000000);
2681 nv_icmd(dev, 0x00000848, 0x00000000);
2682 nv_icmd(dev, 0x00000849, 0x00000000);
2683 nv_icmd(dev, 0x0000084a, 0x00000000);
2684 nv_icmd(dev, 0x0000084b, 0x00000000);
2685 nv_icmd(dev, 0x0000084c, 0x00000000);
2686 nv_icmd(dev, 0x0000084d, 0x00000000);
2687 nv_icmd(dev, 0x0000084e, 0x00000000);
2688 nv_icmd(dev, 0x0000084f, 0x00000000);
2689 nv_icmd(dev, 0x00000850, 0x00000000);
2690 nv_icmd(dev, 0x00000851, 0x00000000);
2691 nv_icmd(dev, 0x00000852, 0x00000000);
2692 nv_icmd(dev, 0x00000853, 0x00000000);
2693 nv_icmd(dev, 0x00000854, 0x00000000);
2694 nv_icmd(dev, 0x00000855, 0x00000000);
2695 nv_icmd(dev, 0x00000856, 0x00000000);
2696 nv_icmd(dev, 0x00000857, 0x00000000);
2697 nv_icmd(dev, 0x00000738, 0x00000000);
2698 nv_icmd(dev, 0x000006aa, 0x00000001);
2699 nv_icmd(dev, 0x000006ab, 0x00000002);
2700 nv_icmd(dev, 0x000006ac, 0x00000080);
2701 nv_icmd(dev, 0x000006ad, 0x00000100);
2702 nv_icmd(dev, 0x000006ae, 0x00000100);
2703 nv_icmd(dev, 0x000006b1, 0x00000011);
2704 nv_icmd(dev, 0x000006bb, 0x000000cf);
2705 nv_icmd(dev, 0x000006ce, 0x2a712488);
2706 nv_icmd(dev, 0x00000739, 0x4085c000);
2707 nv_icmd(dev, 0x0000073a, 0x00000080);
2708 nv_icmd(dev, 0x00000786, 0x80000100);
2709 nv_icmd(dev, 0x0000073c, 0x00010100);
2710 nv_icmd(dev, 0x0000073d, 0x02800000);
2711 nv_icmd(dev, 0x00000787, 0x000000cf);
2712 nv_icmd(dev, 0x0000078c, 0x00000008);
2713 nv_icmd(dev, 0x00000792, 0x00000001);
2714 nv_icmd(dev, 0x00000794, 0x00000001);
2715 nv_icmd(dev, 0x00000795, 0x00000001);
2716 nv_icmd(dev, 0x00000796, 0x00000001);
2717 nv_icmd(dev, 0x00000797, 0x000000cf);
2718 nv_icmd(dev, 0x00000836, 0x00000001);
2719 nv_icmd(dev, 0x0000079a, 0x00000002);
2720 nv_icmd(dev, 0x00000833, 0x04444480);
2721 nv_icmd(dev, 0x000007a1, 0x00000001);
2722 nv_icmd(dev, 0x000007a3, 0x00000001);
2723 nv_icmd(dev, 0x000007a4, 0x00000001);
2724 nv_icmd(dev, 0x000007a5, 0x00000001);
2725 nv_icmd(dev, 0x00000831, 0x00000004);
2726 nv_icmd(dev, 0x0000080c, 0x00000002);
2727 nv_icmd(dev, 0x0000080d, 0x00000100);
2728 nv_icmd(dev, 0x0000080e, 0x00000100);
2729 nv_icmd(dev, 0x0000080f, 0x00000001);
2730 nv_icmd(dev, 0x00000823, 0x00000002);
2731 nv_icmd(dev, 0x00000824, 0x00000100);
2732 nv_icmd(dev, 0x00000825, 0x00000100);
2733 nv_icmd(dev, 0x00000826, 0x00000001);
2734 nv_icmd(dev, 0x0000095d, 0x00000001);
2735 nv_icmd(dev, 0x0000082b, 0x00000004);
2736 nv_icmd(dev, 0x00000942, 0x00010001);
2737 nv_icmd(dev, 0x00000943, 0x00000001);
2738 nv_icmd(dev, 0x00000944, 0x00000022);
2739 nv_icmd(dev, 0x000007c5, 0x00010001);
2740 nv_icmd(dev, 0x00000834, 0x00000001);
2741 nv_icmd(dev, 0x000007c7, 0x00000001);
2742 nv_icmd(dev, 0x0000c1b0, 0x0000000f);
2743 nv_icmd(dev, 0x0000c1b1, 0x0000000f);
2744 nv_icmd(dev, 0x0000c1b2, 0x0000000f);
2745 nv_icmd(dev, 0x0000c1b3, 0x0000000f);
2746 nv_icmd(dev, 0x0000c1b4, 0x0000000f);
2747 nv_icmd(dev, 0x0000c1b5, 0x0000000f);
2748 nv_icmd(dev, 0x0000c1b6, 0x0000000f);
2749 nv_icmd(dev, 0x0000c1b7, 0x0000000f);
2750 nv_icmd(dev, 0x0000c1b8, 0x0fac6881);
2751 nv_icmd(dev, 0x0000c1b9, 0x00fac688);
2752 nv_icmd(dev, 0x0001e100, 0x00000001);
2753 nv_icmd(dev, 0x00001000, 0x00000002);
2754 nv_icmd(dev, 0x000006aa, 0x00000001);
2755 nv_icmd(dev, 0x000006ad, 0x00000100);
2756 nv_icmd(dev, 0x000006ae, 0x00000100);
2757 nv_icmd(dev, 0x000006b1, 0x00000011);
2758 nv_icmd(dev, 0x0000078c, 0x00000008);
2759 nv_icmd(dev, 0x00000792, 0x00000001);
2760 nv_icmd(dev, 0x00000794, 0x00000001);
2761 nv_icmd(dev, 0x00000795, 0x00000001);
2762 nv_icmd(dev, 0x00000796, 0x00000001);
2763 nv_icmd(dev, 0x00000797, 0x000000cf);
2764 nv_icmd(dev, 0x0000079a, 0x00000002);
2765 nv_icmd(dev, 0x00000833, 0x04444480);
2766 nv_icmd(dev, 0x000007a1, 0x00000001);
2767 nv_icmd(dev, 0x000007a3, 0x00000001);
2768 nv_icmd(dev, 0x000007a4, 0x00000001);
2769 nv_icmd(dev, 0x000007a5, 0x00000001);
2770 nv_icmd(dev, 0x00000831, 0x00000004);
2771 nv_icmd(dev, 0x0001e100, 0x00000001);
2772 nv_icmd(dev, 0x00001000, 0x00000014);
2773 nv_icmd(dev, 0x00000351, 0x00000100);
2774 nv_icmd(dev, 0x00000957, 0x00000003);
2775 nv_icmd(dev, 0x0000095d, 0x00000001);
2776 nv_icmd(dev, 0x0000082b, 0x00000004);
2777 nv_icmd(dev, 0x00000942, 0x00010001);
2778 nv_icmd(dev, 0x00000943, 0x00000001);
2779 nv_icmd(dev, 0x000007c5, 0x00010001);
2780 nv_icmd(dev, 0x00000834, 0x00000001);
2781 nv_icmd(dev, 0x000007c7, 0x00000001);
2782 nv_icmd(dev, 0x0001e100, 0x00000001);
2783 nv_icmd(dev, 0x00001000, 0x00000001);
2784 nv_icmd(dev, 0x0000080c, 0x00000002);
2785 nv_icmd(dev, 0x0000080d, 0x00000100);
2786 nv_icmd(dev, 0x0000080e, 0x00000100);
2787 nv_icmd(dev, 0x0000080f, 0x00000001);
2788 nv_icmd(dev, 0x00000823, 0x00000002);
2789 nv_icmd(dev, 0x00000824, 0x00000100);
2790 nv_icmd(dev, 0x00000825, 0x00000100);
2791 nv_icmd(dev, 0x00000826, 0x00000001);
2792 nv_icmd(dev, 0x0001e100, 0x00000001);
2793 nv_wr32(dev, 0x400208, 0x00000000);
2794 nv_wr32(dev, 0x404154, 0x00000400);
2795
2796 nvc0_grctx_generate_9097(dev);
2797 if (fermi >= 0x9197)
2798 nvc0_grctx_generate_9197(dev);
2799 if (fermi >= 0x9297)
2800 nvc0_grctx_generate_9297(dev);
2801 nvc0_grctx_generate_902d(dev);
2802 nvc0_grctx_generate_9039(dev);
2803 nvc0_grctx_generate_90c0(dev);
2804
2805 nv_wr32(dev, 0x000260, r000260);
2806 return 0;
2807}
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
new file mode 100644
index 00000000000..0ec2add72a7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
@@ -0,0 +1,474 @@
1/* fuc microcode for nvc0 PGRAPH/GPC
2 *
3 * Copyright 2011 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the 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) OR AUTHOR(S) 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
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Ben Skeggs
24 */
25
26/* To build:
27 * m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h
28 */
29
30/* TODO
31 * - bracket certain functions with scratch writes, useful for debugging
32 * - watchdog timer around ctx operations
33 */
34
35.section nvc0_grgpc_data
36include(`nvc0_graph.fuc')
37gpc_id: .b32 0
38gpc_mmio_list_head: .b32 0
39gpc_mmio_list_tail: .b32 0
40
41tpc_count: .b32 0
42tpc_mask: .b32 0
43tpc_mmio_list_head: .b32 0
44tpc_mmio_list_tail: .b32 0
45
46cmd_queue: queue_init
47
48// chipset descriptions
49chipsets:
50.b8 0xc0 0 0 0
51.b16 nvc0_gpc_mmio_head
52.b16 nvc0_gpc_mmio_tail
53.b16 nvc0_tpc_mmio_head
54.b16 nvc0_tpc_mmio_tail
55.b8 0xc1 0 0 0
56.b16 nvc0_gpc_mmio_head
57.b16 nvc1_gpc_mmio_tail
58.b16 nvc0_tpc_mmio_head
59.b16 nvc1_tpc_mmio_tail
60.b8 0xc3 0 0 0
61.b16 nvc0_gpc_mmio_head
62.b16 nvc0_gpc_mmio_tail
63.b16 nvc0_tpc_mmio_head
64.b16 nvc3_tpc_mmio_tail
65.b8 0xc4 0 0 0
66.b16 nvc0_gpc_mmio_head
67.b16 nvc0_gpc_mmio_tail
68.b16 nvc0_tpc_mmio_head
69.b16 nvc3_tpc_mmio_tail
70.b8 0xc8 0 0 0
71.b16 nvc0_gpc_mmio_head
72.b16 nvc0_gpc_mmio_tail
73.b16 nvc0_tpc_mmio_head
74.b16 nvc0_tpc_mmio_tail
75.b8 0xce 0 0 0
76.b16 nvc0_gpc_mmio_head
77.b16 nvc0_gpc_mmio_tail
78.b16 nvc0_tpc_mmio_head
79.b16 nvc3_tpc_mmio_tail
80.b8 0 0 0 0
81
82// GPC mmio lists
83nvc0_gpc_mmio_head:
84mmctx_data(0x000380, 1)
85mmctx_data(0x000400, 6)
86mmctx_data(0x000450, 9)
87mmctx_data(0x000600, 1)
88mmctx_data(0x000684, 1)
89mmctx_data(0x000700, 5)
90mmctx_data(0x000800, 1)
91mmctx_data(0x000808, 3)
92mmctx_data(0x000828, 1)
93mmctx_data(0x000830, 1)
94mmctx_data(0x0008d8, 1)
95mmctx_data(0x0008e0, 1)
96mmctx_data(0x0008e8, 6)
97mmctx_data(0x00091c, 1)
98mmctx_data(0x000924, 3)
99mmctx_data(0x000b00, 1)
100mmctx_data(0x000b08, 6)
101mmctx_data(0x000bb8, 1)
102mmctx_data(0x000c08, 1)
103mmctx_data(0x000c10, 8)
104mmctx_data(0x000c80, 1)
105mmctx_data(0x000c8c, 1)
106mmctx_data(0x001000, 3)
107mmctx_data(0x001014, 1)
108nvc0_gpc_mmio_tail:
109mmctx_data(0x000c6c, 1);
110nvc1_gpc_mmio_tail:
111
112// TPC mmio lists
113nvc0_tpc_mmio_head:
114mmctx_data(0x000018, 1)
115mmctx_data(0x00003c, 1)
116mmctx_data(0x000048, 1)
117mmctx_data(0x000064, 1)
118mmctx_data(0x000088, 1)
119mmctx_data(0x000200, 6)
120mmctx_data(0x00021c, 2)
121mmctx_data(0x000300, 6)
122mmctx_data(0x0003d0, 1)
123mmctx_data(0x0003e0, 2)
124mmctx_data(0x000400, 3)
125mmctx_data(0x000420, 1)
126mmctx_data(0x0004b0, 1)
127mmctx_data(0x0004e8, 1)
128mmctx_data(0x0004f4, 1)
129mmctx_data(0x000520, 2)
130mmctx_data(0x000604, 4)
131mmctx_data(0x000644, 20)
132mmctx_data(0x000698, 1)
133mmctx_data(0x000750, 2)
134nvc0_tpc_mmio_tail:
135mmctx_data(0x000758, 1)
136mmctx_data(0x0002c4, 1)
137mmctx_data(0x0004bc, 1)
138mmctx_data(0x0006e0, 1)
139nvc3_tpc_mmio_tail:
140mmctx_data(0x000544, 1)
141nvc1_tpc_mmio_tail:
142
143
144.section nvc0_grgpc_code
145bra init
146define(`include_code')
147include(`nvc0_graph.fuc')
148
149// reports an exception to the host
150//
151// In: $r15 error code (see nvc0_graph.fuc)
152//
153error:
154 push $r14
155 mov $r14 -0x67ec // 0x9814
156 sethi $r14 0x400000
157 call nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code
158 add b32 $r14 0x41c
159 mov $r15 1
160 call nv_wr32 // HUB_CTXCTL_INTR_UP_SET
161 pop $r14
162 ret
163
164// GPC fuc initialisation, executed by triggering ucode start, will
165// fall through to main loop after completion.
166//
167// Input:
168// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
169// CC_SCRATCH[1]: context base
170//
171// Output:
172// CC_SCRATCH[0]:
173// 31:31: set to signal completion
174// CC_SCRATCH[1]:
175// 31:0: GPC context size
176//
177init:
178 clear b32 $r0
179 mov $sp $r0
180
181 // enable fifo access
182 mov $r1 0x1200
183 mov $r2 2
184 iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
185
186 // setup i0 handler, and route all interrupts to it
187 mov $r1 ih
188 mov $iv0 $r1
189 mov $r1 0x400
190 iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
191
192 // enable fifo interrupt
193 mov $r2 4
194 iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
195
196 // enable interrupts
197 bset $flags ie0
198
199 // figure out which GPC we are, and how many TPCs we have
200 mov $r1 0x608
201 shl b32 $r1 6
202 iord $r2 I[$r1 + 0x000] // UNITS
203 mov $r3 1
204 and $r2 0x1f
205 shl b32 $r3 $r2
206 sub b32 $r3 1
207 st b32 D[$r0 + tpc_count] $r2
208 st b32 D[$r0 + tpc_mask] $r3
209 add b32 $r1 0x400
210 iord $r2 I[$r1 + 0x000] // MYINDEX
211 st b32 D[$r0 + gpc_id] $r2
212
213 // find context data for this chipset
214 mov $r2 0x800
215 shl b32 $r2 6
216 iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0]
217 mov $r1 chipsets - 12
218 init_find_chipset:
219 add b32 $r1 12
220 ld b32 $r3 D[$r1 + 0x00]
221 cmpu b32 $r3 $r2
222 bra e init_context
223 cmpu b32 $r3 0
224 bra ne init_find_chipset
225 // unknown chipset
226 ret
227
228 // initialise context base, and size tracking
229 init_context:
230 mov $r2 0x800
231 shl b32 $r2 6
232 iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base
233 clear b32 $r3 // track GPC context size here
234
235 // set mmctx base addresses now so we don't have to do it later,
236 // they don't currently ever change
237 mov $r4 0x700
238 shl b32 $r4 6
239 shr b32 $r5 $r2 8
240 iowr I[$r4 + 0x000] $r5 // MMCTX_SAVE_SWBASE
241 iowr I[$r4 + 0x100] $r5 // MMCTX_LOAD_SWBASE
242
243 // calculate GPC mmio context size, store the chipset-specific
244 // mmio list pointers somewhere we can get at them later without
245 // re-parsing the chipset list
246 clear b32 $r14
247 clear b32 $r15
248 ld b16 $r14 D[$r1 + 4]
249 ld b16 $r15 D[$r1 + 6]
250 st b16 D[$r0 + gpc_mmio_list_head] $r14
251 st b16 D[$r0 + gpc_mmio_list_tail] $r15
252 call mmctx_size
253 add b32 $r2 $r15
254 add b32 $r3 $r15
255
256 // calculate per-TPC mmio context size, store the list pointers
257 ld b16 $r14 D[$r1 + 8]
258 ld b16 $r15 D[$r1 + 10]
259 st b16 D[$r0 + tpc_mmio_list_head] $r14
260 st b16 D[$r0 + tpc_mmio_list_tail] $r15
261 call mmctx_size
262 ld b32 $r14 D[$r0 + tpc_count]
263 mulu $r14 $r15
264 add b32 $r2 $r14
265 add b32 $r3 $r14
266
267 // round up base/size to 256 byte boundary (for strand SWBASE)
268 add b32 $r4 0x1300
269 shr b32 $r3 2
270 iowr I[$r4 + 0x000] $r3 // MMCTX_LOAD_COUNT, wtf for?!?
271 shr b32 $r2 8
272 shr b32 $r3 6
273 add b32 $r2 1
274 add b32 $r3 1
275 shl b32 $r2 8
276 shl b32 $r3 8
277
278 // calculate size of strand context data
279 mov b32 $r15 $r2
280 call strand_ctx_init
281 add b32 $r3 $r15
282
283 // save context size, and tell HUB we're done
284 mov $r1 0x800
285 shl b32 $r1 6
286 iowr I[$r1 + 0x100] $r3 // CC_SCRATCH[1] = context size
287 add b32 $r1 0x800
288 clear b32 $r2
289 bset $r2 31
290 iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000
291
292// Main program loop, very simple, sleeps until woken up by the interrupt
293// handler, pulls a command from the queue and executes its handler
294//
295main:
296 bset $flags $p0
297 sleep $p0
298 mov $r13 cmd_queue
299 call queue_get
300 bra $p1 main
301
302 // 0x0000-0x0003 are all context transfers
303 cmpu b32 $r14 0x04
304 bra nc main_not_ctx_xfer
305 // fetch $flags and mask off $p1/$p2
306 mov $r1 $flags
307 mov $r2 0x0006
308 not b32 $r2
309 and $r1 $r2
310 // set $p1/$p2 according to transfer type
311 shl b32 $r14 1
312 or $r1 $r14
313 mov $flags $r1
314 // transfer context data
315 call ctx_xfer
316 bra main
317
318 main_not_ctx_xfer:
319 shl b32 $r15 $r14 16
320 or $r15 E_BAD_COMMAND
321 call error
322 bra main
323
324// interrupt handler
325ih:
326 push $r8
327 mov $r8 $flags
328 push $r8
329 push $r9
330 push $r10
331 push $r11
332 push $r13
333 push $r14
334 push $r15
335
336 // incoming fifo command?
337 iord $r10 I[$r0 + 0x200] // INTR
338 and $r11 $r10 0x00000004
339 bra e ih_no_fifo
340 // queue incoming fifo command for later processing
341 mov $r11 0x1900
342 mov $r13 cmd_queue
343 iord $r14 I[$r11 + 0x100] // FIFO_CMD
344 iord $r15 I[$r11 + 0x000] // FIFO_DATA
345 call queue_put
346 add b32 $r11 0x400
347 mov $r14 1
348 iowr I[$r11 + 0x000] $r14 // FIFO_ACK
349
350 // ack, and wake up main()
351 ih_no_fifo:
352 iowr I[$r0 + 0x100] $r10 // INTR_ACK
353
354 pop $r15
355 pop $r14
356 pop $r13
357 pop $r11
358 pop $r10
359 pop $r9
360 pop $r8
361 mov $flags $r8
362 pop $r8
363 bclr $flags $p0
364 iret
365
366// Set this GPC's bit in HUB_BAR, used to signal completion of various
367// activities to the HUB fuc
368//
369hub_barrier_done:
370 mov $r15 1
371 ld b32 $r14 D[$r0 + gpc_id]
372 shl b32 $r15 $r14
373 mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET
374 sethi $r14 0x400000
375 call nv_wr32
376 ret
377
378// Disables various things, waits a bit, and re-enables them..
379//
380// Not sure how exactly this helps, perhaps "ENABLE" is not such a
381// good description for the bits we turn off? Anyways, without this,
382// funny things happen.
383//
384ctx_redswitch:
385 mov $r14 0x614
386 shl b32 $r14 6
387 mov $r15 0x020
388 iowr I[$r14] $r15 // GPC_RED_SWITCH = POWER
389 mov $r15 8
390 ctx_redswitch_delay:
391 sub b32 $r15 1
392 bra ne ctx_redswitch_delay
393 mov $r15 0xa20
394 iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER
395 ret
396
397// Transfer GPC context data between GPU and storage area
398//
399// In: $r15 context base address
400// $p1 clear on save, set on load
401// $p2 set if opposite direction done/will be done, so:
402// on save it means: "a load will follow this save"
403// on load it means: "a save preceeded this load"
404//
405ctx_xfer:
406 // set context base address
407 mov $r1 0xa04
408 shl b32 $r1 6
409 iowr I[$r1 + 0x000] $r15// MEM_BASE
410 bra not $p1 ctx_xfer_not_load
411 call ctx_redswitch
412 ctx_xfer_not_load:
413
414 // strands
415 mov $r1 0x4afc
416 sethi $r1 0x20000
417 mov $r2 0xc
418 iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c
419 call strand_wait
420 mov $r2 0x47fc
421 sethi $r2 0x20000
422 iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00
423 xbit $r2 $flags $p1
424 add b32 $r2 3
425 iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
426
427 // mmio context
428 xbit $r10 $flags $p1 // direction
429 or $r10 2 // first
430 mov $r11 0x0000
431 sethi $r11 0x500000
432 ld b32 $r12 D[$r0 + gpc_id]
433 shl b32 $r12 15
434 add b32 $r11 $r12 // base = NV_PGRAPH_GPCn
435 ld b32 $r12 D[$r0 + gpc_mmio_list_head]
436 ld b32 $r13 D[$r0 + gpc_mmio_list_tail]
437 mov $r14 0 // not multi
438 call mmctx_xfer
439
440 // per-TPC mmio context
441 xbit $r10 $flags $p1 // direction
442 or $r10 4 // last
443 mov $r11 0x4000
444 sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0
445 ld b32 $r12 D[$r0 + gpc_id]
446 shl b32 $r12 15
447 add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0
448 ld b32 $r12 D[$r0 + tpc_mmio_list_head]
449 ld b32 $r13 D[$r0 + tpc_mmio_list_tail]
450 ld b32 $r15 D[$r0 + tpc_mask]
451 mov $r14 0x800 // stride = 0x800
452 call mmctx_xfer
453
454 // wait for strands to finish
455 call strand_wait
456
457 // if load, or a save without a load following, do some
458 // unknown stuff that's done after finishing a block of
459 // strand commands
460 bra $p1 ctx_xfer_post
461 bra not $p2 ctx_xfer_done
462 ctx_xfer_post:
463 mov $r1 0x4afc
464 sethi $r1 0x20000
465 mov $r2 0xd
466 iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d
467 call strand_wait
468
469 // mark completion in HUB's barrier
470 ctx_xfer_done:
471 call hub_barrier_done
472 ret
473
474.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
new file mode 100644
index 00000000000..1896c898f5b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
@@ -0,0 +1,483 @@
1uint32_t nvc0_grgpc_data[] = {
2 0x00000000,
3 0x00000000,
4 0x00000000,
5 0x00000000,
6 0x00000000,
7 0x00000000,
8 0x00000000,
9 0x00000000,
10 0x00000000,
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x000000c0,
28 0x011000b0,
29 0x01640114,
30 0x000000c1,
31 0x011400b0,
32 0x01780114,
33 0x000000c3,
34 0x011000b0,
35 0x01740114,
36 0x000000c4,
37 0x011000b0,
38 0x01740114,
39 0x000000c8,
40 0x011000b0,
41 0x01640114,
42 0x000000ce,
43 0x011000b0,
44 0x01740114,
45 0x00000000,
46 0x00000380,
47 0x14000400,
48 0x20000450,
49 0x00000600,
50 0x00000684,
51 0x10000700,
52 0x00000800,
53 0x08000808,
54 0x00000828,
55 0x00000830,
56 0x000008d8,
57 0x000008e0,
58 0x140008e8,
59 0x0000091c,
60 0x08000924,
61 0x00000b00,
62 0x14000b08,
63 0x00000bb8,
64 0x00000c08,
65 0x1c000c10,
66 0x00000c80,
67 0x00000c8c,
68 0x08001000,
69 0x00001014,
70 0x00000c6c,
71 0x00000018,
72 0x0000003c,
73 0x00000048,
74 0x00000064,
75 0x00000088,
76 0x14000200,
77 0x0400021c,
78 0x14000300,
79 0x000003d0,
80 0x040003e0,
81 0x08000400,
82 0x00000420,
83 0x000004b0,
84 0x000004e8,
85 0x000004f4,
86 0x04000520,
87 0x0c000604,
88 0x4c000644,
89 0x00000698,
90 0x04000750,
91 0x00000758,
92 0x000002c4,
93 0x000004bc,
94 0x000006e0,
95 0x00000544,
96};
97
98uint32_t nvc0_grgpc_code[] = {
99 0x03060ef5,
100 0x9800d898,
101 0x86f001d9,
102 0x0489b808,
103 0xf00c1bf4,
104 0x21f502f7,
105 0x00f802ec,
106 0xb60798c4,
107 0x8dbb0384,
108 0x0880b600,
109 0x80008e80,
110 0x90b6018f,
111 0x0f94f001,
112 0xf801d980,
113 0x0131f400,
114 0x9800d898,
115 0x89b801d9,
116 0x210bf404,
117 0xb60789c4,
118 0x9dbb0394,
119 0x0890b600,
120 0x98009e98,
121 0x80b6019f,
122 0x0f84f001,
123 0xf400d880,
124 0x00f80132,
125 0x0728b7f1,
126 0xb906b4b6,
127 0xc9f002ec,
128 0x00bcd01f,
129 0xc800bccf,
130 0x1bf41fcc,
131 0x06a7f0fa,
132 0x010321f5,
133 0xf840bfcf,
134 0x28b7f100,
135 0x06b4b607,
136 0xb980bfd0,
137 0xc9f002ec,
138 0x1ec9f01f,
139 0xcf00bcd0,
140 0xccc800bc,
141 0xfa1bf41f,
142 0x87f100f8,
143 0x84b60430,
144 0x1ff9f006,
145 0xf8008fd0,
146 0x3087f100,
147 0x0684b604,
148 0xf80080d0,
149 0x3c87f100,
150 0x0684b608,
151 0x99f094bd,
152 0x0089d000,
153 0x081887f1,
154 0xd00684b6,
155 0x87f1008a,
156 0x84b60400,
157 0x0088cf06,
158 0xf4888aff,
159 0x87f1f31b,
160 0x84b6085c,
161 0xf094bd06,
162 0x89d00099,
163 0xf100f800,
164 0xb6083c87,
165 0x94bd0684,
166 0xd00099f0,
167 0x87f10089,
168 0x84b60818,
169 0x008ad006,
170 0x040087f1,
171 0xcf0684b6,
172 0x8aff0088,
173 0xf30bf488,
174 0x085c87f1,
175 0xbd0684b6,
176 0x0099f094,
177 0xf80089d0,
178 0x9894bd00,
179 0x85b600e8,
180 0x0180b61a,
181 0xbb0284b6,
182 0xe0b60098,
183 0x04efb804,
184 0xb9eb1bf4,
185 0x00f8029f,
186 0x083c87f1,
187 0xbd0684b6,
188 0x0199f094,
189 0xf10089d0,
190 0xb6071087,
191 0x94bd0684,
192 0xf405bbfd,
193 0x8bd0090b,
194 0x0099f000,
195 0xf405eefd,
196 0x8ed00c0b,
197 0xc08fd080,
198 0xb70199f0,
199 0xc8010080,
200 0xb4b600ab,
201 0x0cb9f010,
202 0xb601aec8,
203 0xbefd11e4,
204 0x008bd005,
205 0xf0008ecf,
206 0x0bf41fe4,
207 0x00ce98fa,
208 0xd005e9fd,
209 0xc0b6c08e,
210 0x04cdb804,
211 0xc8e81bf4,
212 0x1bf402ab,
213 0x008bcf18,
214 0xb01fb4f0,
215 0x1bf410b4,
216 0x02a7f0f7,
217 0xf4c921f4,
218 0xabc81b0e,
219 0x10b4b600,
220 0xf00cb9f0,
221 0x8bd012b9,
222 0x008bcf00,
223 0xf412bbc8,
224 0x87f1fa1b,
225 0x84b6085c,
226 0xf094bd06,
227 0x89d00199,
228 0xf900f800,
229 0x02a7f0a0,
230 0xfcc921f4,
231 0xf100f8a0,
232 0xf04afc87,
233 0x97f00283,
234 0x0089d00c,
235 0x020721f5,
236 0x87f100f8,
237 0x83f04afc,
238 0x0d97f002,
239 0xf50089d0,
240 0xf8020721,
241 0xfca7f100,
242 0x02a3f04f,
243 0x0500aba2,
244 0xd00fc7f0,
245 0xc7f000ac,
246 0x00bcd00b,
247 0x020721f5,
248 0xf000aed0,
249 0xbcd00ac7,
250 0x0721f500,
251 0xf100f802,
252 0xb6083c87,
253 0x94bd0684,
254 0xd00399f0,
255 0x21f50089,
256 0xe7f00213,
257 0x3921f503,
258 0xfca7f102,
259 0x02a3f046,
260 0x0400aba0,
261 0xf040a0d0,
262 0xbcd001c7,
263 0x0721f500,
264 0x010c9202,
265 0xf000acd0,
266 0xbcd002c7,
267 0x0721f500,
268 0x2621f502,
269 0x8087f102,
270 0x0684b608,
271 0xb70089cf,
272 0x95220080,
273 0x8ed008fe,
274 0x408ed000,
275 0xb6808acf,
276 0xa0b606a5,
277 0x00eabb01,
278 0xb60480b6,
279 0x1bf40192,
280 0x08e4b6e8,
281 0xf1f2efbc,
282 0xb6085c87,
283 0x94bd0684,
284 0xd00399f0,
285 0x00f80089,
286 0xe7f1e0f9,
287 0xe3f09814,
288 0x8d21f440,
289 0x041ce0b7,
290 0xf401f7f0,
291 0xe0fc8d21,
292 0x04bd00f8,
293 0xf10004fe,
294 0xf0120017,
295 0x12d00227,
296 0x3e17f100,
297 0x0010fe04,
298 0x040017f1,
299 0xf0c010d0,
300 0x12d00427,
301 0x1031f400,
302 0x060817f1,
303 0xcf0614b6,
304 0x37f00012,
305 0x1f24f001,
306 0xb60432bb,
307 0x02800132,
308 0x04038003,
309 0x040010b7,
310 0x800012cf,
311 0x27f10002,
312 0x24b60800,
313 0x0022cf06,
314 0xb65817f0,
315 0x13980c10,
316 0x0432b800,
317 0xb00b0bf4,
318 0x1bf40034,
319 0xf100f8f1,
320 0xb6080027,
321 0x22cf0624,
322 0xf134bd40,
323 0xb6070047,
324 0x25950644,
325 0x0045d008,
326 0xbd4045d0,
327 0x58f4bde4,
328 0x1f58021e,
329 0x020e4003,
330 0xf5040f40,
331 0xbb013d21,
332 0x3fbb002f,
333 0x041e5800,
334 0x40051f58,
335 0x0f400a0e,
336 0x3d21f50c,
337 0x030e9801,
338 0xbb00effd,
339 0x3ebb002e,
340 0x0040b700,
341 0x0235b613,
342 0xb60043d0,
343 0x35b60825,
344 0x0120b606,
345 0xb60130b6,
346 0x34b60824,
347 0x022fb908,
348 0x026321f5,
349 0xf1003fbb,
350 0xb6080017,
351 0x13d00614,
352 0x0010b740,
353 0xf024bd08,
354 0x12d01f29,
355 0x0031f400,
356 0xf00028f4,
357 0x21f41cd7,
358 0xf401f439,
359 0xf404e4b0,
360 0x81fe1e18,
361 0x0627f001,
362 0x12fd20bd,
363 0x01e4b604,
364 0xfe051efd,
365 0x21f50018,
366 0x0ef404c3,
367 0x10ef94d3,
368 0xf501f5f0,
369 0xf402ec21,
370 0x80f9c60e,
371 0xf90188fe,
372 0xf990f980,
373 0xf9b0f9a0,
374 0xf9e0f9d0,
375 0x800acff0,
376 0xf404abc4,
377 0xb7f11d0b,
378 0xd7f01900,
379 0x40becf1c,
380 0xf400bfcf,
381 0xb0b70421,
382 0xe7f00400,
383 0x00bed001,
384 0xfc400ad0,
385 0xfce0fcf0,
386 0xfcb0fcd0,
387 0xfc90fca0,
388 0x0088fe80,
389 0x32f480fc,
390 0xf001f800,
391 0x0e9801f7,
392 0x04febb00,
393 0x9418e7f1,
394 0xf440e3f0,
395 0x00f88d21,
396 0x0614e7f1,
397 0xf006e4b6,
398 0xefd020f7,
399 0x08f7f000,
400 0xf401f2b6,
401 0xf7f1fd1b,
402 0xefd00a20,
403 0xf100f800,
404 0xb60a0417,
405 0x1fd00614,
406 0x0711f400,
407 0x04a421f5,
408 0x4afc17f1,
409 0xf00213f0,
410 0x12d00c27,
411 0x0721f500,
412 0xfc27f102,
413 0x0223f047,
414 0xf00020d0,
415 0x20b6012c,
416 0x0012d003,
417 0xf001acf0,
418 0xb7f002a5,
419 0x50b3f000,
420 0xb6000c98,
421 0xbcbb0fc4,
422 0x010c9800,
423 0xf0020d98,
424 0x21f500e7,
425 0xacf0015c,
426 0x04a5f001,
427 0x4000b7f1,
428 0x9850b3f0,
429 0xc4b6000c,
430 0x00bcbb0f,
431 0x98050c98,
432 0x0f98060d,
433 0x00e7f104,
434 0x5c21f508,
435 0x0721f501,
436 0x0601f402,
437 0xf11412f4,
438 0xf04afc17,
439 0x27f00213,
440 0x0012d00d,
441 0x020721f5,
442 0x048f21f5,
443 0x000000f8,
444 0x00000000,
445 0x00000000,
446 0x00000000,
447 0x00000000,
448 0x00000000,
449 0x00000000,
450 0x00000000,
451 0x00000000,
452 0x00000000,
453 0x00000000,
454 0x00000000,
455 0x00000000,
456 0x00000000,
457 0x00000000,
458 0x00000000,
459 0x00000000,
460 0x00000000,
461 0x00000000,
462 0x00000000,
463 0x00000000,
464 0x00000000,
465 0x00000000,
466 0x00000000,
467 0x00000000,
468 0x00000000,
469 0x00000000,
470 0x00000000,
471 0x00000000,
472 0x00000000,
473 0x00000000,
474 0x00000000,
475 0x00000000,
476 0x00000000,
477 0x00000000,
478 0x00000000,
479 0x00000000,
480 0x00000000,
481 0x00000000,
482 0x00000000,
483};
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
new file mode 100644
index 00000000000..a1a599124cf
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
@@ -0,0 +1,808 @@
1/* fuc microcode for nvc0 PGRAPH/HUB
2 *
3 * Copyright 2011 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the 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) OR AUTHOR(S) 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
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Ben Skeggs
24 */
25
26/* To build:
27 * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h
28 */
29
30.section nvc0_grhub_data
31include(`nvc0_graph.fuc')
32gpc_count: .b32 0
33rop_count: .b32 0
34cmd_queue: queue_init
35hub_mmio_list_head: .b32 0
36hub_mmio_list_tail: .b32 0
37
38ctx_current: .b32 0
39
40chipsets:
41.b8 0xc0 0 0 0
42.b16 nvc0_hub_mmio_head
43.b16 nvc0_hub_mmio_tail
44.b8 0xc1 0 0 0
45.b16 nvc0_hub_mmio_head
46.b16 nvc1_hub_mmio_tail
47.b8 0xc3 0 0 0
48.b16 nvc0_hub_mmio_head
49.b16 nvc0_hub_mmio_tail
50.b8 0xc4 0 0 0
51.b16 nvc0_hub_mmio_head
52.b16 nvc0_hub_mmio_tail
53.b8 0xc8 0 0 0
54.b16 nvc0_hub_mmio_head
55.b16 nvc0_hub_mmio_tail
56.b8 0xce 0 0 0
57.b16 nvc0_hub_mmio_head
58.b16 nvc0_hub_mmio_tail
59.b8 0 0 0 0
60
61nvc0_hub_mmio_head:
62mmctx_data(0x17e91c, 2)
63mmctx_data(0x400204, 2)
64mmctx_data(0x404004, 11)
65mmctx_data(0x404044, 1)
66mmctx_data(0x404094, 14)
67mmctx_data(0x4040d0, 7)
68mmctx_data(0x4040f8, 1)
69mmctx_data(0x404130, 3)
70mmctx_data(0x404150, 3)
71mmctx_data(0x404164, 2)
72mmctx_data(0x404174, 3)
73mmctx_data(0x404200, 8)
74mmctx_data(0x404404, 14)
75mmctx_data(0x404460, 4)
76mmctx_data(0x404480, 1)
77mmctx_data(0x404498, 1)
78mmctx_data(0x404604, 4)
79mmctx_data(0x404618, 32)
80mmctx_data(0x404698, 21)
81mmctx_data(0x4046f0, 2)
82mmctx_data(0x404700, 22)
83mmctx_data(0x405800, 1)
84mmctx_data(0x405830, 3)
85mmctx_data(0x405854, 1)
86mmctx_data(0x405870, 4)
87mmctx_data(0x405a00, 2)
88mmctx_data(0x405a18, 1)
89mmctx_data(0x406020, 1)
90mmctx_data(0x406028, 4)
91mmctx_data(0x4064a8, 2)
92mmctx_data(0x4064b4, 2)
93mmctx_data(0x407804, 1)
94mmctx_data(0x40780c, 6)
95mmctx_data(0x4078bc, 1)
96mmctx_data(0x408000, 7)
97mmctx_data(0x408064, 1)
98mmctx_data(0x408800, 3)
99mmctx_data(0x408900, 4)
100mmctx_data(0x408980, 1)
101nvc0_hub_mmio_tail:
102mmctx_data(0x4064c0, 2)
103nvc1_hub_mmio_tail:
104
105.align 256
106chan_data:
107chan_mmio_count: .b32 0
108chan_mmio_address: .b32 0
109
110.align 256
111xfer_data: .b32 0
112
113.section nvc0_grhub_code
114bra init
115define(`include_code')
116include(`nvc0_graph.fuc')
117
118// reports an exception to the host
119//
120// In: $r15 error code (see nvc0_graph.fuc)
121//
122error:
123 push $r14
124 mov $r14 0x814
125 shl b32 $r14 6
126 iowr I[$r14 + 0x000] $r15 // CC_SCRATCH[5] = error code
127 mov $r14 0xc1c
128 shl b32 $r14 6
129 mov $r15 1
130 iowr I[$r14 + 0x000] $r15 // INTR_UP_SET
131 pop $r14
132 ret
133
134// HUB fuc initialisation, executed by triggering ucode start, will
135// fall through to main loop after completion.
136//
137// Input:
138// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
139//
140// Output:
141// CC_SCRATCH[0]:
142// 31:31: set to signal completion
143// CC_SCRATCH[1]:
144// 31:0: total PGRAPH context size
145//
146init:
147 clear b32 $r0
148 mov $sp $r0
149 mov $xdbase $r0
150
151 // enable fifo access
152 mov $r1 0x1200
153 mov $r2 2
154 iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
155
156 // setup i0 handler, and route all interrupts to it
157 mov $r1 ih
158 mov $iv0 $r1
159 mov $r1 0x400
160 iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
161
162 // route HUB_CHANNEL_SWITCH to fuc interrupt 8
163 mov $r3 0x404
164 shl b32 $r3 6
165 mov $r2 0x2003 // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
166 iowr I[$r3 + 0x000] $r2
167
168 // not sure what these are, route them because NVIDIA does, and
169 // the IRQ handler will signal the host if we ever get one.. we
170 // may find out if/why we need to handle these if so..
171 //
172 mov $r2 0x2004
173 iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
174 mov $r2 0x200b
175 iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
176 mov $r2 0x200c
177 iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
178
179 // enable all INTR_UP interrupts
180 mov $r2 0xc24
181 shl b32 $r2 6
182 not b32 $r3 $r0
183 iowr I[$r2] $r3
184
185 // enable fifo, ctxsw, 9, 10, 15 interrupts
186 mov $r2 -0x78fc // 0x8704
187 sethi $r2 0
188 iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
189
190 // fifo level triggered, rest edge
191 sub b32 $r1 0x100
192 mov $r2 4
193 iowr I[$r1] $r2
194
195 // enable interrupts
196 bset $flags ie0
197
198 // fetch enabled GPC/ROP counts
199 mov $r14 -0x69fc // 0x409604
200 sethi $r14 0x400000
201 call nv_rd32
202 extr $r1 $r15 16:20
203 st b32 D[$r0 + rop_count] $r1
204 and $r15 0x1f
205 st b32 D[$r0 + gpc_count] $r15
206
207 // set BAR_REQMASK to GPC mask
208 mov $r1 1
209 shl b32 $r1 $r15
210 sub b32 $r1 1
211 mov $r2 0x40c
212 shl b32 $r2 6
213 iowr I[$r2 + 0x000] $r1
214 iowr I[$r2 + 0x100] $r1
215
216 // find context data for this chipset
217 mov $r2 0x800
218 shl b32 $r2 6
219 iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0]
220 mov $r15 chipsets - 8
221 init_find_chipset:
222 add b32 $r15 8
223 ld b32 $r3 D[$r15 + 0x00]
224 cmpu b32 $r3 $r2
225 bra e init_context
226 cmpu b32 $r3 0
227 bra ne init_find_chipset
228 // unknown chipset
229 ret
230
231 // context size calculation, reserve first 256 bytes for use by fuc
232 init_context:
233 mov $r1 256
234
235 // calculate size of mmio context data
236 ld b16 $r14 D[$r15 + 4]
237 ld b16 $r15 D[$r15 + 6]
238 sethi $r14 0
239 st b32 D[$r0 + hub_mmio_list_head] $r14
240 st b32 D[$r0 + hub_mmio_list_tail] $r15
241 call mmctx_size
242
243 // set mmctx base addresses now so we don't have to do it later,
244 // they don't (currently) ever change
245 mov $r3 0x700
246 shl b32 $r3 6
247 shr b32 $r4 $r1 8
248 iowr I[$r3 + 0x000] $r4 // MMCTX_SAVE_SWBASE
249 iowr I[$r3 + 0x100] $r4 // MMCTX_LOAD_SWBASE
250 add b32 $r3 0x1300
251 add b32 $r1 $r15
252 shr b32 $r15 2
253 iowr I[$r3 + 0x000] $r15 // MMCTX_LOAD_COUNT, wtf for?!?
254
255 // strands, base offset needs to be aligned to 256 bytes
256 shr b32 $r1 8
257 add b32 $r1 1
258 shl b32 $r1 8
259 mov b32 $r15 $r1
260 call strand_ctx_init
261 add b32 $r1 $r15
262
263 // initialise each GPC in sequence by passing in the offset of its
264 // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which
265 // has previously been uploaded by the host) running.
266 //
267 // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31
268 // when it has completed, and return the size of its context data
269 // in GPCn_CC_SCRATCH[1]
270 //
271 ld b32 $r3 D[$r0 + gpc_count]
272 mov $r4 0x2000
273 sethi $r4 0x500000
274 init_gpc:
275 // setup, and start GPC ucode running
276 add b32 $r14 $r4 0x804
277 mov b32 $r15 $r1
278 call nv_wr32 // CC_SCRATCH[1] = ctx offset
279 add b32 $r14 $r4 0x800
280 mov b32 $r15 $r2
281 call nv_wr32 // CC_SCRATCH[0] = chipset
282 add b32 $r14 $r4 0x10c
283 clear b32 $r15
284 call nv_wr32
285 add b32 $r14 $r4 0x104
286 call nv_wr32 // ENTRY
287 add b32 $r14 $r4 0x100
288 mov $r15 2 // CTRL_START_TRIGGER
289 call nv_wr32 // CTRL
290
291 // wait for it to complete, and adjust context size
292 add b32 $r14 $r4 0x800
293 init_gpc_wait:
294 call nv_rd32
295 xbit $r15 $r15 31
296 bra e init_gpc_wait
297 add b32 $r14 $r4 0x804
298 call nv_rd32
299 add b32 $r1 $r15
300
301 // next!
302 add b32 $r4 0x8000
303 sub b32 $r3 1
304 bra ne init_gpc
305
306 // save context size, and tell host we're ready
307 mov $r2 0x800
308 shl b32 $r2 6
309 iowr I[$r2 + 0x100] $r1 // CC_SCRATCH[1] = context size
310 add b32 $r2 0x800
311 clear b32 $r1
312 bset $r1 31
313 iowr I[$r2 + 0x000] $r1 // CC_SCRATCH[0] |= 0x80000000
314
315// Main program loop, very simple, sleeps until woken up by the interrupt
316// handler, pulls a command from the queue and executes its handler
317//
318main:
319 // sleep until we have something to do
320 bset $flags $p0
321 sleep $p0
322 mov $r13 cmd_queue
323 call queue_get
324 bra $p1 main
325
326 // context switch, requested by GPU?
327 cmpu b32 $r14 0x4001
328 bra ne main_not_ctx_switch
329 trace_set(T_AUTO)
330 mov $r1 0xb00
331 shl b32 $r1 6
332 iord $r2 I[$r1 + 0x100] // CHAN_NEXT
333 iord $r1 I[$r1 + 0x000] // CHAN_CUR
334
335 xbit $r3 $r1 31
336 bra e chsw_no_prev
337 xbit $r3 $r2 31
338 bra e chsw_prev_no_next
339 push $r2
340 mov b32 $r2 $r1
341 trace_set(T_SAVE)
342 bclr $flags $p1
343 bset $flags $p2
344 call ctx_xfer
345 trace_clr(T_SAVE);
346 pop $r2
347 trace_set(T_LOAD);
348 bset $flags $p1
349 call ctx_xfer
350 trace_clr(T_LOAD);
351 bra chsw_done
352 chsw_prev_no_next:
353 push $r2
354 mov b32 $r2 $r1
355 bclr $flags $p1
356 bclr $flags $p2
357 call ctx_xfer
358 pop $r2
359 mov $r1 0xb00
360 shl b32 $r1 6
361 iowr I[$r1] $r2
362 bra chsw_done
363 chsw_no_prev:
364 xbit $r3 $r2 31
365 bra e chsw_done
366 bset $flags $p1
367 bclr $flags $p2
368 call ctx_xfer
369
370 // ack the context switch request
371 chsw_done:
372 mov $r1 0xb0c
373 shl b32 $r1 6
374 mov $r2 1
375 iowr I[$r1 + 0x000] $r2 // 0x409b0c
376 trace_clr(T_AUTO)
377 bra main
378
379 // request to set current channel? (*not* a context switch)
380 main_not_ctx_switch:
381 cmpu b32 $r14 0x0001
382 bra ne main_not_ctx_chan
383 mov b32 $r2 $r15
384 call ctx_chan
385 bra main_done
386
387 // request to store current channel context?
388 main_not_ctx_chan:
389 cmpu b32 $r14 0x0002
390 bra ne main_not_ctx_save
391 trace_set(T_SAVE)
392 bclr $flags $p1
393 bclr $flags $p2
394 call ctx_xfer
395 trace_clr(T_SAVE)
396 bra main_done
397
398 main_not_ctx_save:
399 shl b32 $r15 $r14 16
400 or $r15 E_BAD_COMMAND
401 call error
402 bra main
403
404 main_done:
405 mov $r1 0x820
406 shl b32 $r1 6
407 clear b32 $r2
408 bset $r2 31
409 iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000
410 bra main
411
412// interrupt handler
413ih:
414 push $r8
415 mov $r8 $flags
416 push $r8
417 push $r9
418 push $r10
419 push $r11
420 push $r13
421 push $r14
422 push $r15
423
424 // incoming fifo command?
425 iord $r10 I[$r0 + 0x200] // INTR
426 and $r11 $r10 0x00000004
427 bra e ih_no_fifo
428 // queue incoming fifo command for later processing
429 mov $r11 0x1900
430 mov $r13 cmd_queue
431 iord $r14 I[$r11 + 0x100] // FIFO_CMD
432 iord $r15 I[$r11 + 0x000] // FIFO_DATA
433 call queue_put
434 add b32 $r11 0x400
435 mov $r14 1
436 iowr I[$r11 + 0x000] $r14 // FIFO_ACK
437
438 // context switch request?
439 ih_no_fifo:
440 and $r11 $r10 0x00000100
441 bra e ih_no_ctxsw
442 // enqueue a context switch for later processing
443 mov $r13 cmd_queue
444 mov $r14 0x4001
445 call queue_put
446
447 // anything we didn't handle, bring it to the host's attention
448 ih_no_ctxsw:
449 mov $r11 0x104
450 not b32 $r11
451 and $r11 $r10 $r11
452 bra e ih_no_other
453 mov $r10 0xc1c
454 shl b32 $r10 6
455 iowr I[$r10] $r11 // INTR_UP_SET
456
457 // ack, and wake up main()
458 ih_no_other:
459 iowr I[$r0 + 0x100] $r10 // INTR_ACK
460
461 pop $r15
462 pop $r14
463 pop $r13
464 pop $r11
465 pop $r10
466 pop $r9
467 pop $r8
468 mov $flags $r8
469 pop $r8
470 bclr $flags $p0
471 iret
472
473// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
474ctx_4160s:
475 mov $r14 0x4160
476 sethi $r14 0x400000
477 mov $r15 1
478 call nv_wr32
479 ctx_4160s_wait:
480 call nv_rd32
481 xbit $r15 $r15 4
482 bra e ctx_4160s_wait
483 ret
484
485// Without clearing again at end of xfer, some things cause PGRAPH
486// to hang with STATUS=0x00000007 until it's cleared.. fbcon can
487// still function with it set however...
488ctx_4160c:
489 mov $r14 0x4160
490 sethi $r14 0x400000
491 clear b32 $r15
492 call nv_wr32
493 ret
494
495// Again, not real sure
496//
497// In: $r15 value to set 0x404170 to
498//
499ctx_4170s:
500 mov $r14 0x4170
501 sethi $r14 0x400000
502 or $r15 0x10
503 call nv_wr32
504 ret
505
506// Waits for a ctx_4170s() call to complete
507//
508ctx_4170w:
509 mov $r14 0x4170
510 sethi $r14 0x400000
511 call nv_rd32
512 and $r15 0x10
513 bra ne ctx_4170w
514 ret
515
516// Disables various things, waits a bit, and re-enables them..
517//
518// Not sure how exactly this helps, perhaps "ENABLE" is not such a
519// good description for the bits we turn off? Anyways, without this,
520// funny things happen.
521//
522ctx_redswitch:
523 mov $r14 0x614
524 shl b32 $r14 6
525 mov $r15 0x270
526 iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
527 mov $r15 8
528 ctx_redswitch_delay:
529 sub b32 $r15 1
530 bra ne ctx_redswitch_delay
531 mov $r15 0x770
532 iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
533 ret
534
535// Not a clue what this is for, except that unless the value is 0x10, the
536// strand context is saved (and presumably restored) incorrectly..
537//
538// In: $r15 value to set to (0x00/0x10 are used)
539//
540ctx_86c:
541 mov $r14 0x86c
542 shl b32 $r14 6
543 iowr I[$r14] $r15 // HUB(0x86c) = val
544 mov $r14 -0x75ec
545 sethi $r14 0x400000
546 call nv_wr32 // ROP(0xa14) = val
547 mov $r14 -0x5794
548 sethi $r14 0x410000
549 call nv_wr32 // GPC(0x86c) = val
550 ret
551
552// ctx_load - load's a channel's ctxctl data, and selects its vm
553//
554// In: $r2 channel address
555//
556ctx_load:
557 trace_set(T_CHAN)
558
559 // switch to channel, somewhat magic in parts..
560 mov $r10 12 // DONE_UNK12
561 call wait_donez
562 mov $r1 0xa24
563 shl b32 $r1 6
564 iowr I[$r1 + 0x000] $r0 // 0x409a24
565 mov $r3 0xb00
566 shl b32 $r3 6
567 iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
568 mov $r1 0xa0c
569 shl b32 $r1 6
570 mov $r4 7
571 iowr I[$r1 + 0x000] $r2 // MEM_CHAN
572 iowr I[$r1 + 0x100] $r4 // MEM_CMD
573 ctx_chan_wait_0:
574 iord $r4 I[$r1 + 0x100]
575 and $r4 0x1f
576 bra ne ctx_chan_wait_0
577 iowr I[$r3 + 0x000] $r2 // CHAN_CUR
578
579 // load channel header, fetch PGRAPH context pointer
580 mov $xtargets $r0
581 bclr $r2 31
582 shl b32 $r2 4
583 add b32 $r2 2
584
585 trace_set(T_LCHAN)
586 mov $r1 0xa04
587 shl b32 $r1 6
588 iowr I[$r1 + 0x000] $r2 // MEM_BASE
589 mov $r1 0xa20
590 shl b32 $r1 6
591 mov $r2 0x0002
592 sethi $r2 0x80000000
593 iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram
594 mov $r1 0x10 // chan + 0x0210
595 mov $r2 xfer_data
596 sethi $r2 0x00020000 // 16 bytes
597 xdld $r1 $r2
598 xdwait
599 trace_clr(T_LCHAN)
600
601 // update current context
602 ld b32 $r1 D[$r0 + xfer_data + 4]
603 shl b32 $r1 24
604 ld b32 $r2 D[$r0 + xfer_data + 0]
605 shr b32 $r2 8
606 or $r1 $r2
607 st b32 D[$r0 + ctx_current] $r1
608
609 // set transfer base to start of context, and fetch context header
610 trace_set(T_LCTXH)
611 mov $r2 0xa04
612 shl b32 $r2 6
613 iowr I[$r2 + 0x000] $r1 // MEM_BASE
614 mov $r2 1
615 mov $r1 0xa20
616 shl b32 $r1 6
617 iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm
618 mov $r1 chan_data
619 sethi $r1 0x00060000 // 256 bytes
620 xdld $r0 $r1
621 xdwait
622 trace_clr(T_LCTXH)
623
624 trace_clr(T_CHAN)
625 ret
626
627// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as
628// the active channel for ctxctl, but not actually transfer
629// any context data. intended for use only during initial
630// context construction.
631//
632// In: $r2 channel address
633//
634ctx_chan:
635 call ctx_4160s
636 call ctx_load
637 mov $r10 12 // DONE_UNK12
638 call wait_donez
639 mov $r1 0xa10
640 shl b32 $r1 6
641 mov $r2 5
642 iowr I[$r1 + 0x000] $r2 // MEM_CMD = 5 (???)
643 ctx_chan_wait:
644 iord $r2 I[$r1 + 0x000]
645 or $r2 $r2
646 bra ne ctx_chan_wait
647 call ctx_4160c
648 ret
649
650// Execute per-context state overrides list
651//
652// Only executed on the first load of a channel. Might want to look into
653// removing this and having the host directly modify the channel's context
654// to change this state... The nouveau DRM already builds this list as
655// it's definitely needed for NVIDIA's, so we may as well use it for now
656//
657// Input: $r1 mmio list length
658//
659ctx_mmio_exec:
660 // set transfer base to be the mmio list
661 ld b32 $r3 D[$r0 + chan_mmio_address]
662 mov $r2 0xa04
663 shl b32 $r2 6
664 iowr I[$r2 + 0x000] $r3 // MEM_BASE
665
666 clear b32 $r3
667 ctx_mmio_loop:
668 // fetch next 256 bytes of mmio list if necessary
669 and $r4 $r3 0xff
670 bra ne ctx_mmio_pull
671 mov $r5 xfer_data
672 sethi $r5 0x00060000 // 256 bytes
673 xdld $r3 $r5
674 xdwait
675
676 // execute a single list entry
677 ctx_mmio_pull:
678 ld b32 $r14 D[$r4 + xfer_data + 0x00]
679 ld b32 $r15 D[$r4 + xfer_data + 0x04]
680 call nv_wr32
681
682 // next!
683 add b32 $r3 8
684 sub b32 $r1 1
685 bra ne ctx_mmio_loop
686
687 // set transfer base back to the current context
688 ctx_mmio_done:
689 ld b32 $r3 D[$r0 + ctx_current]
690 iowr I[$r2 + 0x000] $r3 // MEM_BASE
691
692 // disable the mmio list now, we don't need/want to execute it again
693 st b32 D[$r0 + chan_mmio_count] $r0
694 mov $r1 chan_data
695 sethi $r1 0x00060000 // 256 bytes
696 xdst $r0 $r1
697 xdwait
698 ret
699
700// Transfer HUB context data between GPU and storage area
701//
702// In: $r2 channel address
703// $p1 clear on save, set on load
704// $p2 set if opposite direction done/will be done, so:
705// on save it means: "a load will follow this save"
706// on load it means: "a save preceeded this load"
707//
708ctx_xfer:
709 bra not $p1 ctx_xfer_pre
710 bra $p2 ctx_xfer_pre_load
711 ctx_xfer_pre:
712 mov $r15 0x10
713 call ctx_86c
714 call ctx_4160s
715 bra not $p1 ctx_xfer_exec
716
717 ctx_xfer_pre_load:
718 mov $r15 2
719 call ctx_4170s
720 call ctx_4170w
721 call ctx_redswitch
722 clear b32 $r15
723 call ctx_4170s
724 call ctx_load
725
726 // fetch context pointer, and initiate xfer on all GPCs
727 ctx_xfer_exec:
728 ld b32 $r1 D[$r0 + ctx_current]
729 mov $r2 0x414
730 shl b32 $r2 6
731 iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
732 mov $r14 -0x5b00
733 sethi $r14 0x410000
734 mov b32 $r15 $r1
735 call nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer
736 add b32 $r14 4
737 xbit $r15 $flags $p1
738 xbit $r2 $flags $p2
739 shl b32 $r2 1
740 or $r15 $r2
741 call nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
742
743 // strands
744 mov $r1 0x4afc
745 sethi $r1 0x20000
746 mov $r2 0xc
747 iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c
748 call strand_wait
749 mov $r2 0x47fc
750 sethi $r2 0x20000
751 iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00
752 xbit $r2 $flags $p1
753 add b32 $r2 3
754 iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
755
756 // mmio context
757 xbit $r10 $flags $p1 // direction
758 or $r10 6 // first, last
759 mov $r11 0 // base = 0
760 ld b32 $r12 D[$r0 + hub_mmio_list_head]
761 ld b32 $r13 D[$r0 + hub_mmio_list_tail]
762 mov $r14 0 // not multi
763 call mmctx_xfer
764
765 // wait for GPCs to all complete
766 mov $r10 8 // DONE_BAR
767 call wait_doneo
768
769 // wait for strand xfer to complete
770 call strand_wait
771
772 // post-op
773 bra $p1 ctx_xfer_post
774 mov $r10 12 // DONE_UNK12
775 call wait_donez
776 mov $r1 0xa10
777 shl b32 $r1 6
778 mov $r2 5
779 iowr I[$r1] $r2 // MEM_CMD
780 ctx_xfer_post_save_wait:
781 iord $r2 I[$r1]
782 or $r2 $r2
783 bra ne ctx_xfer_post_save_wait
784
785 bra $p2 ctx_xfer_done
786 ctx_xfer_post:
787 mov $r15 2
788 call ctx_4170s
789 clear b32 $r15
790 call ctx_86c
791 call strand_post
792 call ctx_4170w
793 clear b32 $r15
794 call ctx_4170s
795
796 bra not $p1 ctx_xfer_no_post_mmio
797 ld b32 $r1 D[$r0 + chan_mmio_count]
798 or $r1 $r1
799 bra e ctx_xfer_no_post_mmio
800 call ctx_mmio_exec
801
802 ctx_xfer_no_post_mmio:
803 call ctx_4160c
804
805 ctx_xfer_done:
806 ret
807
808.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
new file mode 100644
index 00000000000..b3b541b6d04
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
@@ -0,0 +1,838 @@
1uint32_t nvc0_grhub_data[] = {
2 0x00000000,
3 0x00000000,
4 0x00000000,
5 0x00000000,
6 0x00000000,
7 0x00000000,
8 0x00000000,
9 0x00000000,
10 0x00000000,
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x000000c0,
26 0x012c0090,
27 0x000000c1,
28 0x01300090,
29 0x000000c3,
30 0x012c0090,
31 0x000000c4,
32 0x012c0090,
33 0x000000c8,
34 0x012c0090,
35 0x000000ce,
36 0x012c0090,
37 0x00000000,
38 0x0417e91c,
39 0x04400204,
40 0x28404004,
41 0x00404044,
42 0x34404094,
43 0x184040d0,
44 0x004040f8,
45 0x08404130,
46 0x08404150,
47 0x04404164,
48 0x08404174,
49 0x1c404200,
50 0x34404404,
51 0x0c404460,
52 0x00404480,
53 0x00404498,
54 0x0c404604,
55 0x7c404618,
56 0x50404698,
57 0x044046f0,
58 0x54404700,
59 0x00405800,
60 0x08405830,
61 0x00405854,
62 0x0c405870,
63 0x04405a00,
64 0x00405a18,
65 0x00406020,
66 0x0c406028,
67 0x044064a8,
68 0x044064b4,
69 0x00407804,
70 0x1440780c,
71 0x004078bc,
72 0x18408000,
73 0x00408064,
74 0x08408800,
75 0x0c408900,
76 0x00408980,
77 0x044064c0,
78 0x00000000,
79 0x00000000,
80 0x00000000,
81 0x00000000,
82 0x00000000,
83 0x00000000,
84 0x00000000,
85 0x00000000,
86 0x00000000,
87 0x00000000,
88 0x00000000,
89 0x00000000,
90 0x00000000,
91 0x00000000,
92 0x00000000,
93 0x00000000,
94 0x00000000,
95 0x00000000,
96 0x00000000,
97 0x00000000,
98 0x00000000,
99 0x00000000,
100 0x00000000,
101 0x00000000,
102 0x00000000,
103 0x00000000,
104 0x00000000,
105 0x00000000,
106 0x00000000,
107 0x00000000,
108 0x00000000,
109 0x00000000,
110 0x00000000,
111 0x00000000,
112 0x00000000,
113 0x00000000,
114 0x00000000,
115 0x00000000,
116 0x00000000,
117 0x00000000,
118 0x00000000,
119 0x00000000,
120 0x00000000,
121 0x00000000,
122 0x00000000,
123 0x00000000,
124 0x00000000,
125 0x00000000,
126 0x00000000,
127 0x00000000,
128 0x00000000,
129 0x00000000,
130 0x00000000,
131 0x00000000,
132 0x00000000,
133 0x00000000,
134 0x00000000,
135 0x00000000,
136 0x00000000,
137 0x00000000,
138 0x00000000,
139 0x00000000,
140 0x00000000,
141 0x00000000,
142 0x00000000,
143 0x00000000,
144 0x00000000,
145 0x00000000,
146 0x00000000,
147 0x00000000,
148 0x00000000,
149 0x00000000,
150 0x00000000,
151 0x00000000,
152 0x00000000,
153 0x00000000,
154 0x00000000,
155 0x00000000,
156 0x00000000,
157 0x00000000,
158 0x00000000,
159 0x00000000,
160 0x00000000,
161 0x00000000,
162 0x00000000,
163 0x00000000,
164 0x00000000,
165 0x00000000,
166 0x00000000,
167 0x00000000,
168 0x00000000,
169 0x00000000,
170 0x00000000,
171 0x00000000,
172 0x00000000,
173 0x00000000,
174 0x00000000,
175 0x00000000,
176 0x00000000,
177 0x00000000,
178 0x00000000,
179 0x00000000,
180 0x00000000,
181 0x00000000,
182 0x00000000,
183 0x00000000,
184 0x00000000,
185 0x00000000,
186 0x00000000,
187 0x00000000,
188 0x00000000,
189 0x00000000,
190 0x00000000,
191 0x00000000,
192 0x00000000,
193 0x00000000,
194 0x00000000,
195};
196
197uint32_t nvc0_grhub_code[] = {
198 0x03090ef5,
199 0x9800d898,
200 0x86f001d9,
201 0x0489b808,
202 0xf00c1bf4,
203 0x21f502f7,
204 0x00f802ec,
205 0xb60798c4,
206 0x8dbb0384,
207 0x0880b600,
208 0x80008e80,
209 0x90b6018f,
210 0x0f94f001,
211 0xf801d980,
212 0x0131f400,
213 0x9800d898,
214 0x89b801d9,
215 0x210bf404,
216 0xb60789c4,
217 0x9dbb0394,
218 0x0890b600,
219 0x98009e98,
220 0x80b6019f,
221 0x0f84f001,
222 0xf400d880,
223 0x00f80132,
224 0x0728b7f1,
225 0xb906b4b6,
226 0xc9f002ec,
227 0x00bcd01f,
228 0xc800bccf,
229 0x1bf41fcc,
230 0x06a7f0fa,
231 0x010321f5,
232 0xf840bfcf,
233 0x28b7f100,
234 0x06b4b607,
235 0xb980bfd0,
236 0xc9f002ec,
237 0x1ec9f01f,
238 0xcf00bcd0,
239 0xccc800bc,
240 0xfa1bf41f,
241 0x87f100f8,
242 0x84b60430,
243 0x1ff9f006,
244 0xf8008fd0,
245 0x3087f100,
246 0x0684b604,
247 0xf80080d0,
248 0x3c87f100,
249 0x0684b608,
250 0x99f094bd,
251 0x0089d000,
252 0x081887f1,
253 0xd00684b6,
254 0x87f1008a,
255 0x84b60400,
256 0x0088cf06,
257 0xf4888aff,
258 0x87f1f31b,
259 0x84b6085c,
260 0xf094bd06,
261 0x89d00099,
262 0xf100f800,
263 0xb6083c87,
264 0x94bd0684,
265 0xd00099f0,
266 0x87f10089,
267 0x84b60818,
268 0x008ad006,
269 0x040087f1,
270 0xcf0684b6,
271 0x8aff0088,
272 0xf30bf488,
273 0x085c87f1,
274 0xbd0684b6,
275 0x0099f094,
276 0xf80089d0,
277 0x9894bd00,
278 0x85b600e8,
279 0x0180b61a,
280 0xbb0284b6,
281 0xe0b60098,
282 0x04efb804,
283 0xb9eb1bf4,
284 0x00f8029f,
285 0x083c87f1,
286 0xbd0684b6,
287 0x0199f094,
288 0xf10089d0,
289 0xb6071087,
290 0x94bd0684,
291 0xf405bbfd,
292 0x8bd0090b,
293 0x0099f000,
294 0xf405eefd,
295 0x8ed00c0b,
296 0xc08fd080,
297 0xb70199f0,
298 0xc8010080,
299 0xb4b600ab,
300 0x0cb9f010,
301 0xb601aec8,
302 0xbefd11e4,
303 0x008bd005,
304 0xf0008ecf,
305 0x0bf41fe4,
306 0x00ce98fa,
307 0xd005e9fd,
308 0xc0b6c08e,
309 0x04cdb804,
310 0xc8e81bf4,
311 0x1bf402ab,
312 0x008bcf18,
313 0xb01fb4f0,
314 0x1bf410b4,
315 0x02a7f0f7,
316 0xf4c921f4,
317 0xabc81b0e,
318 0x10b4b600,
319 0xf00cb9f0,
320 0x8bd012b9,
321 0x008bcf00,
322 0xf412bbc8,
323 0x87f1fa1b,
324 0x84b6085c,
325 0xf094bd06,
326 0x89d00199,
327 0xf900f800,
328 0x02a7f0a0,
329 0xfcc921f4,
330 0xf100f8a0,
331 0xf04afc87,
332 0x97f00283,
333 0x0089d00c,
334 0x020721f5,
335 0x87f100f8,
336 0x83f04afc,
337 0x0d97f002,
338 0xf50089d0,
339 0xf8020721,
340 0xfca7f100,
341 0x02a3f04f,
342 0x0500aba2,
343 0xd00fc7f0,
344 0xc7f000ac,
345 0x00bcd00b,
346 0x020721f5,
347 0xf000aed0,
348 0xbcd00ac7,
349 0x0721f500,
350 0xf100f802,
351 0xb6083c87,
352 0x94bd0684,
353 0xd00399f0,
354 0x21f50089,
355 0xe7f00213,
356 0x3921f503,
357 0xfca7f102,
358 0x02a3f046,
359 0x0400aba0,
360 0xf040a0d0,
361 0xbcd001c7,
362 0x0721f500,
363 0x010c9202,
364 0xf000acd0,
365 0xbcd002c7,
366 0x0721f500,
367 0x2621f502,
368 0x8087f102,
369 0x0684b608,
370 0xb70089cf,
371 0x95220080,
372 0x8ed008fe,
373 0x408ed000,
374 0xb6808acf,
375 0xa0b606a5,
376 0x00eabb01,
377 0xb60480b6,
378 0x1bf40192,
379 0x08e4b6e8,
380 0xf1f2efbc,
381 0xb6085c87,
382 0x94bd0684,
383 0xd00399f0,
384 0x00f80089,
385 0xe7f1e0f9,
386 0xe4b60814,
387 0x00efd006,
388 0x0c1ce7f1,
389 0xf006e4b6,
390 0xefd001f7,
391 0xf8e0fc00,
392 0xfe04bd00,
393 0x07fe0004,
394 0x0017f100,
395 0x0227f012,
396 0xf10012d0,
397 0xfe05b917,
398 0x17f10010,
399 0x10d00400,
400 0x0437f1c0,
401 0x0634b604,
402 0x200327f1,
403 0xf10032d0,
404 0xd0200427,
405 0x27f10132,
406 0x32d0200b,
407 0x0c27f102,
408 0x0732d020,
409 0x0c2427f1,
410 0xb90624b6,
411 0x23d00003,
412 0x0427f100,
413 0x0023f087,
414 0xb70012d0,
415 0xf0010012,
416 0x12d00427,
417 0x1031f400,
418 0x9604e7f1,
419 0xf440e3f0,
420 0xf1c76821,
421 0x01018090,
422 0x801ff4f0,
423 0x17f0000f,
424 0x041fbb01,
425 0xf10112b6,
426 0xb6040c27,
427 0x21d00624,
428 0x4021d000,
429 0x080027f1,
430 0xcf0624b6,
431 0xf7f00022,
432 0x08f0b654,
433 0xb800f398,
434 0x0bf40432,
435 0x0034b00b,
436 0xf8f11bf4,
437 0x0017f100,
438 0x02fe5801,
439 0xf003ff58,
440 0x0e8000e3,
441 0x150f8014,
442 0x013d21f5,
443 0x070037f1,
444 0x950634b6,
445 0x34d00814,
446 0x4034d000,
447 0x130030b7,
448 0xb6001fbb,
449 0x3fd002f5,
450 0x0815b600,
451 0xb60110b6,
452 0x1fb90814,
453 0x6321f502,
454 0x001fbb02,
455 0xf1000398,
456 0xf0200047,
457 0x4ea05043,
458 0x1fb90804,
459 0x8d21f402,
460 0x08004ea0,
461 0xf4022fb9,
462 0x4ea08d21,
463 0xf4bd010c,
464 0xa08d21f4,
465 0xf401044e,
466 0x4ea08d21,
467 0xf7f00100,
468 0x8d21f402,
469 0x08004ea0,
470 0xc86821f4,
471 0x0bf41fff,
472 0x044ea0fa,
473 0x6821f408,
474 0xb7001fbb,
475 0xb6800040,
476 0x1bf40132,
477 0x0027f1b4,
478 0x0624b608,
479 0xb74021d0,
480 0xbd080020,
481 0x1f19f014,
482 0xf40021d0,
483 0x28f40031,
484 0x08d7f000,
485 0xf43921f4,
486 0xe4b1f401,
487 0x1bf54001,
488 0x87f100d1,
489 0x84b6083c,
490 0xf094bd06,
491 0x89d00499,
492 0x0017f100,
493 0x0614b60b,
494 0xcf4012cf,
495 0x13c80011,
496 0x7e0bf41f,
497 0xf41f23c8,
498 0x20f95a0b,
499 0xf10212b9,
500 0xb6083c87,
501 0x94bd0684,
502 0xd00799f0,
503 0x32f40089,
504 0x0231f401,
505 0x082921f5,
506 0x085c87f1,
507 0xbd0684b6,
508 0x0799f094,
509 0xfc0089d0,
510 0x3c87f120,
511 0x0684b608,
512 0x99f094bd,
513 0x0089d006,
514 0xf50131f4,
515 0xf1082921,
516 0xb6085c87,
517 0x94bd0684,
518 0xd00699f0,
519 0x0ef40089,
520 0xb920f931,
521 0x32f40212,
522 0x0232f401,
523 0x082921f5,
524 0x17f120fc,
525 0x14b60b00,
526 0x0012d006,
527 0xc8130ef4,
528 0x0bf41f23,
529 0x0131f40d,
530 0xf50232f4,
531 0xf1082921,
532 0xb60b0c17,
533 0x27f00614,
534 0x0012d001,
535 0x085c87f1,
536 0xbd0684b6,
537 0x0499f094,
538 0xf50089d0,
539 0xb0ff200e,
540 0x1bf401e4,
541 0x02f2b90d,
542 0x07b521f5,
543 0xb0420ef4,
544 0x1bf402e4,
545 0x3c87f12e,
546 0x0684b608,
547 0x99f094bd,
548 0x0089d007,
549 0xf40132f4,
550 0x21f50232,
551 0x87f10829,
552 0x84b6085c,
553 0xf094bd06,
554 0x89d00799,
555 0x110ef400,
556 0xf010ef94,
557 0x21f501f5,
558 0x0ef502ec,
559 0x17f1fed1,
560 0x14b60820,
561 0xf024bd06,
562 0x12d01f29,
563 0xbe0ef500,
564 0xfe80f9fe,
565 0x80f90188,
566 0xa0f990f9,
567 0xd0f9b0f9,
568 0xf0f9e0f9,
569 0xc4800acf,
570 0x0bf404ab,
571 0x00b7f11d,
572 0x08d7f019,
573 0xcf40becf,
574 0x21f400bf,
575 0x00b0b704,
576 0x01e7f004,
577 0xe400bed0,
578 0xf40100ab,
579 0xd7f00d0b,
580 0x01e7f108,
581 0x0421f440,
582 0x0104b7f1,
583 0xabffb0bd,
584 0x0d0bf4b4,
585 0x0c1ca7f1,
586 0xd006a4b6,
587 0x0ad000ab,
588 0xfcf0fc40,
589 0xfcd0fce0,
590 0xfca0fcb0,
591 0xfe80fc90,
592 0x80fc0088,
593 0xf80032f4,
594 0x60e7f101,
595 0x40e3f041,
596 0xf401f7f0,
597 0x21f48d21,
598 0x04ffc868,
599 0xf8fa0bf4,
600 0x60e7f100,
601 0x40e3f041,
602 0x21f4f4bd,
603 0xf100f88d,
604 0xf04170e7,
605 0xf5f040e3,
606 0x8d21f410,
607 0xe7f100f8,
608 0xe3f04170,
609 0x6821f440,
610 0xf410f4f0,
611 0x00f8f31b,
612 0x0614e7f1,
613 0xf106e4b6,
614 0xd00270f7,
615 0xf7f000ef,
616 0x01f2b608,
617 0xf1fd1bf4,
618 0xd00770f7,
619 0x00f800ef,
620 0x086ce7f1,
621 0xd006e4b6,
622 0xe7f100ef,
623 0xe3f08a14,
624 0x8d21f440,
625 0xa86ce7f1,
626 0xf441e3f0,
627 0x00f88d21,
628 0x083c87f1,
629 0xbd0684b6,
630 0x0599f094,
631 0xf00089d0,
632 0x21f40ca7,
633 0x2417f1c9,
634 0x0614b60a,
635 0xf10010d0,
636 0xb60b0037,
637 0x32d00634,
638 0x0c17f140,
639 0x0614b60a,
640 0xd00747f0,
641 0x14d00012,
642 0x4014cf40,
643 0xf41f44f0,
644 0x32d0fa1b,
645 0x000bfe00,
646 0xb61f2af0,
647 0x20b60424,
648 0x3c87f102,
649 0x0684b608,
650 0x99f094bd,
651 0x0089d008,
652 0x0a0417f1,
653 0xd00614b6,
654 0x17f10012,
655 0x14b60a20,
656 0x0227f006,
657 0x800023f1,
658 0xf00012d0,
659 0x27f11017,
660 0x23f00300,
661 0x0512fa02,
662 0x87f103f8,
663 0x84b6085c,
664 0xf094bd06,
665 0x89d00899,
666 0xc1019800,
667 0x981814b6,
668 0x25b6c002,
669 0x0512fd08,
670 0xf1160180,
671 0xb6083c87,
672 0x94bd0684,
673 0xd00999f0,
674 0x27f10089,
675 0x24b60a04,
676 0x0021d006,
677 0xf10127f0,
678 0xb60a2017,
679 0x12d00614,
680 0x0017f100,
681 0x0613f002,
682 0xf80501fa,
683 0x5c87f103,
684 0x0684b608,
685 0x99f094bd,
686 0x0089d009,
687 0x085c87f1,
688 0xbd0684b6,
689 0x0599f094,
690 0xf80089d0,
691 0x3121f500,
692 0xb821f506,
693 0x0ca7f006,
694 0xf1c921f4,
695 0xb60a1017,
696 0x27f00614,
697 0x0012d005,
698 0xfd0012cf,
699 0x1bf40522,
700 0x4921f5fa,
701 0x9800f806,
702 0x27f18103,
703 0x24b60a04,
704 0x0023d006,
705 0x34c434bd,
706 0x0f1bf4ff,
707 0x030057f1,
708 0xfa0653f0,
709 0x03f80535,
710 0x98c04e98,
711 0x21f4c14f,
712 0x0830b68d,
713 0xf40112b6,
714 0x0398df1b,
715 0x0023d016,
716 0xf1800080,
717 0xf0020017,
718 0x01fa0613,
719 0xf803f806,
720 0x0611f400,
721 0xf01102f4,
722 0x21f510f7,
723 0x21f50698,
724 0x11f40631,
725 0x02f7f01c,
726 0x065721f5,
727 0x066621f5,
728 0x067821f5,
729 0x21f5f4bd,
730 0x21f50657,
731 0x019806b8,
732 0x1427f116,
733 0x0624b604,
734 0xf10020d0,
735 0xf0a500e7,
736 0x1fb941e3,
737 0x8d21f402,
738 0xf004e0b6,
739 0x2cf001fc,
740 0x0124b602,
741 0xf405f2fd,
742 0x17f18d21,
743 0x13f04afc,
744 0x0c27f002,
745 0xf50012d0,
746 0xf1020721,
747 0xf047fc27,
748 0x20d00223,
749 0x012cf000,
750 0xd00320b6,
751 0xacf00012,
752 0x06a5f001,
753 0x9800b7f0,
754 0x0d98140c,
755 0x00e7f015,
756 0x015c21f5,
757 0xf508a7f0,
758 0xf5010321,
759 0xf4020721,
760 0xa7f02201,
761 0xc921f40c,
762 0x0a1017f1,
763 0xf00614b6,
764 0x12d00527,
765 0x0012cf00,
766 0xf40522fd,
767 0x02f4fa1b,
768 0x02f7f032,
769 0x065721f5,
770 0x21f5f4bd,
771 0x21f50698,
772 0x21f50226,
773 0xf4bd0666,
774 0x065721f5,
775 0x981011f4,
776 0x11fd8001,
777 0x070bf405,
778 0x07df21f5,
779 0x064921f5,
780 0x000000f8,
781 0x00000000,
782 0x00000000,
783 0x00000000,
784 0x00000000,
785 0x00000000,
786 0x00000000,
787 0x00000000,
788 0x00000000,
789 0x00000000,
790 0x00000000,
791 0x00000000,
792 0x00000000,
793 0x00000000,
794 0x00000000,
795 0x00000000,
796 0x00000000,
797 0x00000000,
798 0x00000000,
799 0x00000000,
800 0x00000000,
801 0x00000000,
802 0x00000000,
803 0x00000000,
804 0x00000000,
805 0x00000000,
806 0x00000000,
807 0x00000000,
808 0x00000000,
809 0x00000000,
810 0x00000000,
811 0x00000000,
812 0x00000000,
813 0x00000000,
814 0x00000000,
815 0x00000000,
816 0x00000000,
817 0x00000000,
818 0x00000000,
819 0x00000000,
820 0x00000000,
821 0x00000000,
822 0x00000000,
823 0x00000000,
824 0x00000000,
825 0x00000000,
826 0x00000000,
827 0x00000000,
828 0x00000000,
829 0x00000000,
830 0x00000000,
831 0x00000000,
832 0x00000000,
833 0x00000000,
834 0x00000000,
835 0x00000000,
836 0x00000000,
837 0x00000000,
838};
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c
new file mode 100644
index 00000000000..b701c439c92
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c
@@ -0,0 +1,223 @@
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_vm.h"
29
30struct nvc0_instmem_priv {
31 struct nouveau_gpuobj *bar1_pgd;
32 struct nouveau_channel *bar1;
33 struct nouveau_gpuobj *bar3_pgd;
34 struct nouveau_channel *bar3;
35};
36
37int
38nvc0_instmem_suspend(struct drm_device *dev)
39{
40 struct drm_nouveau_private *dev_priv = dev->dev_private;
41
42 dev_priv->ramin_available = false;
43 return 0;
44}
45
46void
47nvc0_instmem_resume(struct drm_device *dev)
48{
49 struct drm_nouveau_private *dev_priv = dev->dev_private;
50 struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
51
52 nv_mask(dev, 0x100c80, 0x00000001, 0x00000000);
53 nv_wr32(dev, 0x001704, 0x80000000 | priv->bar1->ramin->vinst >> 12);
54 nv_wr32(dev, 0x001714, 0xc0000000 | priv->bar3->ramin->vinst >> 12);
55 dev_priv->ramin_available = true;
56}
57
58static void
59nvc0_channel_del(struct nouveau_channel **pchan)
60{
61 struct nouveau_channel *chan;
62
63 chan = *pchan;
64 *pchan = NULL;
65 if (!chan)
66 return;
67
68 nouveau_vm_ref(NULL, &chan->vm, NULL);
69 if (drm_mm_initialized(&chan->ramin_heap))
70 drm_mm_takedown(&chan->ramin_heap);
71 nouveau_gpuobj_ref(NULL, &chan->ramin);
72 kfree(chan);
73}
74
75static int
76nvc0_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm,
77 struct nouveau_channel **pchan,
78 struct nouveau_gpuobj *pgd, u64 vm_size)
79{
80 struct nouveau_channel *chan;
81 int ret;
82
83 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
84 if (!chan)
85 return -ENOMEM;
86 chan->dev = dev;
87
88 ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
89 if (ret) {
90 nvc0_channel_del(&chan);
91 return ret;
92 }
93
94 ret = drm_mm_init(&chan->ramin_heap, 0x1000, size - 0x1000);
95 if (ret) {
96 nvc0_channel_del(&chan);
97 return ret;
98 }
99
100 ret = nouveau_vm_ref(vm, &chan->vm, NULL);
101 if (ret) {
102 nvc0_channel_del(&chan);
103 return ret;
104 }
105
106 nv_wo32(chan->ramin, 0x0200, lower_32_bits(pgd->vinst));
107 nv_wo32(chan->ramin, 0x0204, upper_32_bits(pgd->vinst));
108 nv_wo32(chan->ramin, 0x0208, lower_32_bits(vm_size - 1));
109 nv_wo32(chan->ramin, 0x020c, upper_32_bits(vm_size - 1));
110
111 *pchan = chan;
112 return 0;
113}
114
115int
116nvc0_instmem_init(struct drm_device *dev)
117{
118 struct drm_nouveau_private *dev_priv = dev->dev_private;
119 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
120 struct pci_dev *pdev = dev->pdev;
121 struct nvc0_instmem_priv *priv;
122 struct nouveau_vm *vm = NULL;
123 int ret;
124
125 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
126 if (!priv)
127 return -ENOMEM;
128 pinstmem->priv = priv;
129
130 /* BAR3 VM */
131 ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 3), 0,
132 &dev_priv->bar3_vm);
133 if (ret)
134 goto error;
135
136 ret = nouveau_gpuobj_new(dev, NULL,
137 (pci_resource_len(pdev, 3) >> 12) * 8, 0,
138 NVOBJ_FLAG_DONT_MAP |
139 NVOBJ_FLAG_ZERO_ALLOC,
140 &dev_priv->bar3_vm->pgt[0].obj[0]);
141 if (ret)
142 goto error;
143 dev_priv->bar3_vm->pgt[0].refcount[0] = 1;
144
145 nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj[0]);
146
147 ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
148 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar3_pgd);
149 if (ret)
150 goto error;
151
152 ret = nouveau_vm_ref(dev_priv->bar3_vm, &vm, priv->bar3_pgd);
153 if (ret)
154 goto error;
155 nouveau_vm_ref(NULL, &vm, NULL);
156
157 ret = nvc0_channel_new(dev, 8192, dev_priv->bar3_vm, &priv->bar3,
158 priv->bar3_pgd, pci_resource_len(dev->pdev, 3));
159 if (ret)
160 goto error;
161
162 /* BAR1 VM */
163 ret = nouveau_vm_new(dev, 0, pci_resource_len(pdev, 1), 0, &vm);
164 if (ret)
165 goto error;
166
167 ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096,
168 NVOBJ_FLAG_ZERO_ALLOC, &priv->bar1_pgd);
169 if (ret)
170 goto error;
171
172 ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, priv->bar1_pgd);
173 if (ret)
174 goto error;
175 nouveau_vm_ref(NULL, &vm, NULL);
176
177 ret = nvc0_channel_new(dev, 8192, dev_priv->bar1_vm, &priv->bar1,
178 priv->bar1_pgd, pci_resource_len(dev->pdev, 1));
179 if (ret)
180 goto error;
181
182 /* channel vm */
183 ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
184 &dev_priv->chan_vm);
185 if (ret)
186 goto error;
187
188 nvc0_instmem_resume(dev);
189 return 0;
190error:
191 nvc0_instmem_takedown(dev);
192 return ret;
193}
194
195void
196nvc0_instmem_takedown(struct drm_device *dev)
197{
198 struct drm_nouveau_private *dev_priv = dev->dev_private;
199 struct nvc0_instmem_priv *priv = dev_priv->engine.instmem.priv;
200 struct nouveau_vm *vm = NULL;
201
202 nvc0_instmem_suspend(dev);
203
204 nv_wr32(dev, 0x1704, 0x00000000);
205 nv_wr32(dev, 0x1714, 0x00000000);
206
207 nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
208
209 nvc0_channel_del(&priv->bar1);
210 nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
211 nouveau_gpuobj_ref(NULL, &priv->bar1_pgd);
212
213 nvc0_channel_del(&priv->bar3);
214 nouveau_vm_ref(dev_priv->bar3_vm, &vm, NULL);
215 nouveau_vm_ref(NULL, &vm, priv->bar3_pgd);
216 nouveau_gpuobj_ref(NULL, &priv->bar3_pgd);
217 nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
218 nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
219
220 dev_priv->engine.instmem.priv = NULL;
221 kfree(priv);
222}
223
diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c
new file mode 100644
index 00000000000..9e352944a35
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c
@@ -0,0 +1,134 @@
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_vm.h"
29
30void
31nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index,
32 struct nouveau_gpuobj *pgt[2])
33{
34 u32 pde[2] = { 0, 0 };
35
36 if (pgt[0])
37 pde[1] = 0x00000001 | (pgt[0]->vinst >> 8);
38 if (pgt[1])
39 pde[0] = 0x00000001 | (pgt[1]->vinst >> 8);
40
41 nv_wo32(pgd, (index * 8) + 0, pde[0]);
42 nv_wo32(pgd, (index * 8) + 4, pde[1]);
43}
44
45static inline u64
46nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
47{
48 phys >>= 8;
49
50 phys |= 0x00000001; /* present */
51 if (vma->access & NV_MEM_ACCESS_SYS)
52 phys |= 0x00000002;
53
54 phys |= ((u64)target << 32);
55 phys |= ((u64)memtype << 36);
56
57 return phys;
58}
59
60void
61nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
62 struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
63{
64 u32 next = 1 << (vma->node->type - 8);
65
66 phys = nvc0_vm_addr(vma, phys, mem->memtype, 0);
67 pte <<= 3;
68 while (cnt--) {
69 nv_wo32(pgt, pte + 0, lower_32_bits(phys));
70 nv_wo32(pgt, pte + 4, upper_32_bits(phys));
71 phys += next;
72 pte += 8;
73 }
74}
75
76void
77nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
78 struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
79{
80 pte <<= 3;
81 while (cnt--) {
82 u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5);
83 nv_wo32(pgt, pte + 0, lower_32_bits(phys));
84 nv_wo32(pgt, pte + 4, upper_32_bits(phys));
85 pte += 8;
86 }
87}
88
89void
90nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
91{
92 pte <<= 3;
93 while (cnt--) {
94 nv_wo32(pgt, pte + 0, 0x00000000);
95 nv_wo32(pgt, pte + 4, 0x00000000);
96 pte += 8;
97 }
98}
99
100void
101nvc0_vm_flush(struct nouveau_vm *vm)
102{
103 struct drm_nouveau_private *dev_priv = vm->dev->dev_private;
104 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
105 struct drm_device *dev = vm->dev;
106 struct nouveau_vm_pgd *vpgd;
107 unsigned long flags;
108 u32 engine;
109
110 engine = 1;
111 if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm)
112 engine |= 4;
113
114 pinstmem->flush(vm->dev);
115
116 spin_lock_irqsave(&dev_priv->vm_lock, flags);
117 list_for_each_entry(vpgd, &vm->pgd_list, head) {
118 /* looks like maybe a "free flush slots" counter, the
119 * faster you write to 0x100cbc to more it decreases
120 */
121 if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) {
122 NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n",
123 nv_rd32(dev, 0x100c80), engine);
124 }
125 nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8);
126 nv_wr32(dev, 0x100cbc, 0x80000000 | engine);
127 /* wait for flush to be queued? */
128 if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) {
129 NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n",
130 nv_rd32(dev, 0x100c80), engine);
131 }
132 }
133 spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
134}
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
new file mode 100644
index 00000000000..e45a24d84e9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -0,0 +1,117 @@
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_mm.h"
28
29/* 0 = unsupported
30 * 1 = non-compressed
31 * 3 = compressed
32 */
33static const u8 types[256] = {
34 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
35 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
38 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
42 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
46 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
47 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
48 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
49 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
50};
51
52bool
53nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
54{
55 u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
56 return likely((types[memtype] == 1));
57}
58
59int
60nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
61 u32 type, struct nouveau_mem **pmem)
62{
63 struct drm_nouveau_private *dev_priv = dev->dev_private;
64 struct nouveau_mm *mm = dev_priv->engine.vram.mm;
65 struct nouveau_mm_node *r;
66 struct nouveau_mem *mem;
67 int ret;
68
69 size >>= 12;
70 align >>= 12;
71 ncmin >>= 12;
72
73 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
74 if (!mem)
75 return -ENOMEM;
76
77 INIT_LIST_HEAD(&mem->regions);
78 mem->dev = dev_priv->dev;
79 mem->memtype = (type & 0xff);
80 mem->size = size;
81
82 mutex_lock(&mm->mutex);
83 do {
84 ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r);
85 if (ret) {
86 mutex_unlock(&mm->mutex);
87 nv50_vram_del(dev, &mem);
88 return ret;
89 }
90
91 list_add_tail(&r->rl_entry, &mem->regions);
92 size -= r->length;
93 } while (size);
94 mutex_unlock(&mm->mutex);
95
96 r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
97 mem->offset = (u64)r->offset << 12;
98 *pmem = mem;
99 return 0;
100}
101
102int
103nvc0_vram_init(struct drm_device *dev)
104{
105 struct drm_nouveau_private *dev_priv = dev->dev_private;
106 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
107 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
108 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
109 u32 length;
110
111 dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
112 dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
113
114 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
115
116 return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
117}