nouveau_state.c 40.1 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_pm.h"
40
41
42
#include "nv50_display.h"

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

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;
56
57
58
59
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
60
		engine->instmem.flush		= nv04_instmem_flush;
61
62
63
64
65
66
67
68
69
		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;
70
		engine->fifo.takedown		= nv04_fifo_fini;
71
72
73
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
74
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
75
76
77
78
79
		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;
80
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.init		= nv04_display_init;
		engine->display.destroy		= nv04_display_destroy;
85
86
87
88
89
		engine->gpio.init		= nouveau_stub_init;
		engine->gpio.takedown		= nouveau_stub_takedown;
		engine->gpio.get		= NULL;
		engine->gpio.set		= NULL;
		engine->gpio.irq_enable		= NULL;
90
91
92
		engine->pm.clock_get		= nv04_pm_clock_get;
		engine->pm.clock_pre		= nv04_pm_clock_pre;
		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
97
98
99
100
101
		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;
102
103
104
105
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
106
		engine->instmem.flush		= nv04_instmem_flush;
107
108
109
110
111
112
113
		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;
114
115
116
		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;
117
118
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv10_fifo_init;
119
		engine->fifo.takedown		= nv04_fifo_fini;
120
121
122
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
123
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
124
125
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv10_fifo_create_context;
126
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
127
128
		engine->fifo.load_context	= nv10_fifo_load_context;
		engine->fifo.unload_context	= nv10_fifo_unload_context;
129
130
131
132
133
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.init		= nv04_display_init;
		engine->display.destroy		= nv04_display_destroy;
134
135
136
137
138
		engine->gpio.init		= nouveau_stub_init;
		engine->gpio.takedown		= nouveau_stub_takedown;
		engine->gpio.get		= nv10_gpio_get;
		engine->gpio.set		= nv10_gpio_set;
		engine->gpio.irq_enable		= NULL;
139
140
141
		engine->pm.clock_get		= nv04_pm_clock_get;
		engine->pm.clock_pre		= nv04_pm_clock_pre;
		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
146
147
148
149
150
		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;
151
152
153
154
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
155
		engine->instmem.flush		= nv04_instmem_flush;
156
157
158
159
160
161
162
		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;
163
164
165
		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;
166
167
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv10_fifo_init;
168
		engine->fifo.takedown		= nv04_fifo_fini;
169
170
171
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
172
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
173
174
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv10_fifo_create_context;
175
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
176
177
		engine->fifo.load_context	= nv10_fifo_load_context;
		engine->fifo.unload_context	= nv10_fifo_unload_context;
178
179
180
181
182
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.init		= nv04_display_init;
		engine->display.destroy		= nv04_display_destroy;
183
184
185
186
187
		engine->gpio.init		= nouveau_stub_init;
		engine->gpio.takedown		= nouveau_stub_takedown;
		engine->gpio.get		= nv10_gpio_get;
		engine->gpio.set		= nv10_gpio_set;
		engine->gpio.irq_enable		= NULL;
188
189
190
		engine->pm.clock_get		= nv04_pm_clock_get;
		engine->pm.clock_pre		= nv04_pm_clock_pre;
		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
195
196
197
198
199
		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;
200
201
202
203
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
204
		engine->instmem.flush		= nv04_instmem_flush;
205
206
207
208
209
		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;
210
211
		engine->fb.init			= nv30_fb_init;
		engine->fb.takedown		= nv30_fb_takedown;
212
213
214
		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;
215
216
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv10_fifo_init;
217
		engine->fifo.takedown		= nv04_fifo_fini;
218
219
220
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
221
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
222
223
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv10_fifo_create_context;
224
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
225
226
		engine->fifo.load_context	= nv10_fifo_load_context;
		engine->fifo.unload_context	= nv10_fifo_unload_context;
227
228
229
230
231
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.init		= nv04_display_init;
		engine->display.destroy		= nv04_display_destroy;
