nouveau_state.c 43.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Copyright 2005 Stephane Marchesin
 * Copyright 2008 Stuart Bennett
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <linux/swab.h>
27
#include <linux/slab.h>
28
29
30
31
32
#include "drmP.h"
#include "drm.h"
#include "drm_sarea.h"
#include "drm_crtc_helper.h"
#include <linux/vgaarb.h>
33
#include <linux/vga_switcheroo.h>
34
35
36

#include "nouveau_drv.h"
#include "nouveau_drm.h"
37
#include "nouveau_fbcon.h"
38
#include "nouveau_ramht.h"
39
#include "nouveau_gpio.h"
40
#include "nouveau_pm.h"
41
42
43
#include "nv50_display.h"

static void nouveau_stub_takedown(struct drm_device *dev) {}
44
static int nouveau_stub_init(struct drm_device *dev) { return 0; }
45
46
47
48
49
50
51
52
53
54
55
56

static int nouveau_init_engine_ptrs(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine = &dev_priv->engine;

	switch (dev_priv->chipset & 0xf0) {
	case 0x00:
		engine->instmem.init		= nv04_instmem_init;
		engine->instmem.takedown	= nv04_instmem_takedown;
		engine->instmem.suspend		= nv04_instmem_suspend;
		engine->instmem.resume		= nv04_instmem_resume;
57
58
59
60
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
61
		engine->instmem.flush		= nv04_instmem_flush;
62
63
64
65
66
67
68
69
70
		engine->mc.init			= nv04_mc_init;
		engine->mc.takedown		= nv04_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nv04_fb_init;
		engine->fb.takedown		= nv04_fb_takedown;
		engine->fifo.channels		= 16;
		engine->fifo.init		= nv04_fifo_init;
71
		engine->fifo.takedown		= nv04_fifo_fini;
72
73
74
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
75
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
76
77
78
79
80
		engine->fifo.channel_id		= nv04_fifo_channel_id;
		engine->fifo.create_context	= nv04_fifo_create_context;
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
		engine->fifo.load_context	= nv04_fifo_load_context;
		engine->fifo.unload_context	= nv04_fifo_unload_context;
81
82
83
84
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.destroy		= nv04_display_destroy;
85
86
		engine->display.init		= nv04_display_init;
		engine->display.fini		= nv04_display_fini;
87
88
89
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
90
		engine->vram.init		= nv04_fb_vram_init;
91
		engine->vram.takedown		= nouveau_stub_takedown;
92
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
93
94
95
96
97
98
		break;
	case 0x10:
		engine->instmem.init		= nv04_instmem_init;
		engine->instmem.takedown	= nv04_instmem_takedown;
		engine->instmem.suspend		= nv04_instmem_suspend;
		engine->instmem.resume		= nv04_instmem_resume;
99
100
101
102
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
103
		engine->instmem.flush		= nv04_instmem_flush;
104
105
106
107
108
109
110
		engine->mc.init			= nv04_mc_init;
		engine->mc.takedown		= nv04_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nv10_fb_init;
		engine->fb.takedown		= nv10_fb_takedown;
111
112
113
		engine->fb.init_tile_region	= nv10_fb_init_tile_region;
		engine->fb.set_tile_region	= nv10_fb_set_tile_region;
		engine->fb.free_tile_region	= nv10_fb_free_tile_region;
114
115
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv10_fifo_init;
116
		engine->fifo.takedown		= nv04_fifo_fini;
117
118
119
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
120
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
121
122
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv10_fifo_create_context;
123
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
124
125
		engine->fifo.load_context	= nv10_fifo_load_context;
		engine->fifo.unload_context	= nv10_fifo_unload_context;
126
127
128
129
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.destroy		= nv04_display_destroy;
130
131
		engine->display.init		= nv04_display_init;
		engine->display.fini		= nv04_display_fini;
132
133
		engine->gpio.drive		= nv10_gpio_drive;
		engine->gpio.sense		= nv10_gpio_sense;
134
135
136
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
137
138
139
140
141
		if (dev_priv->chipset == 0x1a ||
		    dev_priv->chipset == 0x1f)
			engine->vram.init	= nv1a_fb_vram_init;
		else
			engine->vram.init	= nv10_fb_vram_init;
142
		engine->vram.takedown		= nouveau_stub_takedown;
143
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
144
145
146
147
148
149
		break;
	case 0x20:
		engine->instmem.init		= nv04_instmem_init;
		engine->instmem.takedown	= nv04_instmem_takedown;
		engine->instmem.suspend		= nv04_instmem_suspend;
		engine->instmem.resume		= nv04_instmem_resume;
150
151
152
153
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
154
		engine->instmem.flush		= nv04_instmem_flush;
155
156
157
158
159
		engine->mc.init			= nv04_mc_init;
		engine->mc.takedown		= nv04_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
160
161
162
163
164
		engine->fb.init			= nv20_fb_init;
		engine->fb.takedown		= nv20_fb_takedown;
		engine->fb.init_tile_region	= nv20_fb_init_tile_region;
		engine->fb.set_tile_region	= nv20_fb_set_tile_region;
		engine->fb.free_tile_region	= nv20_fb_free_tile_region;
165
166
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv10_fifo_init;
167
		engine->fifo.takedown		= nv04_fifo_fini;
168
169
170
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
171
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
172
173
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv10_fifo_create_context;
174
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
175
176
		engine->fifo.load_context	= nv10_fifo_load_context;
		engine->fifo.unload_context	= nv10_fifo_unload_context;
177
178
179
180
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.destroy		= nv04_display_destroy;
181
182
		engine->display.init		= nv04_display_init;
		engine->display.fini		= nv04_display_fini;
183
184
		engine->gpio.drive		= nv10_gpio_drive;
		engine->gpio.sense		= nv10_gpio_sense;
185
186
187
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
188
		engine->vram.init		= nv20_fb_vram_init;
189
		engine->vram.takedown		= nouveau_stub_takedown;
190
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
191
192
193
194
195
196
		break;
	case 0x30:
		engine->instmem.init		= nv04_instmem_init;
		engine->instmem.takedown	= nv04_instmem_takedown;
		engine->instmem.suspend		= nv04_instmem_suspend;
		engine->instmem.resume		= nv04_instmem_resume;
197
198
199
200
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
201
		engine->instmem.flush		= nv04_instmem_flush;
202
203
204
205
206
		engine->mc.init			= nv04_mc_init;
		engine->mc.takedown		= nv04_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
207
208
		engine->fb.init			= nv30_fb_init;
		engine->fb.takedown		= nv30_fb_takedown;
209
210
211
		engine->fb.init_tile_region	= nv30_fb_init_tile_region;
		engine->fb.set_tile_region	= nv10_fb_set_tile_region;
		engine->fb.free_tile_region	= nv30_fb_free_tile_region;
212
213
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv10_fifo_init;
214
		engine->fifo.takedown		= nv04_fifo_fini;
215
216
217
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
218
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
219
220
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv10_fifo_create_context;
221
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
222
223
		engine->fifo.load_context	= nv10_fifo_load_context;
		engine->fifo.unload_context	= nv10_fifo_unload_context;
224
225
226
227
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.destroy		= nv04_display_destroy;
228
229
		engine->display.init		= nv04_display_init;
		engine->display.fini		= nv04_display_fini;
230
231
		engine->gpio.drive		= nv10_gpio_drive;
		engine->gpio.sense		= nv10_gpio_sense;
232
233
234
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
235
236
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
237
		engine->vram.init		= nv20_fb_vram_init;
238
		engine->vram.takedown		= nouveau_stub_takedown;
239
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
240
241
242
243
244
245
246
		break;
	case 0x40:
	case 0x60:
		engine->instmem.init		= nv04_instmem_init;
		engine->instmem.takedown	= nv04_instmem_takedown;
		engine->instmem.suspend		= nv04_instmem_suspend;
		engine->instmem.resume		= nv04_instmem_resume;
247
248
249
250
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
251
		engine->instmem.flush		= nv04_instmem_flush;
252
253
254
255
256
257
258
		engine->mc.init			= nv40_mc_init;
		engine->mc.takedown		= nv40_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nv40_fb_init;
		engine->fb.takedown		= nv40_fb_takedown;
259
260
261
		engine->fb.init_tile_region	= nv30_fb_init_tile_region;
		engine->fb.set_tile_region	= nv40_fb_set_tile_region;
		engine->fb.free_tile_region	= nv30_fb_free_tile_region;
262
263
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv40_fifo_init;
264
		engine->fifo.takedown		= nv04_fifo_fini;
265
266
267
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
268
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
269
270
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv40_fifo_create_context;
271
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
272
273
		engine->fifo.load_context	= nv40_fifo_load_context;
		engine->fifo.unload_context	= nv40_fifo_unload_context;
274
275
276
277
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.destroy		= nv04_display_destroy;
278
279
		engine->display.init		= nv04_display_init;
		engine->display.fini		= nv04_display_fini;
280
281
		engine->gpio.init		= nv10_gpio_init;
		engine->gpio.fini		= nv10_gpio_fini;
282
283
		engine->gpio.drive		= nv10_gpio_drive;
		engine->gpio.sense		= nv10_gpio_sense;
284
		engine->gpio.irq_enable		= nv10_gpio_irq_enable;
285
286
287
		engine->pm.clocks_get		= nv40_pm_clocks_get;
		engine->pm.clocks_pre		= nv40_pm_clocks_pre;
		engine->pm.clocks_set		= nv40_pm_clocks_set;
288
289
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
290
		engine->pm.temp_get		= nv40_temp_get;
291
292
		engine->pm.pwm_get		= nv40_pm_pwm_get;
		engine->pm.pwm_set		= nv40_pm_pwm_set;
293
		engine->vram.init		= nv40_fb_vram_init;
294
		engine->vram.takedown		= nouveau_stub_takedown;
295
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
296
297
298
299
		break;
	case 0x50:
	case 0x80: /* gotta love NVIDIA's consistency.. */
	case 0x90:
300
	case 0xa0:
301
302
303
304
		engine->instmem.init		= nv50_instmem_init;
		engine->instmem.takedown	= nv50_instmem_takedown;
		engine->instmem.suspend		= nv50_instmem_suspend;
		engine->instmem.resume		= nv50_instmem_resume;
305
306
307
308
		engine->instmem.get		= nv50_instmem_get;
		engine->instmem.put		= nv50_instmem_put;
		engine->instmem.map		= nv50_instmem_map;
		engine->instmem.unmap		= nv50_instmem_unmap;
309
310
311
312
		if (dev_priv->chipset == 0x50)
			engine->instmem.flush	= nv50_instmem_flush;
		else
			engine->instmem.flush	= nv84_instmem_flush;
313
314
315
316
317
		engine->mc.init			= nv50_mc_init;
		engine->mc.takedown		= nv50_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
318
319
		engine->fb.init			= nv50_fb_init;
		engine->fb.takedown		= nv50_fb_takedown;
320
321
322
323
324
325
326
327
328
329
330
		engine->fifo.channels		= 128;
		engine->fifo.init		= nv50_fifo_init;
		engine->fifo.takedown		= nv50_fifo_takedown;
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
		engine->fifo.channel_id		= nv50_fifo_channel_id;
		engine->fifo.create_context	= nv50_fifo_create_context;
		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
		engine->fifo.load_context	= nv50_fifo_load_context;
		engine->fifo.unload_context	= nv50_fifo_unload_context;
331
		engine->fifo.tlb_flush		= nv50_fifo_tlb_flush;
332
333
334
335
		engine->display.early_init	= nv50_display_early_init;
		engine->display.late_takedown	= nv50_display_late_takedown;
		engine->display.create		= nv50_display_create;
		engine->display.destroy		= nv50_display_destroy;
336
337
		engine->display.init		= nv50_display_init;
		engine->display.fini		= nv50_display_fini;
338
		engine->gpio.init		= nv50_gpio_init;
339
340
341
		engine->gpio.fini		= nv50_gpio_fini;
		engine->gpio.drive		= nv50_gpio_drive;
		engine->gpio.sense		= nv50_gpio_sense;
342
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
343
		switch (dev_priv->chipset) {
344
345
346
347
348
349
350
		case 0x84:
		case 0x86:
		case 0x92:
		case 0x94:
		case 0x96:
		case 0x98:
		case 0xa0:
351
352
		case 0xaa:
		case 0xac:
353
		case 0x50:
354
355
356
			engine->pm.clocks_get	= nv50_pm_clocks_get;
			engine->pm.clocks_pre	= nv50_pm_clocks_pre;
			engine->pm.clocks_set	= nv50_pm_clocks_set;
357
			break;
358
		default:
359
360
361
			engine->pm.clocks_get	= nva3_pm_clocks_get;
			engine->pm.clocks_pre	= nva3_pm_clocks_pre;
			engine->pm.clocks_set	= nva3_pm_clocks_set;
362
			break;
363
		}
364
365
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
366
367
368
369
		if (dev_priv->chipset >= 0x84)
			engine->pm.temp_get	= nv84_temp_get;
		else
			engine->pm.temp_get	= nv40_temp_get;
370
371
		engine->pm.pwm_get		= nv50_pm_pwm_get;
		engine->pm.pwm_set		= nv50_pm_pwm_set;
372
		engine->vram.init		= nv50_vram_init;
373
		engine->vram.takedown		= nv50_vram_fini;
374
375
376
		engine->vram.get		= nv50_vram_new;
		engine->vram.put		= nv50_vram_del;
		engine->vram.flags_valid	= nv50_vram_flags_valid;
377
		break;
378
	case 0xc0:
379
380
381
382
		engine->instmem.init		= nvc0_instmem_init;
		engine->instmem.takedown	= nvc0_instmem_takedown;
		engine->instmem.suspend		= nvc0_instmem_suspend;
		engine->instmem.resume		= nvc0_instmem_resume;
383
384
385
386
387
		engine->instmem.get		= nv50_instmem_get;
		engine->instmem.put		= nv50_instmem_put;
		engine->instmem.map		= nv50_instmem_map;
		engine->instmem.unmap		= nv50_instmem_unmap;
		engine->instmem.flush		= nv84_instmem_flush;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
		engine->mc.init			= nv50_mc_init;
		engine->mc.takedown		= nv50_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nvc0_fb_init;
		engine->fb.takedown		= nvc0_fb_takedown;
		engine->fifo.channels		= 128;
		engine->fifo.init		= nvc0_fifo_init;
		engine->fifo.takedown		= nvc0_fifo_takedown;
		engine->fifo.disable		= nvc0_fifo_disable;
		engine->fifo.enable		= nvc0_fifo_enable;
		engine->fifo.reassign		= nvc0_fifo_reassign;
		engine->fifo.channel_id		= nvc0_fifo_channel_id;
		engine->fifo.create_context	= nvc0_fifo_create_context;
		engine->fifo.destroy_context	= nvc0_fifo_destroy_context;
		engine->fifo.load_context	= nvc0_fifo_load_context;
		engine->fifo.unload_context	= nvc0_fifo_unload_context;
		engine->display.early_init	= nv50_display_early_init;
		engine->display.late_takedown	= nv50_display_late_takedown;
		engine->display.create		= nv50_display_create;
		engine->display.destroy		= nv50_display_destroy;
410
411
		engine->display.init		= nv50_display_init;
		engine->display.fini		= nv50_display_fini;
412
		engine->gpio.init		= nv50_gpio_init;
413
414
415
		engine->gpio.fini		= nv50_gpio_fini;
		engine->gpio.drive		= nv50_gpio_drive;
		engine->gpio.sense		= nv50_gpio_sense;
416
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
417
		engine->vram.init		= nvc0_vram_init;
418
		engine->vram.takedown		= nv50_vram_fini;
419
420
421
		engine->vram.get		= nvc0_vram_new;
		engine->vram.put		= nv50_vram_del;
		engine->vram.flags_valid	= nvc0_vram_flags_valid;
422
		engine->pm.temp_get		= nv84_temp_get;
423
		engine->pm.clocks_get		= nvc0_pm_clocks_get;
424
425
		engine->pm.clocks_pre		= nvc0_pm_clocks_pre;
		engine->pm.clocks_set		= nvc0_pm_clocks_set;
Ben Skeggs's avatar
Ben Skeggs committed
426
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
427
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
428
429
		engine->pm.pwm_get		= nv50_pm_pwm_get;
		engine->pm.pwm_set		= nv50_pm_pwm_set;
430
		break;
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
	case 0xd0:
		engine->instmem.init		= nvc0_instmem_init;
		engine->instmem.takedown	= nvc0_instmem_takedown;
		engine->instmem.suspend		= nvc0_instmem_suspend;
		engine->instmem.resume		= nvc0_instmem_resume;
		engine->instmem.get		= nv50_instmem_get;
		engine->instmem.put		= nv50_instmem_put;
		engine->instmem.map		= nv50_instmem_map;
		engine->instmem.unmap		= nv50_instmem_unmap;
		engine->instmem.flush		= nv84_instmem_flush;
		engine->mc.init			= nv50_mc_init;
		engine->mc.takedown		= nv50_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nvc0_fb_init;
		engine->fb.takedown		= nvc0_fb_takedown;
		engine->fifo.channels		= 128;
		engine->fifo.init		= nvc0_fifo_init;
		engine->fifo.takedown		= nvc0_fifo_takedown;
		engine->fifo.disable		= nvc0_fifo_disable;
		engine->fifo.enable		= nvc0_fifo_enable;
		engine->fifo.reassign		= nvc0_fifo_reassign;
		engine->fifo.channel_id		= nvc0_fifo_channel_id;
		engine->fifo.create_context	= nvc0_fifo_create_context;
		engine->fifo.destroy_context	= nvc0_fifo_destroy_context;
		engine->fifo.load_context	= nvc0_fifo_load_context;
		engine->fifo.unload_context	= nvc0_fifo_unload_context;
		engine->display.early_init	= nouveau_stub_init;
		engine->display.late_takedown	= nouveau_stub_takedown;
461
462
		engine->display.create		= nvd0_display_create;
		engine->display.destroy		= nvd0_display_destroy;
463
464
		engine->display.init		= nvd0_display_init;
		engine->display.fini		= nvd0_display_fini;
465
		engine->gpio.init		= nv50_gpio_init;
466
467
468
		engine->gpio.fini		= nv50_gpio_fini;
		engine->gpio.drive		= nvd0_gpio_drive;
		engine->gpio.sense		= nvd0_gpio_sense;
469
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
470
471
472
473
474
		engine->vram.init		= nvc0_vram_init;
		engine->vram.takedown		= nv50_vram_fini;
		engine->vram.get		= nvc0_vram_new;
		engine->vram.put		= nv50_vram_del;
		engine->vram.flags_valid	= nvc0_vram_flags_valid;
475
		engine->pm.temp_get		= nv84_temp_get;
476
		engine->pm.clocks_get		= nvc0_pm_clocks_get;
477
478
		engine->pm.clocks_pre		= nvc0_pm_clocks_pre;
		engine->pm.clocks_set		= nvc0_pm_clocks_set;
479
480
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
481
		break;
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
	case 0xe0:
		engine->instmem.init		= nvc0_instmem_init;
		engine->instmem.takedown	= nvc0_instmem_takedown;
		engine->instmem.suspend		= nvc0_instmem_suspend;
		engine->instmem.resume		= nvc0_instmem_resume;
		engine->instmem.get		= nv50_instmem_get;
		engine->instmem.put		= nv50_instmem_put;
		engine->instmem.map		= nv50_instmem_map;
		engine->instmem.unmap		= nv50_instmem_unmap;
		engine->instmem.flush		= nv84_instmem_flush;
		engine->mc.init			= nv50_mc_init;
		engine->mc.takedown		= nv50_mc_takedown;
		engine->timer.init		= nv04_timer_init;
		engine->timer.read		= nv04_timer_read;
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nvc0_fb_init;
		engine->fb.takedown		= nvc0_fb_takedown;
		engine->fifo.channels		= 0;
		engine->fifo.init		= nouveau_stub_init;
		engine->fifo.takedown		= nouveau_stub_takedown;
		engine->fifo.disable		= nvc0_fifo_disable;
		engine->fifo.enable		= nvc0_fifo_enable;
		engine->fifo.reassign		= nvc0_fifo_reassign;
		engine->fifo.unload_context	= nouveau_stub_init;
		engine->display.early_init	= nouveau_stub_init;
		engine->display.late_takedown	= nouveau_stub_takedown;
		engine->display.create		= nvd0_display_create;
		engine->display.destroy		= nvd0_display_destroy;
		engine->display.init		= nvd0_display_init;
		engine->display.fini		= nvd0_display_fini;
		engine->gpio.init		= nv50_gpio_init;
		engine->gpio.fini		= nv50_gpio_fini;
		engine->gpio.drive		= nvd0_gpio_drive;
		engine->gpio.sense		= nvd0_gpio_sense;
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
		engine->vram.init		= nvc0_vram_init;
		engine->vram.takedown		= nv50_vram_fini;
		engine->vram.get		= nvc0_vram_new;
		engine->vram.put		= nv50_vram_del;
		engine->vram.flags_valid	= nvc0_vram_flags_valid;
		break;
523
524
525
526
527
	default:
		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
		return 1;
	}

528
529
530
531
532
533
534
535
536
	/* headless mode */
	if (nouveau_modeset == 2) {
		engine->display.early_init = nouveau_stub_init;
		engine->display.late_takedown = nouveau_stub_takedown;
		engine->display.create = nouveau_stub_init;
		engine->display.init = nouveau_stub_init;
		engine->display.destroy = nouveau_stub_takedown;
	}

537
538
539
540
541
542
	return 0;
}

