]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/gpu/drm/nouveau/nouveau_state.c
drm/nouveau/device: include the official chipset names
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / nouveau / nouveau_state.c
CommitLineData
6ee73861
BS
1/*
2 * Copyright 2005 Stephane Marchesin
3 * Copyright 2008 Stuart Bennett
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26#include <linux/swab.h>
5a0e3ad6 27#include <linux/slab.h>
6ee73861
BS
28#include "drmP.h"
29#include "drm.h"
30#include "drm_sarea.h"
31#include "drm_crtc_helper.h"
32#include <linux/vgaarb.h>
6a9ee8af 33#include <linux/vga_switcheroo.h>
6ee73861
BS
34
35#include "nouveau_drv.h"
94580299 36#include <nouveau_drm.h>
38651674 37#include "nouveau_fbcon.h"
330c5988 38#include "nouveau_pm.h"
017e6e29 39#include "nv04_display.h"
6ee73861 40#include "nv50_display.h"
c0077061 41#include "nouveau_acpi.h"
6ee73861 42
6ee73861 43static void nouveau_stub_takedown(struct drm_device *dev) {}
ee2e0131 44static int nouveau_stub_init(struct drm_device *dev) { return 0; }
6ee73861
BS
45
46static int nouveau_init_engine_ptrs(struct drm_device *dev)
47{
48 struct drm_nouveau_private *dev_priv = dev->dev_private;
49 struct nouveau_engine *engine = &dev_priv->engine;
50
51 switch (dev_priv->chipset & 0xf0) {
52 case 0x00:
c88c2e06
FJ
53 engine->display.early_init = nv04_display_early_init;
54 engine->display.late_takedown = nv04_display_late_takedown;
55 engine->display.create = nv04_display_create;
c88c2e06 56 engine->display.destroy = nv04_display_destroy;
2a44e499
BS
57 engine->display.init = nv04_display_init;
58 engine->display.fini = nv04_display_fini;
36f1317e
BS
59 engine->pm.clocks_get = nv04_pm_clocks_get;
60 engine->pm.clocks_pre = nv04_pm_clocks_pre;
61 engine->pm.clocks_set = nv04_pm_clocks_set;
6ee73861
BS
62 break;
63 case 0x10:
c88c2e06
FJ
64 engine->display.early_init = nv04_display_early_init;
65 engine->display.late_takedown = nv04_display_late_takedown;
66 engine->display.create = nv04_display_create;
c88c2e06 67 engine->display.destroy = nv04_display_destroy;
2a44e499
BS
68 engine->display.init = nv04_display_init;
69 engine->display.fini = nv04_display_fini;
36f1317e
BS
70 engine->pm.clocks_get = nv04_pm_clocks_get;
71 engine->pm.clocks_pre = nv04_pm_clocks_pre;
72 engine->pm.clocks_set = nv04_pm_clocks_set;
6ee73861
BS
73 break;
74 case 0x20:
c88c2e06
FJ
75 engine->display.early_init = nv04_display_early_init;
76 engine->display.late_takedown = nv04_display_late_takedown;
77 engine->display.create = nv04_display_create;
c88c2e06 78 engine->display.destroy = nv04_display_destroy;
2a44e499
BS
79 engine->display.init = nv04_display_init;
80 engine->display.fini = nv04_display_fini;
36f1317e
BS
81 engine->pm.clocks_get = nv04_pm_clocks_get;
82 engine->pm.clocks_pre = nv04_pm_clocks_pre;
83 engine->pm.clocks_set = nv04_pm_clocks_set;
6ee73861
BS
84 break;
85 case 0x30:
c88c2e06
FJ
86 engine->display.early_init = nv04_display_early_init;
87 engine->display.late_takedown = nv04_display_late_takedown;
88 engine->display.create = nv04_display_create;
c88c2e06 89 engine->display.destroy = nv04_display_destroy;
2a44e499
BS
90 engine->display.init = nv04_display_init;
91 engine->display.fini = nv04_display_fini;
36f1317e
BS
92 engine->pm.clocks_get = nv04_pm_clocks_get;
93 engine->pm.clocks_pre = nv04_pm_clocks_pre;
94 engine->pm.clocks_set = nv04_pm_clocks_set;
442b626e
BS
95 engine->pm.voltage_get = nouveau_voltage_gpio_get;
96 engine->pm.voltage_set = nouveau_voltage_gpio_set;
6ee73861
BS
97 break;
98 case 0x40:
99 case 0x60:
c88c2e06
FJ
100 engine->display.early_init = nv04_display_early_init;
101 engine->display.late_takedown = nv04_display_late_takedown;
102 engine->display.create = nv04_display_create;
c88c2e06 103 engine->display.destroy = nv04_display_destroy;
2a44e499
BS
104 engine->display.init = nv04_display_init;
105 engine->display.fini = nv04_display_fini;
1262a206
BS
106 engine->pm.clocks_get = nv40_pm_clocks_get;
107 engine->pm.clocks_pre = nv40_pm_clocks_pre;
108 engine->pm.clocks_set = nv40_pm_clocks_set;
442b626e
BS
109 engine->pm.voltage_get = nouveau_voltage_gpio_get;
110 engine->pm.voltage_set = nouveau_voltage_gpio_set;
8155cac4 111 engine->pm.temp_get = nv40_temp_get;
69346180
BS
112 engine->pm.pwm_get = nv40_pm_pwm_get;
113 engine->pm.pwm_set = nv40_pm_pwm_set;
6ee73861
BS
114 break;
115 case 0x50:
116 case 0x80: /* gotta love NVIDIA's consistency.. */
117 case 0x90:
d9f61c2d 118 case 0xa0:
c88c2e06
FJ
119 engine->display.early_init = nv50_display_early_init;
120 engine->display.late_takedown = nv50_display_late_takedown;
121 engine->display.create = nv50_display_create;
c88c2e06 122 engine->display.destroy = nv50_display_destroy;
2a44e499
BS
123 engine->display.init = nv50_display_init;
124 engine->display.fini = nv50_display_fini;
fade7ad5 125 switch (dev_priv->chipset) {
bd2e597d
BS
126 case 0x84:
127 case 0x86:
128 case 0x92:
129 case 0x94:
130 case 0x96:
131 case 0x98:
132 case 0xa0:
5f80198e
BS
133 case 0xaa:
134 case 0xac:
bd2e597d 135 case 0x50:
f3fbaf34
BS
136 engine->pm.clocks_get = nv50_pm_clocks_get;
137 engine->pm.clocks_pre = nv50_pm_clocks_pre;
138 engine->pm.clocks_set = nv50_pm_clocks_set;
fade7ad5 139 break;
bd2e597d 140 default:
ca94a71f
BS
141 engine->pm.clocks_get = nva3_pm_clocks_get;
142 engine->pm.clocks_pre = nva3_pm_clocks_pre;
143 engine->pm.clocks_set = nva3_pm_clocks_set;
bd2e597d 144 break;
fade7ad5 145 }
02c30ca0
BS
146 engine->pm.voltage_get = nouveau_voltage_gpio_get;
147 engine->pm.voltage_set = nouveau_voltage_gpio_set;
8155cac4
FJ
148 if (dev_priv->chipset >= 0x84)
149 engine->pm.temp_get = nv84_temp_get;
150 else
151 engine->pm.temp_get = nv40_temp_get;
5a4267ab
BS
152 engine->pm.pwm_get = nv50_pm_pwm_get;
153 engine->pm.pwm_set = nv50_pm_pwm_set;
6ee73861 154 break;
d9f61c2d 155 case 0xc0:
4b223eef
BS
156 engine->display.early_init = nv50_display_early_init;
157 engine->display.late_takedown = nv50_display_late_takedown;
158 engine->display.create = nv50_display_create;
4b223eef 159 engine->display.destroy = nv50_display_destroy;
2a44e499
BS
160 engine->display.init = nv50_display_init;
161 engine->display.fini = nv50_display_fini;
74cfad18 162 engine->pm.temp_get = nv84_temp_get;
354d0781 163 engine->pm.clocks_get = nvc0_pm_clocks_get;
045da4e5
BS
164 engine->pm.clocks_pre = nvc0_pm_clocks_pre;
165 engine->pm.clocks_set = nvc0_pm_clocks_set;
3c71c233 166 engine->pm.voltage_get = nouveau_voltage_gpio_get;
da1dc4cf 167 engine->pm.voltage_set = nouveau_voltage_gpio_set;
5a4267ab
BS
168 engine->pm.pwm_get = nv50_pm_pwm_get;
169 engine->pm.pwm_set = nv50_pm_pwm_set;
4b223eef 170 break;
d9f61c2d 171 case 0xd0:
d9f61c2d
BS
172 engine->display.early_init = nouveau_stub_init;
173 engine->display.late_takedown = nouveau_stub_takedown;
26f6d88b 174 engine->display.create = nvd0_display_create;
26f6d88b 175 engine->display.destroy = nvd0_display_destroy;
2a44e499
BS
176 engine->display.init = nvd0_display_init;
177 engine->display.fini = nvd0_display_fini;
61091837 178 engine->pm.temp_get = nv84_temp_get;
4784e4aa 179 engine->pm.clocks_get = nvc0_pm_clocks_get;
045da4e5
BS
180 engine->pm.clocks_pre = nvc0_pm_clocks_pre;
181 engine->pm.clocks_set = nvc0_pm_clocks_set;
4784e4aa
BS
182 engine->pm.voltage_get = nouveau_voltage_gpio_get;
183 engine->pm.voltage_set = nouveau_voltage_gpio_set;
d9f61c2d 184 break;
68455a43 185 case 0xe0:
68455a43
BS
186 engine->display.early_init = nouveau_stub_init;
187 engine->display.late_takedown = nouveau_stub_takedown;
188 engine->display.create = nvd0_display_create;
189 engine->display.destroy = nvd0_display_destroy;
190 engine->display.init = nvd0_display_init;
191 engine->display.fini = nvd0_display_fini;
68455a43 192 break;
6ee73861
BS
193 default:
194 NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
195 return 1;
196 }
197
03bc9675
BS
198 /* headless mode */
199 if (nouveau_modeset == 2) {
200 engine->display.early_init = nouveau_stub_init;
201 engine->display.late_takedown = nouveau_stub_takedown;
202 engine->display.create = nouveau_stub_init;
203 engine->display.init = nouveau_stub_init;
204 engine->display.destroy = nouveau_stub_takedown;
205 }
206
6ee73861
BS
207 return 0;
208}
209
210static unsigned int
211nouveau_vga_set_decode(void *priv, bool state)
212{
9967b948
MK
213 struct drm_device *dev = priv;
214 struct drm_nouveau_private *dev_priv = dev->dev_private;
215
216 if (dev_priv->chipset >= 0x40)
217 nv_wr32(dev, 0x88054, state);
218 else
219 nv_wr32(dev, 0x1854, state);
220
6ee73861
BS
221 if (state)
222 return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
223 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
224 else
225 return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
226}
227
6a9ee8af
DA
228static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
229 enum vga_switcheroo_state state)
230{
fbf81762 231 struct drm_device *dev = pci_get_drvdata(pdev);
6a9ee8af
DA
232 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
233 if (state == VGA_SWITCHEROO_ON) {
234 printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
5bcf719b 235 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
6a9ee8af 236 nouveau_pci_resume(pdev);
fbf81762 237 drm_kms_helper_poll_enable(dev);
5bcf719b 238 dev->switch_power_state = DRM_SWITCH_POWER_ON;
6a9ee8af
DA
239 } else {
240 printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
5bcf719b 241 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
fbf81762 242 drm_kms_helper_poll_disable(dev);
d099230c 243 nouveau_switcheroo_optimus_dsm();
6a9ee8af 244 nouveau_pci_suspend(pdev, pmm);
5bcf719b 245 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
6a9ee8af
DA
246 }
247}
248
8d608aa6
DA
249static void nouveau_switcheroo_reprobe(struct pci_dev *pdev)
250{
251 struct drm_device *dev = pci_get_drvdata(pdev);
252 nouveau_fbcon_output_poll_changed(dev);
253}
254
6a9ee8af
DA
255static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev)
256{
257 struct drm_device *dev = pci_get_drvdata(pdev);
258 bool can_switch;
259
260 spin_lock(&dev->count_lock);
261 can_switch = (dev->open_count == 0);
262 spin_unlock(&dev->count_lock);
263 return can_switch;
264}
265
26ec685f
TI
266static const struct vga_switcheroo_client_ops nouveau_switcheroo_ops = {
267 .set_gpu_state = nouveau_switcheroo_set_state,
268 .reprobe = nouveau_switcheroo_reprobe,
269 .can_switch = nouveau_switcheroo_can_switch,
270};
271
6ee73861
BS
272int
273nouveau_card_init(struct drm_device *dev)
274{
275 struct drm_nouveau_private *dev_priv = dev->dev_private;
276 struct nouveau_engine *engine;
ebb945a9 277 int ret;
6ee73861 278
6ee73861 279 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
26ec685f 280 vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops);
6ee73861
BS
281
282 /* Initialise internal driver API hooks */
283 ret = nouveau_init_engine_ptrs(dev);
284 if (ret)
c5804be0 285 goto out;
6ee73861 286 engine = &dev_priv->engine;
ff9e5279 287 spin_lock_init(&dev_priv->context_switch_lock);
6ee73861 288
c88c2e06
FJ
289 /* Make the CRTCs and I2C buses accessible */
290 ret = engine->display.early_init(dev);
291 if (ret)
292 goto out;
293
6ee73861 294 /* Parse BIOS tables / Run init tables if card not POSTed */
cd0b072f
BS
295 ret = nouveau_bios_init(dev);
296 if (ret)
c88c2e06 297 goto out_display_early;
6ee73861 298
4c5df493
BS
299 /* workaround an odd issue on nvc1 by disabling the device's
300 * nosnoop capability. hopefully won't cause issues until a
301 * better fix is found - assuming there is one...
302 */
303 if (dev_priv->chipset == 0xc1) {
304 nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
305 }
306
1575b364
BS
307 ret = nouveau_irq_init(dev);
308 if (ret)
ebb945a9 309 goto out_bios;
1575b364 310
27d5030a 311 ret = nouveau_display_create(dev);
e88efe05 312 if (ret)
1575b364 313 goto out_irq;
6ee73861 314
10b461e4 315 nouveau_backlight_init(dev);
7d3a766b 316 nouveau_pm_init(dev);
10b461e4 317
1575b364 318 if (dev->mode_config.num_crtc) {
f62b27db 319 ret = nouveau_display_init(dev);
1575b364 320 if (ret)
ebb945a9 321 goto out_pm;
6ee73861
BS
322 }
323
6ee73861 324 return 0;
c5804be0 325
7d3a766b
BS
326out_pm:
327 nouveau_pm_fini(dev);
10b461e4 328 nouveau_backlight_exit(dev);
27d5030a 329 nouveau_display_destroy(dev);
c5804be0 330out_irq:
35fa2f2a 331 nouveau_irq_fini(dev);
c5804be0
MK
332out_bios:
333 nouveau_bios_takedown(dev);
c88c2e06
FJ
334out_display_early:
335 engine->display.late_takedown(dev);
c5804be0 336out:
5c5ed6e2 337 vga_switcheroo_unregister_client(dev->pdev);
c5804be0
MK
338 vga_client_register(dev->pdev, NULL, NULL, NULL);
339 return ret;
6ee73861
BS
340}
341
342static void nouveau_card_takedown(struct drm_device *dev)
343{
344 struct drm_nouveau_private *dev_priv = dev->dev_private;
345 struct nouveau_engine *engine = &dev_priv->engine;
346
ebb945a9 347 if (dev->mode_config.num_crtc)
f62b27db 348 nouveau_display_fini(dev);
06b75e35 349
7d3a766b 350 nouveau_pm_fini(dev);
10b461e4 351 nouveau_backlight_exit(dev);
27d5030a 352 nouveau_display_destroy(dev);
06b75e35 353
b6d3d871 354 nouveau_bios_takedown(dev);
668b6c09
BS
355 engine->display.late_takedown(dev);
356
357 nouveau_irq_fini(dev);
6ee73861 358
5c5ed6e2 359 vga_switcheroo_unregister_client(dev->pdev);
b6d3d871 360 vga_client_register(dev->pdev, NULL, NULL, NULL);
6ee73861
BS
361}
362
6ee73861
BS
363/* first module load, setup the mmio/fb mapping */
364/* KMS: we need mmio at load time, not when the first drm client opens. */
365int nouveau_firstopen(struct drm_device *dev)
366{
367 return 0;
368}
369
370/* if we have an OF card, copy vbios to RAMIN */
371static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev)
372{
373#if defined(__powerpc__)
374 int size, i;
375 const uint32_t *bios;
376 struct device_node *dn = pci_device_to_OF_node(dev->pdev);
377 if (!dn) {
378 NV_INFO(dev, "Unable to get the OF node\n");
379 return;
380 }
381
382 bios = of_get_property(dn, "NVDA,BMP", &size);
383 if (bios) {
384 for (i = 0; i < size; i += 4)
385 nv_wi32(dev, i, bios[i/4]);
386 NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size);
387 } else {
388 NV_INFO(dev, "Unable to get the OF bios\n");
389 }
390#endif
391}
392
393int nouveau_load(struct drm_device *dev, unsigned long flags)
394{
395 struct drm_nouveau_private *dev_priv;
2f5394c3 396 uint32_t reg0 = ~0, strap;
cd0b072f 397 int ret;
6ee73861
BS
398
399 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
a0d069ea
DC
400 if (!dev_priv) {
401 ret = -ENOMEM;
402 goto err_out;
403 }
94580299 404 dev_priv->newpriv = dev->dev_private;
6ee73861
BS
405 dev->dev_private = dev_priv;
406 dev_priv->dev = dev;
407
6ee73861
BS
408 NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
409 dev->pci_vendor, dev->pci_device, dev->pdev->class);
410
586c55f6
BS
411 /* determine chipset and derive architecture from it */
412 reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
413 if ((reg0 & 0x0f000000) > 0) {
414 dev_priv->chipset = (reg0 & 0xff00000) >> 20;
415 switch (dev_priv->chipset & 0xf0) {
416 case 0x10:
417 case 0x20:
418 case 0x30:
419 dev_priv->card_type = dev_priv->chipset & 0xf0;
420 break;
421 case 0x40:
422 case 0x60:
423 dev_priv->card_type = NV_40;
424 break;
425 case 0x50:
426 case 0x80:
427 case 0x90:
428 case 0xa0:
429 dev_priv->card_type = NV_50;
430 break;
431 case 0xc0:
432 dev_priv->card_type = NV_C0;
433 break;
434 case 0xd0:
435 dev_priv->card_type = NV_D0;
436 break;
437 case 0xe0:
438 dev_priv->card_type = NV_E0;
439 break;
440 default:
441 break;
2f5394c3 442 }
586c55f6
BS
443 } else
444 if ((reg0 & 0xff00fff0) == 0x20004000) {
445 if (reg0 & 0x00f00000)
446 dev_priv->chipset = 0x05;
447 else
448 dev_priv->chipset = 0x04;
449 dev_priv->card_type = NV_04;
2f5394c3
BS
450 }
451
452 if (!dev_priv->card_type) {
453 NV_ERROR(dev, "unsupported chipset 0x%08x\n", reg0);
454 ret = -EINVAL;
455 goto err_priv;
456 }
457
42eddbd7 458 NV_INFO(dev, "Detected an NV%02x generation card (0x%08x)\n",
2f5394c3 459 dev_priv->card_type, reg0);
6ee73861 460
f2cbe46f
BS
461 /* determine frequency of timing crystal */
462 strap = nv_rd32(dev, 0x101000);
463 if ( dev_priv->chipset < 0x17 ||
464 (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25))
465 strap &= 0x00000040;
466 else
467 strap &= 0x00400040;
468
469 switch (strap) {
470 case 0x00000000: dev_priv->crystal = 13500; break;
471 case 0x00000040: dev_priv->crystal = 14318; break;
472 case 0x00400000: dev_priv->crystal = 27000; break;
473 case 0x00400040: dev_priv->crystal = 25000; break;
474 }
475
476 NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal);
477
6ee73861
BS
478 nouveau_OF_copy_vbios_to_ramin(dev);
479
6ee73861 480 /* For kernel modesetting, init card now and bring up fbcon */
cd0b072f
BS
481 ret = nouveau_card_init(dev);
482 if (ret)
3863c9bc 483 goto err_priv;
6ee73861
BS
484
485 return 0;
a0d069ea 486
a0d069ea 487err_priv:
94580299 488 dev->dev_private = dev_priv->newpriv;
a0d069ea 489 kfree(dev_priv);
a0d069ea
DC
490err_out:
491 return ret;
6ee73861
BS
492}
493
6ee73861
BS
494void nouveau_lastclose(struct drm_device *dev)
495{
5ccb377f 496 vga_switcheroo_process_delayed_switch();
6ee73861
BS
497}
498
499int nouveau_unload(struct drm_device *dev)
500{
501 struct drm_nouveau_private *dev_priv = dev->dev_private;
502
cd0b072f 503 nouveau_card_takedown(dev);
6ee73861 504
94580299 505 dev->dev_private = dev_priv->newpriv;
6ee73861 506 kfree(dev_priv);
6ee73861
BS
507 return 0;
508}