232
233
234
235
236
		engine->gpio.init		= nouveau_stub_init;
		engine->gpio.takedown		= nouveau_stub_takedown;
		engine->gpio.get		= nv10_gpio_get;
		engine->gpio.set		= nv10_gpio_set;
		engine->gpio.irq_enable		= NULL;
237
238
239
240
241
		engine->pm.clock_get		= nv04_pm_clock_get;
		engine->pm.clock_pre		= nv04_pm_clock_pre;
		engine->pm.clock_set		= nv04_pm_clock_set;
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		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
246
247
248
249
250
251
		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;
252
253
254
255
		engine->instmem.get		= nv04_instmem_get;
		engine->instmem.put		= nv04_instmem_put;
		engine->instmem.map		= nv04_instmem_map;
		engine->instmem.unmap		= nv04_instmem_unmap;
256
		engine->instmem.flush		= nv04_instmem_flush;
257
258
259
260
261
262
263
		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;
264
265
266
		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;
267
268
		engine->fifo.channels		= 32;
		engine->fifo.init		= nv40_fifo_init;
269
		engine->fifo.takedown		= nv04_fifo_fini;
270
271
272
		engine->fifo.disable		= nv04_fifo_disable;
		engine->fifo.enable		= nv04_fifo_enable;
		engine->fifo.reassign		= nv04_fifo_reassign;
273
		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
274
275
		engine->fifo.channel_id		= nv10_fifo_channel_id;
		engine->fifo.create_context	= nv40_fifo_create_context;
276
		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
277
278
		engine->fifo.load_context	= nv40_fifo_load_context;
		engine->fifo.unload_context	= nv40_fifo_unload_context;
279
280
281
282
283
		engine->display.early_init	= nv04_display_early_init;
		engine->display.late_takedown	= nv04_display_late_takedown;
		engine->display.create		= nv04_display_create;
		engine->display.init		= nv04_display_init;
		engine->display.destroy		= nv04_display_destroy;
284
285
286
287
288
		engine->gpio.init		= nouveau_stub_init;
		engine->gpio.takedown		= nouveau_stub_takedown;
		engine->gpio.get		= nv10_gpio_get;
		engine->gpio.set		= nv10_gpio_set;
		engine->gpio.irq_enable		= NULL;
289
290
291
		engine->pm.clocks_get		= nv40_pm_clocks_get;
		engine->pm.clocks_pre		= nv40_pm_clocks_pre;
		engine->pm.clocks_set		= nv40_pm_clocks_set;
292
293
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
294
		engine->pm.temp_get		= nv40_temp_get;
295
296
		engine->pm.pwm_get		= nv40_pm_pwm_get;
		engine->pm.pwm_set		= nv40_pm_pwm_set;
297
		engine->vram.init		= nouveau_mem_detect;
298
		engine->vram.takedown		= nouveau_stub_takedown;
299
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
300
301
302
303
		break;
	case 0x50:
	case 0x80: /* gotta love NVIDIA's consistency.. */
	case 0x90:
304
	case 0xa0:
305
306
307
308
		engine->instmem.init		= nv50_instmem_init;
		engine->instmem.takedown	= nv50_instmem_takedown;
		engine->instmem.suspend		= nv50_instmem_suspend;
		engine->instmem.resume		= nv50_instmem_resume;
309
310
311
312
		engine->instmem.get		= nv50_instmem_get;
		engine->instmem.put		= nv50_instmem_put;
		engine->instmem.map		= nv50_instmem_map;
		engine->instmem.unmap		= nv50_instmem_unmap;
313
314
315
316
		if (dev_priv->chipset == 0x50)
			engine->instmem.flush	= nv50_instmem_flush;
		else
			engine->instmem.flush	= nv84_instmem_flush;
317
318
319
320
321
		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;
322
323
		engine->fb.init			= nv50_fb_init;
		engine->fb.takedown		= nv50_fb_takedown;