static unsigned int
nouveau_vga_set_decode(void *priv, bool state)
{
543
544
545
546
547
548
549
550
	struct drm_device *dev = priv;
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	if (dev_priv->chipset >= 0x40)
		nv_wr32(dev, 0x88054, state);
	else
		nv_wr32(dev, 0x1854, state);

551
552
553
554
555
556
557
	if (state)
		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
	else
		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
}

558
559
560
static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
					 enum vga_switcheroo_state state)
{
561
	struct drm_device *dev = pci_get_drvdata(pdev);
562
563
564
	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
	if (state == VGA_SWITCHEROO_ON) {
		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
565
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
566
		nouveau_pci_resume(pdev);
567
		drm_kms_helper_poll_enable(dev);
568
		dev->switch_power_state = DRM_SWITCH_POWER_ON;
569
570
	} else {
		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
571
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
572
		drm_kms_helper_poll_disable(dev);
573
		nouveau_switcheroo_optimus_dsm();
574
		nouveau_pci_suspend(pdev, pmm);
575
		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
576
577
578
	}
}

579
580
581
582
583
584
static void nouveau_switcheroo_reprobe(struct pci_dev *pdev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	nouveau_fbcon_output_poll_changed(dev);
}

585
586
587
588
589
590
591
592
593
594
595
static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	bool can_switch;

	spin_lock(&dev->count_lock);
	can_switch = (dev->open_count == 0);
	spin_unlock(&dev->count_lock);
	return can_switch;
}

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
static void
nouveau_card_channel_fini(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	if (dev_priv->channel)
		nouveau_channel_put_unlocked(&dev_priv->channel);
}

