nouveau_state.c 39.9 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
	default:
		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
		return 1;
	}

487
488
489
490
491
492
493
494
495
	/* 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;
	}

496
497
498
499
500
501
	return 0;
}

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

510
511
512
513
514
515
516
	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;
}

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

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

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

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

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

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

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

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

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

595
596
597
598
599
600
601
602
603
604
605
606
607
608
	/* 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;
609

610
	ret = engine->vram.init(dev);
611
	if (ret)
612
		goto out_fb;
613

614
615
	/* PGPIO */
	ret = nouveau_gpio_create(dev);
616
	if (ret)
617
		goto out_vram;
618

619
620
621
622
	ret = nouveau_gpuobj_init(dev);
	if (ret)
		goto out_gpio;

623
624
	ret = engine->instmem.init(dev);
	if (ret)
625
		goto out_gpuobj;
626

627
	ret = nouveau_mem_vram_init(dev);
628
	if (ret)
629
		goto out_instmem;
630

631
632
633
634
	ret = nouveau_mem_gart_init(dev);
	if (ret)
		goto out_ttmvram;

635
	nouveau_pm_init(dev);
636

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

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

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

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

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

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

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

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

740
741
	nouveau_backlight_init(dev);

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

747
748
		ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
					    NvDmaFB, NvDmaTT);
749
750
		if (ret)
			goto out_fence;
751
752
753
754
755

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

	if (dev->mode_config.num_crtc) {
756
		ret = nouveau_display_init(dev);
757
758
759
760
		if (ret)
			goto out_chan;

		nouveau_fbcon_init(dev);
761
762
763
	}

	return 0;
764

765
766
out_chan:
	nouveau_channel_put_unlocked(&dev_priv->channel);
767
768
out_fence:
	nouveau_fence_fini(dev);
769
out_disp:
770
	nouveau_backlight_exit(dev);
771
	nouveau_display_destroy(dev);
772
out_irq:
Ben Skeggs's avatar
Ben Skeggs committed
773
	nouveau_irq_fini(dev);
774
out_fifo:
775
	if (!dev_priv->noaccel)
776
		engine->fifo.takedown(dev);
777
out_engine:
778
	if (!dev_priv->noaccel) {
779
		for (e = e - 1; e >= 0; e--) {
780
781
			if (!dev_priv->eng[e])
				continue;
782
			dev_priv->eng[e]->fini(dev, e, false);
783
			dev_priv->eng[e]->destroy(dev,e );
784
785
		}
	}
786
	nouveau_pm_fini(dev);
787
	nouveau_mem_gart_fini(dev);
788
789
out_ttmvram:
	nouveau_mem_vram_fini(dev);
790
791
out_instmem:
	engine->instmem.takedown(dev);
792
793
out_gpuobj:
	nouveau_gpuobj_takedown(dev);
794
795
out_gpio:
	nouveau_gpio_destroy(dev);
796
out_vram:
797
	engine->vram.takedown(dev);
798
799
800
801
802
803
out_fb:
	engine->fb.takedown(dev);
out_timer:
	engine->timer.takedown(dev);
out_mc:
	engine->mc.takedown(dev);
804
805
out_bios:
	nouveau_bios_takedown(dev);
806
807
out_display_early:
	engine->display.late_takedown(dev);
808
809
810
out:
	vga_client_register(dev->pdev, NULL, NULL, NULL);
	return ret;
811
812
813
814
815
816
}

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;
817
	int e;
818

819
820
	if (dev->mode_config.num_crtc) {
		nouveau_fbcon_fini(dev);
821
		nouveau_display_fini(dev);
822
	}
823

824
	if (dev_priv->channel) {
825
		nouveau_channel_put_unlocked(&dev_priv->channel);
826
		nouveau_fence_fini(dev);
827
	}
828

829
	nouveau_backlight_exit(dev);
830
	nouveau_display_destroy(dev);
831

832
	if (!dev_priv->noaccel) {
833
		engine->fifo.takedown(dev);
834
835
		for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
			if (dev_priv->eng[e]) {
836
				dev_priv->eng[e]->fini(dev, e, false);
837
838
839
				dev_priv->eng[e]->destroy(dev,e );
			}
		}
840
	}
841

842
843
844
845
846
	if (dev_priv->vga_ram) {
		nouveau_bo_unpin(dev_priv->vga_ram);
		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
	}

847
848
849
850
	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);
851
	nouveau_mem_gart_fini(dev);
852
	nouveau_mem_vram_fini(dev);
853

854
	engine->instmem.takedown(dev);
855
	nouveau_gpuobj_takedown(dev);
856

857
	nouveau_pm_fini(dev);
858
859
860
861
862
863
864

	nouveau_gpio_destroy(dev);
	engine->vram.takedown(dev);
	engine->fb.takedown(dev);
	engine->timer.takedown(dev);
	engine->mc.takedown(dev);

865
	nouveau_bios_takedown(dev);
866
867
868
	engine->display.late_takedown(dev);

	nouveau_irq_fini(dev);
869

870
	vga_client_register(dev->pdev, NULL, NULL, NULL);
871
872
}

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

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

	spin_lock_init(&fpriv->lock);
885
886
	INIT_LIST_HEAD(&fpriv->channels);

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

904
905
906
907
	file_priv->driver_priv = fpriv;
	return 0;
}

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

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

923
924
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
/* 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
}

953
954
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
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;
982
	bool primary = false;
983
984
985
986
	dev_priv->apertures = nouveau_get_apertures(dev);
	if (!dev_priv->apertures)
		return -ENOMEM;

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

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

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

	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
1003
1004
1005
1006
	if (!dev_priv) {
		ret = -ENOMEM;
		goto err_out;
	}
1007
1008
1009
	dev->dev_private = dev_priv;
	dev_priv->dev = dev;

1010
1011
	pci_set_master(dev->pdev);

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
	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
		case 0xd9: /* known broken */
1115
1116
			NV_INFO(dev, "acceleration disabled by default, pass "
				     "noaccel=0 to force enable\n");
1117
1118
1119
1120
1121
1122
1123
1124
			dev_priv->noaccel = true;
			break;
		default:
			dev_priv->noaccel = false;
			break;
		}
	}