324
325
326
327
328
329
330
331
332
333
334
		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;
335
		engine->fifo.tlb_flush		= nv50_fifo_tlb_flush;
336
337
338
339
340
		engine->display.early_init	= nv50_display_early_init;
		engine->display.late_takedown	= nv50_display_late_takedown;
		engine->display.create		= nv50_display_create;
		engine->display.init		= nv50_display_init;
		engine->display.destroy		= nv50_display_destroy;
341
		engine->gpio.init		= nv50_gpio_init;
342
		engine->gpio.takedown		= nv50_gpio_fini;
343
344
		engine->gpio.get		= nv50_gpio_get;
		engine->gpio.set		= nv50_gpio_set;
345
346
		engine->gpio.irq_register	= nv50_gpio_irq_register;
		engine->gpio.irq_unregister	= nv50_gpio_irq_unregister;
347
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
348
		switch (dev_priv->chipset) {
349
350
351
352
353
354
355
		case 0x84:
		case 0x86:
		case 0x92:
		case 0x94:
		case 0x96:
		case 0x98:
		case 0xa0:
356
357
		case 0xaa:
		case 0xac:
358
		case 0x50:
359
360
361
362
			engine->pm.clock_get	= nv50_pm_clock_get;
			engine->pm.clock_pre	= nv50_pm_clock_pre;
			engine->pm.clock_set	= nv50_pm_clock_set;
			break;
363
		default:
364
365
366
			engine->pm.clocks_get	= nva3_pm_clocks_get;
			engine->pm.clocks_pre	= nva3_pm_clocks_pre;
			engine->pm.clocks_set	= nva3_pm_clocks_set;
367
			break;
368
		}
369
370
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
371
372
373
374
		if (dev_priv->chipset >= 0x84)
			engine->pm.temp_get	= nv84_temp_get;
		else
			engine->pm.temp_get	= nv40_temp_get;
375
376
		engine->pm.pwm_get		= nv50_pm_pwm_get;
		engine->pm.pwm_set		= nv50_pm_pwm_set;
377
		engine->vram.init		= nv50_vram_init;
378
		engine->vram.takedown		= nv50_vram_fini;
379
380
381
		engine->vram.get		= nv50_vram_new;
		engine->vram.put		= nv50_vram_del;
		engine->vram.flags_valid	= nv50_vram_flags_valid;
382
		break;
383
	case 0xc0:
384
385
386
387
		engine->instmem.init		= nvc0_instmem_init;
		engine->instmem.takedown	= nvc0_instmem_takedown;
		engine->instmem.suspend		= nvc0_instmem_suspend;
		engine->instmem.resume		= nvc0_instmem_resume;
388
389
390
391
392
		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;
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
		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.init		= nv50_display_init;
		engine->display.destroy		= nv50_display_destroy;
		engine->gpio.init		= nv50_gpio_init;
		engine->gpio.takedown		= nouveau_stub_takedown;
		engine->gpio.get		= nv50_gpio_get;
		engine->gpio.set		= nv50_gpio_set;
420
421
		engine->gpio.irq_register	= nv50_gpio_irq_register;
		engine->gpio.irq_unregister	= nv50_gpio_irq_unregister;
422
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
423
		engine->vram.init		= nvc0_vram_init;
424
		engine->vram.takedown		= nv50_vram_fini;
425
426
427
		engine->vram.get		= nvc0_vram_new;
		engine->vram.put		= nv50_vram_del;
		engine->vram.flags_valid	= nvc0_vram_flags_valid;
428
		engine->pm.temp_get		= nv84_temp_get;
429
		engine->pm.clocks_get		= nvc0_pm_clocks_get;
Ben Skeggs's avatar
Ben Skeggs committed
430
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
431
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
432
433
		engine->pm.pwm_get		= nv50_pm_pwm_get;
		engine->pm.pwm_set		= nv50_pm_pwm_set;