static int
nouveau_card_channel_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan;
	int ret, oclass;

	ret = nouveau_channel_alloc(dev, &chan, NULL, NvDmaFB, NvDmaTT);
	dev_priv->channel = chan;
	if (ret)
		return ret;

	mutex_unlock(&dev_priv->channel->mutex);

	if (dev_priv->card_type <= NV_50) {
		if (dev_priv->card_type < NV_50)
			oclass = 0x0039;
		else
			oclass = 0x5039;

		ret = nouveau_gpuobj_gr_new(chan, NvM2MF, oclass);
		if (ret)
			goto error;

		ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000,
					     &chan->m2mf_ntfy);
		if (ret)
			goto error;

		ret = RING_SPACE(chan, 6);
		if (ret)
			goto error;

		BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
		OUT_RING  (chan, NvM2MF);
		BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
		OUT_RING  (chan, NvNotify0);
		OUT_RING  (chan, chan->vram_handle);
		OUT_RING  (chan, chan->gart_handle);
	} else
	if (dev_priv->card_type <= NV_C0) {
		ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
		if (ret)
			goto error;

		ret = RING_SPACE(chan, 2);
		if (ret)
			goto error;

		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1);
		OUT_RING  (chan, 0x00009039);
	}

	FIRE_RING (chan);
error:
	if (ret)
		nouveau_card_channel_fini(dev);
	return ret;
}