434
		break;
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
461
462
463
464
	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;
465
466
467
		engine->display.create		= nvd0_display_create;
		engine->display.init		= nvd0_display_init;
		engine->display.destroy		= nvd0_display_destroy;
468
		engine->gpio.init		= nv50_gpio_init;
469
		engine->gpio.takedown		= nouveau_stub_takedown;
470
471
472
473
474
		engine->gpio.get		= nvd0_gpio_get;
		engine->gpio.set		= nvd0_gpio_set;
		engine->gpio.irq_register	= nv50_gpio_irq_register;
		engine->gpio.irq_unregister	= nv50_gpio_irq_unregister;
		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
475
476
477
478
479
		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;
480
		engine->pm.temp_get		= nv84_temp_get;
481
482
483
		engine->pm.clocks_get		= nvc0_pm_clocks_get;
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
484
		break;
485
486
487
488
489
	default:
		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
		return 1;
	}

490
491
492
493
494
495
496
497
498
	/* 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;
	}

499
500
501
502
503
504
	return 0;
}

static unsigned int
nouveau_vga_set_decode(void *priv, bool state)
{
505
506
507
508
509
510
511
512
	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);

513
514
515
516
517
518
519
	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;
}

520
521
522
static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
					 enum vga_switcheroo_state state)
{
523
	struct drm_device *dev = pci_get_drvdata(pdev);
524
525
526
	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
	if (state == VGA_SWITCHEROO_ON) {
		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
527
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
528
		nouveau_pci_resume(pdev);
529
		drm_kms_helper_poll_enable(dev);
530
		dev->switch_power_state = DRM_SWITCH_POWER_ON;
531
532
	} else {
		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
533
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
534
		drm_kms_helper_poll_disable(dev);
535
		nouveau_pci_suspend(pdev, pmm);
536
		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
537
538
539
	}
}

540
541
542
543
544
545
static void nouveau_switcheroo_reprobe(struct pci_dev *pdev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	nouveau_fbcon_output_poll_changed(dev);
}

546
547
548
549
550
551
552
553
554
555
556
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;
}

557
558
559
560
561
int
nouveau_card_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine;
562
	int ret, e = 0;
563
564

	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
565
	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
566
				       nouveau_switcheroo_reprobe,
567
				       nouveau_switcheroo_can_switch);
568
569
570
571

	/* Initialise internal driver API hooks */
	ret = nouveau_init_engine_ptrs(dev);
	if (ret)
572
		goto out;
573
	engine = &dev_priv->engine;
574
	spin_lock_init(&dev_priv->channels.lock);
575
	spin_lock_init(&dev_priv->tile.lock);
576
	spin_lock_init(&dev_priv->context_switch_lock);
577
	spin_lock_init(&dev_priv->vm_lock);
578

579
580
581
582
583
	/* Make the CRTCs and I2C buses accessible */
	ret = engine->display.early_init(dev);
	if (ret)
		goto out;

584
	/* Parse BIOS tables / Run init tables if card not POSTed */
585
586
	ret = nouveau_bios_init(dev);
	if (ret)
587
		goto out_display_early;
588

589
590
591
592
593
594
595
596
	/* 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);
	}

597
598
	nouveau_pm_init(dev);

599
	ret = engine->vram.init(dev);
600
601
602
	if (ret)
		goto out_bios;

603
	ret = nouveau_gpuobj_init(dev);
604
	if (ret)
605
		goto out_vram;
606
607
608

	ret = engine->instmem.init(dev);
	if (ret)
609
		goto out_gpuobj;
610

611
	ret = nouveau_mem_vram_init(dev);
612
	if (ret)
613
		goto out_instmem;
614

615
616
617
618
	ret = nouveau_mem_gart_init(dev);
	if (ret)
		goto out_ttmvram;

619
620
621
	/* PMC */
	ret = engine->mc.init(dev);
	if (ret)