665
666
667
668
669
int
nouveau_card_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine;
670
	int ret, e = 0;
671
672

	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
673
	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
674
				       nouveau_switcheroo_reprobe,
675
				       nouveau_switcheroo_can_switch);
676
677
678
679

	/* Initialise internal driver API hooks */
	ret = nouveau_init_engine_ptrs(dev);
	if (ret)
680
		goto out;
681
	engine = &dev_priv->engine;
682
	spin_lock_init(&dev_priv->channels.lock);
683
	spin_lock_init(&dev_priv->tile.lock);
684
	spin_lock_init(&dev_priv->context_switch_lock);
685
	spin_lock_init(&dev_priv->vm_lock);
686

687
688
689
690
691
	/* Make the CRTCs and I2C buses accessible */
	ret = engine->display.early_init(dev);
	if (ret)
		goto out;

692
	/* Parse BIOS tables / Run init tables if card not POSTed */
693
694
	ret = nouveau_bios_init(dev);
	if (ret)
695
		goto out_display_early;
696

697
698
699
700
701
702
703
704
	/* workaround an odd issue on nvc1 by disabling the device's
	 * nosnoop capability.  hopefully won't cause issues until a
	 * better fix is found - assuming there is one...
	 */
	if (dev_priv->chipset == 0xc1) {
		nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
	}