622
		goto out_gart;
623

624
625
626
627
628
	/* PGPIO */
	ret = engine->gpio.init(dev);
	if (ret)
		goto out_mc;

629
630
631
	/* PTIMER */
	ret = engine->timer.init(dev);
	if (ret)
632
		goto out_gpio;
633
634
635
636

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

639
	if (!dev_priv->noaccel) {
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
		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:
			nvc0_graph_create(dev);
			break;
		default:
			break;
		}
663

664
		switch (dev_priv->chipset) {
665
666
667
668
669
670
671
		case 0x84:
		case 0x86:
		case 0x92:
		case 0x94:
		case 0x96:
		case 0xa0:
			nv84_crypt_create(dev);
672
			break;
673
674
675
676
677
		case 0x98:
		case 0xaa:
		case 0xac:
			nv98_crypt_create(dev);
			break;
678
679
		}

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
		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;
		}

699
700
701
702
703
704
705
706
707
708
709
710
711
		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
712
713
714
		if (dev_priv->card_type == NV_40 ||
		    dev_priv->chipset == 0x31 ||
		    dev_priv->chipset == 0x34 ||
715
		    dev_priv->chipset == 0x36) {
716
			nv31_mpeg_create(dev);
717
		}
718

719
720
721
722
723
724
725
726
		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;
			}
		}

727
728
729
		/* PFIFO */
		ret = engine->fifo.init(dev);
		if (ret)
730
			goto out_engine;
731
	}
732

733
734
735
736
	ret = nouveau_irq_init(dev);
	if (ret)
		goto out_fifo;

737
	ret = nouveau_display_create(dev);
738
	if (ret)
739
		goto out_irq;
740

741
742
	nouveau_backlight_init(dev);

743
	if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
744
		ret = nouveau_fence_init(dev);
745
		if (ret)
746
			goto out_disp;
747

748
749
		ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
					    NvDmaFB, NvDmaTT);
750
751
		if (ret)
			goto out_fence;
752
753
754
755
756
757
758
759
760
761
762

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

	if (dev->mode_config.num_crtc) {
		ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
		if (ret)
			goto out_chan;

		nouveau_fbcon_init(dev);
		drm_kms_helper_poll_init(dev);
763
764
765
	}

	return 0;
766

767
768
out_chan:
	nouveau_channel_put_unlocked(&dev_priv->channel);
769
770
out_fence:
	nouveau_fence_fini(dev);
771
out_disp:
772
	nouveau_backlight_exit(dev);
773
	nouveau_display_destroy(dev);
774
out_irq:
Ben Skeggs's avatar
Ben Skeggs committed
775
	nouveau_irq_fini(dev);
776
out_fifo:
777
	if (!dev_priv->noaccel)
778
		engine->fifo.takedown(dev);
779
out_engine:
780
	if (!dev_priv->noaccel) {
781
		for (e = e - 1; e >= 0; e--) {
782
783
			if (!dev_priv->eng[e])
				continue;
784
			dev_priv->eng[e]->fini(dev, e, false);
785
			dev_priv->eng[e]->destroy(dev,e );
786
787
788
		}
	}

789
790
791
	engine->fb.takedown(dev);
out_timer:
	engine->timer.takedown(dev);
792
793
out_gpio:
	engine->gpio.takedown(dev);
794
795
out_mc:
	engine->mc.takedown(dev);
796
797
out_gart:
	nouveau_mem_gart_fini(dev);
798
799
out_ttmvram:
	nouveau_mem_vram_fini(dev);
800
801
out_instmem:
	engine->instmem.takedown(dev);
802
803
804
out_gpuobj:
	nouveau_gpuobj_takedown(dev);
out_vram:
805
	engine->vram.takedown(dev);
806
out_bios:
807
	nouveau_pm_fini(dev);
808
	nouveau_bios_takedown(dev);
809
810
out_display_early:
	engine->display.late_takedown(dev);