705
706
707
708
709
710
711
712
713
714
715
716
717
718
	/* PMC */
	ret = engine->mc.init(dev);
	if (ret)
		goto out_bios;

	/* PTIMER */
	ret = engine->timer.init(dev);
	if (ret)
		goto out_mc;

	/* PFB */
	ret = engine->fb.init(dev);
	if (ret)
		goto out_timer;
719

720
	ret = engine->vram.init(dev);
721
	if (ret)
722
		goto out_fb;
723

724
725
	/* PGPIO */
	ret = nouveau_gpio_create(dev);
726
	if (ret)
727
		goto out_vram;
728

729
730
731
732
	ret = nouveau_gpuobj_init(dev);
	if (ret)
		goto out_gpio;

733
734
	ret = engine->instmem.init(dev);
	if (ret)
735
		goto out_gpuobj;
736

737
	ret = nouveau_mem_vram_init(dev);
738
	if (ret)
739
		goto out_instmem;
740

741
742
743
744
	ret = nouveau_mem_gart_init(dev);
	if (ret)
		goto out_ttmvram;

745
	if (!dev_priv->noaccel) {
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
		switch (dev_priv->card_type) {
		case NV_04:
			nv04_graph_create(dev);
			break;
		case NV_10:
			nv10_graph_create(dev);
			break;
		case NV_20:
		case NV_30:
			nv20_graph_create(dev);
			break;
		case NV_40:
			nv40_graph_create(dev);
			break;
		case NV_50:
			nv50_graph_create(dev);
			break;
		case NV_C0:
764
		case NV_D0:
765
766
767
768
769
			nvc0_graph_create(dev);
			break;
		default:
			break;
		}
770

771
		switch (dev_priv->chipset) {
772
773
774
775
776
777
778
		case 0x84:
		case 0x86:
		case 0x92:
		case 0x94:
		case 0x96:
		case 0xa0:
			nv84_crypt_create(dev);
779
			break;
780
781
782
783
784
		case 0x98:
		case 0xaa:
		case 0xac:
			nv98_crypt_create(dev);
			break;
785
786
		}

787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
		switch (dev_priv->card_type) {
		case NV_50:
			switch (dev_priv->chipset) {
			case 0xa3:
			case 0xa5:
			case 0xa8:
			case 0xaf:
				nva3_copy_create(dev);
				break;
			}
			break;
		case NV_C0:
			nvc0_copy_create(dev, 0);
			nvc0_copy_create(dev, 1);
			break;
		default:
			break;
		}

806
807
808
809
810
811
812
813
814
815
816
817
818
		if (dev_priv->chipset >= 0xa3 || dev_priv->chipset == 0x98) {
			nv84_bsp_create(dev);
			nv84_vp_create(dev);
			nv98_ppp_create(dev);
		} else
		if (dev_priv->chipset >= 0x84) {
			nv50_mpeg_create(dev);
			nv84_bsp_create(dev);
			nv84_vp_create(dev);
		} else
		if (dev_priv->chipset >= 0x50) {
			nv50_mpeg_create(dev);
		} else
819
820
821
		if (dev_priv->card_type == NV_40 ||
		    dev_priv->chipset == 0x31 ||
		    dev_priv->chipset == 0x34 ||
822
		    dev_priv->chipset == 0x36) {
823
			nv31_mpeg_create(dev);
824
		}
825

826
827
828
829
830
831
832
833
		for (e = 0; e < NVOBJ_ENGINE_NR; e++) {
			if (dev_priv->eng[e]) {
				ret = dev_priv->eng[e]->init(dev, e);
				if (ret)
					goto out_engine;
			}
		}

834
835
836
		/* PFIFO */
		ret = engine->fifo.init(dev);
		if (ret)
837
			goto out_engine;
838
	}
839

840
841
842
843
	ret = nouveau_irq_init(dev);
	if (ret)
		goto out_fifo;

844
	ret = nouveau_display_create(dev);
845
	if (ret)
846
		goto out_irq;
847

848
	nouveau_backlight_init(dev);
849
	nouveau_pm_init(dev);
850

851
852
853
	ret = nouveau_fence_init(dev);
	if (ret)
		goto out_pm;
854

855
856
	if (!dev_priv->noaccel) {
		ret = nouveau_card_channel_init(dev);
857
858
		if (ret)
			goto out_fence;
859
860
861
	}

	if (dev->mode_config.num_crtc) {
862
		ret = nouveau_display_init(dev);
863
864
865
866
		if (ret)
			goto out_chan;

		nouveau_fbcon_init(dev);
867
868
869
	}

	return 0;
870

871
out_chan:
872
	nouveau_card_channel_fini(dev);
873
874
out_fence:
	nouveau_fence_fini(dev);
875
876
out_pm:
	nouveau_pm_fini(dev);
877
	nouveau_backlight_exit(dev);
878
	nouveau_display_destroy(dev);
879
out_irq:
Ben Skeggs's avatar
Ben Skeggs committed
880
	nouveau_irq_fini(dev);
881
out_fifo:
882
	if (!dev_priv->noaccel)