811
812
813
out:
	vga_client_register(dev->pdev, NULL, NULL, NULL);
	return ret;
814
815
816
817
818
819
}

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;
820
	int e;
821

822
823
824
825
826
	if (dev->mode_config.num_crtc) {
		drm_kms_helper_poll_fini(dev);
		nouveau_fbcon_fini(dev);
		drm_vblank_cleanup(dev);
	}
827

828
	if (dev_priv->channel) {
829
		nouveau_channel_put_unlocked(&dev_priv->channel);
830
		nouveau_fence_fini(dev);
831
	}
832

833
	nouveau_backlight_exit(dev);
834
	nouveau_display_destroy(dev);
835

836
	if (!dev_priv->noaccel) {
837
		engine->fifo.takedown(dev);
838
839
		for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
			if (dev_priv->eng[e]) {
840
				dev_priv->eng[e]->fini(dev, e, false);
841
842
843
				dev_priv->eng[e]->destroy(dev,e );
			}
		}
844
845
846
	}
	engine->fb.takedown(dev);
	engine->timer.takedown(dev);
847
	engine->gpio.takedown(dev);
848
	engine->mc.takedown(dev);
849
	engine->display.late_takedown(dev);
850

851
852
853
854
855
	if (dev_priv->vga_ram) {
		nouveau_bo_unpin(dev_priv->vga_ram);
		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
	}

856
857
858
859
	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);
860
	nouveau_mem_gart_fini(dev);
861
	nouveau_mem_vram_fini(dev);
862

863
	engine->instmem.takedown(dev);
864
	nouveau_gpuobj_takedown(dev);
865
	engine->vram.takedown(dev);
866

Ben Skeggs's avatar
Ben Skeggs committed
867
	nouveau_irq_fini(dev);
868

869
	nouveau_pm_fini(dev);
870
	nouveau_bios_takedown(dev);
871

872
	vga_client_register(dev->pdev, NULL, NULL, NULL);
873
874
}

875
876
877
int
nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
{
878
	struct drm_nouveau_private *dev_priv = dev->dev_private;
879
	struct nouveau_fpriv *fpriv;
880
	int ret;
881
882
883
884
885
886

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

	spin_lock_init(&fpriv->lock);
887
888
	INIT_LIST_HEAD(&fpriv->channels);

889
890
891
892
893
894
895
896
897
	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) {
898
899
900
901
902
903
		ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
				     &fpriv->vm);
		if (ret) {
			kfree(fpriv);
			return ret;
		}
904
	}
905

906
907
908
909
	file_priv->driver_priv = fpriv;
	return 0;
}

910
911
912
913
914
915
916
/* 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);
}

917
918
919
920
void
nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
{
	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
921
	nouveau_vm_ref(NULL, &fpriv->vm, NULL);
922
923
924
	kfree(fpriv);
}

925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
/* 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
}

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
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;
984
	bool primary = false;
985
986
987
988
	dev_priv->apertures = nouveau_get_apertures(dev);
	if (!dev_priv->apertures)
		return -ENOMEM;

989
990
991
#ifdef CONFIG_X86
	primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
#endif
992

993
	remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary);
994
995
996
	return 0;
}

997
998
999
int nouveau_load(struct drm_device *dev, unsigned long flags)
{
	struct drm_nouveau_private *dev_priv;
1000
	uint32_t reg0, strap;
1001
	resource_size_t mmio_start_offs;
1002
	int ret;
1003
1004

	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
1005
1006
1007
1008
	if (!dev_priv) {
		ret = -ENOMEM;
		goto err_out;
	}
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
	dev->dev_private = dev_priv;
	dev_priv->dev = dev;

	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);

	/* resource 0 is mmio regs */
	/* resource 1 is linear FB */
	/* resource 2 is RAMIN (mmio regs + 0x1000000) */
	/* resource 6 is bios */

	/* map the mmio regs */
	mmio_start_offs = pci_resource_start(dev->pdev, 0);
	dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000);
	if (!dev_priv->mmio) {
		NV_ERROR(dev, "Unable to initialize the mmio mapping. "
			 "Please report your setup to " DRIVER_EMAIL "\n");
1028
		ret = -EINVAL;
1029
		goto err_priv;
1030
1031
1032
1033
1034
1035
	}
	NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
					(unsigned long long)mmio_start_offs);