883
		engine->fifo.takedown(dev);
884
out_engine:
885
	if (!dev_priv->noaccel) {
886
		for (e = e - 1; e >= 0; e--) {
887
888
			if (!dev_priv->eng[e])
				continue;
889
			dev_priv->eng[e]->fini(dev, e, false);
890
			dev_priv->eng[e]->destroy(dev,e );
891
892
		}
	}
893
	nouveau_mem_gart_fini(dev);
894
895
out_ttmvram:
	nouveau_mem_vram_fini(dev);
896
897
out_instmem:
	engine->instmem.takedown(dev);
898
899
out_gpuobj:
	nouveau_gpuobj_takedown(dev);
900
901
out_gpio:
	nouveau_gpio_destroy(dev);
902
out_vram:
903
	engine->vram.takedown(dev);
904
905
906
907
908
909
out_fb:
	engine->fb.takedown(dev);
out_timer:
	engine->timer.takedown(dev);
out_mc:
	engine->mc.takedown(dev);
910
911
out_bios:
	nouveau_bios_takedown(dev);
912
913
out_display_early:
	engine->display.late_takedown(dev);
914
915
916
out:
	vga_client_register(dev->pdev, NULL, NULL, NULL);
	return ret;
917
918
919
920
921
922
}

static void nouveau_card_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine = &dev_priv->engine;
923
	int e;
924

925
926
	if (dev->mode_config.num_crtc) {
		nouveau_fbcon_fini(dev);
927
		nouveau_display_fini(dev);
928
	}
929

930
931
	nouveau_card_channel_fini(dev);
	nouveau_fence_fini(dev);
932
	nouveau_pm_fini(dev);
933
	nouveau_backlight_exit(dev);
934
	nouveau_display_destroy(dev);
935

936
	if (!dev_priv->noaccel) {
937
		engine->fifo.takedown(dev);
938
939
		for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
			if (dev_priv->eng[e]) {
940
				dev_priv->eng[e]->fini(dev, e, false);
941
942
943
				dev_priv->eng[e]->destroy(dev,e );
			}
		}
944
	}
945

946
947
948
949
950
	if (dev_priv->vga_ram) {
		nouveau_bo_unpin(dev_priv->vga_ram);
		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
	}

951
952
953
954
	mutex_lock(&dev->struct_mutex);
	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
	mutex_unlock(&dev->struct_mutex);
955
	nouveau_mem_gart_fini(dev);
956
	nouveau_mem_vram_fini(dev);
957

958
	engine->instmem.takedown(dev);
959
	nouveau_gpuobj_takedown(dev);
960

961
962
963
964
965
966
	nouveau_gpio_destroy(dev);
	engine->vram.takedown(dev);
	engine->fb.takedown(dev);
	engine->timer.takedown(dev);
	engine->mc.takedown(dev);

967
	nouveau_bios_takedown(dev);
968
969
970
	engine->display.late_takedown(dev);

	nouveau_irq_fini(dev);
971

972
	vga_client_register(dev->pdev, NULL, NULL, NULL);
973
974
}

975
976
977
int
nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
{
978
	struct drm_nouveau_private *dev_priv = dev->dev_private;
979
	struct nouveau_fpriv *fpriv;
980
	int ret;
981
982
983
984
985
986

	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
	if (unlikely(!fpriv))
		return -ENOMEM;

	spin_lock_init(&fpriv->lock);
987
988
	INIT_LIST_HEAD(&fpriv->channels);

989
990
991
992
993
994
995
996
997
	if (dev_priv->card_type == NV_50) {
		ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
				     &fpriv->vm);
		if (ret) {
			kfree(fpriv);
			return ret;
		}
	} else
	if (dev_priv->card_type >= NV_C0) {
998
999
1000
1001
1002
1003
		ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
				     &fpriv->vm);
		if (ret) {
			kfree(fpriv);
			return ret;
		}