#ifdef __BIG_ENDIAN
	/* Put the card in BE mode if it's not */
1036
1037
	if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001)
		nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

	DRM_MEMORYBARRIER();
#endif

	/* Time to determine the card architecture */
	reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);

	/* We're dealing with >=NV10 */
	if ((reg0 & 0x0f000000) > 0) {
		/* Bit 27-20 contain the architecture in hex */
		dev_priv->chipset = (reg0 & 0xff00000) >> 20;
	/* NV04 or NV05 */
	} else if ((reg0 & 0xff00fff0) == 0x20004000) {
1051
1052
1053
1054
		if (reg0 & 0x00f00000)
			dev_priv->chipset = 0x05;
		else
			dev_priv->chipset = 0x04;
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
	} else
		dev_priv->chipset = 0xff;

	switch (dev_priv->chipset & 0xf0) {
	case 0x00:
	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;
1075
1076
1077
	case 0xc0:
		dev_priv->card_type = NV_C0;
		break;
1078
1079
1080
	case 0xd0:
		dev_priv->card_type = NV_D0;
		break;
1081
1082
	default:
		NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0);
1083
1084
		ret = -EINVAL;
		goto err_mmio;
1085
1086
1087
1088
1089
	}

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

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
	/* determine frequency of timing crystal */
	strap = nv_rd32(dev, 0x101000);
	if ( dev_priv->chipset < 0x17 ||
	    (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25))
		strap &= 0x00000040;
	else
		strap &= 0x00400040;

	switch (strap) {
	case 0x00000000: dev_priv->crystal = 13500; break;
	case 0x00000040: dev_priv->crystal = 14318; break;
	case 0x00400000: dev_priv->crystal = 27000; break;
	case 0x00400040: dev_priv->crystal = 25000; break;
	}

	NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal);

1107
1108
1109
1110
1111
1112
1113
	/* Determine whether we'll attempt acceleration or not, some
	 * cards are disabled by default here due to them being known
	 * non-functional, or never been tested due to lack of hw.
	 */
	dev_priv->noaccel = !!nouveau_noaccel;
	if (nouveau_noaccel == -1) {
		switch (dev_priv->chipset) {
1114
1115
#if 0
		case 0xXX: /* known broken */
1116
1117
			NV_INFO(dev, "acceleration disabled by default, pass "
				     "noaccel=0 to force enable\n");
1118
1119
			dev_priv->noaccel = true;
			break;
1120
#endif
1121
1122
1123
1124
1125
1126
		default:
			dev_priv->noaccel = false;
			break;
		}
	}

1127
1128
	ret = nouveau_remove_conflicting_drivers(dev);
	if (ret)
1129
		goto err_mmio;
1130

Lucas De Marchi's avatar
Lucas De Marchi committed
1131
	/* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */
1132
1133
1134
1135
1136
1137
	if (dev_priv->card_type >= NV_40) {
		int ramin_bar = 2;
		if (pci_resource_len(dev->pdev, ramin_bar) == 0)
			ramin_bar = 3;

		dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar);
1138
1139
		dev_priv->ramin =
			ioremap(pci_resource_start(dev->pdev, ramin_bar),
1140
1141
				dev_priv->ramin_size);
		if (!dev_priv->ramin) {
1142
			NV_ERROR(dev, "Failed to map PRAMIN BAR\n");
1143
1144
			ret = -ENOMEM;
			goto err_mmio;