1004
	}
1005

1006
1007
1008
1009
	file_priv->driver_priv = fpriv;
	return 0;
}

1010
1011
1012
1013
1014
1015
1016
/* here a client dies, release the stuff that was allocated for its
 * file_priv */
void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
{
	nouveau_channel_cleanup(dev, file_priv);
}

1017
1018
1019
1020
void
nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
{
	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
1021
	nouveau_vm_ref(NULL, &fpriv->vm, NULL);
1022
1023
1024
	kfree(fpriv);
}

1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
/* first module load, setup the mmio/fb mapping */
/* KMS: we need mmio at load time, not when the first drm client opens. */
int nouveau_firstopen(struct drm_device *dev)
{
	return 0;
}

/* if we have an OF card, copy vbios to RAMIN */
static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev)
{
#if defined(__powerpc__)
	int size, i;
	const uint32_t *bios;
	struct device_node *dn = pci_device_to_OF_node(dev->pdev);
	if (!dn) {
		NV_INFO(dev, "Unable to get the OF node\n");
		return;
	}

	bios = of_get_property(dn, "NVDA,BMP", &size);
	if (bios) {
		for (i = 0; i < size; i += 4)
			nv_wi32(dev, i, bios[i/4]);
		NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size);
	} else {
		NV_INFO(dev, "Unable to get the OF bios\n");
	}
#endif
}

1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev)
{
	struct pci_dev *pdev = dev->pdev;
	struct apertures_struct *aper = alloc_apertures(3);
	if (!aper)
		return NULL;

	aper->ranges[0].base = pci_resource_start(pdev, 1);
	aper->ranges[0].size = pci_resource_len(pdev, 1);
	aper->count = 1;

	if (pci_resource_len(pdev, 2)) {
		aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
		aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
		aper->count++;
	}

	if (pci_resource_len(pdev, 3)) {
		aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
		aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
		aper->count++;
	}

	return aper;
}

static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
1084
	bool primary = false;
1085
1086
1087
1088
	dev_priv->apertures = nouveau_get_apertures(dev);
	if (!dev_priv->apertures)
		return -ENOMEM;

1089
1090
1091
#ifdef CONFIG_X86
	primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
#endif
1092

1093
	remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary);
1094
1095
1096
	return 0;
}

1097
1098
1099
int nouveau_load(struct drm_device *dev, unsigned long flags)
{
	struct drm_nouveau_private *dev_priv;
1100
	unsigned long long offset, length;
1101
	uint32_t reg0 = ~0, strap;
1102
	int ret;
1103
1104

	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
1105
1106
1107
1108
	if (!dev_priv) {
		ret = -ENOMEM;
		goto err_out;
	}
1109
1110
1111
	dev->dev_private = dev_priv;
	dev_priv->dev = dev;

1112
1113
	pci_set_master(dev->pdev);

1114
1115
1116
1117
1118
	dev_priv->flags = flags & NOUVEAU_FLAGS;

	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
		 dev->pci_vendor, dev->pci_device, dev->pdev->class);

1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
	/* first up, map the start of mmio and determine the chipset */
	dev_priv->mmio = ioremap(pci_resource_start(dev->pdev, 0), PAGE_SIZE);
	if (dev_priv->mmio) {
#ifdef __BIG_ENDIAN
		/* put the card into big-endian mode if it's not */
		if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001)
			nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);
		DRM_MEMORYBARRIER();
#endif

		/* determine chipset and derive architecture from it */
		reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
		if ((reg0 & 0x0f000000) > 0) {
			dev_priv->chipset = (reg0 & 0xff00000) >> 20;
			switch (dev_priv->chipset & 0xf0) {
			case 0x10:
			case 0x20:
			case 0x30:
				dev_priv->card_type = dev_priv->chipset & 0xf0;
				break;
			case 0x40:
			case 0x60:
				dev_priv->card_type = NV_40;
				break;
			case 0x50:
			case 0x80:
			case 0x90:
			case 0xa0:
				dev_priv->card_type = NV_50;
				break;
			case 0xc0:
				dev_priv->card_type = NV_C0;
				break;
			case 0xd0:
				dev_priv->card_type = NV_D0;
				break;
1155
1156
1157
			case 0xe0:
				dev_priv->card_type = NV_E0;
				break;
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
			default:
				break;
			}
		} else
		if ((reg0 & 0xff00fff0) == 0x20004000) {
			if (reg0 & 0x00f00000)
				dev_priv->chipset = 0x05;
			else
				dev_priv->chipset = 0x04;
			dev_priv->card_type = NV_04;
		}

		iounmap(dev_priv->mmio);
	}

	if (!dev_priv->card_type) {
		NV_ERROR(dev, "unsupported chipset 0x%08x\n", reg0);
		ret = -EINVAL;
		goto err_priv;
	}

	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
		     dev_priv->card_type, reg0);
1181

1182
1183
1184
1185
1186
1187
1188
	/* map the mmio regs, limiting the amount to preserve vmap space */
	offset = pci_resource_start(dev->