aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-02-20 02:46:25 -0500
committerDave Airlie <airlied@redhat.com>2013-02-20 02:54:13 -0500
commit1f3a574a4bfe86ebf7d51fac37e0668397372fd8 (patch)
tree86308b3a63ea03151eff6e6b5c4ea96e2f509993
parentb81e059ec5a7128622ab5d74d78e9b4f361b54ae (diff)
parenta91ed42de25e7e81159c0dd59faf8cac9dfa1d32 (diff)
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
Nothing terribly exciting in here probably: - reworked thermal stuff from mupuf/I, has a chance of possibly working well enough when we get to being able to reclock.. - driver will report mmio access faults on chipsets where it's supported - will now sleep waiting on fences on nv84+ rather than polling - some cleanup of the internal fencing, looking towards sli/dmabuf sync - initial support for anx9805 dp/tmds encoder - nv50+ display fixes related to the above, and also might fix a few other issues - nicer error reporting (will log process names with channel errors) - various other random fixes * 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (87 commits) nouveau: ACPI support depends on X86 and X86_PLATFORM_DEVICES drm/nouveau/i2c: add support for ddc/aux, and dp link training on anx9805 drm/nv50: initial kms support for off-chip TMDS/DP encoders drm/nv50-/disp: initial supervisor support for off-chip encoders drm/nv50-/disp: initial work towards supporting external encoders drm/nv50-/kms: remove unnecessary wait-for-completion points drm/nv50-/disp: move DP link training to core and train from supervisor drm/nv50-/disp: handle supervisor tasks from workqueue drm/nouveau/i2c: create proper chipset-specific class implementations drm/nv50-/disp: 0x0000 is a valid udisp config value drm/nv50/devinit: reverse the logic for running encoder init scripts drm/nouveau/bios: store a type/mask hash in parsed dcb data drm/nouveau/i2c: extend type to 16-bits, add lookup-by-type function drm/nouveau/i2c: aux channels not necessarily on nvio drm/nouveau/i2c: fix a bit of a thinko in nv_wri2cr helper functions drm/nouveau/bios: parse external transmitter type if off-chip drm/nouveau: store i2c port pointer directly in nouveau_encoder drm/nouveau/i2c: handle i2c/aux mux outside of port lookup function drm/nv50/graph: avoid touching 400724, it doesn't exist drm/nouveau: Fix DPMS 1 on G4 Snowball, from snow white to coal black. ...
-rw-r--r--Documentation/thermal/nouveau_thermal81
-rw-r--r--drivers/gpu/drm/nouveau/Kconfig5
-rw-r--r--drivers/gpu/drm/nouveau/Makefile28
-rw-r--r--drivers/gpu/drm/nouveau/core/core/client.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/core/enum.c11
-rw-r--r--drivers/gpu/drm/nouveau/core/core/event.c106
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nva3.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/base.c52
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.c346
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.h78
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv04.c33
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c267
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h37
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c24
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c24
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c156
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c17
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c140
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c25
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c153
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c90
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/base.c21
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c187
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c109
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c64
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv04.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv10.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv20.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv50.c53
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c33
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nve0.c44
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.c40
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nvc0.c29
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h44
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/client.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/device.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/enum.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/event.h36
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/object.h12
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/printk.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/disp.h27
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/fifo.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/software.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h11
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h16
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h19
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bus.h41
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/gpio.h39
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/i2c.h127
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/therm.h37
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/timer.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/os.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c32
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c11
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/init.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/therm.c28
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c76
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c95
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c112
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c105
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c101
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/base.c5
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv04.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv10.c25
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv20.c13
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv30.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv40.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv50.c51
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c43
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nve0.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c64
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/base.c140
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c40
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c45
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c131
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h17
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c279
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c154
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c481
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c143
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c135
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c149
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h32
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c285
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c124
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c218
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c244
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c54
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c107
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c115
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/ic.c54
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c82
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c199
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c99
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c153
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h103
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/temp.c162
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c130
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h12
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c96
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c85
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c297
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c45
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c103
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h42
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c81
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c233
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dfp.c4
-rw-r--r--drivers/gpu/drm/nouveau/nv04_display.c16
-rw-r--r--drivers/gpu/drm/nouveau/nv04_display.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fence.c6
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fence.c118
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fence.h19
-rw-r--r--drivers/gpu/drm/nouveau/nv17_fence.c149
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c294
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fence.c36
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c214
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fence.c186
149 files changed, 7004 insertions, 2740 deletions
diff --git a/Documentation/thermal/nouveau_thermal b/Documentation/thermal/nouveau_thermal
new file mode 100644
index 000000000000..efceb7828f54
--- /dev/null
+++ b/Documentation/thermal/nouveau_thermal
@@ -0,0 +1,81 @@
1Kernel driver nouveau
2===================
3
4Supported chips:
5* NV43+
6
7Authors: Martin Peres (mupuf) <martin.peres@labri.fr>
8
9Description
10---------
11
12This driver allows to read the GPU core temperature, drive the GPU fan and
13set temperature alarms.
14
15Currently, due to the absence of in-kernel API to access HWMON drivers, Nouveau
16cannot access any of the i2c external monitoring chips it may find. If you
17have one of those, temperature and/or fan management through Nouveau's HWMON
18interface is likely not to work. This document may then not cover your situation
19entirely.
20
21Temperature management
22--------------------
23
24Temperature is exposed under as a read-only HWMON attribute temp1_input.
25
26In order to protect the GPU from overheating, Nouveau supports 4 configurable
27temperature thresholds:
28
29 * Fan_boost: Fan speed is set to 100% when reaching this temperature;
30 * Downclock: The GPU will be downclocked to reduce its power dissipation;
31 * Critical: The GPU is put on hold to further lower power dissipation;
32 * Shutdown: Shut the computer down to protect your GPU.
33
34WARNING: Some of these thresholds may not be used by Nouveau depending
35on your chipset.
36
37The default value for these thresholds comes from the GPU's vbios. These
38thresholds can be configured thanks to the following HWMON attributes:
39
40 * Fan_boost: temp1_auto_point1_temp and temp1_auto_point1_temp_hyst;
41 * Downclock: temp1_max and temp1_max_hyst;
42 * Critical: temp1_crit and temp1_crit_hyst;
43 * Shutdown: temp1_emergency and temp1_emergency_hyst.
44
45NOTE: Remember that the values are stored as milli degrees Celcius. Don't forget
46to multiply!
47
48Fan management
49------------
50
51Not all cards have a drivable fan. If you do, then the following HWMON
52attributes should be available:
53
54 * pwm1_enable: Current fan management mode (NONE, MANUAL or AUTO);
55 * pwm1: Current PWM value (power percentage);
56 * pwm1_min: The minimum PWM speed allowed;
57 * pwm1_max: The maximum PWM speed allowed (bypassed when hitting Fan_boost);
58
59You may also have the following attribute:
60
61 * fan1_input: Speed in RPM of your fan.
62
63Your fan can be driven in different modes:
64
65 * 0: The fan is left untouched;
66 * 1: The fan can be driven in manual (use pwm1 to change the speed);
67 * 2; The fan is driven automatically depending on the temperature.
68
69NOTE: Be sure to use the manual mode if you want to drive the fan speed manually
70
71NOTE2: Not all fan management modes may be supported on all chipsets. We are
72working on it.
73
74Bug reports
75---------
76
77Thermal management on Nouveau is new and may not work on all cards. If you have
78inquiries, please ping mupuf on IRC (#nouveau, freenode).
79
80Bug reports should be filled on Freedesktop's bug tracker. Please follow
81http://nouveau.freedesktop.org/wiki/Bugs
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index 47ccc1ad5405..a7ff6d5a34b9 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -11,8 +11,9 @@ config DRM_NOUVEAU
11 select FRAMEBUFFER_CONSOLE if !EXPERT 11 select FRAMEBUFFER_CONSOLE if !EXPERT
12 select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT 12 select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT
13 select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT 13 select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT
14 select ACPI_WMI if ACPI 14 select X86_PLATFORM_DEVICES if ACPI && X86
15 select MXM_WMI if ACPI 15 select ACPI_WMI if ACPI && X86
16 select MXM_WMI if ACPI && X86
16 select POWER_SUPPLY 17 select POWER_SUPPLY
17 help 18 help
18 Choose this option for open-source nVidia support. 19 Choose this option for open-source nVidia support.
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index ab25752a0b1e..51d09729fc56 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -11,6 +11,7 @@ nouveau-y := core/core/client.o
11nouveau-y += core/core/engctx.o 11nouveau-y += core/core/engctx.o
12nouveau-y += core/core/engine.o 12nouveau-y += core/core/engine.o
13nouveau-y += core/core/enum.o 13nouveau-y += core/core/enum.o
14nouveau-y += core/core/event.o
14nouveau-y += core/core/falcon.o 15nouveau-y += core/core/falcon.o
15nouveau-y += core/core/gpuobj.o 16nouveau-y += core/core/gpuobj.o
16nouveau-y += core/core/handle.o 17nouveau-y += core/core/handle.o
@@ -40,6 +41,11 @@ nouveau-y += core/subdev/bios/mxm.o
40nouveau-y += core/subdev/bios/perf.o 41nouveau-y += core/subdev/bios/perf.o
41nouveau-y += core/subdev/bios/pll.o 42nouveau-y += core/subdev/bios/pll.o
42nouveau-y += core/subdev/bios/therm.o 43nouveau-y += core/subdev/bios/therm.o
44nouveau-y += core/subdev/bios/xpio.o
45nouveau-y += core/subdev/bus/nv04.o
46nouveau-y += core/subdev/bus/nv31.o
47nouveau-y += core/subdev/bus/nv50.o
48nouveau-y += core/subdev/bus/nvc0.o
43nouveau-y += core/subdev/clock/nv04.o 49nouveau-y += core/subdev/clock/nv04.o
44nouveau-y += core/subdev/clock/nv40.o 50nouveau-y += core/subdev/clock/nv40.o
45nouveau-y += core/subdev/clock/nv50.o 51nouveau-y += core/subdev/clock/nv50.o
@@ -85,9 +91,16 @@ nouveau-y += core/subdev/gpio/base.o
85nouveau-y += core/subdev/gpio/nv10.o 91nouveau-y += core/subdev/gpio/nv10.o
86nouveau-y += core/subdev/gpio/nv50.o 92nouveau-y += core/subdev/gpio/nv50.o
87nouveau-y += core/subdev/gpio/nvd0.o 93nouveau-y += core/subdev/gpio/nvd0.o
94nouveau-y += core/subdev/gpio/nve0.o
88nouveau-y += core/subdev/i2c/base.o 95nouveau-y += core/subdev/i2c/base.o
96nouveau-y += core/subdev/i2c/anx9805.o
89nouveau-y += core/subdev/i2c/aux.o 97nouveau-y += core/subdev/i2c/aux.o
90nouveau-y += core/subdev/i2c/bit.o 98nouveau-y += core/subdev/i2c/bit.o
99nouveau-y += core/subdev/i2c/nv04.o
100nouveau-y += core/subdev/i2c/nv4e.o
101nouveau-y += core/subdev/i2c/nv50.o
102nouveau-y += core/subdev/i2c/nv94.o
103nouveau-y += core/subdev/i2c/nvd0.o
91nouveau-y += core/subdev/ibus/nvc0.o 104nouveau-y += core/subdev/ibus/nvc0.o
92nouveau-y += core/subdev/ibus/nve0.o 105nouveau-y += core/subdev/ibus/nve0.o
93nouveau-y += core/subdev/instmem/base.o 106nouveau-y += core/subdev/instmem/base.o
@@ -106,10 +119,15 @@ nouveau-y += core/subdev/mxm/mxms.o
106nouveau-y += core/subdev/mxm/nv50.o 119nouveau-y += core/subdev/mxm/nv50.o
107nouveau-y += core/subdev/therm/base.o 120nouveau-y += core/subdev/therm/base.o
108nouveau-y += core/subdev/therm/fan.o 121nouveau-y += core/subdev/therm/fan.o
122nouveau-y += core/subdev/therm/fannil.o
123nouveau-y += core/subdev/therm/fanpwm.o
124nouveau-y += core/subdev/therm/fantog.o
109nouveau-y += core/subdev/therm/ic.o 125nouveau-y += core/subdev/therm/ic.o
126nouveau-y += core/subdev/therm/temp.o
110nouveau-y += core/subdev/therm/nv40.o 127nouveau-y += core/subdev/therm/nv40.o
111nouveau-y += core/subdev/therm/nv50.o 128nouveau-y += core/subdev/therm/nv50.o
112nouveau-y += core/subdev/therm/temp.o 129nouveau-y += core/subdev/therm/nva3.o
130nouveau-y += core/subdev/therm/nvd0.o
113nouveau-y += core/subdev/timer/base.o 131nouveau-y += core/subdev/timer/base.o
114nouveau-y += core/subdev/timer/nv04.o 132nouveau-y += core/subdev/timer/nv04.o
115nouveau-y += core/subdev/vm/base.o 133nouveau-y += core/subdev/vm/base.o
@@ -132,6 +150,7 @@ nouveau-y += core/engine/copy/nvc0.o
132nouveau-y += core/engine/copy/nve0.o 150nouveau-y += core/engine/copy/nve0.o
133nouveau-y += core/engine/crypt/nv84.o 151nouveau-y += core/engine/crypt/nv84.o
134nouveau-y += core/engine/crypt/nv98.o 152nouveau-y += core/engine/crypt/nv98.o
153nouveau-y += core/engine/disp/base.o
135nouveau-y += core/engine/disp/nv04.o 154nouveau-y += core/engine/disp/nv04.o
136nouveau-y += core/engine/disp/nv50.o 155nouveau-y += core/engine/disp/nv50.o
137nouveau-y += core/engine/disp/nv84.o 156nouveau-y += core/engine/disp/nv84.o
@@ -141,11 +160,13 @@ nouveau-y += core/engine/disp/nva3.o
141nouveau-y += core/engine/disp/nvd0.o 160nouveau-y += core/engine/disp/nvd0.o
142nouveau-y += core/engine/disp/nve0.o 161nouveau-y += core/engine/disp/nve0.o
143nouveau-y += core/engine/disp/dacnv50.o 162nouveau-y += core/engine/disp/dacnv50.o
163nouveau-y += core/engine/disp/dport.o
144nouveau-y += core/engine/disp/hdanva3.o 164nouveau-y += core/engine/disp/hdanva3.o
145nouveau-y += core/engine/disp/hdanvd0.o 165nouveau-y += core/engine/disp/hdanvd0.o
146nouveau-y += core/engine/disp/hdminv84.o 166nouveau-y += core/engine/disp/hdminv84.o
147nouveau-y += core/engine/disp/hdminva3.o 167nouveau-y += core/engine/disp/hdminva3.o
148nouveau-y += core/engine/disp/hdminvd0.o 168nouveau-y += core/engine/disp/hdminvd0.o
169nouveau-y += core/engine/disp/piornv50.o
149nouveau-y += core/engine/disp/sornv50.o 170nouveau-y += core/engine/disp/sornv50.o
150nouveau-y += core/engine/disp/sornv94.o 171nouveau-y += core/engine/disp/sornv94.o
151nouveau-y += core/engine/disp/sornvd0.o 172nouveau-y += core/engine/disp/sornvd0.o
@@ -194,7 +215,8 @@ nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
194nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o 215nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o
195nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o 216nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
196nouveau-y += nouveau_prime.o nouveau_abi16.o 217nouveau-y += nouveau_prime.o nouveau_abi16.o
197nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o 218nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o
219nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o
198 220
199# drm/kms 221# drm/kms
200nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o 222nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o
@@ -216,7 +238,9 @@ nouveau-y += nouveau_mem.o
216 238
217# other random bits 239# other random bits
218nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o 240nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
241ifdef CONFIG_X86
219nouveau-$(CONFIG_ACPI) += nouveau_acpi.o 242nouveau-$(CONFIG_ACPI) += nouveau_acpi.o
243endif
220nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o 244nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
221 245
222obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o 246obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c
index 8bbb58f94a19..295c22165eac 100644
--- a/drivers/gpu/drm/nouveau/core/core/client.c
+++ b/drivers/gpu/drm/nouveau/core/core/client.c
@@ -99,3 +99,13 @@ nouveau_client_fini(struct nouveau_client *client, bool suspend)
99 nv_debug(client, "%s completed with %d\n", name[suspend], ret); 99 nv_debug(client, "%s completed with %d\n", name[suspend], ret);
100 return ret; 100 return ret;
101} 101}
102
103const char *
104nouveau_client_name(void *obj)
105{
106 const char *client_name = "unknown";
107 struct nouveau_client *client = nouveau_client(obj);
108 if (client)
109 client_name = client->name;
110 return client_name;
111}
diff --git a/drivers/gpu/drm/nouveau/core/core/enum.c b/drivers/gpu/drm/nouveau/core/core/enum.c
index 7cc7133d82de..dd434790ccc4 100644
--- a/drivers/gpu/drm/nouveau/core/core/enum.c
+++ b/drivers/gpu/drm/nouveau/core/core/enum.c
@@ -40,14 +40,15 @@ nouveau_enum_find(const struct nouveau_enum *en, u32 value)
40 return NULL; 40 return NULL;
41} 41}
42 42
43void 43const struct nouveau_enum *
44nouveau_enum_print(const struct nouveau_enum *en, u32 value) 44nouveau_enum_print(const struct nouveau_enum *en, u32 value)
45{ 45{
46 en = nouveau_enum_find(en, value); 46 en = nouveau_enum_find(en, value);
47 if (en) 47 if (en)
48 printk("%s", en->name); 48 pr_cont("%s", en->name);
49 else 49 else
50 printk("(unknown enum 0x%08x)", value); 50 pr_cont("(unknown enum 0x%08x)", value);
51 return en;
51} 52}
52 53
53void 54void
@@ -55,7 +56,7 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
55{ 56{
56 while (bf->name) { 57 while (bf->name) {
57 if (value & bf->mask) { 58 if (value & bf->mask) {
58 printk(" %s", bf->name); 59 pr_cont(" %s", bf->name);
59 value &= ~bf->mask; 60 value &= ~bf->mask;
60 } 61 }
61 62
@@ -63,5 +64,5 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
63 } 64 }
64 65
65 if (value) 66 if (value)
66 printk(" (unknown bits 0x%08x)", value); 67 pr_cont(" (unknown bits 0x%08x)", value);
67} 68}
diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c
new file mode 100644
index 000000000000..6d01e0f0fc8a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/core/event.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23#include <core/os.h>
24#include <core/event.h>
25
26static void
27nouveau_event_put_locked(struct nouveau_event *event, int index,
28 struct nouveau_eventh *handler)
29{
30 if (!--event->index[index].refs)
31 event->disable(event, index);
32 list_del(&handler->head);
33}
34
35void
36nouveau_event_put(struct nouveau_event *event, int index,
37 struct nouveau_eventh *handler)
38{
39 unsigned long flags;
40
41 spin_lock_irqsave(&event->lock, flags);
42 if (index < event->index_nr)
43 nouveau_event_put_locked(event, index, handler);
44 spin_unlock_irqrestore(&event->lock, flags);
45}
46
47void
48nouveau_event_get(struct nouveau_event *event, int index,
49 struct nouveau_eventh *handler)
50{
51 unsigned long flags;
52
53 spin_lock_irqsave(&event->lock, flags);
54 if (index < event->index_nr) {
55 list_add(&handler->head, &event->index[index].list);
56 if (!event->index[index].refs++)
57 event->enable(event, index);
58 }
59 spin_unlock_irqrestore(&event->lock, flags);
60}
61
62void
63nouveau_event_trigger(struct nouveau_event *event, int index)
64{
65 struct nouveau_eventh *handler, *temp;
66 unsigned long flags;
67
68 if (index >= event->index_nr)
69 return;
70
71 spin_lock_irqsave(&event->lock, flags);
72 list_for_each_entry_safe(handler, temp, &event->index[index].list, head) {
73 if (handler->func(handler, index) == NVKM_EVENT_DROP) {
74 nouveau_event_put_locked(event, index, handler);
75 }
76 }
77 spin_unlock_irqrestore(&event->lock, flags);
78}
79
80void
81nouveau_event_destroy(struct nouveau_event **pevent)
82{
83 struct nouveau_event *event = *pevent;
84 if (event) {
85 kfree(event);
86 *pevent = NULL;
87 }
88}
89
90int
91nouveau_event_create(int index_nr, struct nouveau_event **pevent)
92{
93 struct nouveau_event *event;
94 int i;
95
96 event = *pevent = kzalloc(sizeof(*event) + index_nr *
97 sizeof(event->index[0]), GFP_KERNEL);
98 if (!event)
99 return -ENOMEM;
100
101 spin_lock_init(&event->lock);
102 for (i = 0; i < index_nr; i++)
103 INIT_LIST_HEAD(&event->index[i].list);
104 event->index_nr = index_nr;
105 return 0;
106}
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
index 283248c7b050..d6dc2a65ccd1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/falcon.h> 26#include <core/falcon.h>
26#include <core/class.h> 27#include <core/class.h>
27#include <core/enum.h> 28#include <core/enum.h>
@@ -100,8 +101,9 @@ nva3_copy_intr(struct nouveau_subdev *subdev)
100 if (stat & 0x00000040) { 101 if (stat & 0x00000040) {
101 nv_error(falcon, "DISPATCH_ERROR ["); 102 nv_error(falcon, "DISPATCH_ERROR [");
102 nouveau_enum_print(nva3_copy_isr_error_name, ssta); 103 nouveau_enum_print(nva3_copy_isr_error_name, ssta);
103 printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", 104 pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n",
104 chid, inst << 12, subc, mthd, data); 105 chid, inst << 12, nouveau_client_name(engctx), subc,
106 mthd, data);
105 nv_wo32(falcon, 0x004, 0x00000040); 107 nv_wo32(falcon, 0x004, 0x00000040);
106 stat &= ~0x00000040; 108 stat &= ~0x00000040;
107 } 109 }
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
index b97490512723..5bc021f471f9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/os.h> 26#include <core/os.h>
26#include <core/enum.h> 27#include <core/enum.h>
27#include <core/class.h> 28#include <core/class.h>
@@ -126,10 +127,11 @@ nv84_crypt_intr(struct nouveau_subdev *subdev)
126 chid = pfifo->chid(pfifo, engctx); 127 chid = pfifo->chid(pfifo, engctx);
127 128
128 if (stat) { 129 if (stat) {
129 nv_error(priv, ""); 130 nv_error(priv, "%s", "");
130 nouveau_bitfield_print(nv84_crypt_intr_mask, stat); 131 nouveau_bitfield_print(nv84_crypt_intr_mask, stat);
131 printk(" ch %d [0x%010llx] mthd 0x%04x data 0x%08x\n", 132 pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n",
132 chid, (u64)inst << 12, mthd, data); 133 chid, (u64)inst << 12, nouveau_client_name(engctx),
134 mthd, data);
133 } 135 }
134 136
135 nv_wr32(priv, 0x102130, stat); 137 nv_wr32(priv, 0x102130, stat);
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
index 21986f3bf0c8..8bf8955051d4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/os.h> 26#include <core/os.h>
26#include <core/enum.h> 27#include <core/enum.h>
27#include <core/class.h> 28#include <core/class.h>
@@ -102,8 +103,9 @@ nv98_crypt_intr(struct nouveau_subdev *subdev)
102 if (stat & 0x00000040) { 103 if (stat & 0x00000040) {
103 nv_error(priv, "DISPATCH_ERROR ["); 104 nv_error(priv, "DISPATCH_ERROR [");
104 nouveau_enum_print(nv98_crypt_isr_error_name, ssta); 105 nouveau_enum_print(nv98_crypt_isr_error_name, ssta);
105 printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", 106 pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n",
106 chid, (u64)inst << 12, subc, mthd, data); 107 chid, (u64)inst << 12, nouveau_client_name(engctx),
108 subc, mthd, data);
107 nv_wr32(priv, 0x087004, 0x00000040); 109 nv_wr32(priv, 0x087004, 0x00000040);
108 stat &= ~0x00000040; 110 stat &= ~0x00000040;
109 } 111 }
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/base.c b/drivers/gpu/drm/nouveau/core/engine/disp/base.c
new file mode 100644
index 000000000000..7a5cae42834f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/base.c
@@ -0,0 +1,52 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <engine/disp.h>
26
27void
28_nouveau_disp_dtor(struct nouveau_object *object)
29{
30 struct nouveau_disp *disp = (void *)object;
31 nouveau_event_destroy(&disp->vblank);
32 nouveau_engine_destroy(&disp->base);
33}
34
35int
36nouveau_disp_create_(struct nouveau_object *parent,
37 struct nouveau_object *engine,
38 struct nouveau_oclass *oclass, int heads,
39 const char *intname, const char *extname,
40 int length, void **pobject)
41{
42 struct nouveau_disp *disp;
43 int ret;
44
45 ret = nouveau_engine_create_(parent, engine, oclass, true,
46 intname, extname, length, pobject);
47 disp = *pobject;
48 if (ret)
49 return ret;
50
51 return nouveau_event_create(heads, &disp->vblank);
52}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
new file mode 100644
index 000000000000..fa27b02ff829
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -0,0 +1,346 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/dcb.h>
27#include <subdev/bios/dp.h>
28#include <subdev/bios/init.h>
29#include <subdev/i2c.h>
30
31#include <engine/disp.h>
32
33#include "dport.h"
34
35#define DBG(fmt, args...) nv_debug(dp->disp, "DP:%04x:%04x: " fmt, \
36 dp->outp->hasht, dp->outp->hashm, ##args)
37#define ERR(fmt, args...) nv_error(dp->disp, "DP:%04x:%04x: " fmt, \
38 dp->outp->hasht, dp->outp->hashm, ##args)
39
40/******************************************************************************
41 * link training
42 *****************************************************************************/
43struct dp_state {
44 const struct nouveau_dp_func *func;
45 struct nouveau_disp *disp;
46 struct dcb_output *outp;
47 struct nvbios_dpout info;
48 u8 version;
49 struct nouveau_i2c_port *aux;
50 int head;
51 u8 dpcd[4];
52 int link_nr;
53 u32 link_bw;
54 u8 stat[6];
55 u8 conf[4];
56};
57
58static int
59dp_set_link_config(struct dp_state *dp)
60{
61 struct nouveau_disp *disp = dp->disp;
62 struct nouveau_bios *bios = nouveau_bios(disp);
63 struct nvbios_init init = {
64 .subdev = nv_subdev(dp->disp),
65 .bios = bios,
66 .offset = 0x0000,
67 .outp = dp->outp,
68 .crtc = dp->head,
69 .execute = 1,
70 };
71 u32 lnkcmp;
72 u8 sink[2];
73
74 DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
75
76 /* set desired link configuration on the sink */
77 sink[0] = dp->link_bw / 27000;
78 sink[1] = dp->link_nr;
79 if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP)
80 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
81
82 nv_wraux(dp->aux, DPCD_LC00, sink, 2);
83
84 /* set desired link configuration on the source */
85 if ((lnkcmp = dp->info.lnkcmp)) {
86 if (dp->version < 0x30) {
87 while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp))
88 lnkcmp += 4;
89 init.offset = nv_ro16(bios, lnkcmp + 2);
90 } else {
91 while ((dp->link_bw / 27000) < nv_ro08(bios, lnkcmp))
92 lnkcmp += 3;
93 init.offset = nv_ro16(bios, lnkcmp + 1);
94 }
95
96 nvbios_exec(&init);
97 }
98
99 return dp->func->lnk_ctl(dp->disp, dp->outp, dp->head,
100 dp->link_nr, dp->link_bw / 27000,
101 dp->dpcd[DPCD_RC02] &
102 DPCD_RC02_ENHANCED_FRAME_CAP);
103}
104
105static void
106dp_set_training_pattern(struct dp_state *dp, u8 pattern)
107{
108 u8 sink_tp;
109
110 DBG("training pattern %d\n", pattern);
111 dp->func->pattern(dp->disp, dp->outp, dp->head, pattern);
112
113 nv_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1);
114 sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET;
115 sink_tp |= pattern;
116 nv_wraux(dp->aux, DPCD_LC02, &sink_tp, 1);
117}
118
119static int
120dp_link_train_commit(struct dp_state *dp)
121{
122 int i;
123
124 for (i = 0; i < dp->link_nr; i++) {
125 u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
126 u8 lpre = (lane & 0x0c) >> 2;
127 u8 lvsw = (lane & 0x03) >> 0;
128
129 dp->conf[i] = (lpre << 3) | lvsw;
130 if (lvsw == 3)
131 dp->conf[i] |= DPCD_LC03_MAX_SWING_REACHED;
132 if (lpre == 3)
133 dp->conf[i] |= DPCD_LC03_MAX_PRE_EMPHASIS_REACHED;
134
135 DBG("config lane %d %02x\n", i, dp->conf[i]);
136 dp->func->drv_ctl(dp->disp, dp->outp, dp->head, i, lvsw, lpre);
137 }
138
139 return nv_wraux(dp->aux, DPCD_LC03(0), dp->conf, 4);
140}
141
142static int
143dp_link_train_update(struct dp_state *dp, u32 delay)
144{
145 int ret;
146
147 udelay(delay);
148
149 ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6);
150 if (ret)
151 return ret;
152
153 DBG("status %*ph\n", 6, dp->stat);
154 return 0;
155}
156
157static int
158dp_link_train_cr(struct dp_state *dp)
159{
160 bool cr_done = false, abort = false;
161 int voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET;
162 int tries = 0, i;
163
164 dp_set_training_pattern(dp, 1);
165
166 do {
167 if (dp_link_train_commit(dp) ||
168 dp_link_train_update(dp, 100))
169 break;
170
171 cr_done = true;
172 for (i = 0; i < dp->link_nr; i++) {
173 u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
174 if (!(lane & DPCD_LS02_LANE0_CR_DONE)) {
175 cr_done = false;
176 if (dp->conf[i] & DPCD_LC03_MAX_SWING_REACHED)
177 abort = true;
178 break;
179 }
180 }
181
182 if ((dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET) != voltage) {
183 voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET;
184 tries = 0;
185 }
186 } while (!cr_done && !abort && ++tries < 5);
187
188 return cr_done ? 0 : -1;
189}
190
191static int
192dp_link_train_eq(struct dp_state *dp)
193{
194 bool eq_done, cr_done = true;
195 int tries = 0, i;
196
197 dp_set_training_pattern(dp, 2);
198
199 do {
200 if (dp_link_train_update(dp, 400))
201 break;
202
203 eq_done = !!(dp->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE);
204 for (i = 0; i < dp->link_nr && eq_done; i++) {
205 u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
206 if (!(lane & DPCD_LS02_LANE0_CR_DONE))
207 cr_done = false;
208 if (!(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) ||
209 !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED))
210 eq_done = false;
211 }
212
213 if (dp_link_train_commit(dp))
214 break;
215 } while (!eq_done && cr_done && ++tries <= 5);
216
217 return eq_done ? 0 : -1;
218}
219
220static void
221dp_link_train_init(struct dp_state *dp, bool spread)
222{
223 struct nvbios_init init = {
224 .subdev = nv_subdev(dp->disp),
225 .bios = nouveau_bios(dp->disp),
226 .outp = dp->outp,
227 .crtc = dp->head,
228 .execute = 1,
229 };
230
231 /* set desired spread */
232 if (spread)
233 init.offset = dp->info.script[2];
234 else
235 init.offset = dp->info.script[3];
236 nvbios_exec(&init);
237
238 /* pre-train script */
239 init.offset = dp->info.script[0];
240 nvbios_exec(&init);
241}
242
243static void
244dp_link_train_fini(struct dp_state *dp)
245{
246 struct nvbios_init init = {
247 .subdev = nv_subdev(dp->disp),
248 .bios = nouveau_bios(dp->disp),
249 .outp = dp->outp,
250 .crtc = dp->head,
251 .execute = 1,
252 };
253
254 /* post-train script */
255 init.offset = dp->info.script[1],
256 nvbios_exec(&init);
257}
258
259int
260nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
261 struct dcb_output *outp, int head, u32 datarate)
262{
263 struct nouveau_bios *bios = nouveau_bios(disp);
264 struct nouveau_i2c *i2c = nouveau_i2c(disp);
265 struct dp_state _dp = {
266 .disp = disp,
267 .func = func,
268 .outp = outp,
269 .head = head,
270 }, *dp = &_dp;
271 const u32 bw_list[] = { 270000, 162000, 0 };
272 const u32 *link_bw = bw_list;
273 u8 hdr, cnt, len;
274 u32 data;
275 int ret;
276
277 /* find the bios displayport data relevant to this output */
278 data = nvbios_dpout_match(bios, outp->hasht, outp->hashm, &dp->version,
279 &hdr, &cnt, &len, &dp->info);
280 if (!data) {
281 ERR("bios data not found\n");
282 return -EINVAL;
283 }
284
285 /* acquire the aux channel and fetch some info about the display */
286 if (outp->location)
287 dp->aux = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev));
288 else
289 dp->aux = i2c->find(i2c, NV_I2C_TYPE_DCBI2C(outp->i2c_index));
290 if (!dp->aux) {
291 ERR("no aux channel?!\n");
292 return -ENODEV;
293 }
294
295 ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd));
296 if (ret) {
297 ERR("failed to read DPCD\n");
298 return ret;
299 }
300
301 /* adjust required bandwidth for 8B/10B coding overhead */
302 datarate = (datarate / 8) * 10;
303
304 /* enable down-spreading and execute pre-train script from vbios */
305 dp_link_train_init(dp, dp->dpcd[3] & 0x01);
306
307 /* start off at highest link rate supported by encoder and display */
308 while (*link_bw > (dp->dpcd[1] * 27000))
309 link_bw++;
310
311 while (link_bw[0]) {
312 /* find minimum required lane count at this link rate */
313 dp->link_nr = dp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT;
314 while ((dp->link_nr >> 1) * link_bw[0] > datarate)
315 dp->link_nr >>= 1;
316
317 /* drop link rate to minimum with this lane count */
318 while ((link_bw[1] * dp->link_nr) > datarate)
319 link_bw++;
320 dp->link_bw = link_bw[0];
321
322 /* program selected link configuration */
323 ret = dp_set_link_config(dp);
324 if (ret == 0) {
325 /* attempt to train the link at this configuration */
326 memset(dp->stat, 0x00, sizeof(dp->stat));
327 if (!dp_link_train_cr(dp) &&
328 !dp_link_train_eq(dp))
329 break;
330 } else
331 if (ret >= 1) {
332 /* dp_set_link_config() handled training */
333 break;
334 }
335
336 /* retry at lower rate */
337 link_bw++;
338 }
339
340 /* finish link training */
341 dp_set_training_pattern(dp, 0);
342
343 /* execute post-train script from vbios */
344 dp_link_train_fini(dp);
345 return true;
346}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.h b/drivers/gpu/drm/nouveau/core/engine/disp/dport.h
new file mode 100644
index 000000000000..0e1bbd18ff6c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.h
@@ -0,0 +1,78 @@
1#ifndef __NVKM_DISP_DPORT_H__
2#define __NVKM_DISP_DPORT_H__
3
4/* DPCD Receiver Capabilities */
5#define DPCD_RC00 0x00000
6#define DPCD_RC00_DPCD_REV 0xff
7#define DPCD_RC01 0x00001
8#define DPCD_RC01_MAX_LINK_RATE 0xff
9#define DPCD_RC02 0x00002
10#define DPCD_RC02_ENHANCED_FRAME_CAP 0x80
11#define DPCD_RC02_MAX_LANE_COUNT 0x1f
12#define DPCD_RC03 0x00003
13#define DPCD_RC03_MAX_DOWNSPREAD 0x01
14
15/* DPCD Link Configuration */
16#define DPCD_LC00 0x00100
17#define DPCD_LC00_LINK_BW_SET 0xff
18#define DPCD_LC01 0x00101
19#define DPCD_LC01_ENHANCED_FRAME_EN 0x80
20#define DPCD_LC01_LANE_COUNT_SET 0x1f
21#define DPCD_LC02 0x00102
22#define DPCD_LC02_TRAINING_PATTERN_SET 0x03
23#define DPCD_LC03(l) ((l) + 0x00103)
24#define DPCD_LC03_MAX_PRE_EMPHASIS_REACHED 0x20
25#define DPCD_LC03_PRE_EMPHASIS_SET 0x18
26#define DPCD_LC03_MAX_SWING_REACHED 0x04
27#define DPCD_LC03_VOLTAGE_SWING_SET 0x03
28
29/* DPCD Link/Sink Status */
30#define DPCD_LS02 0x00202
31#define DPCD_LS02_LANE1_SYMBOL_LOCKED 0x40
32#define DPCD_LS02_LANE1_CHANNEL_EQ_DONE 0x20
33#define DPCD_LS02_LANE1_CR_DONE 0x10
34#define DPCD_LS02_LANE0_SYMBOL_LOCKED 0x04
35#define DPCD_LS02_LANE0_CHANNEL_EQ_DONE 0x02
36#define DPCD_LS02_LANE0_CR_DONE 0x01
37#define DPCD_LS03 0x00203
38#define DPCD_LS03_LANE3_SYMBOL_LOCKED 0x40
39#define DPCD_LS03_LANE3_CHANNEL_EQ_DONE 0x20
40#define DPCD_LS03_LANE3_CR_DONE 0x10
41#define DPCD_LS03_LANE2_SYMBOL_LOCKED 0x04
42#define DPCD_LS03_LANE2_CHANNEL_EQ_DONE 0x02
43#define DPCD_LS03_LANE2_CR_DONE 0x01
44#define DPCD_LS04 0x00204
45#define DPCD_LS04_LINK_STATUS_UPDATED 0x80
46#define DPCD_LS04_DOWNSTREAM_PORT_STATUS_CHANGED 0x40
47#define DPCD_LS04_INTERLANE_ALIGN_DONE 0x01
48#define DPCD_LS06 0x00206
49#define DPCD_LS06_LANE1_PRE_EMPHASIS 0xc0
50#define DPCD_LS06_LANE1_VOLTAGE_SWING 0x30
51#define DPCD_LS06_LANE0_PRE_EMPHASIS 0x0c
52#define DPCD_LS06_LANE0_VOLTAGE_SWING 0x03
53#define DPCD_LS07 0x00207
54#define DPCD_LS07_LANE3_PRE_EMPHASIS 0xc0
55#define DPCD_LS07_LANE3_VOLTAGE_SWING 0x30
56#define DPCD_LS07_LANE2_PRE_EMPHASIS 0x0c
57#define DPCD_LS07_LANE2_VOLTAGE_SWING 0x03
58
59struct nouveau_disp;
60struct dcb_output;
61
62struct nouveau_dp_func {
63 int (*pattern)(struct nouveau_disp *, struct dcb_output *,
64 int head, int pattern);
65 int (*lnk_ctl)(struct nouveau_disp *, struct dcb_output *, int head,
66 int link_nr, int link_bw, bool enh_frame);
67 int (*drv_ctl)(struct nouveau_disp *, struct dcb_output *, int head,
68 int lane, int swing, int preem);
69};
70
71extern const struct nouveau_dp_func nv94_sor_dp_func;
72extern const struct nouveau_dp_func nvd0_sor_dp_func;
73extern const struct nouveau_dp_func nv50_pior_dp_func;
74
75int nouveau_dp_train(struct nouveau_disp *, const struct nouveau_dp_func *,
76 struct dcb_output *, int, u32);
77
78#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index 1c919f2af89f..05e903f08a36 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -24,21 +24,33 @@
24 24
25#include <engine/disp.h> 25#include <engine/disp.h>
26 26
27#include <core/event.h>
28#include <core/class.h>
29
27struct nv04_disp_priv { 30struct nv04_disp_priv {
28 struct nouveau_disp base; 31 struct nouveau_disp base;
29}; 32};
30 33
31static struct nouveau_oclass 34static struct nouveau_oclass
32nv04_disp_sclass[] = { 35nv04_disp_sclass[] = {
36 { NV04_DISP_CLASS, &nouveau_object_ofuncs },
33 {}, 37 {},
34}; 38};
35 39
40/*******************************************************************************
41 * Display engine implementation
42 ******************************************************************************/
43
44static void
45nv04_disp_vblank_enable(struct nouveau_event *event, int head)
46{
47 nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
48}
49
36static void 50static void
37nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc) 51nv04_disp_vblank_disable(struct nouveau_event *event, int head)
38{ 52{
39 struct nouveau_disp *disp = &priv->base; 53 nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
40 if (disp->vblank.notify)
41 disp->vblank.notify(disp->vblank.data, crtc);
42} 54}
43 55
44static void 56static void
@@ -49,25 +61,25 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
49 u32 crtc1 = nv_rd32(priv, 0x602100); 61 u32 crtc1 = nv_rd32(priv, 0x602100);
50 62
51 if (crtc0 & 0x00000001) { 63 if (crtc0 & 0x00000001) {
52 nv04_disp_intr_vblank(priv, 0); 64 nouveau_event_trigger(priv->base.vblank, 0);
53 nv_wr32(priv, 0x600100, 0x00000001); 65 nv_wr32(priv, 0x600100, 0x00000001);
54 } 66 }
55 67
56 if (crtc1 & 0x00000001) { 68 if (crtc1 & 0x00000001) {
57 nv04_disp_intr_vblank(priv, 1); 69 nouveau_event_trigger(priv->base.vblank, 1);
58 nv_wr32(priv, 0x602100, 0x00000001); 70 nv_wr32(priv, 0x602100, 0x00000001);
59 } 71 }
60} 72}
61 73
62static int 74static int
63nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 75nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
64 struct nouveau_oclass *oclass, void *data, u32 size, 76 struct nouveau_oclass *oclass, void *data, u32 size,
65 struct nouveau_object **pobject) 77 struct nouveau_object **pobject)
66{ 78{
67 struct nv04_disp_priv *priv; 79 struct nv04_disp_priv *priv;
68 int ret; 80 int ret;
69 81
70 ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY", 82 ret = nouveau_disp_create(parent, engine, oclass, 2, "DISPLAY",
71 "display", &priv); 83 "display", &priv);
72 *pobject = nv_object(priv); 84 *pobject = nv_object(priv);
73 if (ret) 85 if (ret)
@@ -75,6 +87,9 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
75 87
76 nv_engine(priv)->sclass = nv04_disp_sclass; 88 nv_engine(priv)->sclass = nv04_disp_sclass;
77 nv_subdev(priv)->intr = nv04_disp_intr; 89 nv_subdev(priv)->intr = nv04_disp_intr;
90 priv->base.vblank->priv = priv;
91 priv->base.vblank->enable = nv04_disp_vblank_enable;
92 priv->base.vblank->disable = nv04_disp_vblank_disable;
78 return 0; 93 return 0;
79} 94}
80 95
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index ca1a7d76a95b..314dda6d7cb8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -27,7 +27,6 @@
27#include <core/handle.h> 27#include <core/handle.h>
28#include <core/class.h> 28#include <core/class.h>
29 29
30#include <engine/software.h>
31#include <engine/disp.h> 30#include <engine/disp.h>
32 31
33#include <subdev/bios.h> 32#include <subdev/bios.h>
@@ -37,7 +36,6 @@
37#include <subdev/bios/pll.h> 36#include <subdev/bios/pll.h>
38#include <subdev/timer.h> 37#include <subdev/timer.h>
39#include <subdev/fb.h> 38#include <subdev/fb.h>
40#include <subdev/bar.h>
41#include <subdev/clock.h> 39#include <subdev/clock.h>
42 40
43#include "nv50.h" 41#include "nv50.h"
@@ -335,7 +333,7 @@ nv50_disp_sync_ctor(struct nouveau_object *parent,
335 struct nv50_disp_dmac *dmac; 333 struct nv50_disp_dmac *dmac;
336 int ret; 334 int ret;
337 335
338 if (size < sizeof(*data) || args->head > 1) 336 if (size < sizeof(*args) || args->head > 1)
339 return -EINVAL; 337 return -EINVAL;
340 338
341 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, 339 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -374,7 +372,7 @@ nv50_disp_ovly_ctor(struct nouveau_object *parent,
374 struct nv50_disp_dmac *dmac; 372 struct nv50_disp_dmac *dmac;
375 int ret; 373 int ret;
376 374
377 if (size < sizeof(*data) || args->head > 1) 375 if (size < sizeof(*args) || args->head > 1)
378 return -EINVAL; 376 return -EINVAL;
379 377
380 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, 378 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -543,6 +541,18 @@ nv50_disp_curs_ofuncs = {
543 * Base display object 541 * Base display object
544 ******************************************************************************/ 542 ******************************************************************************/
545 543
544static void
545nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
546{
547 nv_mask(event->priv, 0x61002c, (1 << head), (1 << head));
548}
549
550static void
551nv50_disp_base_vblank_disable(struct nouveau_event *event, int head)
552{
553 nv_mask(event->priv, 0x61002c, (1 << head), (0 << head));
554}
555
546static int 556static int
547nv50_disp_base_ctor(struct nouveau_object *parent, 557nv50_disp_base_ctor(struct nouveau_object *parent,
548 struct nouveau_object *engine, 558 struct nouveau_object *engine,
@@ -559,6 +569,9 @@ nv50_disp_base_ctor(struct nouveau_object *parent,
559 if (ret) 569 if (ret)
560 return ret; 570 return ret;
561 571
572 priv->base.vblank->priv = priv;
573 priv->base.vblank->enable = nv50_disp_base_vblank_enable;
574 priv->base.vblank->disable = nv50_disp_base_vblank_disable;
562 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht); 575 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
563} 576}
564 577
@@ -613,7 +626,7 @@ nv50_disp_base_init(struct nouveau_object *object)
613 nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp); 626 nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp);
614 } 627 }
615 628
616 /* ... EXT caps */ 629 /* ... PIOR caps */
617 for (i = 0; i < 3; i++) { 630 for (i = 0; i < 3; i++) {
618 tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); 631 tmp = nv_rd32(priv, 0x61e000 + (i * 0x800));
619 nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); 632 nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp);
@@ -665,6 +678,9 @@ nv50_disp_base_omthds[] = {
665 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 678 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
666 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 679 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
667 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 680 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
681 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
682 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
683 { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
668 {}, 684 {},
669}; 685};
670 686
@@ -756,50 +772,6 @@ nv50_disp_intr_error(struct nv50_disp_priv *priv)
756 } 772 }
757} 773}
758 774
759static void
760nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
761{
762 struct nouveau_bar *bar = nouveau_bar(priv);
763 struct nouveau_disp *disp = &priv->base;
764 struct nouveau_software_chan *chan, *temp;
765 unsigned long flags;
766
767 spin_lock_irqsave(&disp->vblank.lock, flags);
768 list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) {
769 if (chan->vblank.crtc != crtc)
770 continue;
771
772 if (nv_device(priv)->chipset >= 0xc0) {
773 nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
774 bar->flush(bar);
775 nv_wr32(priv, 0x06000c,
776 upper_32_bits(chan->vblank.offset));
777 nv_wr32(priv, 0x060010,
778 lower_32_bits(chan->vblank.offset));
779 nv_wr32(priv, 0x060014, chan->vblank.value);
780 } else {
781 nv_wr32(priv, 0x001704, chan->vblank.channel);
782 nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
783 bar->flush(bar);
784 if (nv_device(priv)->chipset == 0x50) {
785 nv_wr32(priv, 0x001570, chan->vblank.offset);
786 nv_wr32(priv, 0x001574, chan->vblank.value);
787 } else {
788 nv_wr32(priv, 0x060010, chan->vblank.offset);
789 nv_wr32(priv, 0x060014, chan->vblank.value);
790 }
791 }
792
793 list_del(&chan->vblank.head);
794 if (disp->vblank.put)
795 disp->vblank.put(disp->vblank.data, crtc);
796 }
797 spin_unlock_irqrestore(&disp->vblank.lock, flags);
798
799 if (disp->vblank.notify)
800 disp->vblank.notify(disp->vblank.data, crtc);
801}
802
803static u16 775static u16
804exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, 776exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
805 struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 777 struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
@@ -811,8 +783,8 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
811 if (outp < 4) { 783 if (outp < 4) {
812 type = DCB_OUTPUT_ANALOG; 784 type = DCB_OUTPUT_ANALOG;
813 mask = 0; 785 mask = 0;
814 } else { 786 } else
815 outp -= 4; 787 if (outp < 8) {
816 switch (ctrl & 0x00000f00) { 788 switch (ctrl & 0x00000f00) {
817 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; 789 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
818 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; 790 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
@@ -824,6 +796,17 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
824 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); 796 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
825 return 0x0000; 797 return 0x0000;
826 } 798 }
799 outp -= 4;
800 } else {
801 outp = outp - 8;
802 type = 0x0010;
803 mask = 0;
804 switch (ctrl & 0x00000f00) {
805 case 0x00000000: type |= priv->pior.type[outp]; break;
806 default:
807 nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl);
808 return 0x0000;
809 }
827 } 810 }
828 811
829 mask = 0x00c0 & (mask << 6); 812 mask = 0x00c0 & (mask << 6);
@@ -834,6 +817,10 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
834 if (!data) 817 if (!data)
835 return 0x0000; 818 return 0x0000;
836 819
820 /* off-chip encoders require matching the exact encoder type */
821 if (dcb->location != 0)
822 type |= dcb->extdev << 8;
823
837 return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); 824 return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info);
838} 825}
839 826
@@ -848,9 +835,11 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
848 u32 ctrl = 0x00000000; 835 u32 ctrl = 0x00000000;
849 int i; 836 int i;
850 837
838 /* DAC */
851 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) 839 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
852 ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); 840 ctrl = nv_rd32(priv, 0x610b5c + (i * 8));
853 841
842 /* SOR */
854 if (!(ctrl & (1 << head))) { 843 if (!(ctrl & (1 << head))) {
855 if (nv_device(priv)->chipset < 0x90 || 844 if (nv_device(priv)->chipset < 0x90 ||
856 nv_device(priv)->chipset == 0x92 || 845 nv_device(priv)->chipset == 0x92 ||
@@ -865,6 +854,13 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
865 } 854 }
866 } 855 }
867 856
857 /* PIOR */
858 if (!(ctrl & (1 << head))) {
859 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
860 ctrl = nv_rd32(priv, 0x610b84 + (i * 8));
861 i += 8;
862 }
863
868 if (!(ctrl & (1 << head))) 864 if (!(ctrl & (1 << head)))
869 return false; 865 return false;
870 i--; 866 i--;
@@ -894,13 +890,15 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
894 struct nvbios_outp info1; 890 struct nvbios_outp info1;
895 struct nvbios_ocfg info2; 891 struct nvbios_ocfg info2;
896 u8 ver, hdr, cnt, len; 892 u8 ver, hdr, cnt, len;
897 u16 data, conf;
898 u32 ctrl = 0x00000000; 893 u32 ctrl = 0x00000000;
894 u32 data, conf = ~0;
899 int i; 895 int i;
900 896
897 /* DAC */
901 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) 898 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
902 ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); 899 ctrl = nv_rd32(priv, 0x610b58 + (i * 8));
903 900
901 /* SOR */
904 if (!(ctrl & (1 << head))) { 902 if (!(ctrl & (1 << head))) {
905 if (nv_device(priv)->chipset < 0x90 || 903 if (nv_device(priv)->chipset < 0x90 ||
906 nv_device(priv)->chipset == 0x92 || 904 nv_device(priv)->chipset == 0x92 ||
@@ -915,34 +913,46 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
915 } 913 }
916 } 914 }
917 915
916 /* PIOR */
917 if (!(ctrl & (1 << head))) {
918 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
919 ctrl = nv_rd32(priv, 0x610b80 + (i * 8));
920 i += 8;
921 }
922
918 if (!(ctrl & (1 << head))) 923 if (!(ctrl & (1 << head)))
919 return 0x0000; 924 return conf;
920 i--; 925 i--;
921 926
922 data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); 927 data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1);
923 if (!data) 928 if (!data)
924 return 0x0000; 929 return conf;
925 930
926 switch (outp->type) { 931 if (outp->location == 0) {
927 case DCB_OUTPUT_TMDS: 932 switch (outp->type) {
928 conf = (ctrl & 0x00000f00) >> 8; 933 case DCB_OUTPUT_TMDS:
929 if (pclk >= 165000) 934 conf = (ctrl & 0x00000f00) >> 8;
930 conf |= 0x0100; 935 if (pclk >= 165000)
931 break; 936 conf |= 0x0100;
932 case DCB_OUTPUT_LVDS: 937 break;
933 conf = priv->sor.lvdsconf; 938 case DCB_OUTPUT_LVDS:
934 break; 939 conf = priv->sor.lvdsconf;
935 case DCB_OUTPUT_DP: 940 break;
941 case DCB_OUTPUT_DP:
942 conf = (ctrl & 0x00000f00) >> 8;
943 break;
944 case DCB_OUTPUT_ANALOG:
945 default:
946 conf = 0x00ff;
947 break;
948 }
949 } else {
936 conf = (ctrl & 0x00000f00) >> 8; 950 conf = (ctrl & 0x00000f00) >> 8;
937 break; 951 pclk = pclk / 2;
938 case DCB_OUTPUT_ANALOG:
939 default:
940 conf = 0x00ff;
941 break;
942 } 952 }
943 953
944 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 954 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
945 if (data) { 955 if (data && id < 0xff) {
946 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 956 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
947 if (data) { 957 if (data) {
948 struct nvbios_init init = { 958 struct nvbios_init init = {
@@ -954,13 +964,11 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
954 .execute = 1, 964 .execute = 1,
955 }; 965 };
956 966
957 if (nvbios_exec(&init)) 967 nvbios_exec(&init);
958 return 0x0000;
959 return conf;
960 } 968 }
961 } 969 }
962 970
963 return 0x0000; 971 return conf;
964} 972}
965 973
966static void 974static void
@@ -973,7 +981,6 @@ nv50_disp_intr_unk10(struct nv50_disp_priv *priv, u32 super)
973 exec_script(priv, head, 1); 981 exec_script(priv, head, 1);
974 } 982 }
975 983
976 nv_wr32(priv, 0x610024, 0x00000010);
977 nv_wr32(priv, 0x610030, 0x80000000); 984 nv_wr32(priv, 0x610030, 0x80000000);
978} 985}
979 986
@@ -1088,7 +1095,6 @@ static void
1088nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super) 1095nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
1089{ 1096{
1090 struct dcb_output outp; 1097 struct dcb_output outp;
1091 u32 addr, mask, data;
1092 int head; 1098 int head;
1093 1099
1094 /* finish detaching encoder? */ 1100 /* finish detaching encoder? */
@@ -1104,33 +1110,58 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
1104 struct nouveau_clock *clk = nouveau_clock(priv); 1110 struct nouveau_clock *clk = nouveau_clock(priv);
1105 clk->pll_set(clk, PLL_VPLL0 + head, pclk); 1111 clk->pll_set(clk, PLL_VPLL0 + head, pclk);
1106 } 1112 }
1107
1108 nv_mask(priv, 0x614200 + head * 0x800, 0x0000000f, 0x00000000);
1109 } 1113 }
1110 1114
1111 /* (re)attach the relevant OR to the head */ 1115 /* (re)attach the relevant OR to the head */
1112 head = ffs((super & 0x00000180) >> 7) - 1; 1116 head = ffs((super & 0x00000180) >> 7) - 1;
1113 if (head >= 0) { 1117 if (head >= 0) {
1114 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; 1118 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1115 u32 conf = exec_clkcmp(priv, head, 0, pclk, &outp); 1119 u32 hval, hreg = 0x614200 + (head * 0x800);
1116 if (conf) { 1120 u32 oval, oreg;
1117 if (outp.type == DCB_OUTPUT_ANALOG) { 1121 u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp);
1118 addr = 0x614280 + (ffs(outp.or) - 1) * 0x800; 1122 if (conf != ~0) {
1119 mask = 0xffffffff; 1123 if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
1120 data = 0x00000000; 1124 u32 soff = (ffs(outp.or) - 1) * 0x08;
1121 } else { 1125 u32 ctrl = nv_rd32(priv, 0x610798 + soff);
1126 u32 datarate;
1127
1128 switch ((ctrl & 0x000f0000) >> 16) {
1129 case 6: datarate = pclk * 30 / 8; break;
1130 case 5: datarate = pclk * 24 / 8; break;
1131 case 2:
1132 default:
1133 datarate = pclk * 18 / 8;
1134 break;
1135 }
1136
1137 nouveau_dp_train(&priv->base, priv->sor.dp,
1138 &outp, head, datarate);
1139 }
1140
1141 exec_clkcmp(priv, head, 0, pclk, &outp);
1142
1143 if (!outp.location && outp.type == DCB_OUTPUT_ANALOG) {
1144 oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800;
1145 oval = 0x00000000;
1146 hval = 0x00000000;
1147 } else
1148 if (!outp.location) {
1122 if (outp.type == DCB_OUTPUT_DP) 1149 if (outp.type == DCB_OUTPUT_DP)
1123 nv50_disp_intr_unk20_dp(priv, &outp, pclk); 1150 nv50_disp_intr_unk20_dp(priv, &outp, pclk);
1124 addr = 0x614300 + (ffs(outp.or) - 1) * 0x800; 1151 oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800;
1125 mask = 0x00000707; 1152 oval = (conf & 0x0100) ? 0x0101 : 0x0000;
1126 data = (conf & 0x0100) ? 0x0101 : 0x0000; 1153 hval = 0x00000000;
1154 } else {
1155 oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800;
1156 oval = 0x00000001;
1157 hval = 0x00000001;
1127 } 1158 }
1128 1159
1129 nv_mask(priv, addr, mask, data); 1160 nv_mask(priv, hreg, 0x0000000f, hval);
1161 nv_mask(priv, oreg, 0x00000707, oval);
1130 } 1162 }
1131 } 1163 }
1132 1164
1133 nv_wr32(priv, 0x610024, 0x00000020);
1134 nv_wr32(priv, 0x610030, 0x80000000); 1165 nv_wr32(priv, 0x610030, 0x80000000);
1135} 1166}
1136 1167
@@ -1163,28 +1194,47 @@ nv50_disp_intr_unk40(struct nv50_disp_priv *priv, u32 super)
1163 if (head >= 0) { 1194 if (head >= 0) {
1164 struct dcb_output outp; 1195 struct dcb_output outp;
1165 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; 1196 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1166 if (pclk && exec_clkcmp(priv, head, 1, pclk, &outp)) { 1197 if (exec_clkcmp(priv, head, 1, pclk, &outp) != ~0) {
1167 if (outp.type == DCB_OUTPUT_TMDS) 1198 if (outp.location == 0 && outp.type == DCB_OUTPUT_TMDS)
1168 nv50_disp_intr_unk40_tmds(priv, &outp); 1199 nv50_disp_intr_unk40_tmds(priv, &outp);
1200 else
1201 if (outp.location == 1 && outp.type == DCB_OUTPUT_DP) {
1202 u32 soff = (ffs(outp.or) - 1) * 0x08;
1203 u32 ctrl = nv_rd32(priv, 0x610b84 + soff);
1204 u32 datarate;
1205
1206 switch ((ctrl & 0x000f0000) >> 16) {
1207 case 6: datarate = pclk * 30 / 8; break;
1208 case 5: datarate = pclk * 24 / 8; break;
1209 case 2:
1210 default:
1211 datarate = pclk * 18 / 8;
1212 break;
1213 }
1214
1215 nouveau_dp_train(&priv->base, priv->pior.dp,
1216 &outp, head, datarate);
1217 }
1169 } 1218 }
1170 } 1219 }
1171 1220
1172 nv_wr32(priv, 0x610024, 0x00000040);
1173 nv_wr32(priv, 0x610030, 0x80000000); 1221 nv_wr32(priv, 0x610030, 0x80000000);
1174} 1222}
1175 1223
1176static void 1224void
1177nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1) 1225nv50_disp_intr_supervisor(struct work_struct *work)
1178{ 1226{
1227 struct nv50_disp_priv *priv =
1228 container_of(work, struct nv50_disp_priv, supervisor);
1179 u32 super = nv_rd32(priv, 0x610030); 1229 u32 super = nv_rd32(priv, 0x610030);
1180 1230
1181 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super); 1231 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
1182 1232
1183 if (intr1 & 0x00000010) 1233 if (priv->super & 0x00000010)
1184 nv50_disp_intr_unk10(priv, super); 1234 nv50_disp_intr_unk10(priv, super);
1185 if (intr1 & 0x00000020) 1235 if (priv->super & 0x00000020)
1186 nv50_disp_intr_unk20(priv, super); 1236 nv50_disp_intr_unk20(priv, super);
1187 if (intr1 & 0x00000040) 1237 if (priv->super & 0x00000040)
1188 nv50_disp_intr_unk40(priv, super); 1238 nv50_disp_intr_unk40(priv, super);
1189} 1239}
1190 1240
@@ -1201,19 +1251,21 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
1201 } 1251 }
1202 1252
1203 if (intr1 & 0x00000004) { 1253 if (intr1 & 0x00000004) {
1204 nv50_disp_intr_vblank(priv, 0); 1254 nouveau_event_trigger(priv->base.vblank, 0);
1205 nv_wr32(priv, 0x610024, 0x00000004); 1255 nv_wr32(priv, 0x610024, 0x00000004);
1206 intr1 &= ~0x00000004; 1256 intr1 &= ~0x00000004;
1207 } 1257 }
1208 1258
1209 if (intr1 & 0x00000008) { 1259 if (intr1 & 0x00000008) {
1210 nv50_disp_intr_vblank(priv, 1); 1260 nouveau_event_trigger(priv->base.vblank, 1);
1211 nv_wr32(priv, 0x610024, 0x00000008); 1261 nv_wr32(priv, 0x610024, 0x00000008);
1212 intr1 &= ~0x00000008; 1262 intr1 &= ~0x00000008;
1213 } 1263 }
1214 1264
1215 if (intr1 & 0x00000070) { 1265 if (intr1 & 0x00000070) {
1216 nv50_disp_intr_super(priv, intr1); 1266 priv->super = (intr1 & 0x00000070);
1267 schedule_work(&priv->supervisor);
1268 nv_wr32(priv, 0x610024, priv->super);
1217 intr1 &= ~0x00000070; 1269 intr1 &= ~0x00000070;
1218 } 1270 }
1219} 1271}
@@ -1226,7 +1278,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1226 struct nv50_disp_priv *priv; 1278 struct nv50_disp_priv *priv;
1227 int ret; 1279 int ret;
1228 1280
1229 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 1281 ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
1230 "display", &priv); 1282 "display", &priv);
1231 *pobject = nv_object(priv); 1283 *pobject = nv_object(priv);
1232 if (ret) 1284 if (ret)
@@ -1235,16 +1287,17 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1235 nv_engine(priv)->sclass = nv50_disp_base_oclass; 1287 nv_engine(priv)->sclass = nv50_disp_base_oclass;
1236 nv_engine(priv)->cclass = &nv50_disp_cclass; 1288 nv_engine(priv)->cclass = &nv50_disp_cclass;
1237 nv_subdev(priv)->intr = nv50_disp_intr; 1289 nv_subdev(priv)->intr = nv50_disp_intr;
1290 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
1238 priv->sclass = nv50_disp_sclass; 1291 priv->sclass = nv50_disp_sclass;
1239 priv->head.nr = 2; 1292 priv->head.nr = 2;
1240 priv->dac.nr = 3; 1293 priv->dac.nr = 3;
1241 priv->sor.nr = 2; 1294 priv->sor.nr = 2;
1295 priv->pior.nr = 3;
1242 priv->dac.power = nv50_dac_power; 1296 priv->dac.power = nv50_dac_power;
1243 priv->dac.sense = nv50_dac_sense; 1297 priv->dac.sense = nv50_dac_sense;
1244 priv->sor.power = nv50_sor_power; 1298 priv->sor.power = nv50_sor_power;
1245 1299 priv->pior.power = nv50_pior_power;
1246 INIT_LIST_HEAD(&priv->base.vblank.list); 1300 priv->pior.dp = &nv50_pior_dp_func;
1247 spin_lock_init(&priv->base.vblank.lock);
1248 return 0; 1301 return 0;
1249} 1302}
1250 1303
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index a6bb931450f1..1ae6ceb56704 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -3,16 +3,22 @@
3 3
4#include <core/parent.h> 4#include <core/parent.h>
5#include <core/namedb.h> 5#include <core/namedb.h>
6#include <core/engctx.h>
6#include <core/ramht.h> 7#include <core/ramht.h>
8#include <core/event.h>
7 9
8#include <engine/dmaobj.h> 10#include <engine/dmaobj.h>
9#include <engine/disp.h> 11#include <engine/disp.h>
10 12
11struct dcb_output; 13#include "dport.h"
12 14
13struct nv50_disp_priv { 15struct nv50_disp_priv {
14 struct nouveau_disp base; 16 struct nouveau_disp base;
15 struct nouveau_oclass *sclass; 17 struct nouveau_oclass *sclass;
18
19 struct work_struct supervisor;
20 u32 super;
21
16 struct { 22 struct {
17 int nr; 23 int nr;
18 } head; 24 } head;
@@ -26,23 +32,15 @@ struct nv50_disp_priv {
26 int (*power)(struct nv50_disp_priv *, int sor, u32 data); 32 int (*power)(struct nv50_disp_priv *, int sor, u32 data);
27 int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32); 33 int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
28 int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); 34 int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
29 int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link,
30 int head, u16 type, u16 mask, u32 data,
31 struct dcb_output *);
32 int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link,
33 int head, u16 type, u16 mask, u32 data,
34 struct dcb_output *);
35 int (*dp_train)(struct nv50_disp_priv *, int sor, int link,
36 u16 type, u16 mask, u32 data,
37 struct dcb_output *);
38 int (*dp_lnkctl)(struct nv50_disp_priv *, int sor, int link,
39 int head, u16 type, u16 mask, u32 data,
40 struct dcb_output *);
41 int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link,
42 int lane, u16 type, u16 mask, u32 data,
43 struct dcb_output *);
44 u32 lvdsconf; 35 u32 lvdsconf;
36 const struct nouveau_dp_func *dp;
45 } sor; 37 } sor;
38 struct {
39 int nr;
40 int (*power)(struct nv50_disp_priv *, int ext, u32 data);
41 u8 type[3];
42 const struct nouveau_dp_func *dp;
43 } pior;
46}; 44};
47 45
48#define DAC_MTHD(n) (n), (n) + 0x03 46#define DAC_MTHD(n) (n), (n) + 0x03
@@ -81,6 +79,11 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
81int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, 79int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
82 struct dcb_output *); 80 struct dcb_output *);
83 81
82#define PIOR_MTHD(n) (n), (n) + 0x03
83
84int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32);
85int nv50_pior_power(struct nv50_disp_priv *, int, u32);
86
84struct nv50_disp_base { 87struct nv50_disp_base {
85 struct nouveau_parent base; 88 struct nouveau_parent base;
86 struct nouveau_ramht *ramht; 89 struct nouveau_ramht *ramht;
@@ -124,6 +127,7 @@ extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
124extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; 127extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
125extern struct nouveau_ofuncs nv50_disp_base_ofuncs; 128extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
126extern struct nouveau_oclass nv50_disp_cclass; 129extern struct nouveau_oclass nv50_disp_cclass;
130void nv50_disp_intr_supervisor(struct work_struct *);
127void nv50_disp_intr(struct nouveau_subdev *); 131void nv50_disp_intr(struct nouveau_subdev *);
128 132
129extern struct nouveau_omthds nv84_disp_base_omthds[]; 133extern struct nouveau_omthds nv84_disp_base_omthds[];
@@ -137,6 +141,7 @@ extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
137extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; 141extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
138extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; 142extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
139extern struct nouveau_oclass nvd0_disp_cclass; 143extern struct nouveau_oclass nvd0_disp_cclass;
144void nvd0_disp_intr_supervisor(struct work_struct *);
140void nvd0_disp_intr(struct nouveau_subdev *); 145void nvd0_disp_intr(struct nouveau_subdev *);
141 146
142#endif 147#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index fc84eacdfbec..d8c74c0883a1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -46,6 +46,9 @@ nv84_disp_base_omthds[] = {
46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
47 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 47 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
48 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 48 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
49 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
50 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
51 { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
49 {}, 52 {},
50}; 53};
51 54
@@ -63,7 +66,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
63 struct nv50_disp_priv *priv; 66 struct nv50_disp_priv *priv;
64 int ret; 67 int ret;
65 68
66 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 69 ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
67 "display", &priv); 70 "display", &priv);
68 *pobject = nv_object(priv); 71 *pobject = nv_object(priv);
69 if (ret) 72 if (ret)
@@ -72,17 +75,18 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
72 nv_engine(priv)->sclass = nv84_disp_base_oclass; 75 nv_engine(priv)->sclass = nv84_disp_base_oclass;
73 nv_engine(priv)->cclass = &nv50_disp_cclass; 76 nv_engine(priv)->cclass = &nv50_disp_cclass;
74 nv_subdev(priv)->intr = nv50_disp_intr; 77 nv_subdev(priv)->intr = nv50_disp_intr;
78 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
75 priv->sclass = nv84_disp_sclass; 79 priv->sclass = nv84_disp_sclass;
76 priv->head.nr = 2; 80 priv->head.nr = 2;
77 priv->dac.nr = 3; 81 priv->dac.nr = 3;
78 priv->sor.nr = 2; 82 priv->sor.nr = 2;
83 priv->pior.nr = 3;
79 priv->dac.power = nv50_dac_power; 84 priv->dac.power = nv50_dac_power;
80 priv->dac.sense = nv50_dac_sense; 85 priv->dac.sense = nv50_dac_sense;
81 priv->sor.power = nv50_sor_power; 86 priv->sor.power = nv50_sor_power;
82 priv->sor.hdmi = nv84_hdmi_ctrl; 87 priv->sor.hdmi = nv84_hdmi_ctrl;
83 88 priv->pior.power = nv50_pior_power;
84 INIT_LIST_HEAD(&priv->base.vblank.list); 89 priv->pior.dp = &nv50_pior_dp_func;
85 spin_lock_init(&priv->base.vblank.lock);
86 return 0; 90 return 0;
87} 91}
88 92
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index ba9dfd4669a2..a66f949c1f84 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -44,14 +44,11 @@ nv94_disp_base_omthds[] = {
44 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 44 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
45 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 45 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
47 { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd },
48 { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd },
49 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },
50 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd },
51 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd },
52 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd },
53 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 47 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
54 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 48 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
49 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
50 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
51 { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
55 {}, 52 {},
56}; 53};
57 54
@@ -69,7 +66,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
69 struct nv50_disp_priv *priv; 66 struct nv50_disp_priv *priv;
70 int ret; 67 int ret;
71 68
72 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 69 ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
73 "display", &priv); 70 "display", &priv);
74 *pobject = nv_object(priv); 71 *pobject = nv_object(priv);
75 if (ret) 72 if (ret)
@@ -78,22 +75,19 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
78 nv_engine(priv)->sclass = nv94_disp_base_oclass; 75 nv_engine(priv)->sclass = nv94_disp_base_oclass;
79 nv_engine(priv)->cclass = &nv50_disp_cclass; 76 nv_engine(priv)->cclass = &nv50_disp_cclass;
80 nv_subdev(priv)->intr = nv50_disp_intr; 77 nv_subdev(priv)->intr = nv50_disp_intr;
78 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
81 priv->sclass = nv94_disp_sclass; 79 priv->sclass = nv94_disp_sclass;
82 priv->head.nr = 2; 80 priv->head.nr = 2;
83 priv->dac.nr = 3; 81 priv->dac.nr = 3;
84 priv->sor.nr = 4; 82 priv->sor.nr = 4;
83 priv->pior.nr = 3;
85 priv->dac.power = nv50_dac_power; 84 priv->dac.power = nv50_dac_power;
86 priv->dac.sense = nv50_dac_sense; 85 priv->dac.sense = nv50_dac_sense;
87 priv->sor.power = nv50_sor_power; 86 priv->sor.power = nv50_sor_power;
88 priv->sor.hdmi = nv84_hdmi_ctrl; 87 priv->sor.hdmi = nv84_hdmi_ctrl;
89 priv->sor.dp_train = nv94_sor_dp_train; 88 priv->sor.dp = &nv94_sor_dp_func;
90 priv->sor.dp_train_init = nv94_sor_dp_train_init; 89 priv->pior.power = nv50_pior_power;
91 priv->sor.dp_train_fini = nv94_sor_dp_train_fini; 90 priv->pior.dp = &nv50_pior_dp_func;
92 priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
93 priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
94
95 INIT_LIST_HEAD(&priv->base.vblank.list);
96 spin_lock_init(&priv->base.vblank.lock);
97 return 0; 91 return 0;
98} 92}
99 93
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index 5d63902cdeda..6cf8eefac368 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -53,7 +53,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
53 struct nv50_disp_priv *priv; 53 struct nv50_disp_priv *priv;
54 int ret; 54 int ret;
55 55
56 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 56 ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
57 "display", &priv); 57 "display", &priv);
58 *pobject = nv_object(priv); 58 *pobject = nv_object(priv);
59 if (ret) 59 if (ret)
@@ -62,17 +62,18 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
62 nv_engine(priv)->sclass = nva0_disp_base_oclass; 62 nv_engine(priv)->sclass = nva0_disp_base_oclass;
63 nv_engine(priv)->cclass = &nv50_disp_cclass; 63 nv_engine(priv)->cclass = &nv50_disp_cclass;
64 nv_subdev(priv)->intr = nv50_disp_intr; 64 nv_subdev(priv)->intr = nv50_disp_intr;
65 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
65 priv->sclass = nva0_disp_sclass; 66 priv->sclass = nva0_disp_sclass;
66 priv->head.nr = 2; 67 priv->head.nr = 2;
67 priv->dac.nr = 3; 68 priv->dac.nr = 3;
68 priv->sor.nr = 2; 69 priv->sor.nr = 2;
70 priv->pior.nr = 3;
69 priv->dac.power = nv50_dac_power; 71 priv->dac.power = nv50_dac_power;
70 priv->dac.sense = nv50_dac_sense; 72 priv->dac.sense = nv50_dac_sense;
71 priv->sor.power = nv50_sor_power; 73 priv->sor.power = nv50_sor_power;
72 priv->sor.hdmi = nv84_hdmi_ctrl; 74 priv->sor.hdmi = nv84_hdmi_ctrl;
73 75 priv->pior.power = nv50_pior_power;
74 INIT_LIST_HEAD(&priv->base.vblank.list); 76 priv->pior.dp = &nv50_pior_dp_func;
75 spin_lock_init(&priv->base.vblank.lock);
76 return 0; 77 return 0;
77} 78}
78 79
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index e9192ca389fa..b75413169eae 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -45,14 +45,11 @@ nva3_disp_base_omthds[] = {
45 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, 45 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
46 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 46 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
47 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 47 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
48 { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd },
49 { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd },
50 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },
51 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd },
52 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd },
53 { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd },
54 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 48 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
55 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 49 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
50 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
51 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
52 { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
56 {}, 53 {},
57}; 54};
58 55
@@ -70,7 +67,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
70 struct nv50_disp_priv *priv; 67 struct nv50_disp_priv *priv;
71 int ret; 68 int ret;
72 69
73 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 70 ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
74 "display", &priv); 71 "display", &priv);
75 *pobject = nv_object(priv); 72 *pobject = nv_object(priv);
76 if (ret) 73 if (ret)
@@ -79,23 +76,20 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
79 nv_engine(priv)->sclass = nva3_disp_base_oclass; 76 nv_engine(priv)->sclass = nva3_disp_base_oclass;
80 nv_engine(priv)->cclass = &nv50_disp_cclass; 77 nv_engine(priv)->cclass = &nv50_disp_cclass;
81 nv_subdev(priv)->intr = nv50_disp_intr; 78 nv_subdev(priv)->intr = nv50_disp_intr;
79 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
82 priv->sclass = nva3_disp_sclass; 80 priv->sclass = nva3_disp_sclass;
83 priv->head.nr = 2; 81 priv->head.nr = 2;
84 priv->dac.nr = 3; 82 priv->dac.nr = 3;
85 priv->sor.nr = 4; 83 priv->sor.nr = 4;
84 priv->pior.nr = 3;
86 priv->dac.power = nv50_dac_power; 85 priv->dac.power = nv50_dac_power;
87 priv->dac.sense = nv50_dac_sense; 86 priv->dac.sense = nv50_dac_sense;
88 priv->sor.power = nv50_sor_power; 87 priv->sor.power = nv50_sor_power;
89 priv->sor.hda_eld = nva3_hda_eld; 88 priv->sor.hda_eld = nva3_hda_eld;
90 priv->sor.hdmi = nva3_hdmi_ctrl; 89 priv->sor.hdmi = nva3_hdmi_ctrl;
91 priv->sor.dp_train = nv94_sor_dp_train; 90 priv->sor.dp = &nv94_sor_dp_func;
92 priv->sor.dp_train_init = nv94_sor_dp_train_init; 91 priv->pior.power = nv50_pior_power;
93 priv->sor.dp_train_fini = nv94_sor_dp_train_fini; 92 priv->pior.dp = &nv50_pior_dp_func;
94 priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
95 priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
96
97 INIT_LIST_HEAD(&priv->base.vblank.list);
98 spin_lock_init(&priv->base.vblank.lock);
99 return 0; 93 return 0;
100} 94}
101 95
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 9e38ebff5fb3..7106a72e611e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -27,12 +27,10 @@
27#include <core/handle.h> 27#include <core/handle.h>
28#include <core/class.h> 28#include <core/class.h>
29 29
30#include <engine/software.h>
31#include <engine/disp.h> 30#include <engine/disp.h>
32 31
33#include <subdev/timer.h> 32#include <subdev/timer.h>
34#include <subdev/fb.h> 33#include <subdev/fb.h>
35#include <subdev/bar.h>
36#include <subdev/clock.h> 34#include <subdev/clock.h>
37 35
38#include <subdev/bios.h> 36#include <subdev/bios.h>
@@ -230,7 +228,7 @@ nvd0_disp_sync_ctor(struct nouveau_object *parent,
230 struct nv50_disp_dmac *dmac; 228 struct nv50_disp_dmac *dmac;
231 int ret; 229 int ret;
232 230
233 if (size < sizeof(*data) || args->head >= priv->head.nr) 231 if (size < sizeof(*args) || args->head >= priv->head.nr)
234 return -EINVAL; 232 return -EINVAL;
235 233
236 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, 234 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -270,7 +268,7 @@ nvd0_disp_ovly_ctor(struct nouveau_object *parent,
270 struct nv50_disp_dmac *dmac; 268 struct nv50_disp_dmac *dmac;
271 int ret; 269 int ret;
272 270
273 if (size < sizeof(*data) || args->head >= priv->head.nr) 271 if (size < sizeof(*args) || args->head >= priv->head.nr)
274 return -EINVAL; 272 return -EINVAL;
275 273
276 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, 274 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -443,6 +441,18 @@ nvd0_disp_curs_ofuncs = {
443 * Base display object 441 * Base display object
444 ******************************************************************************/ 442 ******************************************************************************/
445 443
444static void
445nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
446{
447 nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
448}
449
450static void
451nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head)
452{
453 nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
454}
455
446static int 456static int
447nvd0_disp_base_ctor(struct nouveau_object *parent, 457nvd0_disp_base_ctor(struct nouveau_object *parent,
448 struct nouveau_object *engine, 458 struct nouveau_object *engine,
@@ -459,6 +469,10 @@ nvd0_disp_base_ctor(struct nouveau_object *parent,
459 if (ret) 469 if (ret)
460 return ret; 470 return ret;
461 471
472 priv->base.vblank->priv = priv;
473 priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
474 priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
475
462 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht); 476 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
463} 477}
464 478
@@ -636,20 +650,19 @@ exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id)
636 650
637static u32 651static u32
638exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp, 652exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp,
639 u32 ctrl, int id, u32 pclk) 653 u32 ctrl, int id, u32 pclk, struct dcb_output *dcb)
640{ 654{
641 struct nouveau_bios *bios = nouveau_bios(priv); 655 struct nouveau_bios *bios = nouveau_bios(priv);
642 struct nvbios_outp info1; 656 struct nvbios_outp info1;
643 struct nvbios_ocfg info2; 657 struct nvbios_ocfg info2;
644 struct dcb_output dcb;
645 u8 ver, hdr, cnt, len; 658 u8 ver, hdr, cnt, len;
646 u16 data, conf; 659 u32 data, conf = ~0;
647 660
648 data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1); 661 data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1);
649 if (data == 0x0000) 662 if (data == 0x0000)
650 return false; 663 return conf;
651 664
652 switch (dcb.type) { 665 switch (dcb->type) {
653 case DCB_OUTPUT_TMDS: 666 case DCB_OUTPUT_TMDS:
654 conf = (ctrl & 0x00000f00) >> 8; 667 conf = (ctrl & 0x00000f00) >> 8;
655 if (pclk >= 165000) 668 if (pclk >= 165000)
@@ -668,25 +681,23 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp,
668 } 681 }
669 682
670 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 683 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
671 if (data) { 684 if (data && id < 0xff) {
672 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 685 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
673 if (data) { 686 if (data) {
674 struct nvbios_init init = { 687 struct nvbios_init init = {
675 .subdev = nv_subdev(priv), 688 .subdev = nv_subdev(priv),
676 .bios = bios, 689 .bios = bios,
677 .offset = data, 690 .offset = data,
678 .outp = &dcb, 691 .outp = dcb,
679 .crtc = head, 692 .crtc = head,
680 .execute = 1, 693 .execute = 1,
681 }; 694 };
682 695
683 if (nvbios_exec(&init)) 696 nvbios_exec(&init);
684 return 0x0000;
685 return conf;
686 } 697 }
687 } 698 }
688 699
689 return 0x0000; 700 return conf;
690} 701}
691 702
692static void 703static void
@@ -752,6 +763,7 @@ nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or)
752static void 763static void
753nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) 764nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
754{ 765{
766 struct dcb_output outp;
755 u32 pclk; 767 u32 pclk;
756 int i; 768 int i;
757 769
@@ -771,10 +783,29 @@ nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
771 nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000); 783 nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000);
772 784
773 for (i = 0; mask && i < 8; i++) { 785 for (i = 0; mask && i < 8; i++) {
774 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg; 786 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20));
775 if (mcp & (1 << head)) { 787 if (mcp & (1 << head)) {
776 if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) { 788 u32 cfg = exec_clkcmp(priv, head, i, mcp, 0xff, pclk, &outp);
789 if (cfg != ~0) {
777 u32 addr, mask, data = 0x00000000; 790 u32 addr, mask, data = 0x00000000;
791
792 if (outp.type == DCB_OUTPUT_DP) {
793 switch ((mcp & 0x000f0000) >> 16) {
794 case 6: pclk = pclk * 30 / 8; break;
795 case 5: pclk = pclk * 24 / 8; break;
796 case 2:
797 default:
798 pclk = pclk * 18 / 8;
799 break;
800 }
801
802 nouveau_dp_train(&priv->base,
803 priv->sor.dp,
804 &outp, head, pclk);
805 }
806
807 exec_clkcmp(priv, head, i, mcp, 0, pclk, &outp);
808
778 if (i < 4) { 809 if (i < 4) {
779 addr = 0x612280 + ((i - 0) * 0x800); 810 addr = 0x612280 + ((i - 0) * 0x800);
780 mask = 0xffffffff; 811 mask = 0xffffffff;
@@ -807,6 +838,7 @@ nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
807static void 838static void
808nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) 839nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
809{ 840{
841 struct dcb_output outp;
810 int pclk, i; 842 int pclk, i;
811 843
812 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; 844 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
@@ -814,7 +846,7 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
814 for (i = 0; mask && i < 8; i++) { 846 for (i = 0; mask && i < 8; i++) {
815 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)); 847 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20));
816 if (mcp & (1 << head)) 848 if (mcp & (1 << head))
817 exec_clkcmp(priv, head, i, mcp, 1, pclk); 849 exec_clkcmp(priv, head, i, mcp, 1, pclk, &outp);
818 } 850 }
819 851
820 nv_wr32(priv, 0x6101d4, 0x00000000); 852 nv_wr32(priv, 0x6101d4, 0x00000000);
@@ -822,33 +854,24 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
822 nv_wr32(priv, 0x6101d0, 0x80000000); 854 nv_wr32(priv, 0x6101d0, 0x80000000);
823} 855}
824 856
825static void 857void
826nvd0_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) 858nvd0_disp_intr_supervisor(struct work_struct *work)
827{ 859{
828 struct nouveau_bar *bar = nouveau_bar(priv); 860 struct nv50_disp_priv *priv =
829 struct nouveau_disp *disp = &priv->base; 861 container_of(work, struct nv50_disp_priv, supervisor);
830 struct nouveau_software_chan *chan, *temp; 862 u32 mask = 0, head = ~0;
831 unsigned long flags;
832
833 spin_lock_irqsave(&disp->vblank.lock, flags);
834 list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) {
835 if (chan->vblank.crtc != crtc)
836 continue;
837
838 nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
839 bar->flush(bar);
840 nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset));
841 nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
842 nv_wr32(priv, 0x060014, chan->vblank.value);
843
844 list_del(&chan->vblank.head);
845 if (disp->vblank.put)
846 disp->vblank.put(disp->vblank.data, crtc);
847 }
848 spin_unlock_irqrestore(&disp->vblank.lock, flags);
849 863
850 if (disp->vblank.notify) 864 while (!mask && ++head < priv->head.nr)
851 disp->vblank.notify(disp->vblank.data, crtc); 865 mask = nv_rd32(priv, 0x6101d4 + (head * 0x800));
866
867 nv_debug(priv, "supervisor %08x %08x %d\n", priv->super, mask, head);
868
869 if (priv->super & 0x00000001)
870 nvd0_display_unk1_handler(priv, head, mask);
871 if (priv->super & 0x00000002)
872 nvd0_display_unk2_handler(priv, head, mask);
873 if (priv->super & 0x00000004)
874 nvd0_display_unk4_handler(priv, head, mask);
852} 875}
853 876
854void 877void
@@ -884,27 +907,11 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
884 907
885 if (intr & 0x00100000) { 908 if (intr & 0x00100000) {
886 u32 stat = nv_rd32(priv, 0x6100ac); 909 u32 stat = nv_rd32(priv, 0x6100ac);
887 u32 mask = 0, crtc = ~0; 910 if (stat & 0x00000007) {
888 911 priv->super = (stat & 0x00000007);
889 while (!mask && ++crtc < priv->head.nr) 912 schedule_work(&priv->supervisor);
890 mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800)); 913 nv_wr32(priv, 0x6100ac, priv->super);
891 914 stat &= ~0x00000007;
892 if (stat & 0x00000001) {
893 nv_wr32(priv, 0x6100ac, 0x00000001);
894 nvd0_display_unk1_handler(priv, crtc, mask);
895 stat &= ~0x00000001;
896 }
897
898 if (stat & 0x00000002) {
899 nv_wr32(priv, 0x6100ac, 0x00000002);
900 nvd0_display_unk2_handler(priv, crtc, mask);
901 stat &= ~0x00000002;
902 }
903
904 if (stat & 0x00000004) {
905 nv_wr32(priv, 0x6100ac, 0x00000004);
906 nvd0_display_unk4_handler(priv, crtc, mask);
907 stat &= ~0x00000004;
908 } 915 }
909 916
910 if (stat) { 917 if (stat) {
@@ -920,7 +927,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
920 if (mask & intr) { 927 if (mask & intr) {
921 u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); 928 u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
922 if (stat & 0x00000001) 929 if (stat & 0x00000001)
923 nvd0_disp_intr_vblank(priv, i); 930 nouveau_event_trigger(priv->base.vblank, i);
924 nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); 931 nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
925 nv_rd32(priv, 0x6100c0 + (i * 0x800)); 932 nv_rd32(priv, 0x6100c0 + (i * 0x800));
926 } 933 }
@@ -933,10 +940,11 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
933 struct nouveau_object **pobject) 940 struct nouveau_object **pobject)
934{ 941{
935 struct nv50_disp_priv *priv; 942 struct nv50_disp_priv *priv;
943 int heads = nv_rd32(parent, 0x022448);
936 int ret; 944 int ret;
937 945
938 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 946 ret = nouveau_disp_create(parent, engine, oclass, heads,
939 "display", &priv); 947 "PDISP", "display", &priv);
940 *pobject = nv_object(priv); 948 *pobject = nv_object(priv);
941 if (ret) 949 if (ret)
942 return ret; 950 return ret;
@@ -944,8 +952,9 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
944 nv_engine(priv)->sclass = nvd0_disp_base_oclass; 952 nv_engine(priv)->sclass = nvd0_disp_base_oclass;
945 nv_engine(priv)->cclass = &nv50_disp_cclass; 953 nv_engine(priv)->cclass = &nv50_disp_cclass;
946 nv_subdev(priv)->intr = nvd0_disp_intr; 954 nv_subdev(priv)->intr = nvd0_disp_intr;
955 INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
947 priv->sclass = nvd0_disp_sclass; 956 priv->sclass = nvd0_disp_sclass;
948 priv->head.nr = nv_rd32(priv, 0x022448); 957 priv->head.nr = heads;
949 priv->dac.nr = 3; 958 priv->dac.nr = 3;
950 priv->sor.nr = 4; 959 priv->sor.nr = 4;
951 priv->dac.power = nv50_dac_power; 960 priv->dac.power = nv50_dac_power;
@@ -953,14 +962,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
953 priv->sor.power = nv50_sor_power; 962 priv->sor.power = nv50_sor_power;
954 priv->sor.hda_eld = nvd0_hda_eld; 963 priv->sor.hda_eld = nvd0_hda_eld;
955 priv->sor.hdmi = nvd0_hdmi_ctrl; 964 priv->sor.hdmi = nvd0_hdmi_ctrl;
956 priv->sor.dp_train = nvd0_sor_dp_train; 965 priv->sor.dp = &nvd0_sor_dp_func;
957 priv->sor.dp_train_init = nv94_sor_dp_train_init;
958 priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
959 priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
960 priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
961
962 INIT_LIST_HEAD(&priv->base.vblank.list);
963 spin_lock_init(&priv->base.vblank.lock);
964 return 0; 966 return 0;
965} 967}
966 968
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 259537c4587e..20725b363d58 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -51,10 +51,11 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
51 struct nouveau_object **pobject) 51 struct nouveau_object **pobject)
52{ 52{
53 struct nv50_disp_priv *priv; 53 struct nv50_disp_priv *priv;
54 int heads = nv_rd32(parent, 0x022448);
54 int ret; 55 int ret;
55 56
56 ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 57 ret = nouveau_disp_create(parent, engine, oclass, heads,
57 "display", &priv); 58 "PDISP", "display", &priv);
58 *pobject = nv_object(priv); 59 *pobject = nv_object(priv);
59 if (ret) 60 if (ret)
60 return ret; 61 return ret;
@@ -62,8 +63,9 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
62 nv_engine(priv)->sclass = nve0_disp_base_oclass; 63 nv_engine(priv)->sclass = nve0_disp_base_oclass;
63 nv_engine(priv)->cclass = &nv50_disp_cclass; 64 nv_engine(priv)->cclass = &nv50_disp_cclass;
64 nv_subdev(priv)->intr = nvd0_disp_intr; 65 nv_subdev(priv)->intr = nvd0_disp_intr;
66 INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
65 priv->sclass = nve0_disp_sclass; 67 priv->sclass = nve0_disp_sclass;
66 priv->head.nr = nv_rd32(priv, 0x022448); 68 priv->head.nr = heads;
67 priv->dac.nr = 3; 69 priv->dac.nr = 3;
68 priv->sor.nr = 4; 70 priv->sor.nr = 4;
69 priv->dac.power = nv50_dac_power; 71 priv->dac.power = nv50_dac_power;
@@ -71,14 +73,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
71 priv->sor.power = nv50_sor_power; 73 priv->sor.power = nv50_sor_power;
72 priv->sor.hda_eld = nvd0_hda_eld; 74 priv->sor.hda_eld = nvd0_hda_eld;
73 priv->sor.hdmi = nvd0_hdmi_ctrl; 75 priv->sor.hdmi = nvd0_hdmi_ctrl;
74 priv->sor.dp_train = nvd0_sor_dp_train; 76 priv->sor.dp = &nvd0_sor_dp_func;
75 priv->sor.dp_train_init = nv94_sor_dp_train_init;
76 priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
77 priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
78 priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
79
80 INIT_LIST_HEAD(&priv->base.vblank.list);
81 spin_lock_init(&priv->base.vblank.lock);
82 return 0; 77 return 0;
83} 78}
84 79
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
new file mode 100644
index 000000000000..2c8ce351b52d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <core/os.h>
26#include <core/class.h>
27
28#include <subdev/bios.h>
29#include <subdev/bios/dcb.h>
30#include <subdev/timer.h>
31#include <subdev/i2c.h>
32
33#include "nv50.h"
34
35/******************************************************************************
36 * DisplayPort
37 *****************************************************************************/
38static struct nouveau_i2c_port *
39nv50_pior_dp_find(struct nouveau_disp *disp, struct dcb_output *outp)
40{
41 struct nouveau_i2c *i2c = nouveau_i2c(disp);
42 return i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev));
43}
44
45static int
46nv50_pior_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp,
47 int head, int pattern)
48{
49 struct nouveau_i2c_port *port;
50 int ret = -EINVAL;
51
52 port = nv50_pior_dp_find(disp, outp);
53 if (port) {
54 if (port->func->pattern)
55 ret = port->func->pattern(port, pattern);
56 else
57 ret = 0;
58 }
59
60 return ret;
61}
62
63static int
64nv50_pior_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
65 int head, int lane_nr, int link_bw, bool enh)
66{
67 struct nouveau_i2c_port *port;
68 int ret = -EINVAL;
69
70 port = nv50_pior_dp_find(disp, outp);
71 if (port && port->func->lnk_ctl)
72 ret = port->func->lnk_ctl(port, lane_nr, link_bw, enh);
73
74 return ret;
75}
76
77static int
78nv50_pior_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
79 int head, int lane, int vsw, int pre)
80{
81 struct nouveau_i2c_port *port;
82 int ret = -EINVAL;
83
84 port = nv50_pior_dp_find(disp, outp);
85 if (port) {
86 if (port->func->drv_ctl)
87 ret = port->func->drv_ctl(port, lane, vsw, pre);
88 else
89 ret = 0;
90 }
91
92 return ret;
93}
94
95const struct nouveau_dp_func
96nv50_pior_dp_func = {
97 .pattern = nv50_pior_dp_pattern,
98 .lnk_ctl = nv50_pior_dp_lnk_ctl,
99 .drv_ctl = nv50_pior_dp_drv_ctl,
100};
101
102/******************************************************************************
103 * General PIOR handling
104 *****************************************************************************/
105int
106nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data)
107{
108 const u32 stat = data & NV50_DISP_PIOR_PWR_STATE;
109 const u32 soff = (or * 0x800);
110 nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
111 nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | stat);
112 nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
113 return 0;
114}
115
116int
117nv50_pior_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
118{
119 struct nv50_disp_priv *priv = (void *)object->engine;
120 const u8 type = (mthd & NV50_DISP_PIOR_MTHD_TYPE) >> 12;
121 const u8 or = (mthd & NV50_DISP_PIOR_MTHD_OR);
122 u32 *data = args;
123 int ret;
124
125 if (size < sizeof(u32))
126 return -EINVAL;
127
128 mthd &= ~NV50_DISP_PIOR_MTHD_TYPE;
129 mthd &= ~NV50_DISP_PIOR_MTHD_OR;
130 switch (mthd) {
131 case NV50_DISP_PIOR_PWR:
132 ret = priv->pior.power(priv, or, data[0]);
133 priv->pior.type[or] = type;
134 break;
135 default:
136 return -EINVAL;
137 }
138
139 return ret;
140}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
index 39b6b67732d0..ab1e918469a8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
@@ -79,31 +79,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
79 priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; 79 priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
80 ret = 0; 80 ret = 0;
81 break; 81 break;
82 case NV94_DISP_SOR_DP_TRAIN:
83 switch (data & NV94_DISP_SOR_DP_TRAIN_OP) {
84 case NV94_DISP_SOR_DP_TRAIN_OP_PATTERN:
85 ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
86 break;
87 case NV94_DISP_SOR_DP_TRAIN_OP_INIT:
88 ret = priv->sor.dp_train_init(priv, or, link, head, type, mask, data, &outp);
89 break;
90 case NV94_DISP_SOR_DP_TRAIN_OP_FINI:
91 ret = priv->sor.dp_train_fini(priv, or, link, head, type, mask, data, &outp);
92 break;
93 default:
94 break;
95 }
96 break;
97 case NV94_DISP_SOR_DP_LNKCTL:
98 ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp);
99 break;
100 case NV94_DISP_SOR_DP_DRVCTL(0):
101 case NV94_DISP_SOR_DP_DRVCTL(1):
102 case NV94_DISP_SOR_DP_DRVCTL(2):
103 case NV94_DISP_SOR_DP_DRVCTL(3):
104 ret = priv->sor.dp_drvctl(priv, or, link, (mthd & 0xc0) >> 6,
105 type, mask, data, &outp);
106 break;
107 default: 82 default:
108 BUG_ON(1); 83 BUG_ON(1);
109 } 84 }
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
index f6edd009762e..7ec4ee83fb64 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
@@ -33,124 +33,53 @@
33#include "nv50.h" 33#include "nv50.h"
34 34
35static inline u32 35static inline u32
36nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) 36nv94_sor_soff(struct dcb_output *outp)
37{ 37{
38 static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ 38 return (ffs(outp->or) - 1) * 0x800;
39 static const u8 nv94[] = { 16, 8, 0, 24 };
40 if (nv_device(priv)->chipset == 0xaf)
41 return nvaf[lane];
42 return nv94[lane];
43} 39}
44 40
45int 41static inline u32
46nv94_sor_dp_train_init(struct nv50_disp_priv *priv, int or, int link, int head, 42nv94_sor_loff(struct dcb_output *outp)
47 u16 type, u16 mask, u32 data, struct dcb_output *dcbo)
48{ 43{
49 struct nouveau_bios *bios = nouveau_bios(priv); 44 return nv94_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80;
50 struct nvbios_dpout info;
51 u8 ver, hdr, cnt, len;
52 u16 outp;
53
54 outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
55 if (outp) {
56 struct nvbios_init init = {
57 .subdev = nv_subdev(priv),
58 .bios = bios,
59 .outp = dcbo,
60 .crtc = head,
61 .execute = 1,
62 };
63
64 if (data & NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON)
65 init.offset = info.script[2];
66 else
67 init.offset = info.script[3];
68 nvbios_exec(&init);
69
70 init.offset = info.script[0];
71 nvbios_exec(&init);
72 }
73
74 return 0;
75} 45}
76 46
77int 47static inline u32
78nv94_sor_dp_train_fini(struct nv50_disp_priv *priv, int or, int link, int head, 48nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
79 u16 type, u16 mask, u32 data, struct dcb_output *dcbo)
80{ 49{
81 struct nouveau_bios *bios = nouveau_bios(priv); 50 static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */
82 struct nvbios_dpout info; 51 static const u8 nv94[] = { 16, 8, 0, 24 };
83 u8 ver, hdr, cnt, len; 52 if (nv_device(priv)->chipset == 0xaf)
84 u16 outp; 53 return nvaf[lane];
85 54 return nv94[lane];
86 outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
87 if (outp) {
88 struct nvbios_init init = {
89 .subdev = nv_subdev(priv),
90 .bios = bios,
91 .offset = info.script[1],
92 .outp = dcbo,
93 .crtc = head,
94 .execute = 1,
95 };
96
97 nvbios_exec(&init);
98 }
99
100 return 0;
101} 55}
102 56
103int 57static int
104nv94_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, 58nv94_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp,
105 u16 type, u16 mask, u32 data, struct dcb_output *info) 59 int head, int pattern)
106{ 60{
107 const u32 loff = (or * 0x800) + (link * 0x80); 61 struct nv50_disp_priv *priv = (void *)disp;
108 const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); 62 const u32 loff = nv94_sor_loff(outp);
109 nv_mask(priv, 0x61c10c + loff, 0x0f000000, patt << 24); 63 nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24);
110 return 0; 64 return 0;
111} 65}
112 66
113int 67static int
114nv94_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, 68nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
115 u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 69 int head, int link_nr, int link_bw, bool enh_frame)
116{ 70{
117 struct nouveau_bios *bios = nouveau_bios(priv); 71 struct nv50_disp_priv *priv = (void *)disp;
118 const u32 loff = (or * 0x800) + (link * 0x80); 72 const u32 soff = nv94_sor_soff(outp);
119 const u32 soff = (or * 0x800); 73 const u32 loff = nv94_sor_loff(outp);
120 u16 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8;
121 u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT);
122 u32 dpctrl = 0x00000000; 74 u32 dpctrl = 0x00000000;
123 u32 clksor = 0x00000000; 75 u32 clksor = 0x00000000;
124 u32 outp, lane = 0; 76 u32 lane = 0;
125 u8 ver, hdr, cnt, len;
126 struct nvbios_dpout info;
127 int i; 77 int i;
128 78
129 /* -> 10Khz units */
130 link_bw *= 2700;
131
132 outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
133 if (outp && info.lnkcmp) {
134 struct nvbios_init init = {
135 .subdev = nv_subdev(priv),
136 .bios = bios,
137 .offset = 0x0000,
138 .outp = dcbo,
139 .crtc = head,
140 .execute = 1,
141 };
142
143 while (link_bw < nv_ro16(bios, info.lnkcmp))
144 info.lnkcmp += 4;
145 init.offset = nv_ro16(bios, info.lnkcmp + 2);
146
147 nvbios_exec(&init);
148 }
149
150 dpctrl |= ((1 << link_nr) - 1) << 16; 79 dpctrl |= ((1 << link_nr) - 1) << 16;
151 if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) 80 if (enh_frame)
152 dpctrl |= 0x00004000; 81 dpctrl |= 0x00004000;
153 if (link_bw > 16200) 82 if (link_bw > 0x06)
154 clksor |= 0x00040000; 83 clksor |= 0x00040000;
155 84
156 for (i = 0; i < link_nr; i++) 85 for (i = 0; i < link_nr; i++)
@@ -162,24 +91,25 @@ nv94_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head,
162 return 0; 91 return 0;
163} 92}
164 93
165int 94static int
166nv94_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, 95nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
167 u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 96 int head, int lane, int swing, int preem)
168{ 97{
169 struct nouveau_bios *bios = nouveau_bios(priv); 98 struct nouveau_bios *bios = nouveau_bios(disp);
170 const u32 loff = (or * 0x800) + (link * 0x80); 99 struct nv50_disp_priv *priv = (void *)disp;
171 const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; 100 const u32 loff = nv94_sor_loff(outp);
172 const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE);
173 u32 addr, shift = nv94_sor_dp_lane_map(priv, lane); 101 u32 addr, shift = nv94_sor_dp_lane_map(priv, lane);
174 u8 ver, hdr, cnt, len; 102 u8 ver, hdr, cnt, len;
175 struct nvbios_dpout outp; 103 struct nvbios_dpout info;
176 struct nvbios_dpcfg ocfg; 104 struct nvbios_dpcfg ocfg;
177 105
178 addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); 106 addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm,
107 &ver, &hdr, &cnt, &len, &info);
179 if (!addr) 108 if (!addr)
180 return -ENODEV; 109 return -ENODEV;
181 110
182 addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); 111 addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem,
112 &ver, &hdr, &cnt, &len, &ocfg);
183 if (!addr) 113 if (!addr)
184 return -EINVAL; 114 return -EINVAL;
185 115
@@ -188,3 +118,10 @@ nv94_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane,
188 nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8); 118 nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8);
189 return 0; 119 return 0;
190} 120}
121
122const struct nouveau_dp_func
123nv94_sor_dp_func = {
124 .pattern = nv94_sor_dp_pattern,
125 .lnk_ctl = nv94_sor_dp_lnk_ctl,
126 .drv_ctl = nv94_sor_dp_drv_ctl,
127};
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
index c37ce7e29f5d..9e1d435d7282 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
@@ -33,59 +33,49 @@
33#include "nv50.h" 33#include "nv50.h"
34 34
35static inline u32 35static inline u32
36nvd0_sor_soff(struct dcb_output *outp)
37{
38 return (ffs(outp->or) - 1) * 0x800;
39}
40
41static inline u32
42nvd0_sor_loff(struct dcb_output *outp)
43{
44 return nvd0_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80;
45}
46
47static inline u32
36nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) 48nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
37{ 49{
38 static const u8 nvd0[] = { 16, 8, 0, 24 }; 50 static const u8 nvd0[] = { 16, 8, 0, 24 };
39 return nvd0[lane]; 51 return nvd0[lane];
40} 52}
41 53
42int 54static int
43nvd0_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, 55nvd0_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp,
44 u16 type, u16 mask, u32 data, struct dcb_output *info) 56 int head, int pattern)
45{ 57{
46 const u32 loff = (or * 0x800) + (link * 0x80); 58 struct nv50_disp_priv *priv = (void *)disp;
47 const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); 59 const u32 loff = nvd0_sor_loff(outp);
48 nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * patt); 60 nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
49 return 0; 61 return 0;
50} 62}
51 63
52int 64static int
53nvd0_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, 65nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
54 u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 66 int head, int link_nr, int link_bw, bool enh_frame)
55{ 67{
56 struct nouveau_bios *bios = nouveau_bios(priv); 68 struct nv50_disp_priv *priv = (void *)disp;
57 const u32 loff = (or * 0x800) + (link * 0x80); 69 const u32 soff = nvd0_sor_soff(outp);
58 const u32 soff = (or * 0x800); 70 const u32 loff = nvd0_sor_loff(outp);
59 const u8 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8;
60 const u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT);
61 u32 dpctrl = 0x00000000; 71 u32 dpctrl = 0x00000000;
62 u32 clksor = 0x00000000; 72 u32 clksor = 0x00000000;
63 u32 outp, lane = 0; 73 u32 lane = 0;
64 u8 ver, hdr, cnt, len;
65 struct nvbios_dpout info;
66 int i; 74 int i;
67 75
68 outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info);
69 if (outp && info.lnkcmp) {
70 struct nvbios_init init = {
71 .subdev = nv_subdev(priv),
72 .bios = bios,
73 .offset = 0x0000,
74 .outp = dcbo,
75 .crtc = head,
76 .execute = 1,
77 };
78
79 while (nv_ro08(bios, info.lnkcmp) < link_bw)
80 info.lnkcmp += 3;
81 init.offset = nv_ro16(bios, info.lnkcmp + 1);
82
83 nvbios_exec(&init);
84 }
85
86 clksor |= link_bw << 18; 76 clksor |= link_bw << 18;
87 dpctrl |= ((1 << link_nr) - 1) << 16; 77 dpctrl |= ((1 << link_nr) - 1) << 16;
88 if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) 78 if (enh_frame)
89 dpctrl |= 0x00004000; 79 dpctrl |= 0x00004000;
90 80
91 for (i = 0; i < link_nr; i++) 81 for (i = 0; i < link_nr; i++)
@@ -97,24 +87,25 @@ nvd0_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head,
97 return 0; 87 return 0;
98} 88}
99 89
100int 90static int
101nvd0_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, 91nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp,
102 u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 92 int head, int lane, int swing, int preem)
103{ 93{
104 struct nouveau_bios *bios = nouveau_bios(priv); 94 struct nouveau_bios *bios = nouveau_bios(disp);
105 const u32 loff = (or * 0x800) + (link * 0x80); 95 struct nv50_disp_priv *priv = (void *)disp;
106 const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; 96 const u32 loff = nvd0_sor_loff(outp);
107 const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE);
108 u32 addr, shift = nvd0_sor_dp_lane_map(priv, lane); 97 u32 addr, shift = nvd0_sor_dp_lane_map(priv, lane);
109 u8 ver, hdr, cnt, len; 98 u8 ver, hdr, cnt, len;
110 struct nvbios_dpout outp; 99 struct nvbios_dpout info;
111 struct nvbios_dpcfg ocfg; 100 struct nvbios_dpcfg ocfg;
112 101
113 addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); 102 addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm,
103 &ver, &hdr, &cnt, &len, &info);
114 if (!addr) 104 if (!addr)
115 return -ENODEV; 105 return -ENODEV;
116 106
117 addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); 107 addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem,
108 &ver, &hdr, &cnt, &len, &ocfg);
118 if (!addr) 109 if (!addr)
119 return -EINVAL; 110 return -EINVAL;
120 111
@@ -124,3 +115,10 @@ nvd0_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane,
124 nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000); 115 nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000);
125 return 0; 116 return 0;
126} 117}
118
119const struct nouveau_dp_func
120nvd0_sor_dp_func = {
121 .pattern = nvd0_sor_dp_pattern,
122 .lnk_ctl = nvd0_sor_dp_lnk_ctl,
123 .drv_ctl = nvd0_sor_dp_drv_ctl,
124};
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
index c2b9db335816..7341ebe131fa 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
@@ -22,8 +22,10 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/object.h> 26#include <core/object.h>
26#include <core/handle.h> 27#include <core/handle.h>
28#include <core/event.h>
27#include <core/class.h> 29#include <core/class.h>
28 30
29#include <engine/dmaobj.h> 31#include <engine/dmaobj.h>
@@ -146,10 +148,25 @@ nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object)
146 return -1; 148 return -1;
147} 149}
148 150
151const char *
152nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid)
153{
154 struct nouveau_fifo_chan *chan = NULL;
155 unsigned long flags;
156
157 spin_lock_irqsave(&fifo->lock, flags);
158 if (chid >= fifo->min && chid <= fifo->max)
159 chan = (void *)fifo->channel[chid];
160 spin_unlock_irqrestore(&fifo->lock, flags);
161
162 return nouveau_client_name(chan);
163}
164
149void 165void
150nouveau_fifo_destroy(struct nouveau_fifo *priv) 166nouveau_fifo_destroy(struct nouveau_fifo *priv)
151{ 167{
152 kfree(priv->channel); 168 kfree(priv->channel);
169 nouveau_event_destroy(&priv->uevent);
153 nouveau_engine_destroy(&priv->base); 170 nouveau_engine_destroy(&priv->base);
154} 171}
155 172
@@ -174,6 +191,10 @@ nouveau_fifo_create_(struct nouveau_object *parent,
174 if (!priv->channel) 191 if (!priv->channel)
175 return -ENOMEM; 192 return -ENOMEM;
176 193
194 ret = nouveau_event_create(1, &priv->uevent);
195 if (ret)
196 return ret;
197
177 priv->chid = nouveau_fifo_chid; 198 priv->chid = nouveau_fifo_chid;
178 spin_lock_init(&priv->lock); 199 spin_lock_init(&priv->lock);
179 return 0; 200 return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
index a47a8548f9e0..f877bd524a92 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
@@ -28,6 +28,7 @@
28#include <core/namedb.h> 28#include <core/namedb.h>
29#include <core/handle.h> 29#include <core/handle.h>
30#include <core/ramht.h> 30#include <core/ramht.h>
31#include <core/event.h>
31 32
32#include <subdev/instmem.h> 33#include <subdev/instmem.h>
33#include <subdev/instmem/nv04.h> 34#include <subdev/instmem/nv04.h>
@@ -398,6 +399,98 @@ out:
398 return handled; 399 return handled;
399} 400}
400 401
402static void
403nv04_fifo_cache_error(struct nouveau_device *device,
404 struct nv04_fifo_priv *priv, u32 chid, u32 get)
405{
406 u32 mthd, data;
407 int ptr;
408
409 /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before wrapping on my
410 * G80 chips, but CACHE1 isn't big enough for this much data.. Tests
411 * show that it wraps around to the start at GET=0x800.. No clue as to
412 * why..
413 */
414 ptr = (get & 0x7ff) >> 2;
415
416 if (device->card_type < NV_40) {
417 mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr));
418 data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr));
419 } else {
420 mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr));
421 data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr));
422 }
423
424 if (!nv04_fifo_swmthd(priv, chid, mthd, data)) {
425 const char *client_name =
426 nouveau_client_name_for_fifo_chid(&priv->base, chid);
427 nv_error(priv,
428 "CACHE_ERROR - ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
429 chid, client_name, (mthd >> 13) & 7, mthd & 0x1ffc,
430 data);
431 }
432
433 nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
434 nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
435
436 nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0,
437 nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1);
438 nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4);
439 nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0,
440 nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1);
441 nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0);
442
443 nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH,
444 nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
445 nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);
446}
447
448static void
449nv04_fifo_dma_pusher(struct nouveau_device *device, struct nv04_fifo_priv *priv,
450 u32 chid)
451{
452 const char *client_name;
453 u32 dma_get = nv_rd32(priv, 0x003244);
454 u32 dma_put = nv_rd32(priv, 0x003240);
455 u32 push = nv_rd32(priv, 0x003220);
456 u32 state = nv_rd32(priv, 0x003228);
457
458 client_name = nouveau_client_name_for_fifo_chid(&priv->base, chid);
459
460 if (device->card_type == NV_50) {
461 u32 ho_get = nv_rd32(priv, 0x003328);
462 u32 ho_put = nv_rd32(priv, 0x003320);
463 u32 ib_get = nv_rd32(priv, 0x003334);
464 u32 ib_put = nv_rd32(priv, 0x003330);
465
466 nv_error(priv,
467 "DMA_PUSHER - ch %d [%s] get 0x%02x%08x put 0x%02x%08x ib_get 0x%08x ib_put 0x%08x state 0x%08x (err: %s) push 0x%08x\n",
468 chid, client_name, ho_get, dma_get, ho_put, dma_put,
469 ib_get, ib_put, state, nv_dma_state_err(state), push);
470
471 /* METHOD_COUNT, in DMA_STATE on earlier chipsets */
472 nv_wr32(priv, 0x003364, 0x00000000);
473 if (dma_get != dma_put || ho_get != ho_put) {
474 nv_wr32(priv, 0x003244, dma_put);
475 nv_wr32(priv, 0x003328, ho_put);
476 } else
477 if (ib_get != ib_put)
478 nv_wr32(priv, 0x003334, ib_put);
479 } else {
480 nv_error(priv,
481 "DMA_PUSHER - ch %d [%s] get 0x%08x put 0x%08x state 0x%08x (err: %s) push 0x%08x\n",
482 chid, client_name, dma_get, dma_put, state,
483 nv_dma_state_err(state), push);
484
485 if (dma_get != dma_put)
486 nv_wr32(priv, 0x003244, dma_put);
487 }
488
489 nv_wr32(priv, 0x003228, 0x00000000);
490 nv_wr32(priv, 0x003220, 0x00000001);
491 nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
492}
493
401void 494void
402nv04_fifo_intr(struct nouveau_subdev *subdev) 495nv04_fifo_intr(struct nouveau_subdev *subdev)
403{ 496{
@@ -416,96 +509,12 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
416 get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET); 509 get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET);
417 510
418 if (status & NV_PFIFO_INTR_CACHE_ERROR) { 511 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
419 uint32_t mthd, data; 512 nv04_fifo_cache_error(device, priv, chid, get);
420 int ptr;
421
422 /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
423 * wrapping on my G80 chips, but CACHE1 isn't big
424 * enough for this much data.. Tests show that it
425 * wraps around to the start at GET=0x800.. No clue
426 * as to why..
427 */
428 ptr = (get & 0x7ff) >> 2;
429
430 if (device->card_type < NV_40) {
431 mthd = nv_rd32(priv,
432 NV04_PFIFO_CACHE1_METHOD(ptr));
433 data = nv_rd32(priv,
434 NV04_PFIFO_CACHE1_DATA(ptr));
435 } else {
436 mthd = nv_rd32(priv,
437 NV40_PFIFO_CACHE1_METHOD(ptr));
438 data = nv_rd32(priv,
439 NV40_PFIFO_CACHE1_DATA(ptr));
440 }
441
442 if (!nv04_fifo_swmthd(priv, chid, mthd, data)) {
443 nv_error(priv, "CACHE_ERROR - Ch %d/%d "
444 "Mthd 0x%04x Data 0x%08x\n",
445 chid, (mthd >> 13) & 7, mthd & 0x1ffc,
446 data);
447 }
448
449 nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
450 nv_wr32(priv, NV03_PFIFO_INTR_0,
451 NV_PFIFO_INTR_CACHE_ERROR);
452
453 nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0,
454 nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1);
455 nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4);
456 nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0,
457 nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1);
458 nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0);
459
460 nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH,
461 nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
462 nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);
463
464 status &= ~NV_PFIFO_INTR_CACHE_ERROR; 513 status &= ~NV_PFIFO_INTR_CACHE_ERROR;
465 } 514 }
466 515
467 if (status & NV_PFIFO_INTR_DMA_PUSHER) { 516 if (status & NV_PFIFO_INTR_DMA_PUSHER) {
468 u32 dma_get = nv_rd32(priv, 0x003244); 517 nv04_fifo_dma_pusher(device, priv, chid);
469 u32 dma_put = nv_rd32(priv, 0x003240);
470 u32 push = nv_rd32(priv, 0x003220);
471 u32 state = nv_rd32(priv, 0x003228);
472
473 if (device->card_type == NV_50) {
474 u32 ho_get = nv_rd32(priv, 0x003328);
475 u32 ho_put = nv_rd32(priv, 0x003320);
476 u32 ib_get = nv_rd32(priv, 0x003334);
477 u32 ib_put = nv_rd32(priv, 0x003330);
478
479 nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%02x%08x "
480 "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
481 "State 0x%08x (err: %s) Push 0x%08x\n",
482 chid, ho_get, dma_get, ho_put,
483 dma_put, ib_get, ib_put, state,
484 nv_dma_state_err(state),
485 push);
486
487 /* METHOD_COUNT, in DMA_STATE on earlier chipsets */
488 nv_wr32(priv, 0x003364, 0x00000000);
489 if (dma_get != dma_put || ho_get != ho_put) {
490 nv_wr32(priv, 0x003244, dma_put);
491 nv_wr32(priv, 0x003328, ho_put);
492 } else
493 if (ib_get != ib_put) {
494 nv_wr32(priv, 0x003334, ib_put);
495 }
496 } else {
497 nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%08x "
498 "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
499 chid, dma_get, dma_put, state,
500 nv_dma_state_err(state), push);
501
502 if (dma_get != dma_put)
503 nv_wr32(priv, 0x003244, dma_put);
504 }
505
506 nv_wr32(priv, 0x003228, 0x00000000);
507 nv_wr32(priv, 0x003220, 0x00000001);
508 nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
509 status &= ~NV_PFIFO_INTR_DMA_PUSHER; 518 status &= ~NV_PFIFO_INTR_DMA_PUSHER;
510 } 519 }
511 520
@@ -528,6 +537,12 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
528 status &= ~0x00000010; 537 status &= ~0x00000010;
529 nv_wr32(priv, 0x002100, 0x00000010); 538 nv_wr32(priv, 0x002100, 0x00000010);
530 } 539 }
540
541 if (status & 0x40000000) {
542 nouveau_event_trigger(priv->base.uevent, 0);
543 nv_wr32(priv, 0x002100, 0x40000000);
544 status &= ~0x40000000;
545 }
531 } 546 }
532 547
533 if (status) { 548 if (status) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
index bd096364f680..840af6172788 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
@@ -129,7 +129,8 @@ nv50_fifo_context_detach(struct nouveau_object *parent, bool suspend,
129 /* do the kickoff... */ 129 /* do the kickoff... */
130 nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); 130 nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12);
131 if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { 131 if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) {
132 nv_error(priv, "channel %d unload timeout\n", chan->base.chid); 132 nv_error(priv, "channel %d [%s] unload timeout\n",
133 chan->base.chid, nouveau_client_name(chan));
133 if (suspend) 134 if (suspend)
134 ret = -EBUSY; 135 ret = -EBUSY;
135 } 136 }
@@ -480,7 +481,7 @@ nv50_fifo_init(struct nouveau_object *object)
480 nv_wr32(priv, 0x002044, 0x01003fff); 481 nv_wr32(priv, 0x002044, 0x01003fff);
481 482
482 nv_wr32(priv, 0x002100, 0xffffffff); 483 nv_wr32(priv, 0x002100, 0xffffffff);
483 nv_wr32(priv, 0x002140, 0xffffffff); 484 nv_wr32(priv, 0x002140, 0xbfffffff);
484 485
485 for (i = 0; i < 128; i++) 486 for (i = 0; i < 128; i++)
486 nv_wr32(priv, 0x002600 + (i * 4), 0x00000000); 487 nv_wr32(priv, 0x002600 + (i * 4), 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
index 1eb1c512f503..094000e87871 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
@@ -26,6 +26,7 @@
26#include <core/client.h> 26#include <core/client.h>
27#include <core/engctx.h> 27#include <core/engctx.h>
28#include <core/ramht.h> 28#include <core/ramht.h>
29#include <core/event.h>
29#include <core/class.h> 30#include <core/class.h>
30#include <core/math.h> 31#include <core/math.h>
31 32
@@ -100,7 +101,8 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend,
100 done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); 101 done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff);
101 nv_wr32(priv, 0x002520, save); 102 nv_wr32(priv, 0x002520, save);
102 if (!done) { 103 if (!done) {
103 nv_error(priv, "channel %d unload timeout\n", chan->base.chid); 104 nv_error(priv, "channel %d [%s] unload timeout\n",
105 chan->base.chid, nouveau_client_name(chan));
104 if (suspend) 106 if (suspend)
105 return -EBUSY; 107 return -EBUSY;
106 } 108 }
@@ -378,6 +380,20 @@ nv84_fifo_cclass = {
378 * PFIFO engine 380 * PFIFO engine
379 ******************************************************************************/ 381 ******************************************************************************/
380 382
383static void
384nv84_fifo_uevent_enable(struct nouveau_event *event, int index)
385{
386 struct nv84_fifo_priv *priv = event->priv;
387 nv_mask(priv, 0x002140, 0x40000000, 0x40000000);
388}
389
390static void
391nv84_fifo_uevent_disable(struct nouveau_event *event, int index)
392{
393 struct nv84_fifo_priv *priv = event->priv;
394 nv_mask(priv, 0x002140, 0x40000000, 0x00000000);
395}
396
381static int 397static int
382nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 398nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
383 struct nouveau_oclass *oclass, void *data, u32 size, 399 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -401,6 +417,10 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
401 if (ret) 417 if (ret)
402 return ret; 418 return ret;
403 419
420 priv->base.uevent->enable = nv84_fifo_uevent_enable;
421 priv->base.uevent->disable = nv84_fifo_uevent_disable;
422 priv->base.uevent->priv = priv;
423
404 nv_subdev(priv)->unit = 0x00000100; 424 nv_subdev(priv)->unit = 0x00000100;
405 nv_subdev(priv)->intr = nv04_fifo_intr; 425 nv_subdev(priv)->intr = nv04_fifo_intr;
406 nv_engine(priv)->cclass = &nv84_fifo_cclass; 426 nv_engine(priv)->cclass = &nv84_fifo_cclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index b4365dde1859..4f226afb5591 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -27,6 +27,7 @@
27#include <core/namedb.h> 27#include <core/namedb.h>
28#include <core/gpuobj.h> 28#include <core/gpuobj.h>
29#include <core/engctx.h> 29#include <core/engctx.h>
30#include <core/event.h>
30#include <core/class.h> 31#include <core/class.h>
31#include <core/math.h> 32#include <core/math.h>
32#include <core/enum.h> 33#include <core/enum.h>
@@ -149,7 +150,8 @@ nvc0_fifo_context_detach(struct nouveau_object *parent, bool suspend,
149 150
150 nv_wr32(priv, 0x002634, chan->base.chid); 151 nv_wr32(priv, 0x002634, chan->base.chid);
151 if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { 152 if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) {
152 nv_error(priv, "channel %d kick timeout\n", chan->base.chid); 153 nv_error(priv, "channel %d [%s] kick timeout\n",
154 chan->base.chid, nouveau_client_name(chan));
153 if (suspend) 155 if (suspend)
154 return -EBUSY; 156 return -EBUSY;
155 } 157 }
@@ -333,17 +335,17 @@ nvc0_fifo_cclass = {
333 ******************************************************************************/ 335 ******************************************************************************/
334 336
335static const struct nouveau_enum nvc0_fifo_fault_unit[] = { 337static const struct nouveau_enum nvc0_fifo_fault_unit[] = {
336 { 0x00, "PGRAPH" }, 338 { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR },
337 { 0x03, "PEEPHOLE" }, 339 { 0x03, "PEEPHOLE" },
338 { 0x04, "BAR1" }, 340 { 0x04, "BAR1" },
339 { 0x05, "BAR3" }, 341 { 0x05, "BAR3" },
340 { 0x07, "PFIFO" }, 342 { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO },
341 { 0x10, "PBSP" }, 343 { 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP },
342 { 0x11, "PPPP" }, 344 { 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP },
343 { 0x13, "PCOUNTER" }, 345 { 0x13, "PCOUNTER" },
344 { 0x14, "PVP" }, 346 { 0x14, "PVP", NULL, NVDEV_ENGINE_VP },
345 { 0x15, "PCOPY0" }, 347 { 0x15, "PCOPY0", NULL, NVDEV_ENGINE_COPY0 },
346 { 0x16, "PCOPY1" }, 348 { 0x16, "PCOPY1", NULL, NVDEV_ENGINE_COPY1 },
347 { 0x17, "PDAEMON" }, 349 { 0x17, "PDAEMON" },
348 {} 350 {}
349}; 351};
@@ -402,6 +404,9 @@ nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit)
402 u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); 404 u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10));
403 u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); 405 u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10));
404 u32 client = (stat & 0x00001f00) >> 8; 406 u32 client = (stat & 0x00001f00) >> 8;
407 const struct nouveau_enum *en;
408 struct nouveau_engine *engine;
409 struct nouveau_object *engctx = NULL;
405 410
406 switch (unit) { 411 switch (unit) {
407 case 3: /* PEEPHOLE */ 412 case 3: /* PEEPHOLE */
@@ -420,16 +425,26 @@ nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit)
420 nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? 425 nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ?
421 "write" : "read", (u64)vahi << 32 | valo); 426 "write" : "read", (u64)vahi << 32 | valo);
422 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); 427 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
423 printk("] from "); 428 pr_cont("] from ");
424 nouveau_enum_print(nvc0_fifo_fault_unit, unit); 429 en = nouveau_enum_print(nvc0_fifo_fault_unit, unit);
425 if (stat & 0x00000040) { 430 if (stat & 0x00000040) {
426 printk("/"); 431 pr_cont("/");
427 nouveau_enum_print(nvc0_fifo_fault_hubclient, client); 432 nouveau_enum_print(nvc0_fifo_fault_hubclient, client);
428 } else { 433 } else {
429 printk("/GPC%d/", (stat & 0x1f000000) >> 24); 434 pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24);
430 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); 435 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client);
431 } 436 }
432 printk(" on channel 0x%010llx\n", (u64)inst << 12); 437
438 if (en && en->data2) {
439 engine = nouveau_engine(priv, en->data2);
440 if (engine)
441 engctx = nouveau_engctx_get(engine, inst);
442
443 }
444 pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
445 nouveau_client_name(engctx));
446
447 nouveau_engctx_put(engctx);
433} 448}
434 449
435static int 450static int
@@ -484,10 +499,12 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)
484 if (show) { 499 if (show) {
485 nv_error(priv, "SUBFIFO%d:", unit); 500 nv_error(priv, "SUBFIFO%d:", unit);
486 nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); 501 nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show);
487 printk("\n"); 502 pr_cont("\n");
488 nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " 503 nv_error(priv,
489 "data 0x%08x\n", 504 "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
490 unit, chid, subc, mthd, data); 505 unit, chid,
506 nouveau_client_name_for_fifo_chid(&priv->base, chid),
507 subc, mthd, data);
491 } 508 }
492 509
493 nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); 510 nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008);
@@ -501,12 +518,34 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
501 u32 mask = nv_rd32(priv, 0x002140); 518 u32 mask = nv_rd32(priv, 0x002140);
502 u32 stat = nv_rd32(priv, 0x002100) & mask; 519 u32 stat = nv_rd32(priv, 0x002100) & mask;
503 520
521 if (stat & 0x00000001) {
522 u32 intr = nv_rd32(priv, 0x00252c);
523 nv_warn(priv, "INTR 0x00000001: 0x%08x\n", intr);
524 nv_wr32(priv, 0x002100, 0x00000001);
525 stat &= ~0x00000001;
526 }
527
504 if (stat & 0x00000100) { 528 if (stat & 0x00000100) {
505 nv_warn(priv, "unknown status 0x00000100\n"); 529 u32 intr = nv_rd32(priv, 0x00254c);
530 nv_warn(priv, "INTR 0x00000100: 0x%08x\n", intr);
506 nv_wr32(priv, 0x002100, 0x00000100); 531 nv_wr32(priv, 0x002100, 0x00000100);
507 stat &= ~0x00000100; 532 stat &= ~0x00000100;
508 } 533 }
509 534
535 if (stat & 0x00010000) {
536 u32 intr = nv_rd32(priv, 0x00256c);
537 nv_warn(priv, "INTR 0x00010000: 0x%08x\n", intr);
538 nv_wr32(priv, 0x002100, 0x00010000);
539 stat &= ~0x00010000;
540 }
541
542 if (stat & 0x01000000) {
543 u32 intr = nv_rd32(priv, 0x00258c);
544 nv_warn(priv, "INTR 0x01000000: 0x%08x\n", intr);
545 nv_wr32(priv, 0x002100, 0x01000000);
546 stat &= ~0x01000000;
547 }
548
510 if (stat & 0x10000000) { 549 if (stat & 0x10000000) {
511 u32 units = nv_rd32(priv, 0x00259c); 550 u32 units = nv_rd32(priv, 0x00259c);
512 u32 u = units; 551 u32 u = units;
@@ -536,11 +575,20 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
536 } 575 }
537 576
538 if (stat & 0x40000000) { 577 if (stat & 0x40000000) {
539 nv_warn(priv, "unknown status 0x40000000\n"); 578 u32 intr0 = nv_rd32(priv, 0x0025a4);
540 nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); 579 u32 intr1 = nv_mask(priv, 0x002a00, 0x00000000, 0x00000);
580 nv_debug(priv, "INTR 0x40000000: 0x%08x 0x%08x\n",
581 intr0, intr1);
541 stat &= ~0x40000000; 582 stat &= ~0x40000000;
542 } 583 }
543 584
585 if (stat & 0x80000000) {
586 u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000);
587 nouveau_event_trigger(priv->base.uevent, 0);
588 nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr);
589 stat &= ~0x80000000;
590 }
591
544 if (stat) { 592 if (stat) {
545 nv_fatal(priv, "unhandled status 0x%08x\n", stat); 593 nv_fatal(priv, "unhandled status 0x%08x\n", stat);
546 nv_wr32(priv, 0x002100, stat); 594 nv_wr32(priv, 0x002100, stat);
@@ -548,6 +596,20 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
548 } 596 }
549} 597}
550 598
599static void
600nvc0_fifo_uevent_enable(struct nouveau_event *event, int index)
601{
602 struct nvc0_fifo_priv *priv = event->priv;
603 nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
604}
605
606static void
607nvc0_fifo_uevent_disable(struct nouveau_event *event, int index)
608{
609 struct nvc0_fifo_priv *priv = event->priv;
610 nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
611}
612
551static int 613static int
552nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 614nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
553 struct nouveau_oclass *oclass, void *data, u32 size, 615 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -581,6 +643,10 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
581 if (ret) 643 if (ret)
582 return ret; 644 return ret;
583 645
646 priv->base.uevent->enable = nvc0_fifo_uevent_enable;
647 priv->base.uevent->disable = nvc0_fifo_uevent_disable;
648 priv->base.uevent->priv = priv;
649
584 nv_subdev(priv)->unit = 0x00000100; 650 nv_subdev(priv)->unit = 0x00000100;
585 nv_subdev(priv)->intr = nvc0_fifo_intr; 651 nv_subdev(priv)->intr = nvc0_fifo_intr;
586 nv_engine(priv)->cclass = &nvc0_fifo_cclass; 652 nv_engine(priv)->cclass = &nvc0_fifo_cclass;
@@ -639,7 +705,8 @@ nvc0_fifo_init(struct nouveau_object *object)
639 705
640 nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ 706 nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
641 nv_wr32(priv, 0x002100, 0xffffffff); 707 nv_wr32(priv, 0x002100, 0xffffffff);
642 nv_wr32(priv, 0x002140, 0xbfffffff); 708 nv_wr32(priv, 0x002140, 0x3fffffff);
709 nv_wr32(priv, 0x002628, 0x00000001); /* makes mthd 0x20 work */
643 return 0; 710 return 0;
644} 711}
645 712
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index c930da99c2c1..4419e40d88e9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -27,6 +27,7 @@
27#include <core/namedb.h> 27#include <core/namedb.h>
28#include <core/gpuobj.h> 28#include <core/gpuobj.h>
29#include <core/engctx.h> 29#include <core/engctx.h>
30#include <core/event.h>
30#include <core/class.h> 31#include <core/class.h>
31#include <core/math.h> 32#include <core/math.h>
32#include <core/enum.h> 33#include <core/enum.h>
@@ -184,7 +185,8 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend,
184 185
185 nv_wr32(priv, 0x002634, chan->base.chid); 186 nv_wr32(priv, 0x002634, chan->base.chid);
186 if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { 187 if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) {
187 nv_error(priv, "channel %d kick timeout\n", chan->base.chid); 188 nv_error(priv, "channel %d [%s] kick timeout\n",
189 chan->base.chid, nouveau_client_name(chan));
188 if (suspend) 190 if (suspend)
189 return -EBUSY; 191 return -EBUSY;
190 } 192 }
@@ -412,20 +414,34 @@ nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
412 u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); 414 u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
413 u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); 415 u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
414 u32 client = (stat & 0x00001f00) >> 8; 416 u32 client = (stat & 0x00001f00) >> 8;
417 const struct nouveau_enum *en;
418 struct nouveau_engine *engine;
419 struct nouveau_object *engctx = NULL;
415 420
416 nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ? 421 nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
417 "write" : "read", (u64)vahi << 32 | valo); 422 "write" : "read", (u64)vahi << 32 | valo);
418 nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); 423 nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f);
419 printk("] from "); 424 pr_cont("] from ");
420 nouveau_enum_print(nve0_fifo_fault_unit, unit); 425 en = nouveau_enum_print(nve0_fifo_fault_unit, unit);
421 if (stat & 0x00000040) { 426 if (stat & 0x00000040) {
422 printk("/"); 427 pr_cont("/");
423 nouveau_enum_print(nve0_fifo_fault_hubclient, client); 428 nouveau_enum_print(nve0_fifo_fault_hubclient, client);
424 } else { 429 } else {
425 printk("/GPC%d/", (stat & 0x1f000000) >> 24); 430 pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24);
426 nouveau_enum_print(nve0_fifo_fault_gpcclient, client); 431 nouveau_enum_print(nve0_fifo_fault_gpcclient, client);
427 } 432 }
428 printk(" on channel 0x%010llx\n", (u64)inst << 12); 433
434 if (en && en->data2) {
435 engine = nouveau_engine(priv, en->data2);
436 if (engine)
437 engctx = nouveau_engctx_get(engine, inst);
438
439 }
440
441 pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
442 nouveau_client_name(engctx));
443
444 nouveau_engctx_put(engctx);
429} 445}
430 446
431static int 447static int
@@ -480,10 +496,12 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
480 if (show) { 496 if (show) {
481 nv_error(priv, "SUBFIFO%d:", unit); 497 nv_error(priv, "SUBFIFO%d:", unit);
482 nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); 498 nouveau_bitfield_print(nve0_fifo_subfifo_intr, show);
483 printk("\n"); 499 pr_cont("\n");
484 nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " 500 nv_error(priv,
485 "data 0x%08x\n", 501 "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
486 unit, chid, subc, mthd, data); 502 unit, chid,
503 nouveau_client_name_for_fifo_chid(&priv->base, chid),
504 subc, mthd, data);
487 } 505 }
488 506
489 nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); 507 nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008);
@@ -537,6 +555,12 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
537 stat &= ~0x40000000; 555 stat &= ~0x40000000;
538 } 556 }
539 557
558 if (stat & 0x80000000) {
559 nouveau_event_trigger(priv->base.uevent, 0);
560 nv_wr32(priv, 0x002100, 0x80000000);
561 stat &= ~0x80000000;
562 }
563
540 if (stat) { 564 if (stat) {
541 nv_fatal(priv, "unhandled status 0x%08x\n", stat); 565 nv_fatal(priv, "unhandled status 0x%08x\n", stat);
542 nv_wr32(priv, 0x002100, stat); 566 nv_wr32(priv, 0x002100, stat);
@@ -544,6 +568,20 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
544 } 568 }
545} 569}
546 570
571static void
572nve0_fifo_uevent_enable(struct nouveau_event *event, int index)
573{
574 struct nve0_fifo_priv *priv = event->priv;
575 nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
576}
577
578static void
579nve0_fifo_uevent_disable(struct nouveau_event *event, int index)
580{
581 struct nve0_fifo_priv *priv = event->priv;
582 nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
583}
584
547static int 585static int
548nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 586nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
549 struct nouveau_oclass *oclass, void *data, u32 size, 587 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -567,6 +605,10 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
567 if (ret) 605 if (ret)
568 return ret; 606 return ret;
569 607
608 priv->base.uevent->enable = nve0_fifo_uevent_enable;
609 priv->base.uevent->disable = nve0_fifo_uevent_disable;
610 priv->base.uevent->priv = priv;
611
570 nv_subdev(priv)->unit = 0x00000100; 612 nv_subdev(priv)->unit = 0x00000100;
571 nv_subdev(priv)->intr = nve0_fifo_intr; 613 nv_subdev(priv)->intr = nve0_fifo_intr;
572 nv_engine(priv)->cclass = &nve0_fifo_cclass; 614 nv_engine(priv)->cclass = &nve0_fifo_cclass;
@@ -617,7 +659,7 @@ nve0_fifo_init(struct nouveau_object *object)
617 659
618 nv_wr32(priv, 0x002a00, 0xffffffff); 660 nv_wr32(priv, 0x002a00, 0xffffffff);
619 nv_wr32(priv, 0x002100, 0xffffffff); 661 nv_wr32(priv, 0x002100, 0xffffffff);
620 nv_wr32(priv, 0x002140, 0xbfffffff); 662 nv_wr32(priv, 0x002140, 0x3fffffff);
621 return 0; 663 return 0;
622} 664}
623 665
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
index e30a9c5ff1fc..ad13dcdd15f9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
@@ -22,6 +22,7 @@
22 * DEALINGS IN THE SOFTWARE. 22 * DEALINGS IN THE SOFTWARE.
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/os.h> 26#include <core/os.h>
26#include <core/class.h> 27#include <core/class.h>
27#include <core/handle.h> 28#include <core/handle.h>
@@ -1297,16 +1298,17 @@ nv04_graph_intr(struct nouveau_subdev *subdev)
1297 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 1298 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001);
1298 1299
1299 if (show) { 1300 if (show) {
1300 nv_error(priv, ""); 1301 nv_error(priv, "%s", "");
1301 nouveau_bitfield_print(nv04_graph_intr_name, show); 1302 nouveau_bitfield_print(nv04_graph_intr_name, show);
1302 printk(" nsource:"); 1303 pr_cont(" nsource:");
1303 nouveau_bitfield_print(nv04_graph_nsource, nsource); 1304 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1304 printk(" nstatus:"); 1305 pr_cont(" nstatus:");
1305 nouveau_bitfield_print(nv04_graph_nstatus, nstatus); 1306 nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
1306 printk("\n"); 1307 pr_cont("\n");
1307 nv_error(priv, "ch %d/%d class 0x%04x " 1308 nv_error(priv,
1308 "mthd 0x%04x data 0x%08x\n", 1309 "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1309 chid, subc, class, mthd, data); 1310 chid, nouveau_client_name(chan), subc, class, mthd,
1311 data);
1310 } 1312 }
1311 1313
1312 nouveau_namedb_put(handle); 1314 nouveau_namedb_put(handle);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
index 5c0f843ea249..23c143aaa556 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
@@ -22,6 +22,7 @@
22 * DEALINGS IN THE SOFTWARE. 22 * DEALINGS IN THE SOFTWARE.
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/os.h> 26#include <core/os.h>
26#include <core/class.h> 27#include <core/class.h>
27#include <core/handle.h> 28#include <core/handle.h>
@@ -1193,16 +1194,17 @@ nv10_graph_intr(struct nouveau_subdev *subdev)
1193 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 1194 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001);
1194 1195
1195 if (show) { 1196 if (show) {
1196 nv_error(priv, ""); 1197 nv_error(priv, "%s", "");
1197 nouveau_bitfield_print(nv10_graph_intr_name, show); 1198 nouveau_bitfield_print(nv10_graph_intr_name, show);
1198 printk(" nsource:"); 1199 pr_cont(" nsource:");
1199 nouveau_bitfield_print(nv04_graph_nsource, nsource); 1200 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1200 printk(" nstatus:"); 1201 pr_cont(" nstatus:");
1201 nouveau_bitfield_print(nv10_graph_nstatus, nstatus); 1202 nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
1202 printk("\n"); 1203 pr_cont("\n");
1203 nv_error(priv, "ch %d/%d class 0x%04x " 1204 nv_error(priv,
1204 "mthd 0x%04x data 0x%08x\n", 1205 "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1205 chid, subc, class, mthd, data); 1206 chid, nouveau_client_name(chan), subc, class, mthd,
1207 data);
1206 } 1208 }
1207 1209
1208 nouveau_namedb_put(handle); 1210 nouveau_namedb_put(handle);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
index 5b20401bf911..0607b9801748 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
@@ -1,3 +1,4 @@
1#include <core/client.h>
1#include <core/os.h> 2#include <core/os.h>
2#include <core/class.h> 3#include <core/class.h>
3#include <core/engctx.h> 4#include <core/engctx.h>
@@ -224,15 +225,17 @@ nv20_graph_intr(struct nouveau_subdev *subdev)
224 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 225 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001);
225 226
226 if (show) { 227 if (show) {
227 nv_error(priv, ""); 228 nv_error(priv, "%s", "");
228 nouveau_bitfield_print(nv10_graph_intr_name, show); 229 nouveau_bitfield_print(nv10_graph_intr_name, show);
229 printk(" nsource:"); 230 pr_cont(" nsource:");
230 nouveau_bitfield_print(nv04_graph_nsource, nsource); 231 nouveau_bitfield_print(nv04_graph_nsource, nsource);
231 printk(" nstatus:"); 232 pr_cont(" nstatus:");
232 nouveau_bitfield_print(nv10_graph_nstatus, nstatus); 233 nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
233 printk("\n"); 234 pr_cont("\n");
234 nv_error(priv, "ch %d/%d class 0x%04x mthd 0x%04x data 0x%08x\n", 235 nv_error(priv,
235 chid, subc, class, mthd, data); 236 "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
237 chid, nouveau_client_name(engctx), subc, class, mthd,
238 data);
236 } 239 }
237 240
238 nouveau_engctx_put(engctx); 241 nouveau_engctx_put(engctx);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
index 0b36dd3deebd..17049d5c723d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/os.h> 26#include <core/os.h>
26#include <core/class.h> 27#include <core/class.h>
27#include <core/handle.h> 28#include <core/handle.h>
@@ -321,16 +322,17 @@ nv40_graph_intr(struct nouveau_subdev *subdev)
321 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 322 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001);
322 323
323 if (show) { 324 if (show) {
324 nv_error(priv, ""); 325 nv_error(priv, "%s", "");
325 nouveau_bitfield_print(nv10_graph_intr_name, show); 326 nouveau_bitfield_print(nv10_graph_intr_name, show);
326 printk(" nsource:"); 327 pr_cont(" nsource:");
327 nouveau_bitfield_print(nv04_graph_nsource, nsource); 328 nouveau_bitfield_print(nv04_graph_nsource, nsource);
328 printk(" nstatus:"); 329 pr_cont(" nstatus:");
329 nouveau_bitfield_print(nv10_graph_nstatus, nstatus); 330 nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
330 printk("\n"); 331 pr_cont("\n");
331 nv_error(priv, "ch %d [0x%08x] subc %d class 0x%04x " 332 nv_error(priv,
332 "mthd 0x%04x data 0x%08x\n", 333 "ch %d [0x%08x %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
333 chid, inst << 4, subc, class, mthd, data); 334 chid, inst << 4, nouveau_client_name(engctx), subc,
335 class, mthd, data);
334 } 336 }
335 337
336 nouveau_engctx_put(engctx); 338 nouveau_engctx_put(engctx);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
index b1c3d835b4c2..f2b1a7a124f2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
@@ -24,6 +24,7 @@
24 24
25#include <core/os.h> 25#include <core/os.h>
26#include <core/class.h> 26#include <core/class.h>
27#include <core/client.h>
27#include <core/handle.h> 28#include <core/handle.h>
28#include <core/engctx.h> 29#include <core/engctx.h>
29#include <core/enum.h> 30#include <core/enum.h>
@@ -418,7 +419,7 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
418 nv_error(priv, "TRAP_MP_EXEC - " 419 nv_error(priv, "TRAP_MP_EXEC - "
419 "TP %d MP %d: ", tpid, i); 420 "TP %d MP %d: ", tpid, i);
420 nouveau_enum_print(nv50_mp_exec_error_names, status); 421 nouveau_enum_print(nv50_mp_exec_error_names, status);
421 printk(" at %06x warp %d, opcode %08x %08x\n", 422 pr_cont(" at %06x warp %d, opcode %08x %08x\n",
422 pc&0xffffff, pc >> 24, 423 pc&0xffffff, pc >> 24,
423 oplow, ophigh); 424 oplow, ophigh);
424 } 425 }
@@ -532,7 +533,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
532 533
533static int 534static int
534nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, 535nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
535 int chid, u64 inst) 536 int chid, u64 inst, struct nouveau_object *engctx)
536{ 537{
537 u32 status = nv_rd32(priv, 0x400108); 538 u32 status = nv_rd32(priv, 0x400108);
538 u32 ustatus; 539 u32 ustatus;
@@ -565,12 +566,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
565 566
566 nv_error(priv, "TRAP DISPATCH_FAULT\n"); 567 nv_error(priv, "TRAP DISPATCH_FAULT\n");
567 if (display && (addr & 0x80000000)) { 568 if (display && (addr & 0x80000000)) {
568 nv_error(priv, "ch %d [0x%010llx] " 569 nv_error(priv,
569 "subc %d class 0x%04x mthd 0x%04x " 570 "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x%08x 400808 0x%08x 400848 0x%08x\n",
570 "data 0x%08x%08x " 571 chid, inst,
571 "400808 0x%08x 400848 0x%08x\n", 572 nouveau_client_name(engctx), subc,
572 chid, inst, subc, class, mthd, datah, 573 class, mthd, datah, datal, addr, r848);
573 datal, addr, r848);
574 } else 574 } else
575 if (display) { 575 if (display) {
576 nv_error(priv, "no stuck command?\n"); 576 nv_error(priv, "no stuck command?\n");
@@ -591,11 +591,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
591 591
592 nv_error(priv, "TRAP DISPATCH_QUERY\n"); 592 nv_error(priv, "TRAP DISPATCH_QUERY\n");
593 if (display && (addr & 0x80000000)) { 593 if (display && (addr & 0x80000000)) {
594 nv_error(priv, "ch %d [0x%010llx] " 594 nv_error(priv,
595 "subc %d class 0x%04x mthd 0x%04x " 595 "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x 40084c 0x%08x\n",
596 "data 0x%08x 40084c 0x%08x\n", 596 chid, inst,
597 chid, inst, subc, class, mthd, 597 nouveau_client_name(engctx), subc,
598 data, addr); 598 class, mthd, data, addr);
599 } else 599 } else
600 if (display) { 600 if (display) {
601 nv_error(priv, "no stuck command?\n"); 601 nv_error(priv, "no stuck command?\n");
@@ -623,7 +623,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
623 if (display) { 623 if (display) {
624 nv_error(priv, "TRAP_M2MF"); 624 nv_error(priv, "TRAP_M2MF");
625 nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); 625 nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus);
626 printk("\n"); 626 pr_cont("\n");
627 nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n", 627 nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n",
628 nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808), 628 nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808),
629 nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810)); 629 nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810));
@@ -644,7 +644,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
644 if (display) { 644 if (display) {
645 nv_error(priv, "TRAP_VFETCH"); 645 nv_error(priv, "TRAP_VFETCH");
646 nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); 646 nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus);
647 printk("\n"); 647 pr_cont("\n");
648 nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n", 648 nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n",
649 nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08), 649 nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08),
650 nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10)); 650 nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10));
@@ -661,7 +661,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
661 if (display) { 661 if (display) {
662 nv_error(priv, "TRAP_STRMOUT"); 662 nv_error(priv, "TRAP_STRMOUT");
663 nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); 663 nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus);
664 printk("\n"); 664 pr_cont("\n");
665 nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n", 665 nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n",
666 nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808), 666 nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808),
667 nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810)); 667 nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810));
@@ -682,7 +682,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
682 if (display) { 682 if (display) {
683 nv_error(priv, "TRAP_CCACHE"); 683 nv_error(priv, "TRAP_CCACHE");
684 nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); 684 nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus);
685 printk("\n"); 685 pr_cont("\n");
686 nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x" 686 nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x"
687 " %08x %08x %08x\n", 687 " %08x %08x %08x\n",
688 nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004), 688 nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004),
@@ -774,11 +774,12 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
774 u32 ecode = nv_rd32(priv, 0x400110); 774 u32 ecode = nv_rd32(priv, 0x400110);
775 nv_error(priv, "DATA_ERROR "); 775 nv_error(priv, "DATA_ERROR ");
776 nouveau_enum_print(nv50_data_error_names, ecode); 776 nouveau_enum_print(nv50_data_error_names, ecode);
777 printk("\n"); 777 pr_cont("\n");
778 } 778 }
779 779
780 if (stat & 0x00200000) { 780 if (stat & 0x00200000) {
781 if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12)) 781 if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12,
782 engctx))
782 show &= ~0x00200000; 783 show &= ~0x00200000;
783 } 784 }
784 785
@@ -786,12 +787,13 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
786 nv_wr32(priv, 0x400500, 0x00010001); 787 nv_wr32(priv, 0x400500, 0x00010001);
787 788
788 if (show) { 789 if (show) {
789 nv_error(priv, ""); 790 nv_error(priv, "%s", "");
790 nouveau_bitfield_print(nv50_graph_intr_name, show); 791 nouveau_bitfield_print(nv50_graph_intr_name, show);
791 printk("\n"); 792 pr_cont("\n");
792 nv_error(priv, "ch %d [0x%010llx] subc %d class 0x%04x " 793 nv_error(priv,
793 "mthd 0x%04x data 0x%08x\n", 794 "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
794 chid, (u64)inst << 12, subc, class, mthd, data); 795 chid, (u64)inst << 12, nouveau_client_name(engctx),
796 subc, class, mthd, data);
795 } 797 }
796 798
797 if (nv_rd32(priv, 0x400824) & (1 << 31)) 799 if (nv_rd32(priv, 0x400824) & (1 << 31))
@@ -907,9 +909,8 @@ nv50_graph_init(struct nouveau_object *object)
907 nv_wr32(priv, 0x400828, 0x00000000); 909 nv_wr32(priv, 0x400828, 0x00000000);
908 nv_wr32(priv, 0x40082c, 0x00000000); 910 nv_wr32(priv, 0x40082c, 0x00000000);
909 nv_wr32(priv, 0x400830, 0x00000000); 911 nv_wr32(priv, 0x400830, 0x00000000);
910 nv_wr32(priv, 0x400724, 0x00000000);
911 nv_wr32(priv, 0x40032c, 0x00000000); 912 nv_wr32(priv, 0x40032c, 0x00000000);
912 nv_wr32(priv, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ 913 nv_wr32(priv, 0x400330, 0x00000000);
913 914
914 /* some unknown zcull magic */ 915 /* some unknown zcull magic */
915 switch (nv_device(priv)->chipset & 0xf0) { 916 switch (nv_device(priv)->chipset & 0xf0) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index 45aff5f5085a..0de0dd724aff 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -433,10 +433,10 @@ nvc0_graph_intr(struct nouveau_subdev *subdev)
433 if (stat & 0x00000010) { 433 if (stat & 0x00000010) {
434 handle = nouveau_handle_get_class(engctx, class); 434 handle = nouveau_handle_get_class(engctx, class);
435 if (!handle || nv_call(handle->object, mthd, data)) { 435 if (!handle || nv_call(handle->object, mthd, data)) {
436 nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " 436 nv_error(priv,
437 "subc %d class 0x%04x mthd 0x%04x " 437 "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
438 "data 0x%08x\n", 438 chid, inst << 12, nouveau_client_name(engctx),
439 chid, inst << 12, subc, class, mthd, data); 439 subc, class, mthd, data);
440 } 440 }
441 nouveau_handle_put(handle); 441 nouveau_handle_put(handle);
442 nv_wr32(priv, 0x400100, 0x00000010); 442 nv_wr32(priv, 0x400100, 0x00000010);
@@ -444,9 +444,10 @@ nvc0_graph_intr(struct nouveau_subdev *subdev)
444 } 444 }
445 445
446 if (stat & 0x00000020) { 446 if (stat & 0x00000020) {
447 nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " 447 nv_error(priv,
448 "class 0x%04x mthd 0x%04x data 0x%08x\n", 448 "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
449 chid, inst << 12, subc, class, mthd, data); 449 chid, inst << 12, nouveau_client_name(engctx), subc,
450 class, mthd, data);
450 nv_wr32(priv, 0x400100, 0x00000020); 451 nv_wr32(priv, 0x400100, 0x00000020);
451 stat &= ~0x00000020; 452 stat &= ~0x00000020;
452 } 453 }
@@ -454,15 +455,16 @@ nvc0_graph_intr(struct nouveau_subdev *subdev)
454 if (stat & 0x00100000) { 455 if (stat & 0x00100000) {
455 nv_error(priv, "DATA_ERROR ["); 456 nv_error(priv, "DATA_ERROR [");
456 nouveau_enum_print(nv50_data_error_names, code); 457 nouveau_enum_print(nv50_data_error_names, code);
457 printk("] ch %d [0x%010llx] subc %d class 0x%04x " 458 pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
458 "mthd 0x%04x data 0x%08x\n", 459 chid, inst << 12, nouveau_client_name(engctx), subc,
459 chid, inst << 12, subc, class, mthd, data); 460 class, mthd, data);
460 nv_wr32(priv, 0x400100, 0x00100000); 461 nv_wr32(priv, 0x400100, 0x00100000);
461 stat &= ~0x00100000; 462 stat &= ~0x00100000;
462 } 463 }
463 464
464 if (stat & 0x00200000) { 465 if (stat & 0x00200000) {
465 nv_error(priv, "TRAP ch %d [0x%010llx]\n", chid, inst << 12); 466 nv_error(priv, "TRAP ch %d [0x%010llx %s]\n", chid, inst << 12,
467 nouveau_client_name(engctx));
466 nvc0_graph_trap_intr(priv); 468 nvc0_graph_trap_intr(priv);
467 nv_wr32(priv, 0x400100, 0x00200000); 469 nv_wr32(priv, 0x400100, 0x00200000);
468 stat &= ~0x00200000; 470 stat &= ~0x00200000;
@@ -611,10 +613,8 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
611static void 613static void
612nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc) 614nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc)
613{ 615{
614 if (fuc->data) { 616 kfree(fuc->data);
615 kfree(fuc->data); 617 fuc->data = NULL;
616 fuc->data = NULL;
617 }
618} 618}
619 619
620void 620void
@@ -622,8 +622,7 @@ nvc0_graph_dtor(struct nouveau_object *object)
622{ 622{
623 struct nvc0_graph_priv *priv = (void *)object; 623 struct nvc0_graph_priv *priv = (void *)object;
624 624
625 if (priv->data) 625 kfree(priv->data);
626 kfree(priv->data);
627 626
628 nvc0_graph_dtor_fw(&priv->fuc409c); 627 nvc0_graph_dtor_fw(&priv->fuc409c);
629 nvc0_graph_dtor_fw(&priv->fuc409d); 628 nvc0_graph_dtor_fw(&priv->fuc409d);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
index 9f82e9702b46..61cec0f6ff1c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
@@ -78,15 +78,16 @@ nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
78} 78}
79 79
80static void 80static void
81nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst) 81nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst,
82 struct nouveau_object *engctx)
82{ 83{
83 u32 trap = nv_rd32(priv, 0x400108); 84 u32 trap = nv_rd32(priv, 0x400108);
84 int rop; 85 int rop;
85 86
86 if (trap & 0x00000001) { 87 if (trap & 0x00000001) {
87 u32 stat = nv_rd32(priv, 0x404000); 88 u32 stat = nv_rd32(priv, 0x404000);
88 nv_error(priv, "DISPATCH ch %d [0x%010llx] 0x%08x\n", 89 nv_error(priv, "DISPATCH ch %d [0x%010llx %s] 0x%08x\n",
89 chid, inst, stat); 90 chid, inst, nouveau_client_name(engctx), stat);
90 nv_wr32(priv, 0x404000, 0xc0000000); 91 nv_wr32(priv, 0x404000, 0xc0000000);
91 nv_wr32(priv, 0x400108, 0x00000001); 92 nv_wr32(priv, 0x400108, 0x00000001);
92 trap &= ~0x00000001; 93 trap &= ~0x00000001;
@@ -94,8 +95,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst)
94 95
95 if (trap & 0x00000010) { 96 if (trap & 0x00000010) {
96 u32 stat = nv_rd32(priv, 0x405840); 97 u32 stat = nv_rd32(priv, 0x405840);
97 nv_error(priv, "SHADER ch %d [0x%010llx] 0x%08x\n", 98 nv_error(priv, "SHADER ch %d [0x%010llx %s] 0x%08x\n",
98 chid, inst, stat); 99 chid, inst, nouveau_client_name(engctx), stat);
99 nv_wr32(priv, 0x405840, 0xc0000000); 100 nv_wr32(priv, 0x405840, 0xc0000000);
100 nv_wr32(priv, 0x400108, 0x00000010); 101 nv_wr32(priv, 0x400108, 0x00000010);
101 trap &= ~0x00000010; 102 trap &= ~0x00000010;
@@ -105,8 +106,10 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst)
105 for (rop = 0; rop < priv->rop_nr; rop++) { 106 for (rop = 0; rop < priv->rop_nr; rop++) {
106 u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); 107 u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070));
107 u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); 108 u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144));
108 nv_error(priv, "ROP%d ch %d [0x%010llx] 0x%08x 0x%08x\n", 109 nv_error(priv,
109 rop, chid, inst, statz, statc); 110 "ROP%d ch %d [0x%010llx %s] 0x%08x 0x%08x\n",
111 rop, chid, inst, nouveau_client_name(engctx),
112 statz, statc);
110 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); 113 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
111 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); 114 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
112 } 115 }
@@ -115,8 +118,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst)
115 } 118 }
116 119
117 if (trap) { 120 if (trap) {
118 nv_error(priv, "TRAP ch %d [0x%010llx] 0x%08x\n", 121 nv_error(priv, "TRAP ch %d [0x%010llx %s] 0x%08x\n",
119 chid, inst, trap); 122 chid, inst, nouveau_client_name(engctx), trap);
120 nv_wr32(priv, 0x400108, trap); 123 nv_wr32(priv, 0x400108, trap);
121 } 124 }
122} 125}
@@ -145,10 +148,10 @@ nve0_graph_intr(struct nouveau_subdev *subdev)
145 if (stat & 0x00000010) { 148 if (stat & 0x00000010) {
146 handle = nouveau_handle_get_class(engctx, class); 149 handle = nouveau_handle_get_class(engctx, class);
147 if (!handle || nv_call(handle->object, mthd, data)) { 150 if (!handle || nv_call(handle->object, mthd, data)) {
148 nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " 151 nv_error(priv,
149 "subc %d class 0x%04x mthd 0x%04x " 152 "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
150 "data 0x%08x\n", 153 chid, inst, nouveau_client_name(engctx), subc,
151 chid, inst, subc, class, mthd, data); 154 class, mthd, data);
152 } 155 }
153 nouveau_handle_put(handle); 156 nouveau_handle_put(handle);
154 nv_wr32(priv, 0x400100, 0x00000010); 157 nv_wr32(priv, 0x400100, 0x00000010);
@@ -156,9 +159,10 @@ nve0_graph_intr(struct nouveau_subdev *subdev)
156 } 159 }
157 160
158 if (stat & 0x00000020) { 161 if (stat & 0x00000020) {
159 nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " 162 nv_error(priv,
160 "class 0x%04x mthd 0x%04x data 0x%08x\n", 163 "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
161 chid, inst, subc, class, mthd, data); 164 chid, inst, nouveau_client_name(engctx), subc, class,
165 mthd, data);
162 nv_wr32(priv, 0x400100, 0x00000020); 166 nv_wr32(priv, 0x400100, 0x00000020);
163 stat &= ~0x00000020; 167 stat &= ~0x00000020;
164 } 168 }
@@ -166,15 +170,15 @@ nve0_graph_intr(struct nouveau_subdev *subdev)
166 if (stat & 0x00100000) { 170 if (stat & 0x00100000) {
167 nv_error(priv, "DATA_ERROR ["); 171 nv_error(priv, "DATA_ERROR [");
168 nouveau_enum_print(nv50_data_error_names, code); 172 nouveau_enum_print(nv50_data_error_names, code);
169 printk("] ch %d [0x%010llx] subc %d class 0x%04x " 173 pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
170 "mthd 0x%04x data 0x%08x\n", 174 chid, inst, nouveau_client_name(engctx), subc, class,
171 chid, inst, subc, class, mthd, data); 175 mthd, data);
172 nv_wr32(priv, 0x400100, 0x00100000); 176 nv_wr32(priv, 0x400100, 0x00100000);
173 stat &= ~0x00100000; 177 stat &= ~0x00100000;
174 } 178 }
175 179
176 if (stat & 0x00200000) { 180 if (stat & 0x00200000) {
177 nve0_graph_trap_isr(priv, chid, inst); 181 nve0_graph_trap_isr(priv, chid, inst, engctx);
178 nv_wr32(priv, 0x400100, 0x00200000); 182 nv_wr32(priv, 0x400100, 0x00200000);
179 stat &= ~0x00200000; 183 stat &= ~0x00200000;
180 } 184 }
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
index 9fd86375f4c4..49ecbb859b25 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/client.h>
25#include <core/os.h> 26#include <core/os.h>
26#include <core/class.h> 27#include <core/class.h>
27#include <core/engctx.h> 28#include <core/engctx.h>
@@ -231,8 +232,10 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev)
231 nv_wr32(priv, 0x00b230, 0x00000001); 232 nv_wr32(priv, 0x00b230, 0x00000001);
232 233
233 if (show) { 234 if (show) {
234 nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", 235 nv_error(priv,
235 chid, inst << 4, stat, type, mthd, data); 236 "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n",
237 chid, inst << 4, nouveau_client_name(engctx), stat,
238 type, mthd, data);
236 } 239 }
237 240
238 nouveau_engctx_put(engctx); 241 nouveau_engctx_put(engctx);
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
index b0e7e1c01ce6..c48e74953771 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
@@ -28,6 +28,9 @@
28#include <core/namedb.h> 28#include <core/namedb.h>
29#include <core/handle.h> 29#include <core/handle.h>
30#include <core/gpuobj.h> 30#include <core/gpuobj.h>
31#include <core/event.h>
32
33#include <subdev/bar.h>
31 34
32#include <engine/software.h> 35#include <engine/software.h>
33#include <engine/disp.h> 36#include <engine/disp.h>
@@ -90,18 +93,11 @@ nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
90{ 93{
91 struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); 94 struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
92 struct nouveau_disp *disp = nouveau_disp(object); 95 struct nouveau_disp *disp = nouveau_disp(object);
93 unsigned long flags;
94 u32 crtc = *(u32 *)args; 96 u32 crtc = *(u32 *)args;
95
96 if (crtc > 1) 97 if (crtc > 1)
97 return -EINVAL; 98 return -EINVAL;
98 99
99 disp->vblank.get(disp->vblank.data, crtc); 100 nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event);
100
101 spin_lock_irqsave(&disp->vblank.lock, flags);
102 list_add(&chan->base.vblank.head, &disp->vblank.list);
103 chan->base.vblank.crtc = crtc;
104 spin_unlock_irqrestore(&disp->vblank.lock, flags);
105 return 0; 101 return 0;
106} 102}
107 103
@@ -136,6 +132,29 @@ nv50_software_sclass[] = {
136 ******************************************************************************/ 132 ******************************************************************************/
137 133
138static int 134static int
135nv50_software_vblsem_release(struct nouveau_eventh *event, int head)
136{
137 struct nouveau_software_chan *chan =
138 container_of(event, struct nouveau_software_chan, vblank.event);
139 struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
140 struct nouveau_bar *bar = nouveau_bar(priv);
141
142 nv_wr32(priv, 0x001704, chan->vblank.channel);
143 nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
144 bar->flush(bar);
145
146 if (nv_device(priv)->chipset == 0x50) {
147 nv_wr32(priv, 0x001570, chan->vblank.offset);
148 nv_wr32(priv, 0x001574, chan->vblank.value);
149 } else {
150 nv_wr32(priv, 0x060010, chan->vblank.offset);
151 nv_wr32(priv, 0x060014, chan->vblank.value);
152 }
153
154 return NVKM_EVENT_DROP;
155}
156
157static int
139nv50_software_context_ctor(struct nouveau_object *parent, 158nv50_software_context_ctor(struct nouveau_object *parent,
140 struct nouveau_object *engine, 159 struct nouveau_object *engine,
141 struct nouveau_oclass *oclass, void *data, u32 size, 160 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -150,6 +169,7 @@ nv50_software_context_ctor(struct nouveau_object *parent,
150 return ret; 169 return ret;
151 170
152 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; 171 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
172 chan->base.vblank.event.func = nv50_software_vblsem_release;
153 return 0; 173 return 0;
154} 174}
155 175
@@ -170,8 +190,8 @@ nv50_software_cclass = {
170 190
171static int 191static int
172nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 192nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
173 struct nouveau_oclass *oclass, void *data, u32 size, 193 struct nouveau_oclass *oclass, void *data, u32 size,
174 struct nouveau_object **pobject) 194 struct nouveau_object **pobject)
175{ 195{
176 struct nv50_software_priv *priv; 196 struct nv50_software_priv *priv;
177 int ret; 197 int ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
index 282a1cd1bc2f..a523eaad47e3 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
@@ -25,6 +25,9 @@
25#include <core/os.h> 25#include <core/os.h>
26#include <core/class.h> 26#include <core/class.h>
27#include <core/engctx.h> 27#include <core/engctx.h>
28#include <core/event.h>
29
30#include <subdev/bar.h>
28 31
29#include <engine/software.h> 32#include <engine/software.h>
30#include <engine/disp.h> 33#include <engine/disp.h>
@@ -72,18 +75,12 @@ nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
72{ 75{
73 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); 76 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent);
74 struct nouveau_disp *disp = nouveau_disp(object); 77 struct nouveau_disp *disp = nouveau_disp(object);
75 unsigned long flags;
76 u32 crtc = *(u32 *)args; 78 u32 crtc = *(u32 *)args;
77 79
78 if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) 80 if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3)
79 return -EINVAL; 81 return -EINVAL;
80 82
81 disp->vblank.get(disp->vblank.data, crtc); 83 nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event);
82
83 spin_lock_irqsave(&disp->vblank.lock, flags);
84 list_add(&chan->base.vblank.head, &disp->vblank.list);
85 chan->base.vblank.crtc = crtc;
86 spin_unlock_irqrestore(&disp->vblank.lock, flags);
87 return 0; 84 return 0;
88} 85}
89 86
@@ -118,6 +115,23 @@ nvc0_software_sclass[] = {
118 ******************************************************************************/ 115 ******************************************************************************/
119 116
120static int 117static int
118nvc0_software_vblsem_release(struct nouveau_eventh *event, int head)
119{
120 struct nouveau_software_chan *chan =
121 container_of(event, struct nouveau_software_chan, vblank.event);
122 struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine;
123 struct nouveau_bar *bar = nouveau_bar(priv);
124
125 nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
126 bar->flush(bar);
127 nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset));
128 nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
129 nv_wr32(priv, 0x060014, chan->vblank.value);
130
131 return NVKM_EVENT_DROP;
132}
133
134static int
121nvc0_software_context_ctor(struct nouveau_object *parent, 135nvc0_software_context_ctor(struct nouveau_object *parent,
122 struct nouveau_object *engine, 136 struct nouveau_object *engine,
123 struct nouveau_oclass *oclass, void *data, u32 size, 137 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -132,6 +146,7 @@ nvc0_software_context_ctor(struct nouveau_object *parent,
132 return ret; 146 return ret;
133 147
134 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; 148 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
149 chan->base.vblank.event.func = nvc0_software_vblsem_release;
135 return 0; 150 return 0;
136} 151}
137 152
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index 47c4b3a5bd3a..92d3ab11d962 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -154,6 +154,14 @@ struct nve0_channel_ind_class {
154 u32 engine; 154 u32 engine;
155}; 155};
156 156
157/* 0046: NV04_DISP
158 */
159
160#define NV04_DISP_CLASS 0x00000046
161
162struct nv04_display_class {
163};
164
157/* 5070: NV50_DISP 165/* 5070: NV50_DISP
158 * 8270: NV84_DISP 166 * 8270: NV84_DISP
159 * 8370: NVA0_DISP 167 * 8370: NVA0_DISP
@@ -190,25 +198,6 @@ struct nve0_channel_ind_class {
190#define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f 198#define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f
191#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 199#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000
192#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff 200#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff
193#define NV94_DISP_SOR_DP_TRAIN 0x00016000
194#define NV94_DISP_SOR_DP_TRAIN_OP 0xf0000000
195#define NV94_DISP_SOR_DP_TRAIN_OP_PATTERN 0x00000000
196#define NV94_DISP_SOR_DP_TRAIN_OP_INIT 0x10000000
197#define NV94_DISP_SOR_DP_TRAIN_OP_FINI 0x20000000
198#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD 0x00000001
199#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF 0x00000000
200#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON 0x00000001
201#define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003
202#define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000
203#define NV94_DISP_SOR_DP_LNKCTL 0x00016040
204#define NV94_DISP_SOR_DP_LNKCTL_FRAME 0x80000000
205#define NV94_DISP_SOR_DP_LNKCTL_FRAME_STD 0x00000000
206#define NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH 0x80000000
207#define NV94_DISP_SOR_DP_LNKCTL_WIDTH 0x00001f00
208#define NV94_DISP_SOR_DP_LNKCTL_COUNT 0x00000007
209#define NV94_DISP_SOR_DP_DRVCTL(l) ((l) * 0x40 + 0x00016100)
210#define NV94_DISP_SOR_DP_DRVCTL_VS 0x00000300
211#define NV94_DISP_SOR_DP_DRVCTL_PE 0x00000003
212 201
213#define NV50_DISP_DAC_MTHD 0x00020000 202#define NV50_DISP_DAC_MTHD 0x00020000
214#define NV50_DISP_DAC_MTHD_TYPE 0x0000f000 203#define NV50_DISP_DAC_MTHD_TYPE 0x0000f000
@@ -230,6 +219,23 @@ struct nve0_channel_ind_class {
230#define NV50_DISP_DAC_LOAD 0x0002000c 219#define NV50_DISP_DAC_LOAD 0x0002000c
231#define NV50_DISP_DAC_LOAD_VALUE 0x00000007 220#define NV50_DISP_DAC_LOAD_VALUE 0x00000007
232 221
222#define NV50_DISP_PIOR_MTHD 0x00030000
223#define NV50_DISP_PIOR_MTHD_TYPE 0x0000f000
224#define NV50_DISP_PIOR_MTHD_OR 0x00000003
225
226#define NV50_DISP_PIOR_PWR 0x00030000
227#define NV50_DISP_PIOR_PWR_STATE 0x00000001
228#define NV50_DISP_PIOR_PWR_STATE_ON 0x00000001
229#define NV50_DISP_PIOR_PWR_STATE_OFF 0x00000000
230#define NV50_DISP_PIOR_TMDS_PWR 0x00032000
231#define NV50_DISP_PIOR_TMDS_PWR_STATE 0x00000001
232#define NV50_DISP_PIOR_TMDS_PWR_STATE_ON 0x00000001
233#define NV50_DISP_PIOR_TMDS_PWR_STATE_OFF 0x00000000
234#define NV50_DISP_PIOR_DP_PWR 0x00036000
235#define NV50_DISP_PIOR_DP_PWR_STATE 0x00000001
236#define NV50_DISP_PIOR_DP_PWR_STATE_ON 0x00000001
237#define NV50_DISP_PIOR_DP_PWR_STATE_OFF 0x00000000
238
233struct nv50_display_class { 239struct nv50_display_class {
234}; 240};
235 241
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h
index 63acc0346ff2..c66eac513803 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/client.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/client.h
@@ -7,7 +7,7 @@ struct nouveau_client {
7 struct nouveau_namedb base; 7 struct nouveau_namedb base;
8 struct nouveau_handle *root; 8 struct nouveau_handle *root;
9 struct nouveau_object *device; 9 struct nouveau_object *device;
10 char name[16]; 10 char name[32];
11 u32 debug; 11 u32 debug;
12 struct nouveau_vm *vm; 12 struct nouveau_vm *vm;
13}; 13};
@@ -41,5 +41,6 @@ int nouveau_client_create_(const char *name, u64 device, const char *cfg,
41 41
42int nouveau_client_init(struct nouveau_client *); 42int nouveau_client_init(struct nouveau_client *);
43int nouveau_client_fini(struct nouveau_client *, bool suspend); 43int nouveau_client_fini(struct nouveau_client *, bool suspend);
44const char *nouveau_client_name(void *obj);
44 45
45#endif 46#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
index e58b6f0984c1..d351a4e5819c 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -26,6 +26,7 @@ enum nv_subdev_type {
26 */ 26 */
27 NVDEV_SUBDEV_MXM, 27 NVDEV_SUBDEV_MXM,
28 NVDEV_SUBDEV_MC, 28 NVDEV_SUBDEV_MC,
29 NVDEV_SUBDEV_BUS,
29 NVDEV_SUBDEV_TIMER, 30 NVDEV_SUBDEV_TIMER,
30 NVDEV_SUBDEV_FB, 31 NVDEV_SUBDEV_FB,
31 NVDEV_SUBDEV_LTCG, 32 NVDEV_SUBDEV_LTCG,
diff --git a/drivers/gpu/drm/nouveau/core/include/core/enum.h b/drivers/gpu/drm/nouveau/core/include/core/enum.h
index e7b1e181943b..4fc62bb8c1f0 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/enum.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/enum.h
@@ -5,12 +5,13 @@ struct nouveau_enum {
5 u32 value; 5 u32 value;
6 const char *name; 6 const char *name;
7 const void *data; 7 const void *data;
8 u32 data2;
8}; 9};
9 10
10const struct nouveau_enum * 11const struct nouveau_enum *
11nouveau_enum_find(const struct nouveau_enum *, u32 value); 12nouveau_enum_find(const struct nouveau_enum *, u32 value);
12 13
13void 14const struct nouveau_enum *
14nouveau_enum_print(const struct nouveau_enum *en, u32 value); 15nouveau_enum_print(const struct nouveau_enum *en, u32 value);
15 16
16struct nouveau_bitfield { 17struct nouveau_bitfield {
diff --git a/drivers/gpu/drm/nouveau/core/include/core/event.h b/drivers/gpu/drm/nouveau/core/include/core/event.h
new file mode 100644
index 000000000000..9e094408f14e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/core/event.h
@@ -0,0 +1,36 @@
1#ifndef __NVKM_EVENT_H__
2#define __NVKM_EVENT_H__
3
4/* return codes from event handlers */
5#define NVKM_EVENT_DROP 0
6#define NVKM_EVENT_KEEP 1
7
8struct nouveau_eventh {
9 struct list_head head;
10 int (*func)(struct nouveau_eventh *, int index);
11};
12
13struct nouveau_event {
14 spinlock_t lock;
15
16 void *priv;
17 void (*enable)(struct nouveau_event *, int index);
18 void (*disable)(struct nouveau_event *, int index);
19
20 int index_nr;
21 struct {
22 struct list_head list;
23 int refs;
24 } index[];
25};
26
27int nouveau_event_create(int index_nr, struct nouveau_event **);
28void nouveau_event_destroy(struct nouveau_event **);
29void nouveau_event_trigger(struct nouveau_event *, int index);
30
31void nouveau_event_get(struct nouveau_event *, int index,
32 struct nouveau_eventh *);
33void nouveau_event_put(struct nouveau_event *, int index,
34 struct nouveau_eventh *);
35
36#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h
index 5982935ee23a..6a902672f6f4 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/object.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/object.h
@@ -133,7 +133,7 @@ static inline u8
133nv_ro08(void *obj, u64 addr) 133nv_ro08(void *obj, u64 addr)
134{ 134{
135 u8 data = nv_ofuncs(obj)->rd08(obj, addr); 135 u8 data = nv_ofuncs(obj)->rd08(obj, addr);
136 nv_spam(obj, "nv_ro08 0x%08x 0x%02x\n", addr, data); 136 nv_spam(obj, "nv_ro08 0x%08llx 0x%02x\n", addr, data);
137 return data; 137 return data;
138} 138}
139 139
@@ -141,7 +141,7 @@ static inline u16
141nv_ro16(void *obj, u64 addr) 141nv_ro16(void *obj, u64 addr)
142{ 142{
143 u16 data = nv_ofuncs(obj)->rd16(obj, addr); 143 u16 data = nv_ofuncs(obj)->rd16(obj, addr);
144 nv_spam(obj, "nv_ro16 0x%08x 0x%04x\n", addr, data); 144 nv_spam(obj, "nv_ro16 0x%08llx 0x%04x\n", addr, data);
145 return data; 145 return data;
146} 146}
147 147
@@ -149,28 +149,28 @@ static inline u32
149nv_ro32(void *obj, u64 addr) 149nv_ro32(void *obj, u64 addr)
150{ 150{
151 u32 data = nv_ofuncs(obj)->rd32(obj, addr); 151 u32 data = nv_ofuncs(obj)->rd32(obj, addr);
152 nv_spam(obj, "nv_ro32 0x%08x 0x%08x\n", addr, data); 152 nv_spam(obj, "nv_ro32 0x%08llx 0x%08x\n", addr, data);
153 return data; 153 return data;
154} 154}
155 155
156static inline void 156static inline void
157nv_wo08(void *obj, u64 addr, u8 data) 157nv_wo08(void *obj, u64 addr, u8 data)
158{ 158{
159 nv_spam(obj, "nv_wo08 0x%08x 0x%02x\n", addr, data); 159 nv_spam(obj, "nv_wo08 0x%08llx 0x%02x\n", addr, data);
160 nv_ofuncs(obj)->wr08(obj, addr, data); 160 nv_ofuncs(obj)->wr08(obj, addr, data);
161} 161}
162 162
163static inline void 163static inline void
164nv_wo16(void *obj, u64 addr, u16 data) 164nv_wo16(void *obj, u64 addr, u16 data)
165{ 165{
166 nv_spam(obj, "nv_wo16 0x%08x 0x%04x\n", addr, data); 166 nv_spam(obj, "nv_wo16 0x%08llx 0x%04x\n", addr, data);
167 nv_ofuncs(obj)->wr16(obj, addr, data); 167 nv_ofuncs(obj)->wr16(obj, addr, data);
168} 168}
169 169
170static inline void 170static inline void
171nv_wo32(void *obj, u64 addr, u32 data) 171nv_wo32(void *obj, u64 addr, u32 data)
172{ 172{
173 nv_spam(obj, "nv_wo32 0x%08x 0x%08x\n", addr, data); 173 nv_spam(obj, "nv_wo32 0x%08llx 0x%08x\n", addr, data);
174 nv_ofuncs(obj)->wr32(obj, addr, data); 174 nv_ofuncs(obj)->wr32(obj, addr, data);
175} 175}
176 176
diff --git a/drivers/gpu/drm/nouveau/core/include/core/printk.h b/drivers/gpu/drm/nouveau/core/include/core/printk.h
index 1d629664f32d..febed2ea5c80 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/printk.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/printk.h
@@ -15,7 +15,8 @@ struct nouveau_object;
15#define NV_PRINTK_TRACE KERN_DEBUG 15#define NV_PRINTK_TRACE KERN_DEBUG
16#define NV_PRINTK_SPAM KERN_DEBUG 16#define NV_PRINTK_SPAM KERN_DEBUG
17 17
18void nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); 18void __printf(4, 5)
19nv_printk_(struct nouveau_object *, const char *, int, const char *, ...);
19 20
20#define nv_printk(o,l,f,a...) do { \ 21#define nv_printk(o,l,f,a...) do { \
21 if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG) \ 22 if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG) \
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
index 46948285f3e7..28da6772c095 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
@@ -4,18 +4,11 @@
4#include <core/object.h> 4#include <core/object.h>
5#include <core/engine.h> 5#include <core/engine.h>
6#include <core/device.h> 6#include <core/device.h>
7#include <core/event.h>
7 8
8struct nouveau_disp { 9struct nouveau_disp {
9 struct nouveau_engine base; 10 struct nouveau_engine base;
10 11 struct nouveau_event *vblank;
11 struct {
12 struct list_head list;
13 spinlock_t lock;
14 void (*notify)(void *, int);
15 void (*get)(void *, int);
16 void (*put)(void *, int);
17 void *data;
18 } vblank;
19}; 12};
20 13
21static inline struct nouveau_disp * 14static inline struct nouveau_disp *
@@ -24,16 +17,22 @@ nouveau_disp(void *obj)
24 return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP]; 17 return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP];
25} 18}
26 19
27#define nouveau_disp_create(p,e,c,i,x,d) \ 20#define nouveau_disp_create(p,e,c,h,i,x,d) \
28 nouveau_engine_create((p), (e), (c), true, (i), (x), (d)) 21 nouveau_disp_create_((p), (e), (c), (h), (i), (x), \
29#define nouveau_disp_destroy(d) \ 22 sizeof(**d), (void **)d)
30 nouveau_engine_destroy(&(d)->base) 23#define nouveau_disp_destroy(d) ({ \
24 struct nouveau_disp *disp = (d); \
25 _nouveau_disp_dtor(nv_object(disp)); \
26})
31#define nouveau_disp_init(d) \ 27#define nouveau_disp_init(d) \
32 nouveau_engine_init(&(d)->base) 28 nouveau_engine_init(&(d)->base)
33#define nouveau_disp_fini(d,s) \ 29#define nouveau_disp_fini(d,s) \
34 nouveau_engine_fini(&(d)->base, (s)) 30 nouveau_engine_fini(&(d)->base, (s))
35 31
36#define _nouveau_disp_dtor _nouveau_engine_dtor 32int nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *,
33 struct nouveau_oclass *, int heads,
34 const char *, const char *, int, void **);
35void _nouveau_disp_dtor(struct nouveau_object *);
37#define _nouveau_disp_init _nouveau_engine_init 36#define _nouveau_disp_init _nouveau_engine_init
38#define _nouveau_disp_fini _nouveau_engine_fini 37#define _nouveau_disp_fini _nouveau_engine_fini
39 38
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
index f18846c8c6fe..b46c197709f3 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
@@ -65,6 +65,8 @@ struct nouveau_fifo_base {
65struct nouveau_fifo { 65struct nouveau_fifo {
66 struct nouveau_engine base; 66 struct nouveau_engine base;
67 67
68 struct nouveau_event *uevent;
69
68 struct nouveau_object **channel; 70 struct nouveau_object **channel;
69 spinlock_t lock; 71 spinlock_t lock;
70 u16 min; 72 u16 min;
@@ -92,6 +94,8 @@ int nouveau_fifo_create_(struct nouveau_object *, struct nouveau_object *,
92 struct nouveau_oclass *, int min, int max, 94 struct nouveau_oclass *, int min, int max,
93 int size, void **); 95 int size, void **);
94void nouveau_fifo_destroy(struct nouveau_fifo *); 96void nouveau_fifo_destroy(struct nouveau_fifo *);
97const char *
98nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid);
95 99
96#define _nouveau_fifo_init _nouveau_engine_init 100#define _nouveau_fifo_init _nouveau_engine_init
97#define _nouveau_fifo_fini _nouveau_engine_fini 101#define _nouveau_fifo_fini _nouveau_engine_fini
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/software.h b/drivers/gpu/drm/nouveau/core/include/engine/software.h
index c945691c8564..45799487e573 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/software.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/software.h
@@ -3,17 +3,17 @@
3 3
4#include <core/engine.h> 4#include <core/engine.h>
5#include <core/engctx.h> 5#include <core/engctx.h>
6#include <core/event.h>
6 7
7struct nouveau_software_chan { 8struct nouveau_software_chan {
8 struct nouveau_engctx base; 9 struct nouveau_engctx base;
9 10
10 struct { 11 struct {
11 struct list_head head; 12 struct nouveau_eventh event;
12 u32 channel; 13 u32 channel;
13 u32 ctxdma; 14 u32 ctxdma;
14 u64 offset; 15 u64 offset;
15 u32 value; 16 u32 value;
16 u32 crtc;
17 } vblank; 17 } vblank;
18 18
19 int (*flip)(void *); 19 int (*flip)(void *);
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h
index b79025da581e..123270e9813a 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h
@@ -16,6 +16,8 @@ enum dcb_output_type {
16 16
17struct dcb_output { 17struct dcb_output {
18 int index; /* may not be raw dcb index if merging has happened */ 18 int index; /* may not be raw dcb index if merging has happened */
19 u16 hasht;
20 u16 hashm;
19 enum dcb_output_type type; 21 enum dcb_output_type type;
20 uint8_t i2c_index; 22 uint8_t i2c_index;
21 uint8_t heads; 23 uint8_t heads;
@@ -25,6 +27,7 @@ struct dcb_output {
25 uint8_t or; 27 uint8_t or;
26 uint8_t link; 28 uint8_t link;
27 bool duallink_possible; 29 bool duallink_possible;
30 uint8_t extdev;
28 union { 31 union {
29 struct sor_conf { 32 struct sor_conf {
30 int link; 33 int link;
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
index e6563b5cb08e..96d3364f6db3 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
@@ -1,17 +1,22 @@
1#ifndef __NVBIOS_GPIO_H__ 1#ifndef __NVBIOS_GPIO_H__
2#define __NVBIOS_GPIO_H__ 2#define __NVBIOS_GPIO_H__
3 3
4struct nouveau_bios;
5
6enum dcb_gpio_func_name { 4enum dcb_gpio_func_name {
7 DCB_GPIO_PANEL_POWER = 0x01, 5 DCB_GPIO_PANEL_POWER = 0x01,
8 DCB_GPIO_TVDAC0 = 0x0c, 6 DCB_GPIO_TVDAC0 = 0x0c,
9 DCB_GPIO_TVDAC1 = 0x2d, 7 DCB_GPIO_TVDAC1 = 0x2d,
10 DCB_GPIO_PWM_FAN = 0x09, 8 DCB_GPIO_FAN = 0x09,
11 DCB_GPIO_FAN_SENSE = 0x3d, 9 DCB_GPIO_FAN_SENSE = 0x3d,
12 DCB_GPIO_UNUSED = 0xff 10 DCB_GPIO_UNUSED = 0xff
13}; 11};
14 12
13#define DCB_GPIO_LOG_DIR 0x02
14#define DCB_GPIO_LOG_DIR_OUT 0x00
15#define DCB_GPIO_LOG_DIR_IN 0x02
16#define DCB_GPIO_LOG_VAL 0x01
17#define DCB_GPIO_LOG_VAL_LO 0x00
18#define DCB_GPIO_LOG_VAL_HI 0x01
19
15struct dcb_gpio_func { 20struct dcb_gpio_func {
16 u8 func; 21 u8 func;
17 u8 line; 22 u8 line;
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h
index 5079bedfd985..10b57a19a7de 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h
@@ -15,7 +15,7 @@ struct dcb_i2c_entry {
15 enum dcb_i2c_type type; 15 enum dcb_i2c_type type;
16 u8 drive; 16 u8 drive;
17 u8 sense; 17 u8 sense;
18 u32 data; 18 u8 share;
19}; 19};
20 20
21u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); 21u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
index a2c4296fc5f6..083541dbe9c8 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
@@ -23,11 +23,27 @@ struct nvbios_therm_sensor {
23 struct nvbios_therm_threshold thrs_shutdown; 23 struct nvbios_therm_threshold thrs_shutdown;
24}; 24};
25 25
26/* no vbios have more than 6 */
27#define NOUVEAU_TEMP_FAN_TRIP_MAX 10
28struct nouveau_therm_trip_point {
29 int fan_duty;
30 int temp;
31 int hysteresis;
32};
33
26struct nvbios_therm_fan { 34struct nvbios_therm_fan {
27 u16 pwm_freq; 35 u16 pwm_freq;
28 36
29 u8 min_duty; 37 u8 min_duty;
30 u8 max_duty; 38 u8 max_duty;
39
40 u16 bump_period;
41 u16 slow_down_period;
42
43 struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX];
44 u8 nr_fan_trip;
45 u8 linear_min_temp;
46 u8 linear_max_temp;
31}; 47};
32 48
33enum nvbios_therm_domain { 49enum nvbios_therm_domain {
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h
new file mode 100644
index 000000000000..360baab52e4c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h
@@ -0,0 +1,19 @@
1#ifndef __NVBIOS_XPIO_H__
2#define __NVBIOS_XPIO_H__
3
4#define NVBIOS_XPIO_FLAG_AUX 0x10
5#define NVBIOS_XPIO_FLAG_AUX0 0x00
6#define NVBIOS_XPIO_FLAG_AUX1 0x10
7
8struct nvbios_xpio {
9 u8 type;
10 u8 addr;
11 u8 flags;
12};
13
14u16 dcb_xpio_table(struct nouveau_bios *, u8 idx,
15 u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
16u16 dcb_xpio_parse(struct nouveau_bios *, u8 idx,
17 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_xpio *);
18
19#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bus.h b/drivers/gpu/drm/nouveau/core/include/subdev/bus.h
new file mode 100644
index 000000000000..7d88ec4a6d06
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bus.h
@@ -0,0 +1,41 @@
1#ifndef __NOUVEAU_BUS_H__
2#define __NOUVEAU_BUS_H__
3
4#include <core/subdev.h>
5#include <core/device.h>
6
7struct nouveau_bus_intr {
8 u32 stat;
9 u32 unit;
10};
11
12struct nouveau_bus {
13 struct nouveau_subdev base;
14};
15
16static inline struct nouveau_bus *
17nouveau_bus(void *obj)
18{
19 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BUS];
20}
21
22#define nouveau_bus_create(p, e, o, d) \
23 nouveau_subdev_create_((p), (e), (o), 0, "PBUS", "master", \
24 sizeof(**d), (void **)d)
25#define nouveau_bus_destroy(p) \
26 nouveau_subdev_destroy(&(p)->base)
27#define nouveau_bus_init(p) \
28 nouveau_subdev_init(&(p)->base)
29#define nouveau_bus_fini(p, s) \
30 nouveau_subdev_fini(&(p)->base, (s))
31
32#define _nouveau_bus_dtor _nouveau_subdev_dtor
33#define _nouveau_bus_init _nouveau_subdev_init
34#define _nouveau_bus_fini _nouveau_subdev_fini
35
36extern struct nouveau_oclass nv04_bus_oclass;
37extern struct nouveau_oclass nv31_bus_oclass;
38extern struct nouveau_oclass nv50_bus_oclass;
39extern struct nouveau_oclass nvc0_bus_oclass;
40
41#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
index b75e8f18e52c..c85b9f1579ad 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
@@ -3,6 +3,7 @@
3 3
4#include <core/subdev.h> 4#include <core/subdev.h>
5#include <core/device.h> 5#include <core/device.h>
6#include <core/event.h>
6 7
7#include <subdev/bios.h> 8#include <subdev/bios.h>
8#include <subdev/bios/gpio.h> 9#include <subdev/bios/gpio.h>
@@ -10,28 +11,18 @@
10struct nouveau_gpio { 11struct nouveau_gpio {
11 struct nouveau_subdev base; 12 struct nouveau_subdev base;
12 13
14 struct nouveau_event *events;
15
13 /* hardware interfaces */ 16 /* hardware interfaces */
14 void (*reset)(struct nouveau_gpio *, u8 func); 17 void (*reset)(struct nouveau_gpio *, u8 func);
15 int (*drive)(struct nouveau_gpio *, int line, int dir, int out); 18 int (*drive)(struct nouveau_gpio *, int line, int dir, int out);
16 int (*sense)(struct nouveau_gpio *, int line); 19 int (*sense)(struct nouveau_gpio *, int line);
17 void (*irq_enable)(struct nouveau_gpio *, int line, bool);
18 20
19 /* software interfaces */ 21 /* software interfaces */
20 int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line, 22 int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line,
21 struct dcb_gpio_func *); 23 struct dcb_gpio_func *);
22 int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); 24 int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state);
23 int (*get)(struct nouveau_gpio *, int idx, u8 tag, u8 line); 25 int (*get)(struct nouveau_gpio *, int idx, u8 tag, u8 line);
24 int (*irq)(struct nouveau_gpio *, int idx, u8 tag, u8 line, bool on);
25
26 /* interrupt handling */
27 struct list_head isr;
28 spinlock_t lock;
29
30 void (*isr_run)(struct nouveau_gpio *, int idx, u32 mask);
31 int (*isr_add)(struct nouveau_gpio *, int idx, u8 tag, u8 line,
32 void (*)(void *, int state), void *data);
33 void (*isr_del)(struct nouveau_gpio *, int idx, u8 tag, u8 line,
34 void (*)(void *, int state), void *data);
35}; 26};
36 27
37static inline struct nouveau_gpio * 28static inline struct nouveau_gpio *
@@ -40,25 +31,23 @@ nouveau_gpio(void *obj)
40 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO]; 31 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO];
41} 32}
42 33
43#define nouveau_gpio_create(p,e,o,d) \ 34#define nouveau_gpio_create(p,e,o,l,d) \
44 nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) 35 nouveau_gpio_create_((p), (e), (o), (l), sizeof(**d), (void **)d)
45#define nouveau_gpio_destroy(p) \ 36#define nouveau_gpio_destroy(p) ({ \
46 nouveau_subdev_destroy(&(p)->base) 37 struct nouveau_gpio *gpio = (p); \
38 _nouveau_gpio_dtor(nv_object(gpio)); \
39})
47#define nouveau_gpio_fini(p,s) \ 40#define nouveau_gpio_fini(p,s) \
48 nouveau_subdev_fini(&(p)->base, (s)) 41 nouveau_subdev_fini(&(p)->base, (s))
49 42
50int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, 43int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *,
51 struct nouveau_oclass *, int, void **); 44 struct nouveau_oclass *, int, int, void **);
52int nouveau_gpio_init(struct nouveau_gpio *); 45void _nouveau_gpio_dtor(struct nouveau_object *);
46int nouveau_gpio_init(struct nouveau_gpio *);
53 47
54extern struct nouveau_oclass nv10_gpio_oclass; 48extern struct nouveau_oclass nv10_gpio_oclass;
55extern struct nouveau_oclass nv50_gpio_oclass; 49extern struct nouveau_oclass nv50_gpio_oclass;
56extern struct nouveau_oclass nvd0_gpio_oclass; 50extern struct nouveau_oclass nvd0_gpio_oclass;
57 51extern struct nouveau_oclass nve0_gpio_oclass;
58void nv50_gpio_dtor(struct nouveau_object *);
59int nv50_gpio_init(struct nouveau_object *);
60int nv50_gpio_fini(struct nouveau_object *, bool);
61void nv50_gpio_intr(struct nouveau_subdev *);
62void nv50_gpio_irq_enable(struct nouveau_gpio *, int line, bool);
63 52
64#endif 53#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
index b93ab01e3785..888384c0bed8 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
@@ -10,23 +10,59 @@
10#define NV_I2C_PORT(n) (0x00 + (n)) 10#define NV_I2C_PORT(n) (0x00 + (n))
11#define NV_I2C_DEFAULT(n) (0x80 + (n)) 11#define NV_I2C_DEFAULT(n) (0x80 + (n))
12 12
13#define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n))
14#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8)
15#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8)
16
13struct nouveau_i2c_port { 17struct nouveau_i2c_port {
18 struct nouveau_object base;
14 struct i2c_adapter adapter; 19 struct i2c_adapter adapter;
15 struct nouveau_i2c *i2c; 20
16 struct i2c_algo_bit_data bit;
17 struct list_head head; 21 struct list_head head;
18 u8 index; 22 u8 index;
19 u8 type; 23
20 u32 dcb; 24 const struct nouveau_i2c_func *func;
21 u32 drive; 25};
22 u32 sense; 26
23 u32 state; 27struct nouveau_i2c_func {
28 void (*acquire)(struct nouveau_i2c_port *);
29 void (*release)(struct nouveau_i2c_port *);
30
31 void (*drive_scl)(struct nouveau_i2c_port *, int);
32 void (*drive_sda)(struct nouveau_i2c_port *, int);
33 int (*sense_scl)(struct nouveau_i2c_port *);
34 int (*sense_sda)(struct nouveau_i2c_port *);
35
36 int (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8);
37 int (*pattern)(struct nouveau_i2c_port *, int pattern);
38 int (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh);
39 int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe);
24}; 40};
25 41
42#define nouveau_i2c_port_create(p,e,o,i,a,d) \
43 nouveau_i2c_port_create_((p), (e), (o), (i), (a), \
44 sizeof(**d), (void **)d)
45#define nouveau_i2c_port_destroy(p) ({ \
46 struct nouveau_i2c_port *port = (p); \
47 _nouveau_i2c_port_dtor(nv_object(i2c)); \
48})
49#define nouveau_i2c_port_init(p) \
50 nouveau_object_init(&(p)->base)
51#define nouveau_i2c_port_fini(p,s) \
52 nouveau_object_fini(&(p)->base, (s))
53
54int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *,
55 struct nouveau_oclass *, u8,
56 const struct i2c_algorithm *, int, void **);
57void _nouveau_i2c_port_dtor(struct nouveau_object *);
58#define _nouveau_i2c_port_init nouveau_object_init
59#define _nouveau_i2c_port_fini nouveau_object_fini
60
26struct nouveau_i2c { 61struct nouveau_i2c {
27 struct nouveau_subdev base; 62 struct nouveau_subdev base;
28 63
29 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); 64 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index);
65 struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type);
30 int (*identify)(struct nouveau_i2c *, int index, 66 int (*identify)(struct nouveau_i2c *, int index,
31 const char *what, struct i2c_board_info *, 67 const char *what, struct i2c_board_info *,
32 bool (*match)(struct nouveau_i2c_port *, 68 bool (*match)(struct nouveau_i2c_port *,
@@ -40,21 +76,76 @@ nouveau_i2c(void *obj)
40 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; 76 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C];
41} 77}
42 78
43extern struct nouveau_oclass nouveau_i2c_oclass; 79#define nouveau_i2c_create(p,e,o,s,d) \
80 nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d)
81#define nouveau_i2c_destroy(p) ({ \
82 struct nouveau_i2c *i2c = (p); \
83 _nouveau_i2c_dtor(nv_object(i2c)); \
84})
85#define nouveau_i2c_init(p) ({ \
86 struct nouveau_i2c *i2c = (p); \
87 _nouveau_i2c_init(nv_object(i2c)); \
88})
89#define nouveau_i2c_fini(p,s) ({ \
90 struct nouveau_i2c *i2c = (p); \
91 _nouveau_i2c_fini(nv_object(i2c), (s)); \
92})
44 93
45void nouveau_i2c_drive_scl(void *, int); 94int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *,
46void nouveau_i2c_drive_sda(void *, int); 95 struct nouveau_oclass *, struct nouveau_oclass *,
47int nouveau_i2c_sense_scl(void *); 96 int, void **);
48int nouveau_i2c_sense_sda(void *); 97void _nouveau_i2c_dtor(struct nouveau_object *);
98int _nouveau_i2c_init(struct nouveau_object *);
99int _nouveau_i2c_fini(struct nouveau_object *, bool);
49 100
50int nv_rdi2cr(struct nouveau_i2c_port *, u8 addr, u8 reg); 101extern struct nouveau_oclass nv04_i2c_oclass;
51int nv_wri2cr(struct nouveau_i2c_port *, u8 addr, u8 reg, u8 val); 102extern struct nouveau_oclass nv4e_i2c_oclass;
52bool nv_probe_i2c(struct nouveau_i2c_port *, u8 addr); 103extern struct nouveau_oclass nv50_i2c_oclass;
53 104extern struct nouveau_oclass nv94_i2c_oclass;
54int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 105extern struct nouveau_oclass nvd0_i2c_oclass;
55int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 106extern struct nouveau_oclass nouveau_anx9805_sclass[];
56 107
57extern const struct i2c_algorithm nouveau_i2c_bit_algo; 108extern const struct i2c_algorithm nouveau_i2c_bit_algo;
58extern const struct i2c_algorithm nouveau_i2c_aux_algo; 109extern const struct i2c_algorithm nouveau_i2c_aux_algo;
59 110
111static inline int
112nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg)
113{
114 u8 val;
115 struct i2c_msg msgs[] = {
116 { .addr = addr, .flags = 0, .len = 1, .buf = &reg },
117 { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val },
118 };
119
120 int ret = i2c_transfer(&port->adapter, msgs, 2);
121 if (ret != 2)
122 return -EIO;
123
124 return val;
125}
126
127static inline int
128nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val)
129{
130 u8 buf[2] = { reg, val };
131 struct i2c_msg msgs[] = {
132 { .addr = addr, .flags = 0, .len = 2, .buf = buf },
133 };
134
135 int ret = i2c_transfer(&port->adapter, msgs, 1);
136 if (ret != 1)
137 return -EIO;
138
139 return 0;
140}
141
142static inline bool
143nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr)
144{
145 return nv_rdi2cr(port, addr, 0) >= 0;
146}
147
148int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size);
149int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size);
150
60#endif 151#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
index faee569fd458..6b17b614629f 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
@@ -4,10 +4,10 @@
4#include <core/device.h> 4#include <core/device.h>
5#include <core/subdev.h> 5#include <core/subdev.h>
6 6
7enum nouveau_therm_fan_mode { 7enum nouveau_therm_mode {
8 FAN_CONTROL_NONE = 0, 8 NOUVEAU_THERM_CTRL_NONE = 0,
9 FAN_CONTROL_MANUAL = 1, 9 NOUVEAU_THERM_CTRL_MANUAL = 1,
10 FAN_CONTROL_NR, 10 NOUVEAU_THERM_CTRL_AUTO = 2,
11}; 11};
12 12
13enum nouveau_therm_attr_type { 13enum nouveau_therm_attr_type {
@@ -28,6 +28,11 @@ enum nouveau_therm_attr_type {
28struct nouveau_therm { 28struct nouveau_therm {
29 struct nouveau_subdev base; 29 struct nouveau_subdev base;
30 30
31 int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
32 int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *);
33 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
34 int (*pwm_clock)(struct nouveau_therm *);
35
31 int (*fan_get)(struct nouveau_therm *); 36 int (*fan_get)(struct nouveau_therm *);
32 int (*fan_set)(struct nouveau_therm *, int); 37 int (*fan_set)(struct nouveau_therm *, int);
33 int (*fan_sense)(struct nouveau_therm *); 38 int (*fan_sense)(struct nouveau_therm *);
@@ -46,13 +51,29 @@ nouveau_therm(void *obj)
46} 51}
47 52
48#define nouveau_therm_create(p,e,o,d) \ 53#define nouveau_therm_create(p,e,o,d) \
49 nouveau_subdev_create((p), (e), (o), 0, "THERM", "therm", d) 54 nouveau_therm_create_((p), (e), (o), sizeof(**d), (void **)d)
50#define nouveau_therm_destroy(p) \ 55#define nouveau_therm_destroy(p) ({ \
51 nouveau_subdev_destroy(&(p)->base) 56 struct nouveau_therm *therm = (p); \
57 _nouveau_therm_dtor(nv_object(therm)); \
58})
59#define nouveau_therm_init(p) ({ \
60 struct nouveau_therm *therm = (p); \
61 _nouveau_therm_init(nv_object(therm)); \
62})
63#define nouveau_therm_fini(p,s) ({ \
64 struct nouveau_therm *therm = (p); \
65 _nouveau_therm_init(nv_object(therm), (s)); \
66})
52 67
53#define _nouveau_therm_dtor _nouveau_subdev_dtor 68int nouveau_therm_create_(struct nouveau_object *, struct nouveau_object *,
69 struct nouveau_oclass *, int, void **);
70void _nouveau_therm_dtor(struct nouveau_object *);
71int _nouveau_therm_init(struct nouveau_object *);
72int _nouveau_therm_fini(struct nouveau_object *, bool);
54 73
55extern struct nouveau_oclass nv40_therm_oclass; 74extern struct nouveau_oclass nv40_therm_oclass;
56extern struct nouveau_oclass nv50_therm_oclass; 75extern struct nouveau_oclass nv50_therm_oclass;
76extern struct nouveau_oclass nva3_therm_oclass;
77extern struct nouveau_oclass nvd0_therm_oclass;
57 78
58#endif 79#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
index c24ec8ab3db4..e465d158d352 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
@@ -10,6 +10,14 @@ struct nouveau_alarm {
10 void (*func)(struct nouveau_alarm *); 10 void (*func)(struct nouveau_alarm *);
11}; 11};
12 12
13static inline void
14nouveau_alarm_init(struct nouveau_alarm *alarm,
15 void (*func)(struct nouveau_alarm *))
16{
17 INIT_LIST_HEAD(&alarm->head);
18 alarm->func = func;
19}
20
13bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); 21bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data);
14bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); 22bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data);
15bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); 23bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h
index cfe3b9cad156..eb496033b55c 100644
--- a/drivers/gpu/drm/nouveau/core/os.h
+++ b/drivers/gpu/drm/nouveau/core/os.h
@@ -16,6 +16,7 @@
16#include <linux/vmalloc.h> 16#include <linux/vmalloc.h>
17#include <linux/acpi.h> 17#include <linux/acpi.h>
18#include <linux/dmi.h> 18#include <linux/dmi.h>
19#include <linux/reboot.h>
19 20
20#include <asm/unaligned.h> 21#include <asm/unaligned.h>
21 22
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
index f621f69fa1a2..e816f06637a7 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
@@ -172,7 +172,7 @@ out:
172 nv_wr32(bios, pcireg, access); 172 nv_wr32(bios, pcireg, access);
173} 173}
174 174
175#if defined(CONFIG_ACPI) 175#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
176int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); 176int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
177bool nouveau_acpi_rom_supported(struct pci_dev *pdev); 177bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
178#else 178#else
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
index 0fd87df99dd6..2d9b9d7a7992 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
@@ -107,6 +107,18 @@ dcb_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len)
107 return 0x0000; 107 return 0x0000;
108} 108}
109 109
110static inline u16
111dcb_outp_hasht(struct dcb_output *outp)
112{
113 return (outp->extdev << 8) | (outp->location << 4) | outp->type;
114}
115
116static inline u16
117dcb_outp_hashm(struct dcb_output *outp)
118{
119 return (outp->heads << 8) | (outp->link << 6) | outp->or;
120}
121
110u16 122u16
111dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, 123dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
112 struct dcb_output *outp) 124 struct dcb_output *outp)
@@ -135,34 +147,28 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
135 case DCB_OUTPUT_DP: 147 case DCB_OUTPUT_DP:
136 outp->link = (conf & 0x00000030) >> 4; 148 outp->link = (conf & 0x00000030) >> 4;
137 outp->sorconf.link = outp->link; /*XXX*/ 149 outp->sorconf.link = outp->link; /*XXX*/
150 outp->extdev = 0x00;
151 if (outp->location != 0)
152 outp->extdev = (conf & 0x0000ff00) >> 8;
138 break; 153 break;
139 default: 154 default:
140 break; 155 break;
141 } 156 }
142 } 157 }
158
159 outp->hasht = dcb_outp_hasht(outp);
160 outp->hashm = dcb_outp_hashm(outp);
143 } 161 }
144 return dcb; 162 return dcb;
145} 163}
146 164
147static inline u16
148dcb_outp_hasht(struct dcb_output *outp)
149{
150 return outp->type;
151}
152
153static inline u16
154dcb_outp_hashm(struct dcb_output *outp)
155{
156 return (outp->heads << 8) | (outp->link << 6) | outp->or;
157}
158
159u16 165u16
160dcb_outp_match(struct nouveau_bios *bios, u16 type, u16 mask, 166dcb_outp_match(struct nouveau_bios *bios, u16 type, u16 mask,
161 u8 *ver, u8 *len, struct dcb_output *outp) 167 u8 *ver, u8 *len, struct dcb_output *outp)
162{ 168{
163 u16 dcb, idx = 0; 169 u16 dcb, idx = 0;
164 while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) { 170 while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) {
165 if (dcb_outp_hasht(outp) == type) { 171 if ((dcb_outp_hasht(outp) & 0x00ff) == (type & 0x00ff)) {
166 if ((dcb_outp_hashm(outp) & mask) == mask) 172 if ((dcb_outp_hashm(outp) & mask) == mask)
167 break; 173 break;
168 } 174 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c b/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c
index 5afb568b2d69..b2a676e53580 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c
@@ -48,7 +48,7 @@ extdev_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
48 return extdev + *hdr; 48 return extdev + *hdr;
49} 49}
50 50
51u16 51static u16
52nvbios_extdev_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) 52nvbios_extdev_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
53{ 53{
54 u8 hdr, cnt; 54 u8 hdr, cnt;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c
index c84e93fa6d95..172a4f999990 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c
@@ -25,6 +25,7 @@
25#include <subdev/bios.h> 25#include <subdev/bios.h>
26#include <subdev/bios/dcb.h> 26#include <subdev/bios/dcb.h>
27#include <subdev/bios/gpio.h> 27#include <subdev/bios/gpio.h>
28#include <subdev/bios/xpio.h>
28 29
29u16 30u16
30dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 31dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
@@ -60,8 +61,14 @@ dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
60u16 61u16
61dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len) 62dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len)
62{ 63{
63 u8 hdr, cnt; 64 u8 hdr, cnt, xver; /* use gpio version for xpio entry parsing */
64 u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000; 65 u16 gpio;
66
67 if (!idx--)
68 gpio = dcb_gpio_table(bios, ver, &hdr, &cnt, len);
69 else
70 gpio = dcb_xpio_table(bios, idx, &xver, &hdr, &cnt, len);
71
65 if (gpio && ent < cnt) 72 if (gpio && ent < cnt)
66 return gpio + hdr + (ent * *len); 73 return gpio + hdr + (ent * *len);
67 return 0x0000; 74 return 0x0000;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c
index ad577db83766..cfb9288c6d28 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c
@@ -70,12 +70,12 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
70 u8 ver, len; 70 u8 ver, len;
71 u16 ent = dcb_i2c_entry(bios, idx, &ver, &len); 71 u16 ent = dcb_i2c_entry(bios, idx, &ver, &len);
72 if (ent) { 72 if (ent) {
73 info->data = nv_ro32(bios, ent + 0); 73 info->type = nv_ro08(bios, ent + 3);
74 info->type = nv_ro08(bios, ent + 3); 74 info->share = DCB_I2C_UNUSED;
75 if (ver < 0x30) { 75 if (ver < 0x30) {
76 info->type &= 0x07; 76 info->type &= 0x07;
77 if (info->type == 0x07) 77 if (info->type == 0x07)
78 info->type = 0xff; 78 info->type = DCB_I2C_UNUSED;
79 } 79 }
80 80
81 switch (info->type) { 81 switch (info->type) {
@@ -88,7 +88,11 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
88 return 0; 88 return 0;
89 case DCB_I2C_NVIO_BIT: 89 case DCB_I2C_NVIO_BIT:
90 case DCB_I2C_NVIO_AUX: 90 case DCB_I2C_NVIO_AUX:
91 info->drive = nv_ro08(bios, ent + 0); 91 info->drive = nv_ro08(bios, ent + 0) & 0x0f;
92 if (nv_ro08(bios, ent + 1) & 0x01) {
93 info->share = nv_ro08(bios, ent + 1) >> 1;
94 info->share &= 0x0f;
95 }
92 return 0; 96 return 0;
93 case DCB_I2C_UNUSED: 97 case DCB_I2C_UNUSED:
94 return 0; 98 return 0;
@@ -121,7 +125,8 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info)
121 if (!info->sense) info->sense = 0x36; 125 if (!info->sense) info->sense = 0x36;
122 } 126 }
123 127
124 info->type = DCB_I2C_NV04_BIT; 128 info->type = DCB_I2C_NV04_BIT;
129 info->share = DCB_I2C_UNUSED;
125 return 0; 130 return 0;
126 } 131 }
127 132
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index 690ed438b2ad..2cc1e6a5eb6a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -231,6 +231,11 @@ init_i2c(struct nvbios_init *init, int index)
231 return NULL; 231 return NULL;
232 } 232 }
233 233
234 if (index == -2 && init->outp->location) {
235 index = NV_I2C_TYPE_EXTAUX(init->outp->extdev);
236 return i2c->find_type(i2c, index);
237 }
238
234 index = init->outp->i2c_index; 239 index = init->outp->i2c_index;
235 } 240 }
236 241
@@ -258,7 +263,7 @@ init_wri2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg, u8 val)
258static int 263static int
259init_rdauxr(struct nvbios_init *init, u32 addr) 264init_rdauxr(struct nvbios_init *init, u32 addr)
260{ 265{
261 struct nouveau_i2c_port *port = init_i2c(init, -1); 266 struct nouveau_i2c_port *port = init_i2c(init, -2);
262 u8 data; 267 u8 data;
263 268
264 if (port && init_exec(init)) { 269 if (port && init_exec(init)) {
@@ -274,7 +279,7 @@ init_rdauxr(struct nvbios_init *init, u32 addr)
274static int 279static int
275init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) 280init_wrauxr(struct nvbios_init *init, u32 addr, u8 data)
276{ 281{
277 struct nouveau_i2c_port *port = init_i2c(init, -1); 282 struct nouveau_i2c_port *port = init_i2c(init, -2);
278 if (port && init_exec(init)) 283 if (port && init_exec(init))
279 return nv_wraux(port, addr, &data, 1); 284 return nv_wraux(port, addr, &data, 1);
280 return -ENODEV; 285 return -ENODEV;
@@ -1816,7 +1821,7 @@ init_ram_restrict_zm_reg_group(struct nvbios_init *init)
1816 u8 i, j; 1821 u8 i, j;
1817 1822
1818 trace("RAM_RESTRICT_ZM_REG_GROUP\t" 1823 trace("RAM_RESTRICT_ZM_REG_GROUP\t"
1819 "R[%08x] 0x%02x 0x%02x\n", addr, incr, num); 1824 "R[0x%08x] 0x%02x 0x%02x\n", addr, incr, num);
1820 init->offset += 7; 1825 init->offset += 7;
1821 1826
1822 for (i = 0; i < num; i++) { 1827 for (i = 0; i < num; i++) {
@@ -1849,7 +1854,7 @@ init_copy_zm_reg(struct nvbios_init *init)
1849 u32 sreg = nv_ro32(bios, init->offset + 1); 1854 u32 sreg = nv_ro32(bios, init->offset + 1);
1850 u32 dreg = nv_ro32(bios, init->offset + 5); 1855 u32 dreg = nv_ro32(bios, init->offset + 5);
1851 1856
1852 trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", sreg, dreg); 1857 trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", dreg, sreg);
1853 init->offset += 9; 1858 init->offset += 9;
1854 1859
1855 init_wr32(init, dreg, init_rd32(init, sreg)); 1860 init_wr32(init, dreg, init_rd32(init, sreg));
@@ -1866,7 +1871,7 @@ init_zm_reg_group(struct nvbios_init *init)
1866 u32 addr = nv_ro32(bios, init->offset + 1); 1871 u32 addr = nv_ro32(bios, init->offset + 1);
1867 u8 count = nv_ro08(bios, init->offset + 5); 1872 u8 count = nv_ro08(bios, init->offset + 5);
1868 1873
1869 trace("ZM_REG_GROUP\tR[0x%06x] =\n"); 1874 trace("ZM_REG_GROUP\tR[0x%06x] =\n", addr);
1870 init->offset += 6; 1875 init->offset += 6;
1871 1876
1872 while (count--) { 1877 while (count--) {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
index 862a08a2ae27..22a20573ed1b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
@@ -55,7 +55,7 @@ therm_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
55 return therm + nv_ro08(bios, therm + 1); 55 return therm + nv_ro08(bios, therm + 1);
56} 56}
57 57
58u16 58static u16
59nvbios_therm_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) 59nvbios_therm_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
60{ 60{
61 u8 hdr, cnt; 61 u8 hdr, cnt;
@@ -155,10 +155,15 @@ int
155nvbios_therm_fan_parse(struct nouveau_bios *bios, 155nvbios_therm_fan_parse(struct nouveau_bios *bios,
156 struct nvbios_therm_fan *fan) 156 struct nvbios_therm_fan *fan)
157{ 157{
158 struct nouveau_therm_trip_point *cur_trip = NULL;
158 u8 ver, len, i; 159 u8 ver, len, i;
159 u16 entry; 160 u16 entry;
160 161
162 uint8_t duty_lut[] = { 0, 0, 25, 0, 40, 0, 50, 0,
163 75, 0, 85, 0, 100, 0, 100, 0 };
164
161 i = 0; 165 i = 0;
166 fan->nr_fan_trip = 0;
162 while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { 167 while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) {
163 s16 value = nv_ro16(bios, entry + 1); 168 s16 value = nv_ro16(bios, entry + 1);
164 169
@@ -167,9 +172,30 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,
167 fan->min_duty = value & 0xff; 172 fan->min_duty = value & 0xff;
168 fan->max_duty = (value & 0xff00) >> 8; 173 fan->max_duty = (value & 0xff00) >> 8;
169 break; 174 break;
175 case 0x24:
176 fan->nr_fan_trip++;
177 cur_trip = &fan->trip[fan->nr_fan_trip - 1];
178 cur_trip->hysteresis = value & 0xf;
179 cur_trip->temp = (value & 0xff0) >> 4;
180 cur_trip->fan_duty = duty_lut[(value & 0xf000) >> 12];
181 break;
182 case 0x25:
183 cur_trip = &fan->trip[fan->nr_fan_trip - 1];
184 cur_trip->fan_duty = value;
185 break;
170 case 0x26: 186 case 0x26:
171 fan->pwm_freq = value; 187 fan->pwm_freq = value;
172 break; 188 break;
189 case 0x3b:
190 fan->bump_period = value;
191 break;
192 case 0x3c:
193 fan->slow_down_period = value;
194 break;
195 case 0x46:
196 fan->linear_min_temp = nv_ro08(bios, entry + 1);
197 fan->linear_max_temp = nv_ro08(bios, entry + 2);
198 break;
173 } 199 }
174 } 200 }
175 201
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c
new file mode 100644
index 000000000000..e9b8e5d30a7a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/bios.h>
26#include <subdev/bios/gpio.h>
27#include <subdev/bios/xpio.h>
28
29static u16
30dcb_xpiod_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
31{
32 u16 data = dcb_gpio_table(bios, ver, hdr, cnt, len);
33 if (data && *ver >= 0x40 && *hdr >= 0x06) {
34 u16 xpio = nv_ro16(bios, data + 0x04);
35 if (xpio) {
36 *ver = nv_ro08(bios, data + 0x00);
37 *hdr = nv_ro08(bios, data + 0x01);
38 *cnt = nv_ro08(bios, data + 0x02);
39 *len = nv_ro08(bios, data + 0x03);
40 return xpio;
41 }
42 }
43 return 0x0000;
44}
45
46u16
47dcb_xpio_table(struct nouveau_bios *bios, u8 idx,
48 u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
49{
50 u16 data = dcb_xpiod_table(bios, ver, hdr, cnt, len);
51 if (data && idx < *cnt) {
52 u16 xpio = nv_ro16(bios, data + *hdr + (idx * *len));
53 if (xpio) {
54 *ver = nv_ro08(bios, data + 0x00);
55 *hdr = nv_ro08(bios, data + 0x01);
56 *cnt = nv_ro08(bios, data + 0x02);
57 *len = nv_ro08(bios, data + 0x03);
58 return xpio;
59 }
60 }
61 return 0x0000;
62}
63
64u16
65dcb_xpio_parse(struct nouveau_bios *bios, u8 idx,
66 u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
67 struct nvbios_xpio *info)
68{
69 u16 data = dcb_xpio_table(bios, idx, ver, hdr, cnt, len);
70 if (data && *len >= 6) {
71 info->type = nv_ro08(bios, data + 0x04);
72 info->addr = nv_ro08(bios, data + 0x05);
73 info->flags = nv_ro08(bios, data + 0x06);
74 }
75 return 0x0000;
76}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c
new file mode 100644
index 000000000000..8c7f8057a185
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright 2012 Nouveau Community
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Martin Peres <martin.peres@labri.fr>
23 * Ben Skeggs
24 */
25
26#include <subdev/bus.h>
27
28struct nv04_bus_priv {
29 struct nouveau_bus base;
30};
31
32static void
33nv04_bus_intr(struct nouveau_subdev *subdev)
34{
35 struct nouveau_bus *pbus = nouveau_bus(subdev);
36 u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140);
37
38 if (stat & 0x00000001) {
39 nv_error(pbus, "BUS ERROR\n");
40 stat &= ~0x00000001;
41 nv_wr32(pbus, 0x001100, 0x00000001);
42 }
43
44 if (stat & 0x00000110) {
45 subdev = nouveau_subdev(subdev, NVDEV_SUBDEV_GPIO);
46 if (subdev && subdev->intr)
47 subdev->intr(subdev);
48 stat &= ~0x00000110;
49 nv_wr32(pbus, 0x001100, 0x00000110);
50 }
51
52 if (stat) {
53 nv_error(pbus, "unknown intr 0x%08x\n", stat);
54 nv_mask(pbus, 0x001140, stat, 0x00000000);
55 }
56}
57
58static int
59nv04_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
60 struct nouveau_oclass *oclass, void *data, u32 size,
61 struct nouveau_object **pobject)
62{
63 struct nv04_bus_priv *priv;
64 int ret;
65
66 ret = nouveau_bus_create(parent, engine, oclass, &priv);
67 *pobject = nv_object(priv);
68 if (ret)
69 return ret;
70
71 nv_subdev(priv)->intr = nv04_bus_intr;
72 return 0;
73}
74
75static int
76nv04_bus_init(struct nouveau_object *object)
77{
78 struct nv04_bus_priv *priv = (void *)object;
79
80 nv_wr32(priv, 0x001100, 0xffffffff);
81 nv_wr32(priv, 0x001140, 0x00000111);
82
83 return nouveau_bus_init(&priv->base);
84}
85
86struct nouveau_oclass
87nv04_bus_oclass = {
88 .handle = NV_SUBDEV(BUS, 0x04),
89 .ofuncs = &(struct nouveau_ofuncs) {
90 .ctor = nv04_bus_ctor,
91 .dtor = _nouveau_bus_dtor,
92 .init = nv04_bus_init,
93 .fini = _nouveau_bus_fini,
94 },
95};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c
new file mode 100644
index 000000000000..34132aef34e1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c
@@ -0,0 +1,112 @@
1/*
2 * Copyright 2012 Nouveau Community
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Martin Peres <martin.peres@labri.fr>
23 * Ben Skeggs
24 */
25
26#include <subdev/bus.h>
27
28struct nv31_bus_priv {
29 struct nouveau_bus base;
30};
31
32static void
33nv31_bus_intr(struct nouveau_subdev *subdev)
34{
35 struct nouveau_bus *pbus = nouveau_bus(subdev);
36 u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140);
37 u32 gpio = nv_rd32(pbus, 0x001104) & nv_rd32(pbus, 0x001144);
38
39 if (gpio) {
40 subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_GPIO);
41 if (subdev && subdev->intr)
42 subdev->intr(subdev);
43 }
44
45 if (stat & 0x00000008) { /* NV41- */
46 u32 addr = nv_rd32(pbus, 0x009084);
47 u32 data = nv_rd32(pbus, 0x009088);
48
49 nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n",
50 (addr & 0x00000002) ? "write" : "read", data,
51 (addr & 0x00fffffc));
52
53 stat &= ~0x00000008;
54 nv_wr32(pbus, 0x001100, 0x00000008);
55 }
56
57 if (stat & 0x00070000) {
58 subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_THERM);
59 if (subdev && subdev->intr)
60 subdev->intr(subdev);
61 stat &= ~0x00070000;
62 nv_wr32(pbus, 0x001100, 0x00070000);
63 }
64
65 if (stat) {
66 nv_error(pbus, "unknown intr 0x%08x\n", stat);
67 nv_mask(pbus, 0x001140, stat, 0x00000000);
68 }
69}
70
71static int
72nv31_bus_init(struct nouveau_object *object)
73{
74 struct nv31_bus_priv *priv = (void *)object;
75 int ret;
76
77 ret = nouveau_bus_init(&priv->base);
78 if (ret)
79 return ret;
80
81 nv_wr32(priv, 0x001100, 0xffffffff);
82 nv_wr32(priv, 0x001140, 0x00070008);
83 return 0;
84}
85
86static int
87nv31_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
88 struct nouveau_oclass *oclass, void *data, u32 size,
89 struct nouveau_object **pobject)
90{
91 struct nv31_bus_priv *priv;
92 int ret;
93
94 ret = nouveau_bus_create(parent, engine, oclass, &priv);
95 *pobject = nv_object(priv);
96 if (ret)
97 return ret;
98
99 nv_subdev(priv)->intr = nv31_bus_intr;
100 return 0;
101}
102
103struct nouveau_oclass
104nv31_bus_oclass = {
105 .handle = NV_SUBDEV(BUS, 0x31),
106 .ofuncs = &(struct nouveau_ofuncs) {
107 .ctor = nv31_bus_ctor,
108 .dtor = _nouveau_bus_dtor,
109 .init = nv31_bus_init,
110 .fini = _nouveau_bus_fini,
111 },
112};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c
new file mode 100644
index 000000000000..f5b2117fa8c6
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright 2012 Nouveau Community
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Martin Peres <martin.peres@labri.fr>
23 * Ben Skeggs
24 */
25
26#include <subdev/bus.h>
27
28struct nv50_bus_priv {
29 struct nouveau_bus base;
30};
31
32static void
33nv50_bus_intr(struct nouveau_subdev *subdev)
34{
35 struct nouveau_bus *pbus = nouveau_bus(subdev);
36 u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140);
37
38 if (stat & 0x00000008) {
39 u32 addr = nv_rd32(pbus, 0x009084);
40 u32 data = nv_rd32(pbus, 0x009088);
41
42 nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n",
43 (addr & 0x00000002) ? "write" : "read", data,
44 (addr & 0x00fffffc));
45
46 stat &= ~0x00000008;
47 nv_wr32(pbus, 0x001100, 0x00000008);
48 }
49
50 if (stat & 0x00010000) {
51 subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_THERM);
52 if (subdev && subdev->intr)
53 subdev->intr(subdev);
54 stat &= ~0x00010000;
55 nv_wr32(pbus, 0x001100, 0x00010000);
56 }
57
58 if (stat) {
59 nv_error(pbus, "unknown intr 0x%08x\n", stat);
60 nv_mask(pbus, 0x001140, stat, 0);
61 }
62}
63
64static int
65nv50_bus_init(struct nouveau_object *object)
66{
67 struct nv50_bus_priv *priv = (void *)object;
68 int ret;
69
70 ret = nouveau_bus_init(&priv->base);
71 if (ret)
72 return ret;
73
74 nv_wr32(priv, 0x001100, 0xffffffff);
75 nv_wr32(priv, 0x001140, 0x00010008);
76 return 0;
77}
78
79static int
80nv50_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
81 struct nouveau_oclass *oclass, void *data, u32 size,
82 struct nouveau_object **pobject)
83{
84 struct nv50_bus_priv *priv;
85 int ret;
86
87 ret = nouveau_bus_create(parent, engine, oclass, &priv);
88 *pobject = nv_object(priv);
89 if (ret)
90 return ret;
91
92 nv_subdev(priv)->intr = nv50_bus_intr;
93 return 0;
94}
95
96struct nouveau_oclass
97nv50_bus_oclass = {
98 .handle = NV_SUBDEV(BUS, 0x50),
99 .ofuncs = &(struct nouveau_ofuncs) {
100 .ctor = nv50_bus_ctor,
101 .dtor = _nouveau_bus_dtor,
102 .init = nv50_bus_init,
103 .fini = _nouveau_bus_fini,
104 },
105};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c
new file mode 100644
index 000000000000..b192d6246363
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c
@@ -0,0 +1,101 @@
1/*
2 * Copyright 2012 Nouveau Community
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Martin Peres <martin.peres@labri.fr>
23 * Ben Skeggs
24 */
25
26#include <subdev/bus.h>
27
28struct nvc0_bus_priv {
29 struct nouveau_bus base;
30};
31
32static void
33nvc0_bus_intr(struct nouveau_subdev *subdev)
34{
35 struct nouveau_bus *pbus = nouveau_bus(subdev);
36 u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140);
37
38 if (stat & 0x0000000e) {
39 u32 addr = nv_rd32(pbus, 0x009084);
40 u32 data = nv_rd32(pbus, 0x009088);
41
42 nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x [ %s%s%s]\n",
43 (addr & 0x00000002) ? "write" : "read", data,
44 (addr & 0x00fffffc),
45 (stat & 0x00000002) ? "!ENGINE " : "",
46 (stat & 0x00000004) ? "IBUS " : "",
47 (stat & 0x00000008) ? "TIMEOUT " : "");
48
49 nv_wr32(pbus, 0x009084, 0x00000000);
50 nv_wr32(pbus, 0x001100, (stat & 0x0000000e));
51 stat &= ~0x0000000e;
52 }
53
54 if (stat) {
55 nv_error(pbus, "unknown intr 0x%08x\n", stat);
56 nv_mask(pbus, 0x001140, stat, 0x00000000);
57 }
58}
59
60static int
61nvc0_bus_init(struct nouveau_object *object)
62{
63 struct nvc0_bus_priv *priv = (void *)object;
64 int ret;
65
66 ret = nouveau_bus_init(&priv->base);
67 if (ret)
68 return ret;
69
70 nv_wr32(priv, 0x001100, 0xffffffff);
71 nv_wr32(priv, 0x001140, 0x0000000e);
72 return 0;
73}
74
75static int
76nvc0_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
77 struct nouveau_oclass *oclass, void *data, u32 size,
78 struct nouveau_object **pobject)
79{
80 struct nvc0_bus_priv *priv;
81 int ret;
82
83 ret = nouveau_bus_create(parent, engine, oclass, &priv);
84 *pobject = nv_object(priv);
85 if (ret)
86 return ret;
87
88 nv_subdev(priv)->intr = nvc0_bus_intr;
89 return 0;
90}
91
92struct nouveau_oclass
93nvc0_bus_oclass = {
94 .handle = NV_SUBDEV(BUS, 0xc0),
95 .ofuncs = &(struct nouveau_ofuncs) {
96 .ctor = nvc0_bus_ctor,
97 .dtor = _nouveau_bus_dtor,
98 .init = nvc0_bus_init,
99 .fini = _nouveau_bus_fini,
100 },
101};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c
index f8a7ed4166cf..3937ced5c753 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c
@@ -66,6 +66,7 @@ static const u64 disable_map[] = {
66 [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, 66 [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE,
67 [NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE, 67 [NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE,
68 [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE, 68 [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE,
69 [NVDEV_SUBDEV_BUS] = NV_DEVICE_DISABLE_CORE,
69 [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE, 70 [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE,
70 [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE, 71 [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE,
71 [NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE, 72 [NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE,
@@ -103,8 +104,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
103 struct nouveau_device *device; 104 struct nouveau_device *device;
104 struct nouveau_devobj *devobj; 105 struct nouveau_devobj *devobj;
105 struct nv_device_class *args = data; 106 struct nv_device_class *args = data;
106 u64 disable, boot0, strap; 107 u32 boot0, strap;
107 u64 mmio_base, mmio_size; 108 u64 disable, mmio_base, mmio_size;
108 void __iomem *map; 109 void __iomem *map;
109 int ret, i, c; 110 int ret, i, c;
110 111
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c
index 8626d0d6cbbc..473c5c03d3c9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/i2c.h> 28#include <subdev/i2c.h>
28#include <subdev/clock.h> 29#include <subdev/clock.h>
29#include <subdev/devinit.h> 30#include <subdev/devinit.h>
@@ -46,10 +47,11 @@ nv04_identify(struct nouveau_device *device)
46 case 0x04: 47 case 0x04:
47 device->cname = "NV04"; 48 device->cname = "NV04";
48 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 49 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
49 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 50 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
50 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 51 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
51 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; 52 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
52 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 53 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
54 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
53 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 55 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
54 device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; 56 device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass;
55 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 57 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -63,10 +65,11 @@ nv04_identify(struct nouveau_device *device)
63 case 0x05: 65 case 0x05:
64 device->cname = "NV05"; 66 device->cname = "NV05";
65 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 67 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
66 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 68 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
67 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 69 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
68 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; 70 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
69 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 71 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
72 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
70 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 73 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
71 device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; 74 device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass;
72 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 75 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
index 9c40b0fb23f6..d0774f5bebe1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/gpio.h> 28#include <subdev/gpio.h>
28#include <subdev/i2c.h> 29#include <subdev/i2c.h>
29#include <subdev/clock.h> 30#include <subdev/clock.h>
@@ -48,10 +49,11 @@ nv10_identify(struct nouveau_device *device)
48 device->cname = "NV10"; 49 device->cname = "NV10";
49 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 50 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
50 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 51 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
51 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 52 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
52 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 53 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
53 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 54 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
54 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 55 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
56 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
55 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 57 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
56 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 58 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
57 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 59 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -64,10 +66,11 @@ nv10_identify(struct nouveau_device *device)
64 device->cname = "NV15"; 66 device->cname = "NV15";
65 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 67 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
66 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 68 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
67 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 69 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
68 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 70 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
69 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 71 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
70 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 72 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
73 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
71 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 74 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
72 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 75 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
73 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 76 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -82,10 +85,11 @@ nv10_identify(struct nouveau_device *device)
82 device->cname = "NV16"; 85 device->cname = "NV16";
83 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
84 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
85 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 88 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
86 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
87 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 90 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
88 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 91 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
92 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
89 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 93 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
90 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 94 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
91 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 95 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -100,10 +104,11 @@ nv10_identify(struct nouveau_device *device)
100 device->cname = "nForce"; 104 device->cname = "nForce";
101 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 105 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
102 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 106 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
103 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 107 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
104 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 108 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
105 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 109 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
106 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 110 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
111 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
107 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 112 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
108 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass; 113 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass;
109 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 114 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -118,10 +123,11 @@ nv10_identify(struct nouveau_device *device)
118 device->cname = "NV11"; 123 device->cname = "NV11";
119 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 124 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
120 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 125 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
121 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 126 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
122 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 127 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
123 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 128 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
124 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 129 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
130 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
125 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 131 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
126 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 132 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
127 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 133 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -136,10 +142,11 @@ nv10_identify(struct nouveau_device *device)
136 device->cname = "NV17"; 142 device->cname = "NV17";
137 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 143 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
138 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 144 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
139 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 145 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
140 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 146 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
141 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 147 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
142 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 148 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
149 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
143 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 150 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
144 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 151 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
145 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 152 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -154,10 +161,11 @@ nv10_identify(struct nouveau_device *device)
154 device->cname = "nForce2"; 161 device->cname = "nForce2";
155 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 162 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
156 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 163 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
157 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 164 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
158 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 165 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
159 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 166 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
160 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 167 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
168 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
161 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 169 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
162 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass; 170 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass;
163 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 171 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -172,10 +180,11 @@ nv10_identify(struct nouveau_device *device)
172 device->cname = "NV18"; 180 device->cname = "NV18";
173 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 181 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
174 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 182 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
175 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 183 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
176 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 184 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
177 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 185 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
178 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 186 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
187 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
179 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 188 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
180 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 189 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
181 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 190 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c
index 74f88f48e1c2..ab920e0dc45b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/gpio.h> 28#include <subdev/gpio.h>
28#include <subdev/i2c.h> 29#include <subdev/i2c.h>
29#include <subdev/clock.h> 30#include <subdev/clock.h>
@@ -49,10 +50,11 @@ nv20_identify(struct nouveau_device *device)
49 device->cname = "NV20"; 50 device->cname = "NV20";
50 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 51 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
51 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 52 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
52 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 53 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
53 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 54 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
54 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 55 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
55 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 56 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
57 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
56 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 58 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
57 device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; 59 device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass;
58 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 60 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -67,10 +69,11 @@ nv20_identify(struct nouveau_device *device)
67 device->cname = "NV25"; 69 device->cname = "NV25";
68 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 70 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
69 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 71 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
70 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 72 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
71 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 73 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
72 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 74 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
73 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 75 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
76 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
74 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 77 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
75 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; 78 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass;
76 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 79 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -85,10 +88,11 @@ nv20_identify(struct nouveau_device *device)
85 device->cname = "NV28"; 88 device->cname = "NV28";
86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 89 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 90 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
88 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 91 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 92 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
90 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 93 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
91 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 94 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
95 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
92 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 96 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
93 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; 97 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass;
94 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 98 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -103,10 +107,11 @@ nv20_identify(struct nouveau_device *device)
103 device->cname = "NV2A"; 107 device->cname = "NV2A";
104 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 108 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
105 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 109 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
106 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 110 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
107 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 111 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
108 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 112 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
109 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 113 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
114 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
110 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 115 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
111 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; 116 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass;
112 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 117 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c
index 0ac1b2c4f61d..5f2110261b04 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/gpio.h> 28#include <subdev/gpio.h>
28#include <subdev/i2c.h> 29#include <subdev/i2c.h>
29#include <subdev/clock.h> 30#include <subdev/clock.h>
@@ -49,10 +50,11 @@ nv30_identify(struct nouveau_device *device)
49 device->cname = "NV30"; 50 device->cname = "NV30";
50 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 51 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
51 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 52 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
52 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 53 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
53 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 54 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
54 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 55 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
55 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 56 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
57 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
56 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 58 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
57 device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; 59 device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
58 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 60 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -67,10 +69,11 @@ nv30_identify(struct nouveau_device *device)
67 device->cname = "NV35"; 69 device->cname = "NV35";
68 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 70 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
69 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 71 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
70 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 72 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
71 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 73 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
72 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 74 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
73 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 75 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
76 device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass;
74 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 77 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
75 device->oclass[NVDEV_SUBDEV_FB ] = &nv35_fb_oclass; 78 device->oclass[NVDEV_SUBDEV_FB ] = &nv35_fb_oclass;
76 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 79 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -85,10 +88,11 @@ nv30_identify(struct nouveau_device *device)
85 device->cname = "NV31"; 88 device->cname = "NV31";
86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 89 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 90 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
88 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 91 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 92 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
90 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 93 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
91 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 94 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
95 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
92 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 96 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
93 device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; 97 device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass;
94 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 98 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -104,10 +108,11 @@ nv30_identify(struct nouveau_device *device)
104 device->cname = "NV36"; 108 device->cname = "NV36";
105 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 109 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
106 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 110 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
107 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 111 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
108 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 112 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
109 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 113 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
110 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 114 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
115 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
111 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 116 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
112 device->oclass[NVDEV_SUBDEV_FB ] = &nv36_fb_oclass; 117 device->oclass[NVDEV_SUBDEV_FB ] = &nv36_fb_oclass;
113 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 118 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
@@ -123,10 +128,11 @@ nv30_identify(struct nouveau_device *device)
123 device->cname = "NV34"; 128 device->cname = "NV34";
124 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 129 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
125 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 130 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
126 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 131 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
127 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 132 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
128 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 133 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
129 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 134 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
135 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
130 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 136 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
131 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 137 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass;
132 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; 138 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
index 41d59689a021..f3d55efe9ac9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
@@ -24,6 +24,8 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
28#include <subdev/vm.h>
27#include <subdev/gpio.h> 29#include <subdev/gpio.h>
28#include <subdev/i2c.h> 30#include <subdev/i2c.h>
29#include <subdev/clock.h> 31#include <subdev/clock.h>
@@ -50,11 +52,12 @@ nv40_identify(struct nouveau_device *device)
50 device->cname = "NV40"; 52 device->cname = "NV40";
51 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 53 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
52 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 54 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
53 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 55 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
54 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 56 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
55 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 57 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
56 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 58 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
57 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 59 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
60 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
58 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 61 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
59 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 62 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
60 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 63 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -70,11 +73,12 @@ nv40_identify(struct nouveau_device *device)
70 device->cname = "NV41"; 73 device->cname = "NV41";
71 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 74 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
72 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 75 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
73 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 76 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
74 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 77 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
75 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 78 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
76 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 79 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
77 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 80 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
81 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
78 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 82 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
79 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; 83 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass;
80 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 84 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -90,11 +94,12 @@ nv40_identify(struct nouveau_device *device)
90 device->cname = "NV42"; 94 device->cname = "NV42";
91 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 95 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
92 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 96 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
93 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 97 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
94 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 98 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
95 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 99 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
96 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 100 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
97 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 101 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
102 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
98 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 103 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
99 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; 104 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass;
100 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 105 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -110,11 +115,12 @@ nv40_identify(struct nouveau_device *device)
110 device->cname = "NV43"; 115 device->cname = "NV43";
111 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 116 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
112 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 117 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
113 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 118 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
114 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 119 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
115 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 120 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
116 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 121 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
117 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 122 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
123 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
118 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 124 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
119 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; 125 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass;
120 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 126 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -130,11 +136,12 @@ nv40_identify(struct nouveau_device *device)
130 device->cname = "NV45"; 136 device->cname = "NV45";
131 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 137 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
132 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 138 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
133 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 139 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
134 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 140 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
135 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 141 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
136 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 142 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
137 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 143 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
144 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
138 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 145 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
139 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 146 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
140 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 147 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -150,11 +157,12 @@ nv40_identify(struct nouveau_device *device)
150 device->cname = "G70"; 157 device->cname = "G70";
151 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 158 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
152 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 159 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
153 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 160 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
154 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 161 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
155 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 162 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
156 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 163 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
157 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 164 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
165 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
158 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 166 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
159 device->oclass[NVDEV_SUBDEV_FB ] = &nv47_fb_oclass; 167 device->oclass[NVDEV_SUBDEV_FB ] = &nv47_fb_oclass;
160 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 168 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -170,11 +178,12 @@ nv40_identify(struct nouveau_device *device)
170 device->cname = "G71"; 178 device->cname = "G71";
171 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 179 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
172 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 180 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
173 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 181 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
174 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 182 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
175 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 183 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
176 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 184 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
177 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 185 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
186 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
178 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 187 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
179 device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass; 188 device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass;
180 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 189 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -190,11 +199,12 @@ nv40_identify(struct nouveau_device *device)
190 device->cname = "G73"; 199 device->cname = "G73";
191 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 200 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
192 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 201 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
193 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 202 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
194 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 203 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
195 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 204 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
196 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 205 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
197 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 206 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
207 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
198 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 208 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
199 device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass; 209 device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass;
200 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 210 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -210,11 +220,12 @@ nv40_identify(struct nouveau_device *device)
210 device->cname = "NV44"; 220 device->cname = "NV44";
211 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 221 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
212 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 222 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
213 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 223 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
214 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 224 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
215 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 225 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
216 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 226 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
217 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 227 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
228 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
218 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 229 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
219 device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass; 230 device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass;
220 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 231 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -230,11 +241,12 @@ nv40_identify(struct nouveau_device *device)
230 device->cname = "G72"; 241 device->cname = "G72";
231 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 242 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
232 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 243 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
233 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 244 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
234 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 245 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
235 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 246 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
236 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 247 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
237 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 248 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
249 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
238 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 250 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
239 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 251 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass;
240 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 252 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -250,11 +262,12 @@ nv40_identify(struct nouveau_device *device)
250 device->cname = "NV44A"; 262 device->cname = "NV44A";
251 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 263 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
252 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 264 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
253 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 265 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
254 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 266 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
255 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 267 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
256 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 268 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
257 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 269 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
270 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
258 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 271 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
259 device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass; 272 device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass;
260 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 273 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -270,11 +283,12 @@ nv40_identify(struct nouveau_device *device)
270 device->cname = "C61"; 283 device->cname = "C61";
271 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 284 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
272 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 285 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
273 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 286 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
274 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 287 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
275 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 288 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
276 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 289 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
277 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 290 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
291 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
278 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 292 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
279 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 293 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass;
280 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 294 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -290,11 +304,12 @@ nv40_identify(struct nouveau_device *device)
290 device->cname = "C51"; 304 device->cname = "C51";
291 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 305 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
292 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 306 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
293 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 307 device->oclass[NVDEV_SUBDEV_I2C ] = &nv4e_i2c_oclass;
294 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 308 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
295 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 309 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
296 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 310 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
297 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 311 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
312 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
298 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 313 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
299 device->oclass[NVDEV_SUBDEV_FB ] = &nv4e_fb_oclass; 314 device->oclass[NVDEV_SUBDEV_FB ] = &nv4e_fb_oclass;
300 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 315 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -310,11 +325,12 @@ nv40_identify(struct nouveau_device *device)
310 device->cname = "C73"; 325 device->cname = "C73";
311 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 326 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
312 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 327 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
313 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 328 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
314 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 329 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
315 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 330 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
316 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 331 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
317 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 332 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
333 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
318 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 334 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
319 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 335 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass;
320 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 336 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -330,11 +346,12 @@ nv40_identify(struct nouveau_device *device)
330 device->cname = "C67"; 346 device->cname = "C67";
331 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 347 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
332 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 348 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
333 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 349 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
334 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 350 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
335 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 351 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
336 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 352 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
337 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 353 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
354 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
338 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 355 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
339 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 356 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass;
340 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 357 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
@@ -350,11 +367,12 @@ nv40_identify(struct nouveau_device *device)
350 device->cname = "C68"; 367 device->cname = "C68";
351 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 368 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
352 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 369 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass;
353 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 370 device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass;
354 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 371 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
355 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 372 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
356 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 373 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
357 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 374 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
375 device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass;
358 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 376 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
359 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 377 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass;
360 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 378 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
index 6ccfd8585ba2..5ed2fa51ddc2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/gpio.h> 28#include <subdev/gpio.h>
28#include <subdev/i2c.h> 29#include <subdev/i2c.h>
29#include <subdev/clock.h> 30#include <subdev/clock.h>
@@ -57,12 +58,13 @@ nv50_identify(struct nouveau_device *device)
57 device->cname = "G80"; 58 device->cname = "G80";
58 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 59 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
59 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 60 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
60 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 61 device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
61 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 62 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
62 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 63 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
63 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 64 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
64 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 65 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
65 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 66 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
67 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
66 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 68 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
67 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 69 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
68 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 70 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -79,12 +81,13 @@ nv50_identify(struct nouveau_device *device)
79 device->cname = "G84"; 81 device->cname = "G84";
80 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 82 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
81 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 83 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
82 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 84 device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
83 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 85 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
84 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 86 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
85 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 87 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
86 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 88 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
87 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 89 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
90 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
88 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 91 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
89 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 92 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
90 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 93 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -104,12 +107,13 @@ nv50_identify(struct nouveau_device *device)
104 device->cname = "G86"; 107 device->cname = "G86";
105 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 108 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
106 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 109 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
107 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 110 device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
108 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 111 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
109 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 112 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
110 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 113 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
111 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 114 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
112 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 115 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
116 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
113 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 117 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
114 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 118 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
115 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 119 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -129,12 +133,13 @@ nv50_identify(struct nouveau_device *device)
129 device->cname = "G92"; 133 device->cname = "G92";
130 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 134 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
131 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 135 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
132 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 136 device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
133 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 137 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
134 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 138 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
135 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 139 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
136 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 140 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
137 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 141 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
142 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
138 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 143 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
139 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 144 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
140 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 145 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -154,12 +159,13 @@ nv50_identify(struct nouveau_device *device)
154 device->cname = "G94"; 159 device->cname = "G94";
155 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 160 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
156 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 161 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
157 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 162 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
158 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 163 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
159 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 164 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
160 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 165 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
161 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 166 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
162 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 167 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
168 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
163 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 169 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
164 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 170 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
165 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 171 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -179,12 +185,13 @@ nv50_identify(struct nouveau_device *device)
179 device->cname = "G96"; 185 device->cname = "G96";
180 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 186 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
181 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 187 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
182 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 188 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
183 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 189 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
184 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 190 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
185 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 191 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
186 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 192 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
187 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 193 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
194 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
188 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 195 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
189 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 196 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
190 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 197 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -204,12 +211,13 @@ nv50_identify(struct nouveau_device *device)
204 device->cname = "G98"; 211 device->cname = "G98";
205 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 212 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
206 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 213 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
207 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 214 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
208 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 215 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
209 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 216 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
210 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 217 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
211 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 218 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
212 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 219 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
220 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
213 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 221 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
214 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 222 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
215 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 223 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -229,12 +237,13 @@ nv50_identify(struct nouveau_device *device)
229 device->cname = "G200"; 237 device->cname = "G200";
230 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 238 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
231 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 239 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
232 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 240 device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass;
233 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 241 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
234 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 242 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
235 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 243 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
236 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 244 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
237 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 245 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
246 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
238 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 247 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
239 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 248 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
240 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 249 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -254,12 +263,13 @@ nv50_identify(struct nouveau_device *device)
254 device->cname = "MCP77/MCP78"; 263 device->cname = "MCP77/MCP78";
255 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 264 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
256 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 265 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
257 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 266 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
258 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 267 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
259 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 268 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
260 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 269 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
261 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 270 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
262 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 271 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
272 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
263 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 273 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
264 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 274 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
265 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 275 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -279,12 +289,13 @@ nv50_identify(struct nouveau_device *device)
279 device->cname = "MCP79/MCP7A"; 289 device->cname = "MCP79/MCP7A";
280 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 290 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
281 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 291 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
282 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 292 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
283 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 293 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
284 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 294 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
285 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 295 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
286 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 296 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
287 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 297 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
298 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
288 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 299 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
289 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 300 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
290 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 301 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -304,12 +315,13 @@ nv50_identify(struct nouveau_device *device)
304 device->cname = "GT215"; 315 device->cname = "GT215";
305 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 316 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
306 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 317 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
307 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 318 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
308 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 319 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
309 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 320 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
310 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 321 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
311 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 322 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
312 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 323 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
324 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
313 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 325 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
314 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 326 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
315 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 327 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -330,12 +342,13 @@ nv50_identify(struct nouveau_device *device)
330 device->cname = "GT216"; 342 device->cname = "GT216";
331 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 343 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
332 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 344 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
333 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 345 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
334 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 346 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
335 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 347 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
336 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 348 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
337 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 349 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
338 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 350 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
351 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
339 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 352 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
340 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 353 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
341 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 354 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -355,12 +368,13 @@ nv50_identify(struct nouveau_device *device)
355 device->cname = "GT218"; 368 device->cname = "GT218";
356 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 369 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
357 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 370 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
358 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 371 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
359 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 372 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
360 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 373 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
361 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 374 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
362 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 375 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
363 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 376 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
377 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
364 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 378 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
365 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 379 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
366 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 380 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
@@ -380,12 +394,13 @@ nv50_identify(struct nouveau_device *device)
380 device->cname = "MCP89"; 394 device->cname = "MCP89";
381 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 395 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
382 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 396 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
383 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 397 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
384 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 398 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
385 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 399 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
386 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 400 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
387 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 401 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
388 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 402 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
403 device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass;
389 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 404 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
390 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 405 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass;
391 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; 406 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c
index f0461685a422..4393eb4d6564 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/gpio.h> 28#include <subdev/gpio.h>
28#include <subdev/i2c.h> 29#include <subdev/i2c.h>
29#include <subdev/clock.h> 30#include <subdev/clock.h>
@@ -57,12 +58,13 @@ nvc0_identify(struct nouveau_device *device)
57 device->cname = "GF100"; 58 device->cname = "GF100";
58 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 59 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
59 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 60 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
60 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 61 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
61 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 62 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
62 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 63 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
63 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 64 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
64 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 65 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
65 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 66 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
67 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
66 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 68 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
67 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 69 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
68 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 70 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -85,12 +87,13 @@ nvc0_identify(struct nouveau_device *device)
85 device->cname = "GF104"; 87 device->cname = "GF104";
86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 88 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 89 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
88 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 90 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 91 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
90 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 92 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
91 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 93 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
92 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 94 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
93 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 95 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
96 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
94 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 97 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
95 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 98 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
96 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 99 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -113,12 +116,13 @@ nvc0_identify(struct nouveau_device *device)
113 device->cname = "GF106"; 116 device->cname = "GF106";
114 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 117 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
115 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 118 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
116 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 119 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
117 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 120 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
118 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 121 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
119 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 122 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
120 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 123 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
121 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 124 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
125 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
122 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 126 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
123 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 127 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
124 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 128 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -141,12 +145,13 @@ nvc0_identify(struct nouveau_device *device)
141 device->cname = "GF114"; 145 device->cname = "GF114";
142 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 146 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
143 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 147 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
144 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 148 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
145 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 149 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
146 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 150 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
147 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 151 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
148 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 152 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
149 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 153 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
154 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
150 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 155 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
151 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 156 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
152 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 157 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -169,12 +174,13 @@ nvc0_identify(struct nouveau_device *device)
169 device->cname = "GF116"; 174 device->cname = "GF116";
170 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 175 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
171 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 176 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
172 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 177 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
173 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 178 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
174 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 179 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
175 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 180 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
176 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 181 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
177 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 182 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
183 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
178 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 184 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
179 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 185 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
180 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 186 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -197,12 +203,13 @@ nvc0_identify(struct nouveau_device *device)
197 device->cname = "GF108"; 203 device->cname = "GF108";
198 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 204 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
199 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 205 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
200 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 206 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
201 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 207 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
202 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 208 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
203 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 209 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
204 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 210 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
205 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 211 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
212 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
206 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 213 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
207 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 214 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
208 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 215 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -225,12 +232,13 @@ nvc0_identify(struct nouveau_device *device)
225 device->cname = "GF110"; 232 device->cname = "GF110";
226 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 233 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
227 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 234 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass;
228 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 235 device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass;
229 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 236 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
230 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 237 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
231 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 238 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
232 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 239 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
233 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 240 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
241 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
234 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 242 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
235 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 243 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
236 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 244 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -253,12 +261,13 @@ nvc0_identify(struct nouveau_device *device)
253 device->cname = "GF119"; 261 device->cname = "GF119";
254 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 262 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
255 device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 263 device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass;
256 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 264 device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
257 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 265 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
258 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 266 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
259 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 267 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
260 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 268 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
261 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 269 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
270 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
262 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 271 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
263 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 272 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
264 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 273 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -282,4 +291,4 @@ nvc0_identify(struct nouveau_device *device)
282 } 291 }
283 292
284 return 0; 293 return 0;
285} 294 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
index 03a652876e73..5c12391619fd 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
@@ -24,6 +24,7 @@
24 24
25#include <subdev/device.h> 25#include <subdev/device.h>
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bus.h>
27#include <subdev/gpio.h> 28#include <subdev/gpio.h>
28#include <subdev/i2c.h> 29#include <subdev/i2c.h>
29#include <subdev/clock.h> 30#include <subdev/clock.h>
@@ -56,13 +57,14 @@ nve0_identify(struct nouveau_device *device)
56 case 0xe4: 57 case 0xe4:
57 device->cname = "GK104"; 58 device->cname = "GK104";
58 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 59 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
59 device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 60 device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass;
60 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 61 device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
61 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 62 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
62 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 63 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
63 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 64 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
64 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 65 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
65 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 66 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
67 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
66 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 68 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
67 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 69 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
68 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 70 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -84,13 +86,14 @@ nve0_identify(struct nouveau_device *device)
84 case 0xe7: 86 case 0xe7:
85 device->cname = "GK107"; 87 device->cname = "GK107";
86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 88 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 89 device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass;
88 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 90 device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 91 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
90 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 92 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
91 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 93 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
92 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 94 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
93 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 95 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
96 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
94 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 97 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
95 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 98 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
96 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 99 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
@@ -112,13 +115,14 @@ nve0_identify(struct nouveau_device *device)
112 case 0xe6: 115 case 0xe6:
113 device->cname = "GK106"; 116 device->cname = "GK106";
114 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 117 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
115 device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 118 device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass;
116 device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 119 device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
117 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 120 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
118 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 121 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
119 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 122 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
120 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 123 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
121 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 124 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
125 device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
122 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 126 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
123 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 127 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
124 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; 128 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
index ae7249b09797..4a8577838417 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
@@ -78,12 +78,13 @@ nv50_devinit_init(struct nouveau_object *object)
78 if (ret) 78 if (ret)
79 return ret; 79 return ret;
80 80
81 /* if we ran the init tables, execute first script pointer for each 81 /* if we ran the init tables, we have to execute the first script
82 * display table output entry that has a matching dcb entry. 82 * pointer of each dcb entry's display encoder table in order
83 * to properly initialise each encoder.
83 */ 84 */
84 while (priv->base.post && ver) { 85 while (priv->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
85 u16 data = nvbios_outp_parse(bios, i++, &ver, &hdr, &cnt, &len, &info); 86 if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
86 if (data && dcb_outp_match(bios, info.type, info.mask, &ver, &len, &outp)) { 87 &ver, &hdr, &cnt, &len, &info)) {
87 struct nvbios_init init = { 88 struct nvbios_init init = {
88 .subdev = nv_subdev(priv), 89 .subdev = nv_subdev(priv),
89 .bios = bios, 90 .bios = bios,
@@ -95,7 +96,8 @@ nv50_devinit_init(struct nouveau_object *object)
95 96
96 nvbios_exec(&init); 97 nvbios_exec(&init);
97 } 98 }
98 }; 99 i++;
100 }
99 101
100 return 0; 102 return 0;
101} 103}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index 487cb8c6c204..a4338d92b02e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -22,8 +22,10 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/object.h> 25#include <core/client.h>
26#include <core/enum.h> 26#include <core/enum.h>
27#include <core/engctx.h>
28#include <core/object.h>
27 29
28#include <subdev/fb.h> 30#include <subdev/fb.h>
29#include <subdev/bios.h> 31#include <subdev/bios.h>
@@ -302,17 +304,18 @@ static const struct nouveau_enum vm_client[] = {
302}; 304};
303 305
304static const struct nouveau_enum vm_engine[] = { 306static const struct nouveau_enum vm_engine[] = {
305 { 0x00000000, "PGRAPH", NULL }, 307 { 0x00000000, "PGRAPH", NULL, NVDEV_ENGINE_GR },
306 { 0x00000001, "PVP", NULL }, 308 { 0x00000001, "PVP", NULL, NVDEV_ENGINE_VP },
307 { 0x00000004, "PEEPHOLE", NULL }, 309 { 0x00000004, "PEEPHOLE", NULL },
308 { 0x00000005, "PFIFO", vm_pfifo_subclients }, 310 { 0x00000005, "PFIFO", vm_pfifo_subclients, NVDEV_ENGINE_FIFO },
309 { 0x00000006, "BAR", vm_bar_subclients }, 311 { 0x00000006, "BAR", vm_bar_subclients },
310 { 0x00000008, "PPPP", NULL }, 312 { 0x00000008, "PPPP", NULL, NVDEV_ENGINE_PPP },
311 { 0x00000009, "PBSP", NULL }, 313 { 0x00000008, "PMPEG", NULL, NVDEV_ENGINE_MPEG },
312 { 0x0000000a, "PCRYPT", NULL }, 314 { 0x00000009, "PBSP", NULL, NVDEV_ENGINE_BSP },
315 { 0x0000000a, "PCRYPT", NULL, NVDEV_ENGINE_CRYPT },
313 { 0x0000000b, "PCOUNTER", NULL }, 316 { 0x0000000b, "PCOUNTER", NULL },
314 { 0x0000000c, "SEMAPHORE_BG", NULL }, 317 { 0x0000000c, "SEMAPHORE_BG", NULL },
315 { 0x0000000d, "PCOPY", NULL }, 318 { 0x0000000d, "PCOPY", NULL, NVDEV_ENGINE_COPY0 },
316 { 0x0000000e, "PDAEMON", NULL }, 319 { 0x0000000e, "PDAEMON", NULL },
317 {} 320 {}
318}; 321};
@@ -334,8 +337,10 @@ static void
334nv50_fb_intr(struct nouveau_subdev *subdev) 337nv50_fb_intr(struct nouveau_subdev *subdev)
335{ 338{
336 struct nouveau_device *device = nv_device(subdev); 339 struct nouveau_device *device = nv_device(subdev);
340 struct nouveau_engine *engine;
337 struct nv50_fb_priv *priv = (void *)subdev; 341 struct nv50_fb_priv *priv = (void *)subdev;
338 const struct nouveau_enum *en, *cl; 342 const struct nouveau_enum *en, *cl;
343 struct nouveau_object *engctx = NULL;
339 u32 trap[6], idx, chan; 344 u32 trap[6], idx, chan;
340 u8 st0, st1, st2, st3; 345 u8 st0, st1, st2, st3;
341 int i; 346 int i;
@@ -366,36 +371,55 @@ nv50_fb_intr(struct nouveau_subdev *subdev)
366 } 371 }
367 chan = (trap[2] << 16) | trap[1]; 372 chan = (trap[2] << 16) | trap[1];
368 373
369 nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ", 374 en = nouveau_enum_find(vm_engine, st0);
375
376 if (en && en->data2) {
377 const struct nouveau_enum *orig_en = en;
378 while (en->name && en->value == st0 && en->data2) {
379 engine = nouveau_engine(subdev, en->data2);
380 if (engine) {
381 engctx = nouveau_engctx_get(engine, chan);
382 if (engctx)
383 break;
384 }
385 en++;
386 }
387 if (!engctx)
388 en = orig_en;
389 }
390
391 nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x [%s] ",
370 (trap[5] & 0x00000100) ? "read" : "write", 392 (trap[5] & 0x00000100) ? "read" : "write",
371 trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan); 393 trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan,
394 nouveau_client_name(engctx));
395
396 nouveau_engctx_put(engctx);
372 397
373 en = nouveau_enum_find(vm_engine, st0);
374 if (en) 398 if (en)
375 printk("%s/", en->name); 399 pr_cont("%s/", en->name);
376 else 400 else
377 printk("%02x/", st0); 401 pr_cont("%02x/", st0);
378 402
379 cl = nouveau_enum_find(vm_client, st2); 403 cl = nouveau_enum_find(vm_client, st2);
380 if (cl) 404 if (cl)
381 printk("%s/", cl->name); 405 pr_cont("%s/", cl->name);
382 else 406 else
383 printk("%02x/", st2); 407 pr_cont("%02x/", st2);
384 408
385 if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); 409 if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3);
386 else if (en && en->data) cl = nouveau_enum_find(en->data, st3); 410 else if (en && en->data) cl = nouveau_enum_find(en->data, st3);
387 else cl = NULL; 411 else cl = NULL;
388 if (cl) 412 if (cl)
389 printk("%s", cl->name); 413 pr_cont("%s", cl->name);
390 else 414 else
391 printk("%02x", st3); 415 pr_cont("%02x", st3);
392 416
393 printk(" reason: "); 417 pr_cont(" reason: ");
394 en = nouveau_enum_find(vm_fault, st1); 418 en = nouveau_enum_find(vm_fault, st1);
395 if (en) 419 if (en)
396 printk("%s\n", en->name); 420 pr_cont("%s\n", en->name);
397 else 421 else
398 printk("0x%08x\n", st1); 422 pr_cont("0x%08x\n", st1);
399} 423}
400 424
401static int 425static int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
index 9fb0f9b92d49..d422acc9af15 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
@@ -102,135 +102,19 @@ nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line)
102 return ret; 102 return ret;
103} 103}
104 104
105static int 105void
106nouveau_gpio_irq(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, bool on) 106_nouveau_gpio_dtor(struct nouveau_object *object)
107{
108 struct dcb_gpio_func func;
109 int ret;
110
111 ret = nouveau_gpio_find(gpio, idx, tag, line, &func);
112 if (ret == 0) {
113 if (idx == 0 && gpio->irq_enable)
114 gpio->irq_enable(gpio, func.line, on);
115 else
116 ret = -ENODEV;
117 }
118
119 return ret;
120}
121
122struct gpio_isr {
123 struct nouveau_gpio *gpio;
124 struct list_head head;
125 struct work_struct work;
126 int idx;
127 struct dcb_gpio_func func;
128 void (*handler)(void *, int);
129 void *data;
130 bool inhibit;
131};
132
133static void
134nouveau_gpio_isr_bh(struct work_struct *work)
135{
136 struct gpio_isr *isr = container_of(work, struct gpio_isr, work);
137 struct nouveau_gpio *gpio = isr->gpio;
138 unsigned long flags;
139 int state;
140
141 state = nouveau_gpio_get(gpio, isr->idx, isr->func.func,
142 isr->func.line);
143 if (state >= 0)
144 isr->handler(isr->data, state);
145
146 spin_lock_irqsave(&gpio->lock, flags);
147 isr->inhibit = false;
148 spin_unlock_irqrestore(&gpio->lock, flags);
149}
150
151static void
152nouveau_gpio_isr_run(struct nouveau_gpio *gpio, int idx, u32 line_mask)
153{
154 struct gpio_isr *isr;
155
156 if (idx != 0)
157 return;
158
159 spin_lock(&gpio->lock);
160 list_for_each_entry(isr, &gpio->isr, head) {
161 if (line_mask & (1 << isr->func.line)) {
162 if (isr->inhibit)
163 continue;
164 isr->inhibit = true;
165 schedule_work(&isr->work);
166 }
167 }
168 spin_unlock(&gpio->lock);
169}
170
171static int
172nouveau_gpio_isr_add(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line,
173 void (*handler)(void *, int), void *data)
174{
175 struct gpio_isr *isr;
176 unsigned long flags;
177 int ret;
178
179 isr = kzalloc(sizeof(*isr), GFP_KERNEL);
180 if (!isr)
181 return -ENOMEM;
182
183 ret = nouveau_gpio_find(gpio, idx, tag, line, &isr->func);
184 if (ret) {
185 kfree(isr);
186 return ret;
187 }
188
189 INIT_WORK(&isr->work, nouveau_gpio_isr_bh);
190 isr->gpio = gpio;
191 isr->handler = handler;
192 isr->data = data;
193 isr->idx = idx;
194
195 spin_lock_irqsave(&gpio->lock, flags);
196 list_add(&isr->head, &gpio->isr);
197 spin_unlock_irqrestore(&gpio->lock, flags);
198 return 0;
199}
200
201static void
202nouveau_gpio_isr_del(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line,
203 void (*handler)(void *, int), void *data)
204{ 107{
205 struct gpio_isr *isr, *tmp; 108 struct nouveau_gpio *gpio = (void *)object;
206 struct dcb_gpio_func func; 109 nouveau_event_destroy(&gpio->events);
207 unsigned long flags; 110 nouveau_subdev_destroy(&gpio->base);
208 LIST_HEAD(tofree);
209 int ret;
210
211 ret = nouveau_gpio_find(gpio, idx, tag, line, &func);
212 if (ret == 0) {
213 spin_lock_irqsave(&gpio->lock, flags);
214 list_for_each_entry_safe(isr, tmp, &gpio->isr, head) {
215 if (memcmp(&isr->func, &func, sizeof(func)) ||
216 isr->idx != idx ||
217 isr->handler != handler || isr->data != data)
218 continue;
219 list_move_tail(&isr->head, &tofree);
220 }
221 spin_unlock_irqrestore(&gpio->lock, flags);
222
223 list_for_each_entry_safe(isr, tmp, &tofree, head) {
224 flush_work(&isr->work);
225 kfree(isr);
226 }
227 }
228} 111}
229 112
230int 113int
231nouveau_gpio_create_(struct nouveau_object *parent, 114nouveau_gpio_create_(struct nouveau_object *parent,
232 struct nouveau_object *engine, 115 struct nouveau_object *engine,
233 struct nouveau_oclass *oclass, int length, void **pobject) 116 struct nouveau_oclass *oclass, int lines,
117 int length, void **pobject)
234{ 118{
235 struct nouveau_gpio *gpio; 119 struct nouveau_gpio *gpio;
236 int ret; 120 int ret;
@@ -241,15 +125,13 @@ nouveau_gpio_create_(struct nouveau_object *parent,
241 if (ret) 125 if (ret)
242 return ret; 126 return ret;
243 127
128 ret = nouveau_event_create(lines, &gpio->events);
129 if (ret)
130 return ret;
131
244 gpio->find = nouveau_gpio_find; 132 gpio->find = nouveau_gpio_find;
245 gpio->set = nouveau_gpio_set; 133 gpio->set = nouveau_gpio_set;
246 gpio->get = nouveau_gpio_get; 134 gpio->get = nouveau_gpio_get;
247 gpio->irq = nouveau_gpio_irq;
248 gpio->isr_run = nouveau_gpio_isr_run;
249 gpio->isr_add = nouveau_gpio_isr_add;
250 gpio->isr_del = nouveau_gpio_isr_del;
251 INIT_LIST_HEAD(&gpio->isr);
252 spin_lock_init(&gpio->lock);
253 return 0; 135 return 0;
254} 136}
255 137
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
index 168d16a9a8e9..76d5d5465ddd 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
@@ -24,7 +24,7 @@
24 * 24 *
25 */ 25 */
26 26
27#include <subdev/gpio.h> 27#include "priv.h"
28 28
29struct nv10_gpio_priv { 29struct nv10_gpio_priv {
30 struct nouveau_gpio base; 30 struct nouveau_gpio base;
@@ -83,27 +83,36 @@ nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
83} 83}
84 84
85static void 85static void
86nv10_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on)
87{
88 u32 mask = 0x00010001 << line;
89
90 nv_wr32(gpio, 0x001104, mask);
91 nv_mask(gpio, 0x001144, mask, on ? mask : 0);
92}
93
94static void
95nv10_gpio_intr(struct nouveau_subdev *subdev) 86nv10_gpio_intr(struct nouveau_subdev *subdev)
96{ 87{
97 struct nv10_gpio_priv *priv = (void *)subdev; 88 struct nv10_gpio_priv *priv = (void *)subdev;
98 u32 intr = nv_rd32(priv, 0x001104); 89 u32 intr = nv_rd32(priv, 0x001104);
99 u32 hi = (intr & 0x0000ffff) >> 0; 90 u32 hi = (intr & 0x0000ffff) >> 0;
100 u32 lo = (intr & 0xffff0000) >> 16; 91 u32 lo = (intr & 0xffff0000) >> 16;
92 int i;
101 93
102 priv->base.isr_run(&priv->base, 0, hi | lo); 94 for (i = 0; (hi | lo) && i < 32; i++) {
95 if ((hi | lo) & (1 << i))
96 nouveau_event_trigger(priv->base.events, i);
97 }
103 98
104 nv_wr32(priv, 0x001104, intr); 99 nv_wr32(priv, 0x001104, intr);
105} 100}
106 101
102static void
103nv10_gpio_intr_enable(struct nouveau_event *event, int line)
104{
105 nv_wr32(event->priv, 0x001104, 0x00010001 << line);
106 nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00010001 << line);
107}
108
109static void
110nv10_gpio_intr_disable(struct nouveau_event *event, int line)
111{
112 nv_wr32(event->priv, 0x001104, 0x00010001 << line);
113 nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00000000);
114}
115
107static int 116static int
108nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 117nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
109 struct nouveau_oclass *oclass, void *data, u32 size, 118 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -112,14 +121,16 @@ nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
112 struct nv10_gpio_priv *priv; 121 struct nv10_gpio_priv *priv;
113 int ret; 122 int ret;
114 123
115 ret = nouveau_gpio_create(parent, engine, oclass, &priv); 124 ret = nouveau_gpio_create(parent, engine, oclass, 16, &priv);
116 *pobject = nv_object(priv); 125 *pobject = nv_object(priv);
117 if (ret) 126 if (ret)
118 return ret; 127 return ret;
119 128
120 priv->base.drive = nv10_gpio_drive; 129 priv->base.drive = nv10_gpio_drive;
121 priv->base.sense = nv10_gpio_sense; 130 priv->base.sense = nv10_gpio_sense;
122 priv->base.irq_enable = nv10_gpio_irq_enable; 131 priv->base.events->priv = priv;
132 priv->base.events->enable = nv10_gpio_intr_enable;
133 priv->base.events->disable = nv10_gpio_intr_disable;
123 nv_subdev(priv)->intr = nv10_gpio_intr; 134 nv_subdev(priv)->intr = nv10_gpio_intr;
124 return 0; 135 return 0;
125} 136}
@@ -141,8 +152,6 @@ nv10_gpio_init(struct nouveau_object *object)
141 if (ret) 152 if (ret)
142 return ret; 153 return ret;
143 154
144 nv_wr32(priv, 0x001140, 0x00000000);
145 nv_wr32(priv, 0x001100, 0xffffffff);
146 nv_wr32(priv, 0x001144, 0x00000000); 155 nv_wr32(priv, 0x001144, 0x00000000);
147 nv_wr32(priv, 0x001104, 0xffffffff); 156 nv_wr32(priv, 0x001104, 0xffffffff);
148 return 0; 157 return 0;
@@ -152,7 +161,6 @@ static int
152nv10_gpio_fini(struct nouveau_object *object, bool suspend) 161nv10_gpio_fini(struct nouveau_object *object, bool suspend)
153{ 162{
154 struct nv10_gpio_priv *priv = (void *)object; 163 struct nv10_gpio_priv *priv = (void *)object;
155 nv_wr32(priv, 0x001140, 0x00000000);
156 nv_wr32(priv, 0x001144, 0x00000000); 164 nv_wr32(priv, 0x001144, 0x00000000);
157 return nouveau_gpio_fini(&priv->base, suspend); 165 return nouveau_gpio_fini(&priv->base, suspend);
158} 166}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
index bf13a1200f26..bf489dcf46e2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
@@ -22,7 +22,7 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <subdev/gpio.h> 25#include "priv.h"
26 26
27struct nv50_gpio_priv { 27struct nv50_gpio_priv {
28 struct nouveau_gpio base; 28 struct nouveau_gpio base;
@@ -95,21 +95,12 @@ nv50_gpio_sense(struct nouveau_gpio *gpio, int line)
95} 95}
96 96
97void 97void
98nv50_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on)
99{
100 u32 reg = line < 16 ? 0xe050 : 0xe070;
101 u32 mask = 0x00010001 << (line & 0xf);
102
103 nv_wr32(gpio, reg + 4, mask);
104 nv_mask(gpio, reg + 0, mask, on ? mask : 0);
105}
106
107void
108nv50_gpio_intr(struct nouveau_subdev *subdev) 98nv50_gpio_intr(struct nouveau_subdev *subdev)
109{ 99{
110 struct nv50_gpio_priv *priv = (void *)subdev; 100 struct nv50_gpio_priv *priv = (void *)subdev;
111 u32 intr0, intr1 = 0; 101 u32 intr0, intr1 = 0;
112 u32 hi, lo; 102 u32 hi, lo;
103 int i;
113 104
114 intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); 105 intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050);
115 if (nv_device(priv)->chipset >= 0x90) 106 if (nv_device(priv)->chipset >= 0x90)
@@ -117,13 +108,35 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
117 108
118 hi = (intr0 & 0x0000ffff) | (intr1 << 16); 109 hi = (intr0 & 0x0000ffff) | (intr1 << 16);
119 lo = (intr0 >> 16) | (intr1 & 0xffff0000); 110 lo = (intr0 >> 16) | (intr1 & 0xffff0000);
120 priv->base.isr_run(&priv->base, 0, hi | lo); 111
112 for (i = 0; (hi | lo) && i < 32; i++) {
113 if ((hi | lo) & (1 << i))
114 nouveau_event_trigger(priv->base.events, i);
115 }
121 116
122 nv_wr32(priv, 0xe054, intr0); 117 nv_wr32(priv, 0xe054, intr0);
123 if (nv_device(priv)->chipset >= 0x90) 118 if (nv_device(priv)->chipset >= 0x90)
124 nv_wr32(priv, 0xe074, intr1); 119 nv_wr32(priv, 0xe074, intr1);
125} 120}
126 121
122void
123nv50_gpio_intr_enable(struct nouveau_event *event, int line)
124{
125 const u32 addr = line < 16 ? 0xe050 : 0xe070;
126 const u32 mask = 0x00010001 << (line & 0xf);
127 nv_wr32(event->priv, addr + 0x04, mask);
128 nv_mask(event->priv, addr + 0x00, mask, mask);
129}
130
131void
132nv50_gpio_intr_disable(struct nouveau_event *event, int line)
133{
134 const u32 addr = line < 16 ? 0xe050 : 0xe070;
135 const u32 mask = 0x00010001 << (line & 0xf);
136 nv_wr32(event->priv, addr + 0x04, mask);
137 nv_mask(event->priv, addr + 0x00, mask, 0x00000000);
138}
139
127static int 140static int
128nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 141nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
129 struct nouveau_oclass *oclass, void *data, u32 size, 142 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -132,7 +145,9 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
132 struct nv50_gpio_priv *priv; 145 struct nv50_gpio_priv *priv;
133 int ret; 146 int ret;
134 147
135 ret = nouveau_gpio_create(parent, engine, oclass, &priv); 148 ret = nouveau_gpio_create(parent, engine, oclass,
149 nv_device(parent)->chipset >= 0x90 ? 32 : 16,
150 &priv);
136 *pobject = nv_object(priv); 151 *pobject = nv_object(priv);
137 if (ret) 152 if (ret)
138 return ret; 153 return ret;
@@ -140,7 +155,9 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
140 priv->base.reset = nv50_gpio_reset; 155 priv->base.reset = nv50_gpio_reset;
141 priv->base.drive = nv50_gpio_drive; 156 priv->base.drive = nv50_gpio_drive;
142 priv->base.sense = nv50_gpio_sense; 157 priv->base.sense = nv50_gpio_sense;
143 priv->base.irq_enable = nv50_gpio_irq_enable; 158 priv->base.events->priv = priv;
159 priv->base.events->enable = nv50_gpio_intr_enable;
160 priv->base.events->disable = nv50_gpio_intr_disable;
144 nv_subdev(priv)->intr = nv50_gpio_intr; 161 nv_subdev(priv)->intr = nv50_gpio_intr;
145 return 0; 162 return 0;
146} 163}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
index 83e8b8f16e6a..010431e3acec 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
@@ -22,13 +22,13 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <subdev/gpio.h> 25#include "priv.h"
26 26
27struct nvd0_gpio_priv { 27struct nvd0_gpio_priv {
28 struct nouveau_gpio base; 28 struct nouveau_gpio base;
29}; 29};
30 30
31static void 31void
32nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) 32nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)
33{ 33{
34 struct nouveau_bios *bios = nouveau_bios(gpio); 34 struct nouveau_bios *bios = nouveau_bios(gpio);
@@ -57,7 +57,7 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)
57 } 57 }
58} 58}
59 59
60static int 60int
61nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) 61nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
62{ 62{
63 u32 data = ((dir ^ 1) << 13) | (out << 12); 63 u32 data = ((dir ^ 1) << 13) | (out << 12);
@@ -66,7 +66,7 @@ nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
66 return 0; 66 return 0;
67} 67}
68 68
69static int 69int
70nvd0_gpio_sense(struct nouveau_gpio *gpio, int line) 70nvd0_gpio_sense(struct nouveau_gpio *gpio, int line)
71{ 71{
72 return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); 72 return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000);
@@ -80,7 +80,7 @@ nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
80 struct nvd0_gpio_priv *priv; 80 struct nvd0_gpio_priv *priv;
81 int ret; 81 int ret;
82 82
83 ret = nouveau_gpio_create(parent, engine, oclass, &priv); 83 ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv);
84 *pobject = nv_object(priv); 84 *pobject = nv_object(priv);
85 if (ret) 85 if (ret)
86 return ret; 86 return ret;
@@ -88,7 +88,9 @@ nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
88 priv->base.reset = nvd0_gpio_reset; 88 priv->base.reset = nvd0_gpio_reset;
89 priv->base.drive = nvd0_gpio_drive; 89 priv->base.drive = nvd0_gpio_drive;
90 priv->base.sense = nvd0_gpio_sense; 90 priv->base.sense = nvd0_gpio_sense;
91 priv->base.irq_enable = nv50_gpio_irq_enable; 91 priv->base.events->priv = priv;
92 priv->base.events->enable = nv50_gpio_intr_enable;
93 priv->base.events->disable = nv50_gpio_intr_disable;
92 nv_subdev(priv)->intr = nv50_gpio_intr; 94 nv_subdev(priv)->intr = nv50_gpio_intr;
93 return 0; 95 return 0;
94} 96}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c
new file mode 100644
index 000000000000..16b8c5bf5efa
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c
@@ -0,0 +1,131 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "priv.h"
26
27struct nve0_gpio_priv {
28 struct nouveau_gpio base;
29};
30
31void
32nve0_gpio_intr(struct nouveau_subdev *subdev)
33{
34 struct nve0_gpio_priv *priv = (void *)subdev;
35 u32 intr0 = nv_rd32(priv, 0xdc00) & nv_rd32(priv, 0xdc08);
36 u32 intr1 = nv_rd32(priv, 0xdc80) & nv_rd32(priv, 0xdc88);
37 u32 hi = (intr0 & 0x0000ffff) | (intr1 << 16);
38 u32 lo = (intr0 >> 16) | (intr1 & 0xffff0000);
39 int i;
40
41 for (i = 0; (hi | lo) && i < 32; i++) {
42 if ((hi | lo) & (1 << i))
43 nouveau_event_trigger(priv->base.events, i);
44 }
45
46 nv_wr32(priv, 0xdc00, intr0);
47 nv_wr32(priv, 0xdc88, intr1);
48}
49
50void
51nve0_gpio_intr_enable(struct nouveau_event *event, int line)
52{
53 const u32 addr = line < 16 ? 0xdc00 : 0xdc80;
54 const u32 mask = 0x00010001 << (line & 0xf);
55 nv_wr32(event->priv, addr + 0x08, mask);
56 nv_mask(event->priv, addr + 0x00, mask, mask);
57}
58
59void
60nve0_gpio_intr_disable(struct nouveau_event *event, int line)
61{
62 const u32 addr = line < 16 ? 0xdc00 : 0xdc80;
63 const u32 mask = 0x00010001 << (line & 0xf);
64 nv_wr32(event->priv, addr + 0x08, mask);
65 nv_mask(event->priv, addr + 0x00, mask, 0x00000000);
66}
67
68int
69nve0_gpio_fini(struct nouveau_object *object, bool suspend)
70{
71 struct nve0_gpio_priv *priv = (void *)object;
72 nv_wr32(priv, 0xdc08, 0x00000000);
73 nv_wr32(priv, 0xdc88, 0x00000000);
74 return nouveau_gpio_fini(&priv->base, suspend);
75}
76
77int
78nve0_gpio_init(struct nouveau_object *object)
79{
80 struct nve0_gpio_priv *priv = (void *)object;
81 int ret;
82
83 ret = nouveau_gpio_init(&priv->base);
84 if (ret)
85 return ret;
86
87 nv_wr32(priv, 0xdc00, 0xffffffff);
88 nv_wr32(priv, 0xdc80, 0xffffffff);
89 return 0;
90}
91
92void
93nve0_gpio_dtor(struct nouveau_object *object)
94{
95 struct nve0_gpio_priv *priv = (void *)object;
96 nouveau_gpio_destroy(&priv->base);
97}
98
99static int
100nve0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
101 struct nouveau_oclass *oclass, void *data, u32 size,
102 struct nouveau_object **pobject)
103{
104 struct nve0_gpio_priv *priv;
105 int ret;
106
107 ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv);
108 *pobject = nv_object(priv);
109 if (ret)
110 return ret;
111
112 priv->base.reset = nvd0_gpio_reset;
113 priv->base.drive = nvd0_gpio_drive;
114 priv->base.sense = nvd0_gpio_sense;
115 priv->base.events->priv = priv;
116 priv->base.events->enable = nve0_gpio_intr_enable;
117 priv->base.events->disable = nve0_gpio_intr_disable;
118 nv_subdev(priv)->intr = nve0_gpio_intr;
119 return 0;
120}
121
122struct nouveau_oclass
123nve0_gpio_oclass = {
124 .handle = NV_SUBDEV(GPIO, 0xe0),
125 .ofuncs = &(struct nouveau_ofuncs) {
126 .ctor = nve0_gpio_ctor,
127 .dtor = nv50_gpio_dtor,
128 .init = nve0_gpio_init,
129 .fini = nve0_gpio_fini,
130 },
131};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h b/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h
new file mode 100644
index 000000000000..2ee1c895c782
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h
@@ -0,0 +1,17 @@
1#ifndef __NVKM_GPIO_H__
2#define __NVKM_GPIO_H__
3
4#include <subdev/gpio.h>
5
6void nv50_gpio_dtor(struct nouveau_object *);
7int nv50_gpio_init(struct nouveau_object *);
8int nv50_gpio_fini(struct nouveau_object *, bool);
9void nv50_gpio_intr(struct nouveau_subdev *);
10void nv50_gpio_intr_enable(struct nouveau_event *, int line);
11void nv50_gpio_intr_disable(struct nouveau_event *, int line);
12
13void nvd0_gpio_reset(struct nouveau_gpio *, u8);
14int nvd0_gpio_drive(struct nouveau_gpio *, int, int, int);
15int nvd0_gpio_sense(struct nouveau_gpio *, int);
16
17#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
new file mode 100644
index 000000000000..dec94e9d776a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
@@ -0,0 +1,279 @@
1/*
2 * Copyright 2013 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#include <subdev/i2c.h>
26
27struct anx9805_i2c_port {
28 struct nouveau_i2c_port base;
29 u32 addr;
30 u32 ctrl;
31};
32
33static int
34anx9805_train(struct nouveau_i2c_port *port, int link_nr, int link_bw, bool enh)
35{
36 struct anx9805_i2c_port *chan = (void *)port;
37 struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent;
38 u8 tmp, i;
39
40 nv_wri2cr(mast, chan->addr, 0xa0, link_bw);
41 nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00));
42 nv_wri2cr(mast, chan->addr, 0xa2, 0x01);
43 nv_wri2cr(mast, chan->addr, 0xa8, 0x01);
44
45 i = 0;
46 while ((tmp = nv_rdi2cr(mast, chan->addr, 0xa8)) & 0x01) {
47 mdelay(5);
48 if (i++ == 100) {
49 nv_error(port, "link training timed out\n");
50 return -ETIMEDOUT;
51 }
52 }
53
54 if (tmp & 0x70) {
55 nv_error(port, "link training failed: 0x%02x\n", tmp);
56 return -EIO;
57 }
58
59 return 1;
60}
61
62static int
63anx9805_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size)
64{
65 struct anx9805_i2c_port *chan = (void *)port;
66 struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent;
67 int i, ret = -ETIMEDOUT;
68 u8 tmp;
69
70 tmp = nv_rdi2cr(mast, chan->ctrl, 0x07) & ~0x04;
71 nv_wri2cr(mast, chan->ctrl, 0x07, tmp | 0x04);
72 nv_wri2cr(mast, chan->ctrl, 0x07, tmp);
73 nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01);
74
75 nv_wri2cr(mast, chan->addr, 0xe4, 0x80);
76 for (i = 0; !(type & 1) && i < size; i++)
77 nv_wri2cr(mast, chan->addr, 0xf0 + i, data[i]);
78 nv_wri2cr(mast, chan->addr, 0xe5, ((size - 1) << 4) | type);
79 nv_wri2cr(mast, chan->addr, 0xe6, (addr & 0x000ff) >> 0);
80 nv_wri2cr(mast, chan->addr, 0xe7, (addr & 0x0ff00) >> 8);
81 nv_wri2cr(mast, chan->addr, 0xe8, (addr & 0xf0000) >> 16);
82 nv_wri2cr(mast, chan->addr, 0xe9, 0x01);
83
84 i = 0;
85 while ((tmp = nv_rdi2cr(mast, chan->addr, 0xe9)) & 0x01) {
86 mdelay(5);
87 if (i++ == 32)
88 goto done;
89 }
90
91 if ((tmp = nv_rdi2cr(mast, chan->ctrl, 0xf7)) & 0x01) {
92 ret = -EIO;
93 goto done;
94 }
95
96 for (i = 0; (type & 1) && i < size; i++)
97 data[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i);
98 ret = 0;
99done:
100 nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01);
101 return ret;
102}
103
104static const struct nouveau_i2c_func
105anx9805_aux_func = {
106 .aux = anx9805_aux,
107 .lnk_ctl = anx9805_train,
108};
109
110static int
111anx9805_aux_chan_ctor(struct nouveau_object *parent,
112 struct nouveau_object *engine,
113 struct nouveau_oclass *oclass, void *data, u32 index,
114 struct nouveau_object **pobject)
115{
116 struct nouveau_i2c_port *mast = (void *)parent;
117 struct anx9805_i2c_port *chan;
118 int ret;
119
120 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
121 &nouveau_i2c_aux_algo, &chan);
122 *pobject = nv_object(chan);
123 if (ret)
124 return ret;
125
126 switch ((oclass->handle & 0xff00) >> 8) {
127 case 0x0d:
128 chan->addr = 0x38;
129 chan->ctrl = 0x39;
130 break;
131 case 0x0e:
132 chan->addr = 0x3c;
133 chan->ctrl = 0x3b;
134 break;
135 default:
136 BUG_ON(1);
137 }
138
139 if (mast->adapter.algo == &i2c_bit_algo) {
140 struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
141 algo->udelay = max(algo->udelay, 40);
142 }
143
144 chan->base.func = &anx9805_aux_func;
145 return 0;
146}
147
148static struct nouveau_ofuncs
149anx9805_aux_ofuncs = {
150 .ctor = anx9805_aux_chan_ctor,
151 .dtor = _nouveau_i2c_port_dtor,
152 .init = _nouveau_i2c_port_init,
153 .fini = _nouveau_i2c_port_fini,
154};
155
156static int
157anx9805_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
158{
159 struct anx9805_i2c_port *port = adap->algo_data;
160 struct nouveau_i2c_port *mast = (void *)nv_object(port)->parent;
161 struct i2c_msg *msg = msgs;
162 int ret = -ETIMEDOUT;
163 int i, j, cnt = num;
164 u8 seg = 0x00, off = 0x00, tmp;
165
166 tmp = nv_rdi2cr(mast, port->ctrl, 0x07) & ~0x10;
167 nv_wri2cr(mast, port->ctrl, 0x07, tmp | 0x10);
168 nv_wri2cr(mast, port->ctrl, 0x07, tmp);
169 nv_wri2cr(mast, port->addr, 0x43, 0x05);
170 mdelay(5);
171
172 while (cnt--) {
173 if ( (msg->flags & I2C_M_RD) && msg->addr == 0x50) {
174 nv_wri2cr(mast, port->addr, 0x40, msg->addr << 1);
175 nv_wri2cr(mast, port->addr, 0x41, seg);
176 nv_wri2cr(mast, port->addr, 0x42, off);
177 nv_wri2cr(mast, port->addr, 0x44, msg->len);
178 nv_wri2cr(mast, port->addr, 0x45, 0x00);
179 nv_wri2cr(mast, port->addr, 0x43, 0x01);
180 for (i = 0; i < msg->len; i++) {
181 j = 0;
182 while (nv_rdi2cr(mast, port->addr, 0x46) & 0x10) {
183 mdelay(5);
184 if (j++ == 32)
185 goto done;
186 }
187 msg->buf[i] = nv_rdi2cr(mast, port->addr, 0x47);
188 }
189 } else
190 if (!(msg->flags & I2C_M_RD)) {
191 if (msg->addr == 0x50 && msg->len == 0x01) {
192 off = msg->buf[0];
193 } else
194 if (msg->addr == 0x30 && msg->len == 0x01) {
195 seg = msg->buf[0];
196 } else
197 goto done;
198 } else {
199 goto done;
200 }
201 msg++;
202 }
203
204 ret = num;
205done:
206 nv_wri2cr(mast, port->addr, 0x43, 0x00);
207 return ret;
208}
209
210static u32
211anx9805_func(struct i2c_adapter *adap)
212{
213 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
214}
215
216static const struct i2c_algorithm
217anx9805_i2c_algo = {
218 .master_xfer = anx9805_xfer,
219 .functionality = anx9805_func
220};
221
222static const struct nouveau_i2c_func
223anx9805_i2c_func = {
224};
225
226static int
227anx9805_ddc_port_ctor(struct nouveau_object *parent,
228 struct nouveau_object *engine,
229 struct nouveau_oclass *oclass, void *data, u32 index,
230 struct nouveau_object **pobject)
231{
232 struct nouveau_i2c_port *mast = (void *)parent;
233 struct anx9805_i2c_port *port;
234 int ret;
235
236 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
237 &anx9805_i2c_algo, &port);
238 *pobject = nv_object(port);
239 if (ret)
240 return ret;
241
242 switch ((oclass->handle & 0xff00) >> 8) {
243 case 0x0d:
244 port->addr = 0x3d;
245 port->ctrl = 0x39;
246 break;
247 case 0x0e:
248 port->addr = 0x3f;
249 port->ctrl = 0x3b;
250 break;
251 default:
252 BUG_ON(1);
253 }
254
255 if (mast->adapter.algo == &i2c_bit_algo) {
256 struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
257 algo->udelay = max(algo->udelay, 40);
258 }
259
260 port->base.func = &anx9805_i2c_func;
261 return 0;
262}
263
264static struct nouveau_ofuncs
265anx9805_ddc_ofuncs = {
266 .ctor = anx9805_ddc_port_ctor,
267 .dtor = _nouveau_i2c_port_dtor,
268 .init = _nouveau_i2c_port_init,
269 .fini = _nouveau_i2c_port_fini,
270};
271
272struct nouveau_oclass
273nouveau_anx9805_sclass[] = {
274 { .handle = NV_I2C_TYPE_EXTDDC(0x0d), .ofuncs = &anx9805_ddc_ofuncs },
275 { .handle = NV_I2C_TYPE_EXTAUX(0x0d), .ofuncs = &anx9805_aux_ofuncs },
276 { .handle = NV_I2C_TYPE_EXTDDC(0x0e), .ofuncs = &anx9805_ddc_ofuncs },
277 { .handle = NV_I2C_TYPE_EXTAUX(0x0e), .ofuncs = &anx9805_aux_ofuncs },
278 {}
279};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c
index dc27e794a851..5de074ad170b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c
@@ -24,151 +24,40 @@
24 24
25#include <subdev/i2c.h> 25#include <subdev/i2c.h>
26 26
27/******************************************************************************
28 * aux channel util functions
29 *****************************************************************************/
30#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args)
31#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args)
32
33static void
34auxch_fini(struct nouveau_i2c *aux, int ch)
35{
36 nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
37}
38
39static int
40auxch_init(struct nouveau_i2c *aux, int ch)
41{
42 const u32 unksel = 1; /* nfi which to use, or if it matters.. */
43 const u32 ureq = unksel ? 0x00100000 : 0x00200000;
44 const u32 urep = unksel ? 0x01000000 : 0x02000000;
45 u32 ctrl, timeout;
46
47 /* wait up to 1ms for any previous transaction to be done... */
48 timeout = 1000;
49 do {
50 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
51 udelay(1);
52 if (!timeout--) {
53 AUX_ERR("begin idle timeout 0x%08x\n", ctrl);
54 return -EBUSY;
55 }
56 } while (ctrl & 0x03010000);
57
58 /* set some magic, and wait up to 1ms for it to appear */
59 nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
60 timeout = 1000;
61 do {
62 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
63 udelay(1);
64 if (!timeout--) {
65 AUX_ERR("magic wait 0x%08x\n", ctrl);
66 auxch_fini(aux, ch);
67 return -EBUSY;
68 }
69 } while ((ctrl & 0x03000000) != urep);
70
71 return 0;
72}
73
74static int
75auxch_tx(struct nouveau_i2c *aux, int ch, u8 type, u32 addr, u8 *data, u8 size)
76{
77 u32 ctrl, stat, timeout, retries;
78 u32 xbuf[4] = {};
79 int ret, i;
80
81 AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
82
83 ret = auxch_init(aux, ch);
84 if (ret)
85 goto out;
86
87 stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50));
88 if (!(stat & 0x10000000)) {
89 AUX_DBG("sink not detected\n");
90 ret = -ENXIO;
91 goto out;
92 }
93
94 if (!(type & 1)) {
95 memcpy(xbuf, data, size);
96 for (i = 0; i < 16; i += 4) {
97 AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
98 nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
99 }
100 }
101
102 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
103 ctrl &= ~0x0001f0ff;
104 ctrl |= type << 12;
105 ctrl |= size - 1;
106 nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr);
107
108 /* retry transaction a number of times on failure... */
109 ret = -EREMOTEIO;
110 for (retries = 0; retries < 32; retries++) {
111 /* reset, and delay a while if this is a retry */
112 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
113 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
114 if (retries)
115 udelay(400);
116
117 /* transaction request, wait up to 1ms for it to complete */
118 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
119
120 timeout = 1000;
121 do {
122 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
123 udelay(1);
124 if (!timeout--) {
125 AUX_ERR("tx req timeout 0x%08x\n", ctrl);
126 goto out;
127 }
128 } while (ctrl & 0x00010000);
129
130 /* read status, and check if transaction completed ok */
131 stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0);
132 if (!(stat & 0x000f0f00)) {
133 ret = 0;
134 break;
135 }
136
137 AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
138 }
139
140 if (type & 1) {
141 for (i = 0; i < 16; i += 4) {
142 xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i);
143 AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
144 }
145 memcpy(data, xbuf, size);
146 }
147
148out:
149 auxch_fini(aux, ch);
150 return ret;
151}
152
153int 27int
154nv_rdaux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) 28nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)
155{ 29{
156 return auxch_tx(auxch->i2c, auxch->drive, 9, addr, data, size); 30 if (port->func->aux) {
31 if (port->func->acquire)
32 port->func->acquire(port);
33 return port->func->aux(port, 9, addr, data, size);
34 }
35 return -ENODEV;
157} 36}
158 37
159int 38int
160nv_wraux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) 39nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)
161{ 40{
162 return auxch_tx(auxch->i2c, auxch->drive, 8, addr, data, size); 41 if (port->func->aux) {
42 if (port->func->acquire)
43 port->func->acquire(port);
44 return port->func->aux(port, 8, addr, data, size);
45 }
46 return -ENODEV;
163} 47}
164 48
165static int 49static int
166aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 50aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
167{ 51{
168 struct nouveau_i2c_port *auxch = (struct nouveau_i2c_port *)adap; 52 struct nouveau_i2c_port *port = adap->algo_data;
169 struct i2c_msg *msg = msgs; 53 struct i2c_msg *msg = msgs;
170 int ret, mcnt = num; 54 int ret, mcnt = num;
171 55
56 if (!port->func->aux)
57 return -ENODEV;
58 if ( port->func->acquire)
59 port->func->acquire(port);
60
172 while (mcnt--) { 61 while (mcnt--) {
173 u8 remaining = msg->len; 62 u8 remaining = msg->len;
174 u8 *ptr = msg->buf; 63 u8 *ptr = msg->buf;
@@ -185,8 +74,7 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
185 if (mcnt || remaining > 16) 74 if (mcnt || remaining > 16)
186 cmd |= 4; /* MOT */ 75 cmd |= 4; /* MOT */
187 76
188 ret = auxch_tx(auxch->i2c, auxch->drive, cmd, 77 ret = port->func->aux(port, cmd, msg->addr, ptr, cnt);
189 msg->addr, ptr, cnt);
190 if (ret < 0) 78 if (ret < 0)
191 return ret; 79 return ret;
192 80
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index dbfc2abf0cfe..a114a0ed7e98 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2012 Red Hat Inc. 2 * Copyright 2013 Red Hat Inc.
3 * 3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a 4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"), 5 * copy of this software and associated documentation files (the "Software"),
@@ -22,64 +22,136 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include "core/option.h" 25#include <core/option.h>
26 26
27#include "subdev/i2c.h" 27#include <subdev/bios.h>
28#include "subdev/vga.h" 28#include <subdev/bios/dcb.h>
29#include <subdev/bios/i2c.h>
30#include <subdev/i2c.h>
31#include <subdev/vga.h>
29 32
30int 33/******************************************************************************
31nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) 34 * interface to linux i2c bit-banging algorithm
35 *****************************************************************************/
36
37#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
38#define CSTMSEL true
39#else
40#define CSTMSEL false
41#endif
42
43static int
44nouveau_i2c_pre_xfer(struct i2c_adapter *adap)
32{ 45{
33 u8 val; 46 struct i2c_algo_bit_data *bit = adap->algo_data;
34 struct i2c_msg msgs[] = { 47 struct nouveau_i2c_port *port = bit->data;
35 { .addr = addr, .flags = 0, .len = 1, .buf = &reg }, 48 if (port->func->acquire)
36 { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, 49 port->func->acquire(port);
37 }; 50 return 0;
51}
38 52
39 int ret = i2c_transfer(&port->adapter, msgs, 2); 53static void
40 if (ret != 2) 54nouveau_i2c_setscl(void *data, int state)
41 return -EIO; 55{
56 struct nouveau_i2c_port *port = data;
57 port->func->drive_scl(port, state);
58}
42 59
43 return val; 60static void
61nouveau_i2c_setsda(void *data, int state)
62{
63 struct nouveau_i2c_port *port = data;
64 port->func->drive_sda(port, state);
44} 65}
45 66
46int 67static int
47nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) 68nouveau_i2c_getscl(void *data)
48{ 69{
49 struct i2c_msg msgs[] = { 70 struct nouveau_i2c_port *port = data;
50 { .addr = addr, .flags = 0, .len = 1, .buf = &reg }, 71 return port->func->sense_scl(port);
51 { .addr = addr, .flags = 0, .len = 1, .buf = &val }, 72}
52 };
53 73
54 int ret = i2c_transfer(&port->adapter, msgs, 2); 74static int
55 if (ret != 2) 75nouveau_i2c_getsda(void *data)
56 return -EIO; 76{
77 struct nouveau_i2c_port *port = data;
78 return port->func->sense_sda(port);
79}
57 80
58 return 0; 81/******************************************************************************
82 * base i2c "port" class implementation
83 *****************************************************************************/
84
85void
86_nouveau_i2c_port_dtor(struct nouveau_object *object)
87{
88 struct nouveau_i2c_port *port = (void *)object;
89 i2c_del_adapter(&port->adapter);
90 nouveau_object_destroy(&port->base);
59} 91}
60 92
61bool 93int
62nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) 94nouveau_i2c_port_create_(struct nouveau_object *parent,
95 struct nouveau_object *engine,
96 struct nouveau_oclass *oclass, u8 index,
97 const struct i2c_algorithm *algo,
98 int size, void **pobject)
63{ 99{
64 u8 buf[] = { 0 }; 100 struct nouveau_device *device = nv_device(parent);
65 struct i2c_msg msgs[] = { 101 struct nouveau_i2c *i2c = (void *)engine;
66 { 102 struct nouveau_i2c_port *port;
67 .addr = addr, 103 int ret;
68 .flags = 0,
69 .len = 1,
70 .buf = buf,
71 },
72 {
73 .addr = addr,
74 .flags = I2C_M_RD,
75 .len = 1,
76 .buf = buf,
77 }
78 };
79 104
80 return i2c_transfer(&port->adapter, msgs, 2) == 2; 105 ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject);
106 port = *pobject;
107 if (ret)
108 return ret;
109
110 snprintf(port->adapter.name, sizeof(port->adapter.name),
111 "nouveau-%s-%d", device->name, index);
112 port->adapter.owner = THIS_MODULE;
113 port->adapter.dev.parent = &device->pdev->dev;
114 port->index = index;
115 i2c_set_adapdata(&port->adapter, i2c);
116
117 if ( algo == &nouveau_i2c_bit_algo &&
118 !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) {
119 struct i2c_algo_bit_data *bit;
120
121 bit = kzalloc(sizeof(*bit), GFP_KERNEL);
122 if (!bit)
123 return -ENOMEM;
124
125 bit->udelay = 10;
126 bit->timeout = usecs_to_jiffies(2200);
127 bit->data = port;
128 bit->pre_xfer = nouveau_i2c_pre_xfer;
129 bit->setsda = nouveau_i2c_setsda;
130 bit->setscl = nouveau_i2c_setscl;
131 bit->getsda = nouveau_i2c_getsda;
132 bit->getscl = nouveau_i2c_getscl;
133
134 port->adapter.algo_data = bit;
135 ret = i2c_bit_add_bus(&port->adapter);
136 } else {
137 port->adapter.algo_data = port;
138 port->adapter.algo = algo;
139 ret = i2c_add_adapter(&port->adapter);
140 }
141
142 /* drop port's i2c subdev refcount, i2c handles this itself */
143 if (ret == 0) {
144 list_add_tail(&port->head, &i2c->ports);
145 atomic_dec(&engine->refcount);
146 }
147
148 return ret;
81} 149}
82 150
151/******************************************************************************
152 * base i2c subdev class implementation
153 *****************************************************************************/
154
83static struct nouveau_i2c_port * 155static struct nouveau_i2c_port *
84nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index) 156nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index)
85{ 157{
@@ -103,29 +175,23 @@ nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index)
103 175
104 list_for_each_entry(port, &i2c->ports, head) { 176 list_for_each_entry(port, &i2c->ports, head) {
105 if (port->index == index) 177 if (port->index == index)
106 break; 178 return port;
107 } 179 }
108 180
109 if (&port->head == &i2c->ports) 181 return NULL;
110 return NULL; 182}
111 183
112 if (nv_device(i2c)->card_type >= NV_50 && (port->dcb & 0x00000100)) { 184static struct nouveau_i2c_port *
113 u32 reg = 0x00e500, val; 185nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type)
114 if (port->type == 6) { 186{
115 reg += port->drive * 0x50; 187 struct nouveau_i2c_port *port;
116 val = 0x2002;
117 } else {
118 reg += ((port->dcb & 0x1e00) >> 9) * 0x50;
119 val = 0xe001;
120 }
121 188
122 /* nfi, but neither auxch or i2c work if it's 1 */ 189 list_for_each_entry(port, &i2c->ports, head) {
123 nv_mask(i2c, reg + 0x0c, 0x00000001, 0x00000000); 190 if (nv_hclass(port) == type)
124 /* nfi, but switches auxch vs normal i2c */ 191 return port;
125 nv_mask(i2c, reg + 0x00, 0x0000f003, val);
126 } 192 }
127 193
128 return port; 194 return NULL;
129} 195}
130 196
131static int 197static int
@@ -155,109 +221,86 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
155 return -ENODEV; 221 return -ENODEV;
156} 222}
157 223
158void 224int
159nouveau_i2c_drive_scl(void *data, int state) 225_nouveau_i2c_fini(struct nouveau_object *object, bool suspend)
160{ 226{
161 struct nouveau_i2c_port *port = data; 227 struct nouveau_i2c *i2c = (void *)object;
228 struct nouveau_i2c_port *port;
229 int ret;
162 230
163 if (port->type == DCB_I2C_NV04_BIT) { 231 list_for_each_entry(port, &i2c->ports, head) {
164 u8 val = nv_rdvgac(port->i2c, 0, port->drive); 232 ret = nv_ofuncs(port)->fini(nv_object(port), suspend);
165 if (state) val |= 0x20; 233 if (ret && suspend)
166 else val &= 0xdf; 234 goto fail;
167 nv_wrvgac(port->i2c, 0, port->drive, val | 0x01);
168 } else
169 if (port->type == DCB_I2C_NV4E_BIT) {
170 nv_mask(port->i2c, port->drive, 0x2f, state ? 0x21 : 0x01);
171 } else
172 if (port->type == DCB_I2C_NVIO_BIT) {
173 if (state) port->state |= 0x01;
174 else port->state &= 0xfe;
175 nv_wr32(port->i2c, port->drive, 4 | port->state);
176 } 235 }
177}
178
179void
180nouveau_i2c_drive_sda(void *data, int state)
181{
182 struct nouveau_i2c_port *port = data;
183 236
184 if (port->type == DCB_I2C_NV04_BIT) { 237 return nouveau_subdev_fini(&i2c->base, suspend);
185 u8 val = nv_rdvgac(port->i2c, 0, port->drive); 238fail:
186 if (state) val |= 0x10; 239 list_for_each_entry_continue_reverse(port, &i2c->ports, head) {
187 else val &= 0xef; 240 nv_ofuncs(port)->init(nv_object(port));
188 nv_wrvgac(port->i2c, 0, port->drive, val | 0x01);
189 } else
190 if (port->type == DCB_I2C_NV4E_BIT) {
191 nv_mask(port->i2c, port->drive, 0x1f, state ? 0x11 : 0x01);
192 } else
193 if (port->type == DCB_I2C_NVIO_BIT) {
194 if (state) port->state |= 0x02;
195 else port->state &= 0xfd;
196 nv_wr32(port->i2c, port->drive, 4 | port->state);
197 } 241 }
242
243 return ret;
198} 244}
199 245
200int 246int
201nouveau_i2c_sense_scl(void *data) 247_nouveau_i2c_init(struct nouveau_object *object)
202{ 248{
203 struct nouveau_i2c_port *port = data; 249 struct nouveau_i2c *i2c = (void *)object;
204 struct nouveau_device *device = nv_device(port->i2c); 250 struct nouveau_i2c_port *port;
205 251 int ret;
206 if (port->type == DCB_I2C_NV04_BIT) { 252
207 return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x04); 253 ret = nouveau_subdev_init(&i2c->base);
208 } else 254 if (ret == 0) {
209 if (port->type == DCB_I2C_NV4E_BIT) { 255 list_for_each_entry(port, &i2c->ports, head) {
210 return !!(nv_rd32(port->i2c, port->sense) & 0x00040000); 256 ret = nv_ofuncs(port)->init(nv_object(port));
211 } else 257 if (ret)
212 if (port->type == DCB_I2C_NVIO_BIT) { 258 goto fail;
213 if (device->card_type < NV_D0) 259 }
214 return !!(nv_rd32(port->i2c, port->sense) & 0x01);
215 else
216 return !!(nv_rd32(port->i2c, port->sense) & 0x10);
217 } 260 }
218 261
219 return 0; 262 return ret;
263fail:
264 list_for_each_entry_continue_reverse(port, &i2c->ports, head) {
265 nv_ofuncs(port)->fini(nv_object(port), false);
266 }
267
268 return ret;
220} 269}
221 270
222int 271void
223nouveau_i2c_sense_sda(void *data) 272_nouveau_i2c_dtor(struct nouveau_object *object)
224{ 273{
225 struct nouveau_i2c_port *port = data; 274 struct nouveau_i2c *i2c = (void *)object;
226 struct nouveau_device *device = nv_device(port->i2c); 275 struct nouveau_i2c_port *port, *temp;
227 276
228 if (port->type == DCB_I2C_NV04_BIT) { 277 list_for_each_entry_safe(port, temp, &i2c->ports, head) {
229 return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x08); 278 nouveau_object_ref(NULL, (struct nouveau_object **)&port);
230 } else
231 if (port->type == DCB_I2C_NV4E_BIT) {
232 return !!(nv_rd32(port->i2c, port->sense) & 0x00080000);
233 } else
234 if (port->type == DCB_I2C_NVIO_BIT) {
235 if (device->card_type < NV_D0)
236 return !!(nv_rd32(port->i2c, port->sense) & 0x02);
237 else
238 return !!(nv_rd32(port->i2c, port->sense) & 0x20);
239 } 279 }
240 280
241 return 0; 281 nouveau_subdev_destroy(&i2c->base);
242} 282}
243 283
244static const u32 nv50_i2c_port[] = { 284static struct nouveau_oclass *
245 0x00e138, 0x00e150, 0x00e168, 0x00e180, 285nouveau_i2c_extdev_sclass[] = {
246 0x00e254, 0x00e274, 0x00e764, 0x00e780, 286 nouveau_anx9805_sclass,
247 0x00e79c, 0x00e7b8
248}; 287};
249 288
250static int 289int
251nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 290nouveau_i2c_create_(struct nouveau_object *parent,
252 struct nouveau_oclass *oclass, void *data, u32 size, 291 struct nouveau_object *engine,
253 struct nouveau_object **pobject) 292 struct nouveau_oclass *oclass,
293 struct nouveau_oclass *sclass,
294 int length, void **pobject)
254{ 295{
255 struct nouveau_device *device = nv_device(parent);
256 struct nouveau_bios *bios = nouveau_bios(parent); 296 struct nouveau_bios *bios = nouveau_bios(parent);
257 struct nouveau_i2c_port *port;
258 struct nouveau_i2c *i2c; 297 struct nouveau_i2c *i2c;
298 struct nouveau_object *object;
259 struct dcb_i2c_entry info; 299 struct dcb_i2c_entry info;
260 int ret, i = -1; 300 int ret, i, j, index = -1;
301 struct dcb_output outp;
302 u8 ver, hdr;
303 u32 data;
261 304
262 ret = nouveau_subdev_create(parent, engine, oclass, 0, 305 ret = nouveau_subdev_create(parent, engine, oclass, 0,
263 "I2C", "i2c", &i2c); 306 "I2C", "i2c", &i2c);
@@ -266,142 +309,60 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
266 return ret; 309 return ret;
267 310
268 i2c->find = nouveau_i2c_find; 311 i2c->find = nouveau_i2c_find;
312 i2c->find_type = nouveau_i2c_find_type;
269 i2c->identify = nouveau_i2c_identify; 313 i2c->identify = nouveau_i2c_identify;
270 INIT_LIST_HEAD(&i2c->ports); 314 INIT_LIST_HEAD(&i2c->ports);
271 315
272 while (!dcb_i2c_parse(bios, ++i, &info)) { 316 while (!dcb_i2c_parse(bios, ++index, &info)) {
273 if (info.type == DCB_I2C_UNUSED) 317 if (info.type == DCB_I2C_UNUSED)
274 continue; 318 continue;
275 319
276 port = kzalloc(sizeof(*port), GFP_KERNEL); 320 oclass = sclass;
277 if (!port) { 321 do {
278 nv_error(i2c, "failed port memory alloc at %d\n", i); 322 ret = -EINVAL;
279 break; 323 if (oclass->handle == info.type) {
280 } 324 ret = nouveau_object_ctor(*pobject, *pobject,
281 325 oclass, &info,
282 port->type = info.type; 326 index, &object);
283 switch (port->type) {
284 case DCB_I2C_NV04_BIT:
285 port->drive = info.drive;
286 port->sense = info.sense;
287 break;
288 case DCB_I2C_NV4E_BIT:
289 port->drive = 0x600800 + info.drive;
290 port->sense = port->drive;
291 break;
292 case DCB_I2C_NVIO_BIT:
293 port->drive = info.drive & 0x0f;
294 if (device->card_type < NV_D0) {
295 if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
296 break;
297 port->drive = nv50_i2c_port[port->drive];
298 port->sense = port->drive;
299 } else {
300 port->drive = 0x00d014 + (port->drive * 0x20);
301 port->sense = port->drive;
302 } 327 }
328 } while (ret && (++oclass)->handle);
329 }
330
331 /* in addition to the busses specified in the i2c table, there
332 * may be ddc/aux channels hiding behind external tmds/dp/etc
333 * transmitters.
334 */
335 index = ((index + 0x0f) / 0x10) * 0x10;
336 i = -1;
337 while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &outp))) {
338 if (!outp.location || !outp.extdev)
339 continue;
340
341 switch (outp.type) {
342 case DCB_OUTPUT_TMDS:
343 info.type = NV_I2C_TYPE_EXTDDC(outp.extdev);
303 break; 344 break;
304 case DCB_I2C_NVIO_AUX: 345 case DCB_OUTPUT_DP:
305 port->drive = info.drive & 0x0f; 346 info.type = NV_I2C_TYPE_EXTAUX(outp.extdev);
306 port->sense = port->drive;
307 port->adapter.algo = &nouveau_i2c_aux_algo;
308 break; 347 break;
309 default: 348 default:
310 break;
311 }
312
313 if (!port->adapter.algo && !port->drive) {
314 nv_error(i2c, "I2C%d: type %d index %x/%x unknown\n",
315 i, port->type, port->drive, port->sense);
316 kfree(port);
317 continue; 349 continue;
318 } 350 }
319 351
320 snprintf(port->adapter.name, sizeof(port->adapter.name), 352 ret = -ENODEV;
321 "nouveau-%s-%d", device->name, i); 353 j = -1;
322 port->adapter.owner = THIS_MODULE; 354 while (ret && ++j < ARRAY_SIZE(nouveau_i2c_extdev_sclass)) {
323 port->adapter.dev.parent = &device->pdev->dev; 355 parent = nv_object(i2c->find(i2c, outp.i2c_index));
324 port->i2c = i2c; 356 oclass = nouveau_i2c_extdev_sclass[j];
325 port->index = i; 357 do {
326 port->dcb = info.data; 358 if (oclass->handle != info.type)
327 i2c_set_adapdata(&port->adapter, i2c); 359 continue;
328 360 ret = nouveau_object_ctor(parent, *pobject,
329 if (port->adapter.algo != &nouveau_i2c_aux_algo) { 361 oclass, NULL,
330 nouveau_i2c_drive_scl(port, 0); 362 index++, &object);
331 nouveau_i2c_drive_sda(port, 1); 363 } while (ret && (++oclass)->handle);
332 nouveau_i2c_drive_scl(port, 1);
333
334#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
335 if (nouveau_boolopt(device->cfgopt, "NvI2C", true)) {
336#else
337 if (nouveau_boolopt(device->cfgopt, "NvI2C", false)) {
338#endif
339 port->adapter.algo = &nouveau_i2c_bit_algo;
340 ret = i2c_add_adapter(&port->adapter);
341 } else {
342 port->adapter.algo_data = &port->bit;
343 port->bit.udelay = 10;
344 port->bit.timeout = usecs_to_jiffies(2200);
345 port->bit.data = port;
346 port->bit.setsda = nouveau_i2c_drive_sda;
347 port->bit.setscl = nouveau_i2c_drive_scl;
348 port->bit.getsda = nouveau_i2c_sense_sda;
349 port->bit.getscl = nouveau_i2c_sense_scl;
350 ret = i2c_bit_add_bus(&port->adapter);
351 }
352 } else {
353 port->adapter.algo = &nouveau_i2c_aux_algo;
354 ret = i2c_add_adapter(&port->adapter);
355 }
356
357 if (ret) {
358 nv_error(i2c, "I2C%d: failed register: %d\n", i, ret);
359 kfree(port);
360 continue;
361 } 364 }
362
363 list_add_tail(&port->head, &i2c->ports);
364 } 365 }
365 366
366 return 0; 367 return 0;
367} 368}
368
369static void
370nouveau_i2c_dtor(struct nouveau_object *object)
371{
372 struct nouveau_i2c *i2c = (void *)object;
373 struct nouveau_i2c_port *port, *temp;
374
375 list_for_each_entry_safe(port, temp, &i2c->ports, head) {
376 i2c_del_adapter(&port->adapter);
377 list_del(&port->head);
378 kfree(port);
379 }
380
381 nouveau_subdev_destroy(&i2c->base);
382}
383
384static int
385nouveau_i2c_init(struct nouveau_object *object)
386{
387 struct nouveau_i2c *i2c = (void *)object;
388 return nouveau_subdev_init(&i2c->base);
389}
390
391static int
392nouveau_i2c_fini(struct nouveau_object *object, bool suspend)
393{
394 struct nouveau_i2c *i2c = (void *)object;
395 return nouveau_subdev_fini(&i2c->base, suspend);
396}
397
398struct nouveau_oclass
399nouveau_i2c_oclass = {
400 .handle = NV_SUBDEV(I2C, 0x00),
401 .ofuncs = &(struct nouveau_ofuncs) {
402 .ctor = nouveau_i2c_ctor,
403 .dtor = nouveau_i2c_dtor,
404 .init = nouveau_i2c_init,
405 .fini = nouveau_i2c_fini,
406 },
407};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c
index 1c4c9a5c8e2e..a6e72d3b06b5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c
@@ -32,25 +32,25 @@
32static inline void 32static inline void
33i2c_drive_scl(struct nouveau_i2c_port *port, int state) 33i2c_drive_scl(struct nouveau_i2c_port *port, int state)
34{ 34{
35 nouveau_i2c_drive_scl(port, state); 35 port->func->drive_scl(port, state);
36} 36}
37 37
38static inline void 38static inline void
39i2c_drive_sda(struct nouveau_i2c_port *port, int state) 39i2c_drive_sda(struct nouveau_i2c_port *port, int state)
40{ 40{
41 nouveau_i2c_drive_sda(port, state); 41 port->func->drive_sda(port, state);
42} 42}
43 43
44static inline int 44static inline int
45i2c_sense_scl(struct nouveau_i2c_port *port) 45i2c_sense_scl(struct nouveau_i2c_port *port)
46{ 46{
47 return nouveau_i2c_sense_scl(port); 47 return port->func->sense_scl(port);
48} 48}
49 49
50static inline int 50static inline int
51i2c_sense_sda(struct nouveau_i2c_port *port) 51i2c_sense_sda(struct nouveau_i2c_port *port)
52{ 52{
53 return nouveau_i2c_sense_sda(port); 53 return port->func->sense_sda(port);
54} 54}
55 55
56static void 56static void
@@ -77,9 +77,8 @@ i2c_start(struct nouveau_i2c_port *port)
77{ 77{
78 int ret = 0; 78 int ret = 0;
79 79
80 port->state = i2c_sense_scl(port); 80 if (!i2c_sense_scl(port) ||
81 port->state |= i2c_sense_sda(port) << 1; 81 !i2c_sense_sda(port)) {
82 if (port->state != 3) {
83 i2c_drive_scl(port, 0); 82 i2c_drive_scl(port, 0);
84 i2c_drive_sda(port, 1); 83 i2c_drive_sda(port, 1);
85 if (!i2c_raise_scl(port)) 84 if (!i2c_raise_scl(port))
@@ -184,10 +183,13 @@ i2c_addr(struct nouveau_i2c_port *port, struct i2c_msg *msg)
184static int 183static int
185i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 184i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
186{ 185{
187 struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap; 186 struct nouveau_i2c_port *port = adap->algo_data;
188 struct i2c_msg *msg = msgs; 187 struct i2c_msg *msg = msgs;
189 int ret = 0, mcnt = num; 188 int ret = 0, mcnt = num;
190 189
190 if (port->func->acquire)
191 port->func->acquire(port);
192
191 while (!ret && mcnt--) { 193 while (!ret && mcnt--) {
192 u8 remaining = msg->len; 194 u8 remaining = msg->len;
193 u8 *ptr = msg->buf; 195 u8 *ptr = msg->buf;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
new file mode 100644
index 000000000000..2ad18840fe63
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/i2c.h>
26#include <subdev/vga.h>
27
28struct nv04_i2c_priv {
29 struct nouveau_i2c base;
30};
31
32struct nv04_i2c_port {
33 struct nouveau_i2c_port base;
34 u8 drive;
35 u8 sense;
36};
37
38static void
39nv04_i2c_drive_scl(struct nouveau_i2c_port *base, int state)
40{
41 struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
42 struct nv04_i2c_port *port = (void *)base;
43 u8 val = nv_rdvgac(priv, 0, port->drive);
44 if (state) val |= 0x20;
45 else val &= 0xdf;
46 nv_wrvgac(priv, 0, port->drive, val | 0x01);
47}
48
49static void
50nv04_i2c_drive_sda(struct nouveau_i2c_port *base, int state)
51{
52 struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
53 struct nv04_i2c_port *port = (void *)base;
54 u8 val = nv_rdvgac(priv, 0, port->drive);
55 if (state) val |= 0x10;
56 else val &= 0xef;
57 nv_wrvgac(priv, 0, port->drive, val | 0x01);
58}
59
60static int
61nv04_i2c_sense_scl(struct nouveau_i2c_port *base)
62{
63 struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
64 struct nv04_i2c_port *port = (void *)base;
65 return !!(nv_rdvgac(priv, 0, port->sense) & 0x04);
66}
67
68static int
69nv04_i2c_sense_sda(struct nouveau_i2c_port *base)
70{
71 struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine;
72 struct nv04_i2c_port *port = (void *)base;
73 return !!(nv_rdvgac(priv, 0, port->sense) & 0x08);
74}
75
76static const struct nouveau_i2c_func
77nv04_i2c_func = {
78 .drive_scl = nv04_i2c_drive_scl,
79 .drive_sda = nv04_i2c_drive_sda,
80 .sense_scl = nv04_i2c_sense_scl,
81 .sense_sda = nv04_i2c_sense_sda,
82};
83
84static int
85nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
86 struct nouveau_oclass *oclass, void *data, u32 index,
87 struct nouveau_object **pobject)
88{
89 struct dcb_i2c_entry *info = data;
90 struct nv04_i2c_port *port;
91 int ret;
92
93 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
94 &nouveau_i2c_bit_algo, &port);
95 *pobject = nv_object(port);
96 if (ret)
97 return ret;
98
99 port->base.func = &nv04_i2c_func;
100 port->drive = info->drive;
101 port->sense = info->sense;
102 return 0;
103}
104
105static struct nouveau_oclass
106nv04_i2c_sclass[] = {
107 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV04_BIT),
108 .ofuncs = &(struct nouveau_ofuncs) {
109 .ctor = nv04_i2c_port_ctor,
110 .dtor = _nouveau_i2c_port_dtor,
111 .init = _nouveau_i2c_port_init,
112 .fini = _nouveau_i2c_port_fini,
113 },
114 },
115 {}
116};
117
118static int
119nv04_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
120 struct nouveau_oclass *oclass, void *data, u32 size,
121 struct nouveau_object **pobject)
122{
123 struct nv04_i2c_priv *priv;
124 int ret;
125
126 ret = nouveau_i2c_create(parent, engine, oclass, nv04_i2c_sclass, &priv);
127 *pobject = nv_object(priv);
128 if (ret)
129 return ret;
130
131 return 0;
132}
133
134struct nouveau_oclass
135nv04_i2c_oclass = {
136 .handle = NV_SUBDEV(I2C, 0x04),
137 .ofuncs = &(struct nouveau_ofuncs) {
138 .ctor = nv04_i2c_ctor,
139 .dtor = _nouveau_i2c_dtor,
140 .init = _nouveau_i2c_init,
141 .fini = _nouveau_i2c_fini,
142 },
143};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
new file mode 100644
index 000000000000..f501ae25dbb3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
@@ -0,0 +1,135 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/i2c.h>
26#include <subdev/vga.h>
27
28struct nv4e_i2c_priv {
29 struct nouveau_i2c base;
30};
31
32struct nv4e_i2c_port {
33 struct nouveau_i2c_port base;
34 u32 addr;
35};
36
37static void
38nv4e_i2c_drive_scl(struct nouveau_i2c_port *base, int state)
39{
40 struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
41 struct nv4e_i2c_port *port = (void *)base;
42 nv_mask(priv, port->addr, 0x2f, state ? 0x21 : 0x01);
43}
44
45static void
46nv4e_i2c_drive_sda(struct nouveau_i2c_port *base, int state)
47{
48 struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
49 struct nv4e_i2c_port *port = (void *)base;
50 nv_mask(priv, port->addr, 0x1f, state ? 0x11 : 0x01);
51}
52
53static int
54nv4e_i2c_sense_scl(struct nouveau_i2c_port *base)
55{
56 struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
57 struct nv4e_i2c_port *port = (void *)base;
58 return !!(nv_rd32(priv, port->addr) & 0x00040000);
59}
60
61static int
62nv4e_i2c_sense_sda(struct nouveau_i2c_port *base)
63{
64 struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine;
65 struct nv4e_i2c_port *port = (void *)base;
66 return !!(nv_rd32(priv, port->addr) & 0x00080000);
67}
68
69static const struct nouveau_i2c_func
70nv4e_i2c_func = {
71 .drive_scl = nv4e_i2c_drive_scl,
72 .drive_sda = nv4e_i2c_drive_sda,
73 .sense_scl = nv4e_i2c_sense_scl,
74 .sense_sda = nv4e_i2c_sense_sda,
75};
76
77static int
78nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
79 struct nouveau_oclass *oclass, void *data, u32 index,
80 struct nouveau_object **pobject)
81{
82 struct dcb_i2c_entry *info = data;
83 struct nv4e_i2c_port *port;
84 int ret;
85
86 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
87 &nouveau_i2c_bit_algo, &port);
88 *pobject = nv_object(port);
89 if (ret)
90 return ret;
91
92 port->base.func = &nv4e_i2c_func;
93 port->addr = 0x600800 + info->drive;
94 return 0;
95}
96
97static struct nouveau_oclass
98nv4e_i2c_sclass[] = {
99 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV4E_BIT),
100 .ofuncs = &(struct nouveau_ofuncs) {
101 .ctor = nv4e_i2c_port_ctor,
102 .dtor = _nouveau_i2c_port_dtor,
103 .init = _nouveau_i2c_port_init,
104 .fini = _nouveau_i2c_port_fini,
105 },
106 },
107 {}
108};
109
110static int
111nv4e_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
112 struct nouveau_oclass *oclass, void *data, u32 size,
113 struct nouveau_object **pobject)
114{
115 struct nv4e_i2c_priv *priv;
116 int ret;
117
118 ret = nouveau_i2c_create(parent, engine, oclass, nv4e_i2c_sclass, &priv);
119 *pobject = nv_object(priv);
120 if (ret)
121 return ret;
122
123 return 0;
124}
125
126struct nouveau_oclass
127nv4e_i2c_oclass = {
128 .handle = NV_SUBDEV(I2C, 0x4e),
129 .ofuncs = &(struct nouveau_ofuncs) {
130 .ctor = nv4e_i2c_ctor,
131 .dtor = _nouveau_i2c_dtor,
132 .init = _nouveau_i2c_init,
133 .fini = _nouveau_i2c_fini,
134 },
135};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
new file mode 100644
index 000000000000..378dfa324e5f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
@@ -0,0 +1,149 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv50.h"
26
27void
28nv50_i2c_drive_scl(struct nouveau_i2c_port *base, int state)
29{
30 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
31 struct nv50_i2c_port *port = (void *)base;
32 if (state) port->state |= 0x01;
33 else port->state &= 0xfe;
34 nv_wr32(priv, port->addr, port->state);
35}
36
37void
38nv50_i2c_drive_sda(struct nouveau_i2c_port *base, int state)
39{
40 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
41 struct nv50_i2c_port *port = (void *)base;
42 if (state) port->state |= 0x02;
43 else port->state &= 0xfd;
44 nv_wr32(priv, port->addr, port->state);
45}
46
47int
48nv50_i2c_sense_scl(struct nouveau_i2c_port *base)
49{
50 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
51 struct nv50_i2c_port *port = (void *)base;
52 return !!(nv_rd32(priv, port->addr) & 0x00000001);
53}
54
55int
56nv50_i2c_sense_sda(struct nouveau_i2c_port *base)
57{
58 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
59 struct nv50_i2c_port *port = (void *)base;
60 return !!(nv_rd32(priv, port->addr) & 0x00000002);
61}
62
63static const struct nouveau_i2c_func
64nv50_i2c_func = {
65 .drive_scl = nv50_i2c_drive_scl,
66 .drive_sda = nv50_i2c_drive_sda,
67 .sense_scl = nv50_i2c_sense_scl,
68 .sense_sda = nv50_i2c_sense_sda,
69};
70
71const u32 nv50_i2c_addr[] = {
72 0x00e138, 0x00e150, 0x00e168, 0x00e180,
73 0x00e254, 0x00e274, 0x00e764, 0x00e780,
74 0x00e79c, 0x00e7b8
75};
76const int nv50_i2c_addr_nr = ARRAY_SIZE(nv50_i2c_addr);
77
78static int
79nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
80 struct nouveau_oclass *oclass, void *data, u32 index,
81 struct nouveau_object **pobject)
82{
83 struct dcb_i2c_entry *info = data;
84 struct nv50_i2c_port *port;
85 int ret;
86
87 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
88 &nouveau_i2c_bit_algo, &port);
89 *pobject = nv_object(port);
90 if (ret)
91 return ret;
92
93 if (info->drive >= nv50_i2c_addr_nr)
94 return -EINVAL;
95
96 port->base.func = &nv50_i2c_func;
97 port->state = 0x00000007;
98 port->addr = nv50_i2c_addr[info->drive];
99 return 0;
100}
101
102int
103nv50_i2c_port_init(struct nouveau_object *object)
104{
105 struct nv50_i2c_priv *priv = (void *)object->engine;
106 struct nv50_i2c_port *port = (void *)object;
107 nv_wr32(priv, port->addr, port->state);
108 return nouveau_i2c_port_init(&port->base);
109}
110
111static struct nouveau_oclass
112nv50_i2c_sclass[] = {
113 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
114 .ofuncs = &(struct nouveau_ofuncs) {
115 .ctor = nv50_i2c_port_ctor,
116 .dtor = _nouveau_i2c_port_dtor,
117 .init = nv50_i2c_port_init,
118 .fini = _nouveau_i2c_port_fini,
119 },
120 },
121 {}
122};
123
124static int
125nv50_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
126 struct nouveau_oclass *oclass, void *data, u32 size,
127 struct nouveau_object **pobject)
128{
129 struct nv50_i2c_priv *priv;
130 int ret;
131
132 ret = nouveau_i2c_create(parent, engine, oclass, nv50_i2c_sclass, &priv);
133 *pobject = nv_object(priv);
134 if (ret)
135 return ret;
136
137 return 0;
138}
139
140struct nouveau_oclass
141nv50_i2c_oclass = {
142 .handle = NV_SUBDEV(I2C, 0x50),
143 .ofuncs = &(struct nouveau_ofuncs) {
144 .ctor = nv50_i2c_ctor,
145 .dtor = _nouveau_i2c_dtor,
146 .init = _nouveau_i2c_init,
147 .fini = _nouveau_i2c_fini,
148 },
149};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h
new file mode 100644
index 000000000000..4e5ba48ebf5a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h
@@ -0,0 +1,32 @@
1#ifndef __NV50_I2C_H__
2#define __NV50_I2C_H__
3
4#include <subdev/i2c.h>
5
6struct nv50_i2c_priv {
7 struct nouveau_i2c base;
8};
9
10struct nv50_i2c_port {
11 struct nouveau_i2c_port base;
12 u32 addr;
13 u32 ctrl;
14 u32 data;
15 u32 state;
16};
17
18extern const u32 nv50_i2c_addr[];
19extern const int nv50_i2c_addr_nr;
20int nv50_i2c_port_init(struct nouveau_object *);
21int nv50_i2c_sense_scl(struct nouveau_i2c_port *);
22int nv50_i2c_sense_sda(struct nouveau_i2c_port *);
23void nv50_i2c_drive_scl(struct nouveau_i2c_port *, int state);
24void nv50_i2c_drive_sda(struct nouveau_i2c_port *, int state);
25
26int nv94_aux_port_ctor(struct nouveau_object *, struct nouveau_object *,
27 struct nouveau_oclass *, void *, u32,
28 struct nouveau_object **);
29void nv94_i2c_acquire(struct nouveau_i2c_port *);
30void nv94_i2c_release(struct nouveau_i2c_port *);
31
32#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
new file mode 100644
index 000000000000..61b771670bfe
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
@@ -0,0 +1,285 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv50.h"
26
27#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args)
28#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args)
29
30static void
31auxch_fini(struct nouveau_i2c *aux, int ch)
32{
33 nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000);
34}
35
36static int
37auxch_init(struct nouveau_i2c *aux, int ch)
38{
39 const u32 unksel = 1; /* nfi which to use, or if it matters.. */
40 const u32 ureq = unksel ? 0x00100000 : 0x00200000;
41 const u32 urep = unksel ? 0x01000000 : 0x02000000;
42 u32 ctrl, timeout;
43
44 /* wait up to 1ms for any previous transaction to be done... */
45 timeout = 1000;
46 do {
47 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
48 udelay(1);
49 if (!timeout--) {
50 AUX_ERR("begin idle timeout 0x%08x\n", ctrl);
51 return -EBUSY;
52 }
53 } while (ctrl & 0x03010000);
54
55 /* set some magic, and wait up to 1ms for it to appear */
56 nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq);
57 timeout = 1000;
58 do {
59 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
60 udelay(1);
61 if (!timeout--) {
62 AUX_ERR("magic wait 0x%08x\n", ctrl);
63 auxch_fini(aux, ch);
64 return -EBUSY;
65 }
66 } while ((ctrl & 0x03000000) != urep);
67
68 return 0;
69}
70
71int
72nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size)
73{
74 struct nouveau_i2c *aux = nouveau_i2c(base);
75 struct nv50_i2c_port *port = (void *)base;
76 u32 ctrl, stat, timeout, retries;
77 u32 xbuf[4] = {};
78 int ch = port->addr;
79 int ret, i;
80
81 AUX_DBG("%d: 0x%08x %d\n", type, addr, size);
82
83 ret = auxch_init(aux, ch);
84 if (ret)
85 goto out;
86
87 stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50));
88 if (!(stat & 0x10000000)) {
89 AUX_DBG("sink not detected\n");
90 ret = -ENXIO;
91 goto out;
92 }
93
94 if (!(type & 1)) {
95 memcpy(xbuf, data, size);
96 for (i = 0; i < 16; i += 4) {
97 AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
98 nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
99 }
100 }
101
102 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
103 ctrl &= ~0x0001f0ff;
104 ctrl |= type << 12;
105 ctrl |= size - 1;
106 nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr);
107
108 /* retry transaction a number of times on failure... */
109 ret = -EREMOTEIO;
110 for (retries = 0; retries < 32; retries++) {
111 /* reset, and delay a while if this is a retry */
112 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
113 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
114 if (retries)
115 udelay(400);
116
117 /* transaction request, wait up to 1ms for it to complete */
118 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);
119
120 timeout = 1000;
121 do {
122 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
123 udelay(1);
124 if (!timeout--) {
125 AUX_ERR("tx req timeout 0x%08x\n", ctrl);
126 goto out;
127 }
128 } while (ctrl & 0x00010000);
129
130 /* read status, and check if transaction completed ok */
131 stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0);
132 if (!(stat & 0x000f0f00)) {
133 ret = 0;
134 break;
135 }
136
137 AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
138 }
139
140 if (type & 1) {
141 for (i = 0; i < 16; i += 4) {
142 xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i);
143 AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
144 }
145 memcpy(data, xbuf, size);
146 }
147
148out:
149 auxch_fini(aux, ch);
150 return ret;
151}
152
153void
154nv94_i2c_acquire(struct nouveau_i2c_port *base)
155{
156 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
157 struct nv50_i2c_port *port = (void *)base;
158 if (port->ctrl) {
159 nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000);
160 nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data);
161 }
162}
163
164void
165nv94_i2c_release(struct nouveau_i2c_port *base)
166{
167}
168
169static const struct nouveau_i2c_func
170nv94_i2c_func = {
171 .acquire = nv94_i2c_acquire,
172 .release = nv94_i2c_release,
173 .drive_scl = nv50_i2c_drive_scl,
174 .drive_sda = nv50_i2c_drive_sda,
175 .sense_scl = nv50_i2c_sense_scl,
176 .sense_sda = nv50_i2c_sense_sda,
177};
178
179static int
180nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
181 struct nouveau_oclass *oclass, void *data, u32 index,
182 struct nouveau_object **pobject)
183{
184 struct dcb_i2c_entry *info = data;
185 struct nv50_i2c_port *port;
186 int ret;
187
188 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
189 &nouveau_i2c_bit_algo, &port);
190 *pobject = nv_object(port);
191 if (ret)
192 return ret;
193
194 if (info->drive >= nv50_i2c_addr_nr)
195 return -EINVAL;
196
197 port->base.func = &nv94_i2c_func;
198 port->state = 7;
199 port->addr = nv50_i2c_addr[info->drive];
200 if (info->share != DCB_I2C_UNUSED) {
201 port->ctrl = 0x00e500 + (info->share * 0x50);
202 port->data = 0x0000e001;
203 }
204 return 0;
205}
206
207static const struct nouveau_i2c_func
208nv94_aux_func = {
209 .acquire = nv94_i2c_acquire,
210 .release = nv94_i2c_release,
211 .aux = nv94_aux,
212};
213
214int
215nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
216 struct nouveau_oclass *oclass, void *data, u32 index,
217 struct nouveau_object **pobject)
218{
219 struct dcb_i2c_entry *info = data;
220 struct nv50_i2c_port *port;
221 int ret;
222
223 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
224 &nouveau_i2c_aux_algo, &port);
225 *pobject = nv_object(port);
226 if (ret)
227 return ret;
228
229 port->base.func = &nv94_aux_func;
230 port->addr = info->drive;
231 if (info->share != DCB_I2C_UNUSED) {
232 port->ctrl = 0x00e500 + (info->drive * 0x50);
233 port->data = 0x00002002;
234 }
235
236 return 0;
237}
238
239static struct nouveau_oclass
240nv94_i2c_sclass[] = {
241 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
242 .ofuncs = &(struct nouveau_ofuncs) {
243 .ctor = nv94_i2c_port_ctor,
244 .dtor = _nouveau_i2c_port_dtor,
245 .init = nv50_i2c_port_init,
246 .fini = _nouveau_i2c_port_fini,
247 },
248 },
249 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX),
250 .ofuncs = &(struct nouveau_ofuncs) {
251 .ctor = nv94_aux_port_ctor,
252 .dtor = _nouveau_i2c_port_dtor,
253 .init = _nouveau_i2c_port_init,
254 .fini = _nouveau_i2c_port_fini,
255 },
256 },
257 {}
258};
259
260static int
261nv94_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
262 struct nouveau_oclass *oclass, void *data, u32 size,
263 struct nouveau_object **pobject)
264{
265 struct nv50_i2c_priv *priv;
266 int ret;
267
268 ret = nouveau_i2c_create(parent, engine, oclass, nv94_i2c_sclass, &priv);
269 *pobject = nv_object(priv);
270 if (ret)
271 return ret;
272
273 return 0;
274}
275
276struct nouveau_oclass
277nv94_i2c_oclass = {
278 .handle = NV_SUBDEV(I2C, 0x94),
279 .ofuncs = &(struct nouveau_ofuncs) {
280 .ctor = nv94_i2c_ctor,
281 .dtor = _nouveau_i2c_dtor,
282 .init = _nouveau_i2c_init,
283 .fini = _nouveau_i2c_fini,
284 },
285};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
new file mode 100644
index 000000000000..f761b8a610f1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
@@ -0,0 +1,124 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "nv50.h"
26
27static int
28nvd0_i2c_sense_scl(struct nouveau_i2c_port *base)
29{
30 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
31 struct nv50_i2c_port *port = (void *)base;
32 return !!(nv_rd32(priv, port->addr) & 0x00000010);
33}
34
35static int
36nvd0_i2c_sense_sda(struct nouveau_i2c_port *base)
37{
38 struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
39 struct nv50_i2c_port *port = (void *)base;
40 return !!(nv_rd32(priv, port->addr) & 0x00000020);
41}
42
43static const struct nouveau_i2c_func
44nvd0_i2c_func = {
45 .acquire = nv94_i2c_acquire,
46 .release = nv94_i2c_release,
47 .drive_scl = nv50_i2c_drive_scl,
48 .drive_sda = nv50_i2c_drive_sda,
49 .sense_scl = nvd0_i2c_sense_scl,
50 .sense_sda = nvd0_i2c_sense_sda,
51};
52
53static int
54nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
55 struct nouveau_oclass *oclass, void *data, u32 index,
56 struct nouveau_object **pobject)
57{
58 struct dcb_i2c_entry *info = data;
59 struct nv50_i2c_port *port;
60 int ret;
61
62 ret = nouveau_i2c_port_create(parent, engine, oclass, index,
63 &nouveau_i2c_bit_algo, &port);
64 *pobject = nv_object(port);
65 if (ret)
66 return ret;
67
68 port->base.func = &nvd0_i2c_func;
69 port->state = 0x00000007;
70 port->addr = 0x00d014 + (info->drive * 0x20);
71 if (info->share != DCB_I2C_UNUSED) {
72 port->ctrl = 0x00e500 + (info->share * 0x50);
73 port->data = 0x0000e001;
74 }
75 return 0;
76}
77
78static struct nouveau_oclass
79nvd0_i2c_sclass[] = {
80 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
81 .ofuncs = &(struct nouveau_ofuncs) {
82 .ctor = nvd0_i2c_port_ctor,
83 .dtor = _nouveau_i2c_port_dtor,
84 .init = nv50_i2c_port_init,
85 .fini = _nouveau_i2c_port_fini,
86 },
87 },
88 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX),
89 .ofuncs = &(struct nouveau_ofuncs) {
90 .ctor = nv94_aux_port_ctor,
91 .dtor = _nouveau_i2c_port_dtor,
92 .init = _nouveau_i2c_port_init,
93 .fini = _nouveau_i2c_port_fini,
94 },
95 },
96 {}
97};
98
99static int
100nvd0_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
101 struct nouveau_oclass *oclass, void *data, u32 size,
102 struct nouveau_object **pobject)
103{
104 struct nv50_i2c_priv *priv;
105 int ret;
106
107 ret = nouveau_i2c_create(parent, engine, oclass, nvd0_i2c_sclass, &priv);
108 *pobject = nv_object(priv);
109 if (ret)
110 return ret;
111
112 return 0;
113}
114
115struct nouveau_oclass
116nvd0_i2c_oclass = {
117 .handle = NV_SUBDEV(I2C, 0xd0),
118 .ofuncs = &(struct nouveau_ofuncs) {
119 .ctor = nvd0_i2c_ctor,
120 .dtor = _nouveau_i2c_dtor,
121 .init = _nouveau_i2c_init,
122 .fini = _nouveau_i2c_fini,
123 },
124};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
index 23ebe477a6f0..89da8fa7ea0f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
@@ -37,7 +37,7 @@ nv04_mc_intr[] = {
37 { 0x00100000, NVDEV_SUBDEV_TIMER }, 37 { 0x00100000, NVDEV_SUBDEV_TIMER },
38 { 0x01000000, NVDEV_ENGINE_DISP }, /* NV04- PCRTC0 */ 38 { 0x01000000, NVDEV_ENGINE_DISP }, /* NV04- PCRTC0 */
39 { 0x02000000, NVDEV_ENGINE_DISP }, /* NV11- PCRTC1 */ 39 { 0x02000000, NVDEV_ENGINE_DISP }, /* NV11- PCRTC1 */
40 { 0x10000000, NVDEV_SUBDEV_GPIO }, /* PBUS */ 40 { 0x10000000, NVDEV_SUBDEV_BUS },
41 { 0x80000000, NVDEV_ENGINE_SW }, 41 { 0x80000000, NVDEV_ENGINE_SW },
42 {} 42 {}
43}; 43};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
index 8d759f830323..5965add6daee 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
@@ -38,6 +38,7 @@ nv50_mc_intr[] = {
38 { 0x00100000, NVDEV_SUBDEV_TIMER }, 38 { 0x00100000, NVDEV_SUBDEV_TIMER },
39 { 0x00200000, NVDEV_SUBDEV_GPIO }, 39 { 0x00200000, NVDEV_SUBDEV_GPIO },
40 { 0x04000000, NVDEV_ENGINE_DISP }, 40 { 0x04000000, NVDEV_ENGINE_DISP },
41 { 0x10000000, NVDEV_SUBDEV_BUS },
41 { 0x80000000, NVDEV_ENGINE_SW }, 42 { 0x80000000, NVDEV_ENGINE_SW },
42 { 0x0000d101, NVDEV_SUBDEV_FB }, 43 { 0x0000d101, NVDEV_SUBDEV_FB },
43 {}, 44 {},
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
index ceb5c83f9459..3a80b29dce0f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
@@ -35,10 +35,12 @@ nv98_mc_intr[] = {
35 { 0x00001000, NVDEV_ENGINE_GR }, 35 { 0x00001000, NVDEV_ENGINE_GR },
36 { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ 36 { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */
37 { 0x00008000, NVDEV_ENGINE_BSP }, 37 { 0x00008000, NVDEV_ENGINE_BSP },
38 { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */
38 { 0x00100000, NVDEV_SUBDEV_TIMER }, 39 { 0x00100000, NVDEV_SUBDEV_TIMER },
39 { 0x00200000, NVDEV_SUBDEV_GPIO }, 40 { 0x00200000, NVDEV_SUBDEV_GPIO },
40 { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */ 41 { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */
41 { 0x04000000, NVDEV_ENGINE_DISP }, 42 { 0x04000000, NVDEV_ENGINE_DISP },
43 { 0x10000000, NVDEV_SUBDEV_BUS },
42 { 0x80000000, NVDEV_ENGINE_SW }, 44 { 0x80000000, NVDEV_ENGINE_SW },
43 { 0x0040d101, NVDEV_SUBDEV_FB }, 45 { 0x0040d101, NVDEV_SUBDEV_FB },
44 {}, 46 {},
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
index 92796682722d..42bbf72023a8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
@@ -36,11 +36,13 @@ nvc0_mc_intr[] = {
36 { 0x00000100, NVDEV_ENGINE_FIFO }, 36 { 0x00000100, NVDEV_ENGINE_FIFO },
37 { 0x00001000, NVDEV_ENGINE_GR }, 37 { 0x00001000, NVDEV_ENGINE_GR },
38 { 0x00008000, NVDEV_ENGINE_BSP }, 38 { 0x00008000, NVDEV_ENGINE_BSP },
39 { 0x00040000, NVDEV_SUBDEV_THERM },
39 { 0x00020000, NVDEV_ENGINE_VP }, 40 { 0x00020000, NVDEV_ENGINE_VP },
40 { 0x00100000, NVDEV_SUBDEV_TIMER }, 41 { 0x00100000, NVDEV_SUBDEV_TIMER },
41 { 0x00200000, NVDEV_SUBDEV_GPIO }, 42 { 0x00200000, NVDEV_SUBDEV_GPIO },
42 { 0x02000000, NVDEV_SUBDEV_LTCG }, 43 { 0x02000000, NVDEV_SUBDEV_LTCG },
43 { 0x04000000, NVDEV_ENGINE_DISP }, 44 { 0x04000000, NVDEV_ENGINE_DISP },
45 { 0x10000000, NVDEV_SUBDEV_BUS },
44 { 0x40000000, NVDEV_SUBDEV_IBUS }, 46 { 0x40000000, NVDEV_SUBDEV_IBUS },
45 { 0x80000000, NVDEV_ENGINE_SW }, 47 { 0x80000000, NVDEV_ENGINE_SW },
46 {}, 48 {},
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c
index 839ca1edc132..4bde7f7f7b81 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c
@@ -156,15 +156,15 @@ mxms_foreach(struct nouveau_mxm *mxm, u8 types,
156 156
157 nv_debug(mxm, "%4s: ", mxms_desc_name[type]); 157 nv_debug(mxm, "%4s: ", mxms_desc_name[type]);
158 for (j = headerlen - 1; j >= 0; j--) 158 for (j = headerlen - 1; j >= 0; j--)
159 printk("%02x", dump[j]); 159 pr_cont("%02x", dump[j]);
160 printk("\n"); 160 pr_cont("\n");
161 dump += headerlen; 161 dump += headerlen;
162 162
163 for (i = 0; i < entries; i++, dump += recordlen) { 163 for (i = 0; i < entries; i++, dump += recordlen) {
164 nv_debug(mxm, " "); 164 nv_debug(mxm, " ");
165 for (j = recordlen - 1; j >= 0; j--) 165 for (j = recordlen - 1; j >= 0; j--)
166 printk("%02x", dump[j]); 166 pr_cont("%02x", dump[j]);
167 printk("\n"); 167 pr_cont("\n");
168 } 168 }
169 } 169 }
170 170
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
index 1674c74a76c8..f794dc89a3b2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c
@@ -29,6 +29,134 @@
29 29
30#include "priv.h" 30#include "priv.h"
31 31
32static int
33nouveau_therm_update_trip(struct nouveau_therm *therm)
34{
35 struct nouveau_therm_priv *priv = (void *)therm;
36 struct nouveau_therm_trip_point *trip = priv->fan->bios.trip,
37 *cur_trip = NULL,
38 *last_trip = priv->last_trip;
39 u8 temp = therm->temp_get(therm);
40 u16 duty, i;
41
42 /* look for the trip point corresponding to the current temperature */
43 cur_trip = NULL;
44 for (i = 0; i < priv->fan->bios.nr_fan_trip; i++) {
45 if (temp >= trip[i].temp)
46 cur_trip = &trip[i];
47 }
48
49 /* account for the hysteresis cycle */
50 if (last_trip && temp <= (last_trip->temp) &&
51 temp > (last_trip->temp - last_trip->hysteresis))
52 cur_trip = last_trip;
53
54 if (cur_trip) {
55 duty = cur_trip->fan_duty;
56 priv->last_trip = cur_trip;
57 } else {
58 duty = 0;
59 priv->last_trip = NULL;
60 }
61
62 return duty;
63}
64
65static int
66nouveau_therm_update_linear(struct nouveau_therm *therm)
67{
68 struct nouveau_therm_priv *priv = (void *)therm;
69 u8 linear_min_temp = priv->fan->bios.linear_min_temp;
70 u8 linear_max_temp = priv->fan->bios.linear_max_temp;
71 u8 temp = therm->temp_get(therm);
72 u16 duty;
73
74 /* handle the non-linear part first */
75 if (temp < linear_min_temp)
76 return priv->fan->bios.min_duty;
77 else if (temp > linear_max_temp)
78 return priv->fan->bios.max_duty;
79
80 /* we are in the linear zone */
81 duty = (temp - linear_min_temp);
82 duty *= (priv->fan->bios.max_duty - priv->fan->bios.min_duty);
83 duty /= (linear_max_temp - linear_min_temp);
84 duty += priv->fan->bios.min_duty;
85
86 return duty;
87}
88
89static void
90nouveau_therm_update(struct nouveau_therm *therm, int mode)
91{
92 struct nouveau_timer *ptimer = nouveau_timer(therm);
93 struct nouveau_therm_priv *priv = (void *)therm;
94 unsigned long flags;
95 int duty;
96
97 spin_lock_irqsave(&priv->lock, flags);
98 if (mode < 0)
99 mode = priv->mode;
100 priv->mode = mode;
101
102 switch (mode) {
103 case NOUVEAU_THERM_CTRL_MANUAL:
104 duty = nouveau_therm_fan_get(therm);
105 if (duty < 0)
106 duty = 100;
107 break;
108 case NOUVEAU_THERM_CTRL_AUTO:
109 if (priv->fan->bios.nr_fan_trip)
110 duty = nouveau_therm_update_trip(therm);
111 else
112 duty = nouveau_therm_update_linear(therm);
113 break;
114 case NOUVEAU_THERM_CTRL_NONE:
115 default:
116 goto done;
117 }
118
119 nv_debug(therm, "FAN target request: %d%%\n", duty);
120 nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty);
121
122done:
123 if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO))
124 ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
125 spin_unlock_irqrestore(&priv->lock, flags);
126}
127
128static void
129nouveau_therm_alarm(struct nouveau_alarm *alarm)
130{
131 struct nouveau_therm_priv *priv =
132 container_of(alarm, struct nouveau_therm_priv, alarm);
133 nouveau_therm_update(&priv->base, -1);
134}
135
136int
137nouveau_therm_mode(struct nouveau_therm *therm, int mode)
138{
139 struct nouveau_therm_priv *priv = (void *)therm;
140 struct nouveau_device *device = nv_device(therm);
141 static const char *name[] = {
142 "disabled",
143 "manual",
144 "automatic"
145 };
146
147 /* The default PDAEMON ucode interferes with fan management */
148 if ((mode >= ARRAY_SIZE(name)) ||
149 (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
150 return -EINVAL;
151
152 if (priv->mode == mode)
153 return 0;
154
155 nv_info(therm, "Thermal management: %s\n", name[mode]);
156 nouveau_therm_update(therm, mode);
157 return 0;
158}
159
32int 160int
33nouveau_therm_attr_get(struct nouveau_therm *therm, 161nouveau_therm_attr_get(struct nouveau_therm *therm,
34 enum nouveau_therm_attr_type type) 162 enum nouveau_therm_attr_type type)
@@ -37,11 +165,11 @@ nouveau_therm_attr_get(struct nouveau_therm *therm,
37 165
38 switch (type) { 166 switch (type) {
39 case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: 167 case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY:
40 return priv->bios_fan.min_duty; 168 return priv->fan->bios.min_duty;
41 case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: 169 case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY:
42 return priv->bios_fan.max_duty; 170 return priv->fan->bios.max_duty;
43 case NOUVEAU_THERM_ATTR_FAN_MODE: 171 case NOUVEAU_THERM_ATTR_FAN_MODE:
44 return priv->fan.mode; 172 return priv->mode;
45 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: 173 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST:
46 return priv->bios_sensor.thrs_fan_boost.temp; 174 return priv->bios_sensor.thrs_fan_boost.temp;
47 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: 175 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST:
@@ -73,42 +201,50 @@ nouveau_therm_attr_set(struct nouveau_therm *therm,
73 case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: 201 case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY:
74 if (value < 0) 202 if (value < 0)
75 value = 0; 203 value = 0;
76 if (value > priv->bios_fan.max_duty) 204 if (value > priv->fan->bios.max_duty)
77 value = priv->bios_fan.max_duty; 205 value = priv->fan->bios.max_duty;
78 priv->bios_fan.min_duty = value; 206 priv->fan->bios.min_duty = value;
79 return 0; 207 return 0;
80 case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: 208 case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY:
81 if (value < 0) 209 if (value < 0)
82 value = 0; 210 value = 0;
83 if (value < priv->bios_fan.min_duty) 211 if (value < priv->fan->bios.min_duty)
84 value = priv->bios_fan.min_duty; 212 value = priv->fan->bios.min_duty;
85 priv->bios_fan.max_duty = value; 213 priv->fan->bios.max_duty = value;
86 return 0; 214 return 0;
87 case NOUVEAU_THERM_ATTR_FAN_MODE: 215 case NOUVEAU_THERM_ATTR_FAN_MODE:
88 return nouveau_therm_fan_set_mode(therm, value); 216 return nouveau_therm_mode(therm, value);
89 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: 217 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST:
90 priv->bios_sensor.thrs_fan_boost.temp = value; 218 priv->bios_sensor.thrs_fan_boost.temp = value;
219 priv->sensor.program_alarms(therm);
91 return 0; 220 return 0;
92 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: 221 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST:
93 priv->bios_sensor.thrs_fan_boost.hysteresis = value; 222 priv->bios_sensor.thrs_fan_boost.hysteresis = value;
223 priv->sensor.program_alarms(therm);
94 return 0; 224 return 0;
95 case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: 225 case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK:
96 priv->bios_sensor.thrs_down_clock.temp = value; 226 priv->bios_sensor.thrs_down_clock.temp = value;
227 priv->sensor.program_alarms(therm);
97 return 0; 228 return 0;
98 case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: 229 case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST:
99 priv->bios_sensor.thrs_down_clock.hysteresis = value; 230 priv->bios_sensor.thrs_down_clock.hysteresis = value;
231 priv->sensor.program_alarms(therm);
100 return 0; 232 return 0;
101 case NOUVEAU_THERM_ATTR_THRS_CRITICAL: 233 case NOUVEAU_THERM_ATTR_THRS_CRITICAL:
102 priv->bios_sensor.thrs_critical.temp = value; 234 priv->bios_sensor.thrs_critical.temp = value;
235 priv->sensor.program_alarms(therm);
103 return 0; 236 return 0;
104 case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: 237 case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST:
105 priv->bios_sensor.thrs_critical.hysteresis = value; 238 priv->bios_sensor.thrs_critical.hysteresis = value;
239 priv->sensor.program_alarms(therm);
106 return 0; 240 return 0;
107 case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: 241 case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN:
108 priv->bios_sensor.thrs_shutdown.temp = value; 242 priv->bios_sensor.thrs_shutdown.temp = value;
243 priv->sensor.program_alarms(therm);
109 return 0; 244 return 0;
110 case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: 245 case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST:
111 priv->bios_sensor.thrs_shutdown.hysteresis = value; 246 priv->bios_sensor.thrs_shutdown.hysteresis = value;
247 priv->sensor.program_alarms(therm);
112 return 0; 248 return 0;
113 } 249 }
114 250
@@ -116,7 +252,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm,
116} 252}
117 253
118int 254int
119nouveau_therm_init(struct nouveau_object *object) 255_nouveau_therm_init(struct nouveau_object *object)
120{ 256{
121 struct nouveau_therm *therm = (void *)object; 257 struct nouveau_therm *therm = (void *)object;
122 struct nouveau_therm_priv *priv = (void *)therm; 258 struct nouveau_therm_priv *priv = (void *)therm;
@@ -126,19 +262,69 @@ nouveau_therm_init(struct nouveau_object *object)
126 if (ret) 262 if (ret)
127 return ret; 263 return ret;
128 264
129 if (priv->fan.percent >= 0) 265 if (priv->suspend >= 0)
130 therm->fan_set(therm, priv->fan.percent); 266 nouveau_therm_mode(therm, priv->mode);
131 267 priv->sensor.program_alarms(therm);
132 return 0; 268 return 0;
133} 269}
134 270
135int 271int
136nouveau_therm_fini(struct nouveau_object *object, bool suspend) 272_nouveau_therm_fini(struct nouveau_object *object, bool suspend)
137{ 273{
138 struct nouveau_therm *therm = (void *)object; 274 struct nouveau_therm *therm = (void *)object;
139 struct nouveau_therm_priv *priv = (void *)therm; 275 struct nouveau_therm_priv *priv = (void *)therm;
140 276
141 priv->fan.percent = therm->fan_get(therm); 277 if (suspend) {
278 priv->suspend = priv->mode;
279 priv->mode = NOUVEAU_THERM_CTRL_NONE;
280 }
142 281
143 return nouveau_subdev_fini(&therm->base, suspend); 282 return nouveau_subdev_fini(&therm->base, suspend);
144} 283}
284
285int
286nouveau_therm_create_(struct nouveau_object *parent,
287 struct nouveau_object *engine,
288 struct nouveau_oclass *oclass,
289 int length, void **pobject)
290{
291 struct nouveau_therm_priv *priv;
292 int ret;
293
294 ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PTHERM",
295 "therm", length, pobject);
296 priv = *pobject;
297 if (ret)
298 return ret;
299
300 nouveau_alarm_init(&priv->alarm, nouveau_therm_alarm);
301 spin_lock_init(&priv->lock);
302 spin_lock_init(&priv->sensor.alarm_program_lock);
303
304 priv->base.fan_get = nouveau_therm_fan_user_get;
305 priv->base.fan_set = nouveau_therm_fan_user_set;
306 priv->base.fan_sense = nouveau_therm_fan_sense;
307 priv->base.attr_get = nouveau_therm_attr_get;
308 priv->base.attr_set = nouveau_therm_attr_set;
309 priv->mode = priv->suspend = -1; /* undefined */
310 return 0;
311}
312
313int
314nouveau_therm_preinit(struct nouveau_therm *therm)
315{
316 nouveau_therm_ic_ctor(therm);
317 nouveau_therm_sensor_ctor(therm);
318 nouveau_therm_fan_ctor(therm);
319
320 nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE);
321 return 0;
322}
323
324void
325_nouveau_therm_dtor(struct nouveau_object *object)
326{
327 struct nouveau_therm_priv *priv = (void *)object;
328 kfree(priv->fan);
329 nouveau_subdev_destroy(&priv->base.base);
330}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 523178685180..c728380d3d62 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -27,90 +27,107 @@
27 27
28#include <core/object.h> 28#include <core/object.h>
29#include <core/device.h> 29#include <core/device.h>
30
30#include <subdev/gpio.h> 31#include <subdev/gpio.h>
31#include <subdev/timer.h> 32#include <subdev/timer.h>
32 33
33int 34static int
34nouveau_therm_fan_get(struct nouveau_therm *therm) 35nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)
35{ 36{
37 struct nouveau_therm *therm = fan->parent;
36 struct nouveau_therm_priv *priv = (void *)therm; 38 struct nouveau_therm_priv *priv = (void *)therm;
37 struct nouveau_gpio *gpio = nouveau_gpio(therm); 39 struct nouveau_timer *ptimer = nouveau_timer(priv);
38 struct dcb_gpio_func func; 40 unsigned long flags;
39 int card_type = nv_device(therm)->card_type; 41 int ret = 0;
40 u32 divs, duty; 42 int duty;
41 int ret; 43
42 44 /* update target fan speed, restricting to allowed range */
43 if (!priv->fan.pwm_get) 45 spin_lock_irqsave(&fan->lock, flags);
44 return -ENODEV; 46 if (target < 0)
47 target = fan->percent;
48 target = max_t(u8, target, fan->bios.min_duty);
49 target = min_t(u8, target, fan->bios.max_duty);
50 if (fan->percent != target) {
51 nv_debug(therm, "FAN target: %d\n", target);
52 fan->percent = target;
53 }
45 54
46 ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); 55 /* check that we're not already at the target duty cycle */
47 if (ret == 0) { 56 duty = fan->get(therm);
48 ret = priv->fan.pwm_get(therm, func.line, &divs, &duty); 57 if (duty == target)
49 if (ret == 0 && divs) { 58 goto done;
50 divs = max(divs, duty); 59
51 if (card_type <= NV_40 || (func.log[0] & 1)) 60 /* smooth out the fanspeed increase/decrease */
52 duty = divs - duty; 61 if (!immediate && duty >= 0) {
53 return (duty * 100) / divs; 62 /* the constant "3" is a rough approximation taken from
54 } 63 * nvidia's behaviour.
64 * it is meant to bump the fan speed more incrementally
65 */
66 if (duty < target)
67 duty = min(duty + 3, target);
68 else if (duty > target)
69 duty = max(duty - 3, target);
70 } else {
71 duty = target;
72 }
55 73
56 return gpio->get(gpio, 0, func.func, func.line) * 100; 74 nv_debug(therm, "FAN update: %d\n", duty);
75 ret = fan->set(therm, duty);
76 if (ret)
77 goto done;
78
79 /* schedule next fan update, if not at target speed already */
80 if (list_empty(&fan->alarm.head) && target != duty) {
81 u16 bump_period = fan->bios.bump_period;
82 u16 slow_down_period = fan->bios.slow_down_period;
83 u64 delay;
84
85 if (duty > target)
86 delay = slow_down_period;
87 else if (duty == target)
88 delay = min(bump_period, slow_down_period) ;
89 else
90 delay = bump_period;
91
92 ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm);
57 } 93 }
58 94
59 return -ENODEV; 95done:
96 spin_unlock_irqrestore(&fan->lock, flags);
97 return ret;
98}
99
100static void
101nouveau_fan_alarm(struct nouveau_alarm *alarm)
102{
103 struct nouveau_fan *fan = container_of(alarm, struct nouveau_fan, alarm);
104 nouveau_fan_update(fan, false, -1);
60} 105}
61 106
62int 107int
63nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) 108nouveau_therm_fan_get(struct nouveau_therm *therm)
64{ 109{
65 struct nouveau_therm_priv *priv = (void *)therm; 110 struct nouveau_therm_priv *priv = (void *)therm;
66 struct nouveau_gpio *gpio = nouveau_gpio(therm); 111 return priv->fan->get(therm);
67 struct dcb_gpio_func func; 112}
68 int card_type = nv_device(therm)->card_type;
69 u32 divs, duty;
70 int ret;
71
72 if (priv->fan.mode == FAN_CONTROL_NONE)
73 return -EINVAL;
74
75 if (!priv->fan.pwm_set)
76 return -ENODEV;
77
78 if (percent < priv->bios_fan.min_duty)
79 percent = priv->bios_fan.min_duty;
80 if (percent > priv->bios_fan.max_duty)
81 percent = priv->bios_fan.max_duty;
82
83 ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func);
84 if (ret == 0) {
85 divs = priv->bios_perf_fan.pwm_divisor;
86 if (priv->bios_fan.pwm_freq) {
87 divs = 1;
88 if (priv->fan.pwm_clock)
89 divs = priv->fan.pwm_clock(therm);
90 divs /= priv->bios_fan.pwm_freq;
91 }
92
93 duty = ((divs * percent) + 99) / 100;
94 if (card_type <= NV_40 || (func.log[0] & 1))
95 duty = divs - duty;
96
97 ret = priv->fan.pwm_set(therm, func.line, divs, duty);
98 return ret;
99 }
100 113
101 return -ENODEV; 114int
115nouveau_therm_fan_set(struct nouveau_therm *therm, bool immediate, int percent)
116{
117 struct nouveau_therm_priv *priv = (void *)therm;
118 return nouveau_fan_update(priv->fan, immediate, percent);
102} 119}
103 120
104int 121int
105nouveau_therm_fan_sense(struct nouveau_therm *therm) 122nouveau_therm_fan_sense(struct nouveau_therm *therm)
106{ 123{
124 struct nouveau_therm_priv *priv = (void *)therm;
107 struct nouveau_timer *ptimer = nouveau_timer(therm); 125 struct nouveau_timer *ptimer = nouveau_timer(therm);
108 struct nouveau_gpio *gpio = nouveau_gpio(therm); 126 struct nouveau_gpio *gpio = nouveau_gpio(therm);
109 struct dcb_gpio_func func;
110 u32 cycles, cur, prev; 127 u32 cycles, cur, prev;
111 u64 start, end, tach; 128 u64 start, end, tach;
112 129
113 if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) 130 if (priv->fan->tach.func == DCB_GPIO_UNUSED)
114 return -ENODEV; 131 return -ENODEV;
115 132
116 /* Time a complete rotation and extrapolate to RPM: 133 /* Time a complete rotation and extrapolate to RPM:
@@ -118,12 +135,12 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm)
118 * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation. 135 * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation.
119 */ 136 */
120 start = ptimer->read(ptimer); 137 start = ptimer->read(ptimer);
121 prev = gpio->get(gpio, 0, func.func, func.line); 138 prev = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line);
122 cycles = 0; 139 cycles = 0;
123 do { 140 do {
124 usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ 141 usleep_range(500, 1000); /* supports 0 < rpm < 7500 */
125 142
126 cur = gpio->get(gpio, 0, func.func, func.line); 143 cur = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line);
127 if (prev != cur) { 144 if (prev != cur) {
128 if (!start) 145 if (!start)
129 start = ptimer->read(ptimer); 146 start = ptimer->read(ptimer);
@@ -142,34 +159,6 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm)
142} 159}
143 160
144int 161int
145nouveau_therm_fan_set_mode(struct nouveau_therm *therm,
146 enum nouveau_therm_fan_mode mode)
147{
148 struct nouveau_therm_priv *priv = (void *)therm;
149
150 if (priv->fan.mode == mode)
151 return 0;
152
153 if (mode < FAN_CONTROL_NONE || mode >= FAN_CONTROL_NR)
154 return -EINVAL;
155
156 switch (mode)
157 {
158 case FAN_CONTROL_NONE:
159 nv_info(therm, "switch fan to no-control mode\n");
160 break;
161 case FAN_CONTROL_MANUAL:
162 nv_info(therm, "switch fan to manual mode\n");
163 break;
164 case FAN_CONTROL_NR:
165 break;
166 }
167
168 priv->fan.mode = mode;
169 return 0;
170}
171
172int
173nouveau_therm_fan_user_get(struct nouveau_therm *therm) 162nouveau_therm_fan_user_get(struct nouveau_therm *therm)
174{ 163{
175 return nouveau_therm_fan_get(therm); 164 return nouveau_therm_fan_get(therm);
@@ -180,55 +169,86 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent)
180{ 169{
181 struct nouveau_therm_priv *priv = (void *)therm; 170 struct nouveau_therm_priv *priv = (void *)therm;
182 171
183 if (priv->fan.mode != FAN_CONTROL_MANUAL) 172 if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL)
184 return -EINVAL; 173 return -EINVAL;
185 174
186 return nouveau_therm_fan_set(therm, percent); 175 return nouveau_therm_fan_set(therm, true, percent);
187} 176}
188 177
189void 178static void
190nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) 179nouveau_therm_fan_set_defaults(struct nouveau_therm *therm)
191{ 180{
192 struct nouveau_therm_priv *priv = (void *)therm; 181 struct nouveau_therm_priv *priv = (void *)therm;
193 182
194 priv->bios_fan.pwm_freq = 0; 183 priv->fan->bios.pwm_freq = 0;
195 priv->bios_fan.min_duty = 0; 184 priv->fan->bios.min_duty = 0;
196 priv->bios_fan.max_duty = 100; 185 priv->fan->bios.max_duty = 100;
186 priv->fan->bios.bump_period = 500;
187 priv->fan->bios.slow_down_period = 2000;
188 priv->fan->bios.linear_min_temp = 40;
189 priv->fan->bios.linear_max_temp = 85;
197} 190}
198 191
199
200static void 192static void
201nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) 193nouveau_therm_fan_safety_checks(struct nouveau_therm *therm)
202{ 194{
203 struct nouveau_therm_priv *priv = (void *)therm; 195 struct nouveau_therm_priv *priv = (void *)therm;
204 196
205 if (priv->bios_fan.min_duty > 100) 197 if (priv->fan->bios.min_duty > 100)
206 priv->bios_fan.min_duty = 100; 198 priv->fan->bios.min_duty = 100;
207 if (priv->bios_fan.max_duty > 100) 199 if (priv->fan->bios.max_duty > 100)
208 priv->bios_fan.max_duty = 100; 200 priv->fan->bios.max_duty = 100;
209 201
210 if (priv->bios_fan.min_duty > priv->bios_fan.max_duty) 202 if (priv->fan->bios.min_duty > priv->fan->bios.max_duty)
211 priv->bios_fan.min_duty = priv->bios_fan.max_duty; 203 priv->fan->bios.min_duty = priv->fan->bios.max_duty;
212}
213
214int nouveau_fan_pwm_clock_dummy(struct nouveau_therm *therm)
215{
216 return 1;
217} 204}
218 205
219int 206int
220nouveau_therm_fan_ctor(struct nouveau_therm *therm) 207nouveau_therm_fan_ctor(struct nouveau_therm *therm)
221{ 208{
222 struct nouveau_therm_priv *priv = (void *)therm; 209 struct nouveau_therm_priv *priv = (void *)therm;
210 struct nouveau_gpio *gpio = nouveau_gpio(therm);
223 struct nouveau_bios *bios = nouveau_bios(therm); 211 struct nouveau_bios *bios = nouveau_bios(therm);
212 struct dcb_gpio_func func;
213 int ret;
224 214
215 /* attempt to locate a drivable fan, and determine control method */
216 ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
217 if (ret == 0) {
218 if (func.log[0] & DCB_GPIO_LOG_DIR_IN) {
219 nv_debug(therm, "GPIO_FAN is in input mode\n");
220 ret = -EINVAL;
221 } else {
222 ret = nouveau_fanpwm_create(therm, &func);
223 if (ret != 0)
224 ret = nouveau_fantog_create(therm, &func);
225 }
226 }
227
228 /* no controllable fan found, create a dummy fan module */
229 if (ret != 0) {
230 ret = nouveau_fannil_create(therm);
231 if (ret)
232 return ret;
233 }
234
235 nv_info(therm, "FAN control: %s\n", priv->fan->type);
236
237 /* attempt to detect a tachometer connection */
238 ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach);
239 if (ret)
240 priv->fan->tach.func = DCB_GPIO_UNUSED;
241
242 /* initialise fan bump/slow update handling */
243 priv->fan->parent = therm;
244 nouveau_alarm_init(&priv->fan->alarm, nouveau_fan_alarm);
245 spin_lock_init(&priv->fan->lock);
246
247 /* other random init... */
225 nouveau_therm_fan_set_defaults(therm); 248 nouveau_therm_fan_set_defaults(therm);
226 nvbios_perf_fan_parse(bios, &priv->bios_perf_fan); 249 nvbios_perf_fan_parse(bios, &priv->fan->perf);
227 if (nvbios_therm_fan_parse(bios, &priv->bios_fan)) 250 if (nvbios_therm_fan_parse(bios, &priv->fan->bios))
228 nv_error(therm, "parsing the thermal table failed\n"); 251 nv_error(therm, "parsing the thermal table failed\n");
229 nouveau_therm_fan_safety_checks(therm); 252 nouveau_therm_fan_safety_checks(therm);
230
231 nouveau_therm_fan_set_mode(therm, FAN_CONTROL_NONE);
232
233 return 0; 253 return 0;
234} 254}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c
new file mode 100644
index 000000000000..b78c182e1d51
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "priv.h"
26
27static int
28nouveau_fannil_get(struct nouveau_therm *therm)
29{
30 return -ENODEV;
31}
32
33static int
34nouveau_fannil_set(struct nouveau_therm *therm, int percent)
35{
36 return -ENODEV;
37}
38
39int
40nouveau_fannil_create(struct nouveau_therm *therm)
41{
42 struct nouveau_therm_priv *tpriv = (void *)therm;
43 struct nouveau_fan *priv;
44
45 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
46 tpriv->fan = priv;
47 if (!priv)
48 return -ENOMEM;
49
50 priv->type = "none / external";
51 priv->get = nouveau_fannil_get;
52 priv->set = nouveau_fannil_set;
53 return 0;
54}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
new file mode 100644
index 000000000000..5f71db8e8992
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
@@ -0,0 +1,107 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 * Martin Peres
24 */
25
26#include <core/option.h>
27#include <subdev/gpio.h>
28
29#include "priv.h"
30
31struct nouveau_fanpwm_priv {
32 struct nouveau_fan base;
33 struct dcb_gpio_func func;
34};
35
36static int
37nouveau_fanpwm_get(struct nouveau_therm *therm)
38{
39 struct nouveau_therm_priv *tpriv = (void *)therm;
40 struct nouveau_fanpwm_priv *priv = (void *)tpriv->fan;
41 struct nouveau_gpio *gpio = nouveau_gpio(therm);
42 int card_type = nv_device(therm)->card_type;
43 u32 divs, duty;
44 int ret;
45
46 ret = therm->pwm_get(therm, priv->func.line, &divs, &duty);
47 if (ret == 0 && divs) {
48 divs = max(divs, duty);
49 if (card_type <= NV_40 || (priv->func.log[0] & 1))
50 duty = divs - duty;
51 return (duty * 100) / divs;
52 }
53
54 return gpio->get(gpio, 0, priv->func.func, priv->func.line) * 100;
55}
56
57static int
58nouveau_fanpwm_set(struct nouveau_therm *therm, int percent)
59{
60 struct nouveau_therm_priv *tpriv = (void *)therm;
61 struct nouveau_fanpwm_priv *priv = (void *)tpriv->fan;
62 int card_type = nv_device(therm)->card_type;
63 u32 divs, duty;
64 int ret;
65
66 divs = priv->base.perf.pwm_divisor;
67 if (priv->base.bios.pwm_freq) {
68 divs = 1;
69 if (therm->pwm_clock)
70 divs = therm->pwm_clock(therm);
71 divs /= priv->base.bios.pwm_freq;
72 }
73
74 duty = ((divs * percent) + 99) / 100;
75 if (card_type <= NV_40 || (priv->func.log[0] & 1))
76 duty = divs - duty;
77
78 ret = therm->pwm_set(therm, priv->func.line, divs, duty);
79 if (ret == 0)
80 ret = therm->pwm_ctrl(therm, priv->func.line, true);
81 return ret;
82}
83
84int
85nouveau_fanpwm_create(struct nouveau_therm *therm, struct dcb_gpio_func *func)
86{
87 struct nouveau_device *device = nv_device(therm);
88 struct nouveau_therm_priv *tpriv = (void *)therm;
89 struct nouveau_fanpwm_priv *priv;
90 u32 divs, duty;
91
92 if (!nouveau_boolopt(device->cfgopt, "NvFanPWM", func->param) ||
93 !therm->pwm_ctrl ||
94 therm->pwm_get(therm, func->line, &divs, &duty) == -ENODEV)
95 return -ENODEV;
96
97 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
98 tpriv->fan = &priv->base;
99 if (!priv)
100 return -ENOMEM;
101
102 priv->base.type = "PWM";
103 priv->base.get = nouveau_fanpwm_get;
104 priv->base.set = nouveau_fanpwm_set;
105 priv->func = *func;
106 return 0;
107}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c
new file mode 100644
index 000000000000..e601773ee475
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c
@@ -0,0 +1,115 @@
1/*
2 * Copyright 2012 The Nouveau community
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Martin Peres
23 */
24
25#include "priv.h"
26
27#include <core/object.h>
28#include <core/device.h>
29
30#include <subdev/gpio.h>
31#include <subdev/timer.h>
32
33struct nouveau_fantog_priv {
34 struct nouveau_fan base;
35 struct nouveau_alarm alarm;
36 spinlock_t lock;
37 u32 period_us;
38 u32 percent;
39 struct dcb_gpio_func func;
40};
41
42static void
43nouveau_fantog_update(struct nouveau_fantog_priv *priv, int percent)
44{
45 struct nouveau_therm_priv *tpriv = (void *)priv->base.parent;
46 struct nouveau_timer *ptimer = nouveau_timer(tpriv);
47 struct nouveau_gpio *gpio = nouveau_gpio(tpriv);
48 unsigned long flags;
49 int duty;
50
51 spin_lock_irqsave(&priv->lock, flags);
52 if (percent < 0)
53 percent = priv->percent;
54 priv->percent = percent;
55
56 duty = !gpio->get(gpio, 0, DCB_GPIO_FAN, 0xff);
57 gpio->set(gpio, 0, DCB_GPIO_FAN, 0xff, duty);
58
59 if (list_empty(&priv->alarm.head) && percent != (duty * 100)) {
60 u64 next_change = (percent * priv->period_us) / 100;
61 if (!duty)
62 next_change = priv->period_us - next_change;
63 ptimer->alarm(ptimer, next_change * 1000, &priv->alarm);
64 }
65 spin_unlock_irqrestore(&priv->lock, flags);
66}
67
68static void
69nouveau_fantog_alarm(struct nouveau_alarm *alarm)
70{
71 struct nouveau_fantog_priv *priv =
72 container_of(alarm, struct nouveau_fantog_priv, alarm);
73 nouveau_fantog_update(priv, -1);
74}
75
76static int
77nouveau_fantog_get(struct nouveau_therm *therm)
78{
79 struct nouveau_therm_priv *tpriv = (void *)therm;
80 struct nouveau_fantog_priv *priv = (void *)tpriv->fan;
81 return priv->percent;
82}
83
84static int
85nouveau_fantog_set(struct nouveau_therm *therm, int percent)
86{
87 struct nouveau_therm_priv *tpriv = (void *)therm;
88 struct nouveau_fantog_priv *priv = (void *)tpriv->fan;
89 if (therm->pwm_ctrl)
90 therm->pwm_ctrl(therm, priv->func.line, false);
91 nouveau_fantog_update(priv, percent);
92 return 0;
93}
94
95int
96nouveau_fantog_create(struct nouveau_therm *therm, struct dcb_gpio_func *func)
97{
98 struct nouveau_therm_priv *tpriv = (void *)therm;
99 struct nouveau_fantog_priv *priv;
100
101 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
102 tpriv->fan = &priv->base;
103 if (!priv)
104 return -ENOMEM;
105
106 priv->base.type = "toggle";
107 priv->base.get = nouveau_fantog_get;
108 priv->base.set = nouveau_fantog_set;
109 nouveau_alarm_init(&priv->alarm, nouveau_fantog_alarm);
110 priv->period_us = 100000; /* 10Hz */
111 priv->percent = 100;
112 priv->func = *func;
113 spin_lock_init(&priv->lock);
114 return 0;
115}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
index e512ff0aae60..e24090bac195 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
@@ -31,7 +31,7 @@ static bool
31probe_monitoring_device(struct nouveau_i2c_port *i2c, 31probe_monitoring_device(struct nouveau_i2c_port *i2c,
32 struct i2c_board_info *info) 32 struct i2c_board_info *info)
33{ 33{
34 struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c->i2c); 34 struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
35 struct i2c_client *client; 35 struct i2c_client *client;
36 36
37 request_module("%s%s", I2C_MODULE_PREFIX, info->type); 37 request_module("%s%s", I2C_MODULE_PREFIX, info->type);
@@ -53,6 +53,31 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
53 return true; 53 return true;
54} 54}
55 55
56static struct i2c_board_info
57nv_board_infos[] = {
58 { I2C_BOARD_INFO("w83l785ts", 0x2d) },
59 { I2C_BOARD_INFO("w83781d", 0x2d) },
60 { I2C_BOARD_INFO("adt7473", 0x2e) },
61 { I2C_BOARD_INFO("adt7473", 0x2d) },
62 { I2C_BOARD_INFO("adt7473", 0x2c) },
63 { I2C_BOARD_INFO("f75375", 0x2e) },
64 { I2C_BOARD_INFO("lm99", 0x4c) },
65 { I2C_BOARD_INFO("lm90", 0x4c) },
66 { I2C_BOARD_INFO("lm90", 0x4d) },
67 { I2C_BOARD_INFO("adm1021", 0x18) },
68 { I2C_BOARD_INFO("adm1021", 0x19) },
69 { I2C_BOARD_INFO("adm1021", 0x1a) },
70 { I2C_BOARD_INFO("adm1021", 0x29) },
71 { I2C_BOARD_INFO("adm1021", 0x2a) },
72 { I2C_BOARD_INFO("adm1021", 0x2b) },
73 { I2C_BOARD_INFO("adm1021", 0x4c) },
74 { I2C_BOARD_INFO("adm1021", 0x4d) },
75 { I2C_BOARD_INFO("adm1021", 0x4e) },
76 { I2C_BOARD_INFO("lm63", 0x18) },
77 { I2C_BOARD_INFO("lm63", 0x4e) },
78 { }
79};
80
56void 81void
57nouveau_therm_ic_ctor(struct nouveau_therm *therm) 82nouveau_therm_ic_ctor(struct nouveau_therm *therm)
58{ 83{
@@ -60,29 +85,6 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
60 struct nouveau_bios *bios = nouveau_bios(therm); 85 struct nouveau_bios *bios = nouveau_bios(therm);
61 struct nouveau_i2c *i2c = nouveau_i2c(therm); 86 struct nouveau_i2c *i2c = nouveau_i2c(therm);
62 struct nvbios_extdev_func extdev_entry; 87 struct nvbios_extdev_func extdev_entry;
63 struct i2c_board_info info[] = {
64 { I2C_BOARD_INFO("w83l785ts", 0x2d) },
65 { I2C_BOARD_INFO("w83781d", 0x2d) },
66 { I2C_BOARD_INFO("adt7473", 0x2e) },
67 { I2C_BOARD_INFO("adt7473", 0x2d) },
68 { I2C_BOARD_INFO("adt7473", 0x2c) },
69 { I2C_BOARD_INFO("f75375", 0x2e) },
70 { I2C_BOARD_INFO("lm99", 0x4c) },
71 { I2C_BOARD_INFO("lm90", 0x4c) },
72 { I2C_BOARD_INFO("lm90", 0x4d) },
73 { I2C_BOARD_INFO("adm1021", 0x18) },
74 { I2C_BOARD_INFO("adm1021", 0x19) },
75 { I2C_BOARD_INFO("adm1021", 0x1a) },
76 { I2C_BOARD_INFO("adm1021", 0x29) },
77 { I2C_BOARD_INFO("adm1021", 0x2a) },
78 { I2C_BOARD_INFO("adm1021", 0x2b) },
79 { I2C_BOARD_INFO("adm1021", 0x4c) },
80 { I2C_BOARD_INFO("adm1021", 0x4d) },
81 { I2C_BOARD_INFO("adm1021", 0x4e) },
82 { I2C_BOARD_INFO("lm63", 0x18) },
83 { I2C_BOARD_INFO("lm63", 0x4e) },
84 { }
85 };
86 88
87 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { 89 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) {
88 struct i2c_board_info board[] = { 90 struct i2c_board_info board[] = {
@@ -111,6 +113,6 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
111 /* The vbios doesn't provide the address of an exisiting monitoring 113 /* The vbios doesn't provide the address of an exisiting monitoring
112 device. Let's try our static list. 114 device. Let's try our static list.
113 */ 115 */
114 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, 116 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
115 probe_monitoring_device); 117 nv_board_infos, probe_monitoring_device);
116} 118}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
index fcf2cfe731d6..0f5363edb964 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
@@ -25,6 +25,10 @@
25 25
26#include "priv.h" 26#include "priv.h"
27 27
28struct nv40_therm_priv {
29 struct nouveau_therm_priv base;
30};
31
28static int 32static int
29nv40_sensor_setup(struct nouveau_therm *therm) 33nv40_sensor_setup(struct nouveau_therm *therm)
30{ 34{
@@ -34,6 +38,7 @@ nv40_sensor_setup(struct nouveau_therm *therm)
34 if (device->chipset >= 0x46) { 38 if (device->chipset >= 0x46) {
35 nv_mask(therm, 0x15b8, 0x80000000, 0); 39 nv_mask(therm, 0x15b8, 0x80000000, 0);
36 nv_wr32(therm, 0x15b0, 0x80003fff); 40 nv_wr32(therm, 0x15b0, 0x80003fff);
41 mdelay(10); /* wait for the temperature to stabilize */
37 return nv_rd32(therm, 0x15b4) & 0x3fff; 42 return nv_rd32(therm, 0x15b4) & 0x3fff;
38 } else { 43 } else {
39 nv_wr32(therm, 0x15b0, 0xff); 44 nv_wr32(therm, 0x15b0, 0xff);
@@ -75,7 +80,20 @@ nv40_temp_get(struct nouveau_therm *therm)
75 return core_temp; 80 return core_temp;
76} 81}
77 82
78int 83static int
84nv40_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
85{
86 u32 mask = enable ? 0x80000000 : 0x0000000;
87 if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask);
88 else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask);
89 else {
90 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
91 return -ENODEV;
92 }
93 return 0;
94}
95
96static int
79nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 97nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
80{ 98{
81 if (line == 2) { 99 if (line == 2) {
@@ -101,15 +119,15 @@ nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
101 return -EINVAL; 119 return -EINVAL;
102} 120}
103 121
104int 122static int
105nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) 123nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
106{ 124{
107 if (line == 2) { 125 if (line == 2) {
108 nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs); 126 nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
109 } else 127 } else
110 if (line == 9) { 128 if (line == 9) {
111 nv_wr32(therm, 0x0015f8, divs); 129 nv_wr32(therm, 0x0015f8, divs);
112 nv_wr32(therm, 0x0015f4, duty | 0x80000000); 130 nv_mask(therm, 0x0015f4, 0x7fffffff, duty);
113 } else { 131 } else {
114 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); 132 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
115 return -ENODEV; 133 return -ENODEV;
@@ -118,37 +136,51 @@ nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
118 return 0; 136 return 0;
119} 137}
120 138
139static void
140nv40_therm_intr(struct nouveau_subdev *subdev)
141{
142 struct nouveau_therm *therm = nouveau_therm(subdev);
143 uint32_t stat = nv_rd32(therm, 0x1100);
144
145 /* traitement */
146
147 /* ack all IRQs */
148 nv_wr32(therm, 0x1100, 0x70000);
149
150 nv_error(therm, "THERM received an IRQ: stat = %x\n", stat);
151}
152
121static int 153static int
122nv40_therm_ctor(struct nouveau_object *parent, 154nv40_therm_ctor(struct nouveau_object *parent,
123 struct nouveau_object *engine, 155 struct nouveau_object *engine,
124 struct nouveau_oclass *oclass, void *data, u32 size, 156 struct nouveau_oclass *oclass, void *data, u32 size,
125 struct nouveau_object **pobject) 157 struct nouveau_object **pobject)
126{ 158{
127 struct nouveau_therm_priv *priv; 159 struct nv40_therm_priv *priv;
128 struct nouveau_therm *therm;
129 int ret; 160 int ret;
130 161
131 ret = nouveau_therm_create(parent, engine, oclass, &priv); 162 ret = nouveau_therm_create(parent, engine, oclass, &priv);
132 *pobject = nv_object(priv); 163 *pobject = nv_object(priv);
133 therm = (void *) priv;
134 if (ret) 164 if (ret)
135 return ret; 165 return ret;
136 166
137 nouveau_therm_ic_ctor(therm); 167 priv->base.base.pwm_ctrl = nv40_fan_pwm_ctrl;
138 nouveau_therm_sensor_ctor(therm); 168 priv->base.base.pwm_get = nv40_fan_pwm_get;
139 nouveau_therm_fan_ctor(therm); 169 priv->base.base.pwm_set = nv40_fan_pwm_set;
170 priv->base.base.temp_get = nv40_temp_get;
171 priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling;
172 nv_subdev(priv)->intr = nv40_therm_intr;
173 return nouveau_therm_preinit(&priv->base.base);
174}
140 175
141 priv->fan.pwm_get = nv40_fan_pwm_get; 176static int
142 priv->fan.pwm_set = nv40_fan_pwm_set; 177nv40_therm_init(struct nouveau_object *object)
178{
179 struct nouveau_therm *therm = (void *)object;
143 180
144 therm->temp_get = nv40_temp_get; 181 nv40_sensor_setup(therm);
145 therm->fan_get = nouveau_therm_fan_user_get;
146 therm->fan_set = nouveau_therm_fan_user_set;
147 therm->fan_sense = nouveau_therm_fan_sense;
148 therm->attr_get = nouveau_therm_attr_get;
149 therm->attr_set = nouveau_therm_attr_set;
150 182
151 return 0; 183 return _nouveau_therm_init(object);
152} 184}
153 185
154struct nouveau_oclass 186struct nouveau_oclass
@@ -157,7 +189,7 @@ nv40_therm_oclass = {
157 .ofuncs = &(struct nouveau_ofuncs) { 189 .ofuncs = &(struct nouveau_ofuncs) {
158 .ctor = nv40_therm_ctor, 190 .ctor = nv40_therm_ctor,
159 .dtor = _nouveau_therm_dtor, 191 .dtor = _nouveau_therm_dtor,
160 .init = nouveau_therm_init, 192 .init = nv40_therm_init,
161 .fini = nouveau_therm_fini, 193 .fini = _nouveau_therm_fini,
162 }, 194 },
163}; \ No newline at end of file 195};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index 9360ddd469e7..86632cbd65ce 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -25,6 +25,10 @@
25 25
26#include "priv.h" 26#include "priv.h"
27 27
28struct nv50_therm_priv {
29 struct nouveau_therm_priv base;
30};
31
28static int 32static int
29pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx) 33pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx)
30{ 34{
@@ -51,6 +55,16 @@ pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx)
51} 55}
52 56
53int 57int
58nv50_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
59{
60 u32 data = enable ? 0x00000001 : 0x00000000;
61 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
62 if (ret == 0)
63 nv_mask(therm, ctrl, 0x00010001 << line, data << line);
64 return ret;
65}
66
67int
54nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 68nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
55{ 69{
56 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); 70 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
@@ -73,7 +87,6 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
73 if (ret) 87 if (ret)
74 return ret; 88 return ret;
75 89
76 nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line);
77 nv_wr32(therm, 0x00e114 + (id * 8), divs); 90 nv_wr32(therm, 0x00e114 + (id * 8), divs);
78 nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); 91 nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000);
79 return 0; 92 return 0;
@@ -111,38 +124,178 @@ nv50_temp_get(struct nouveau_therm *therm)
111 return nv_rd32(therm, 0x20400); 124 return nv_rd32(therm, 0x20400);
112} 125}
113 126
127static void
128nv50_therm_program_alarms(struct nouveau_therm *therm)
129{
130 struct nouveau_therm_priv *priv = (void *)therm;
131 struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
132 unsigned long flags;
133
134 spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
135
136 /* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */
137 nv_wr32(therm, 0x20000, 0x000003ff);
138
139 /* shutdown: The computer should be shutdown when reached */
140 nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis);
141 nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp);
142
143 /* THRS_1 : fan boost*/
144 nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp);
145
146 /* THRS_2 : critical */
147 nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp);
148
149 /* THRS_4 : down clock */
150 nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp);
151 spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
152
153 nv_info(therm,
154 "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
155 sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
156 sensor->thrs_down_clock.temp,
157 sensor->thrs_down_clock.hysteresis,
158 sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
159 sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
160
161}
162
163/* must be called with alarm_program_lock taken ! */
164static void
165nv50_therm_threshold_hyst_emulation(struct nouveau_therm *therm,
166 uint32_t thrs_reg, u8 status_bit,
167 const struct nvbios_therm_threshold *thrs,
168 enum nouveau_therm_thrs thrs_name)
169{
170 enum nouveau_therm_thrs_direction direction;
171 enum nouveau_therm_thrs_state prev_state, new_state;
172 int temp, cur;
173
174 prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name);
175 temp = nv_rd32(therm, thrs_reg);
176
177 /* program the next threshold */
178 if (temp == thrs->temp) {
179 nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis);
180 new_state = NOUVEAU_THERM_THRS_HIGHER;
181 } else {
182 nv_wr32(therm, thrs_reg, thrs->temp);
183 new_state = NOUVEAU_THERM_THRS_LOWER;
184 }
185
186 /* fix the state (in case someone reprogrammed the alarms) */
187 cur = therm->temp_get(therm);
188 if (new_state == NOUVEAU_THERM_THRS_LOWER && cur > thrs->temp)
189 new_state = NOUVEAU_THERM_THRS_HIGHER;
190 else if (new_state == NOUVEAU_THERM_THRS_HIGHER &&
191 cur < thrs->temp - thrs->hysteresis)
192 new_state = NOUVEAU_THERM_THRS_LOWER;
193 nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state);
194
195 /* find the direction */
196 if (prev_state < new_state)
197 direction = NOUVEAU_THERM_THRS_RISING;
198 else if (prev_state > new_state)
199 direction = NOUVEAU_THERM_THRS_FALLING;
200 else
201 return;
202
203 /* advertise a change in direction */
204 nouveau_therm_sensor_event(therm, thrs_name, direction);
205}
206
207static void
208nv50_therm_intr(struct nouveau_subdev *subdev)
209{
210 struct nouveau_therm *therm = nouveau_therm(subdev);
211 struct nouveau_therm_priv *priv = (void *)therm;
212 struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
213 unsigned long flags;
214 uint32_t intr;
215
216 spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
217
218 intr = nv_rd32(therm, 0x20100);
219
220 /* THRS_4: downclock */
221 if (intr & 0x002) {
222 nv50_therm_threshold_hyst_emulation(therm, 0x20414, 24,
223 &sensor->thrs_down_clock,
224 NOUVEAU_THERM_THRS_DOWNCLOCK);
225 intr &= ~0x002;
226 }
227
228 /* shutdown */
229 if (intr & 0x004) {
230 nv50_therm_threshold_hyst_emulation(therm, 0x20480, 20,
231 &sensor->thrs_shutdown,
232 NOUVEAU_THERM_THRS_SHUTDOWN);
233 intr &= ~0x004;
234 }
235
236 /* THRS_1 : fan boost */
237 if (intr & 0x008) {
238 nv50_therm_threshold_hyst_emulation(therm, 0x204c4, 21,
239 &sensor->thrs_fan_boost,
240 NOUVEAU_THERM_THRS_FANBOOST);
241 intr &= ~0x008;
242 }
243
244 /* THRS_2 : critical */
245 if (intr & 0x010) {
246 nv50_therm_threshold_hyst_emulation(therm, 0x204c0, 22,
247 &sensor->thrs_critical,
248 NOUVEAU_THERM_THRS_CRITICAL);
249 intr &= ~0x010;
250 }
251
252 if (intr)
253 nv_error(therm, "unhandled intr 0x%08x\n", intr);
254
255 /* ACK everything */
256 nv_wr32(therm, 0x20100, 0xffffffff);
257 nv_wr32(therm, 0x1100, 0x10000); /* PBUS */
258
259 spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
260}
261
114static int 262static int
115nv50_therm_ctor(struct nouveau_object *parent, 263nv50_therm_ctor(struct nouveau_object *parent,
116 struct nouveau_object *engine, 264 struct nouveau_object *engine,
117 struct nouveau_oclass *oclass, void *data, u32 size, 265 struct nouveau_oclass *oclass, void *data, u32 size,
118 struct nouveau_object **pobject) 266 struct nouveau_object **pobject)
119{ 267{
120 struct nouveau_therm_priv *priv; 268 struct nv50_therm_priv *priv;
121 struct nouveau_therm *therm;
122 int ret; 269 int ret;
123 270
124 ret = nouveau_therm_create(parent, engine, oclass, &priv); 271 ret = nouveau_therm_create(parent, engine, oclass, &priv);
125 *pobject = nv_object(priv); 272 *pobject = nv_object(priv);
126 therm = (void *) priv;
127 if (ret) 273 if (ret)
128 return ret; 274 return ret;
129 275
130 nouveau_therm_ic_ctor(therm); 276 priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl;
131 nouveau_therm_sensor_ctor(therm); 277 priv->base.base.pwm_get = nv50_fan_pwm_get;
132 nouveau_therm_fan_ctor(therm); 278 priv->base.base.pwm_set = nv50_fan_pwm_set;
279 priv->base.base.pwm_clock = nv50_fan_pwm_clock;
280 priv->base.base.temp_get = nv50_temp_get;
281 priv->base.sensor.program_alarms = nv50_therm_program_alarms;
282 nv_subdev(priv)->intr = nv50_therm_intr;
133 283
134 priv->fan.pwm_get = nv50_fan_pwm_get; 284 /* init the thresholds */
135 priv->fan.pwm_set = nv50_fan_pwm_set; 285 nouveau_therm_sensor_set_threshold_state(&priv->base.base,
136 priv->fan.pwm_clock = nv50_fan_pwm_clock; 286 NOUVEAU_THERM_THRS_SHUTDOWN,
287 NOUVEAU_THERM_THRS_LOWER);
288 nouveau_therm_sensor_set_threshold_state(&priv->base.base,
289 NOUVEAU_THERM_THRS_FANBOOST,
290 NOUVEAU_THERM_THRS_LOWER);
291 nouveau_therm_sensor_set_threshold_state(&priv->base.base,
292 NOUVEAU_THERM_THRS_CRITICAL,
293 NOUVEAU_THERM_THRS_LOWER);
294 nouveau_therm_sensor_set_threshold_state(&priv->base.base,
295 NOUVEAU_THERM_THRS_DOWNCLOCK,
296 NOUVEAU_THERM_THRS_LOWER);
137 297
138 therm->temp_get = nv50_temp_get; 298 return nouveau_therm_preinit(&priv->base.base);
139 therm->fan_get = nouveau_therm_fan_user_get;
140 therm->fan_set = nouveau_therm_fan_user_set;
141 therm->fan_sense = nouveau_therm_fan_sense;
142 therm->attr_get = nouveau_therm_attr_get;
143 therm->attr_set = nouveau_therm_attr_set;
144
145 return 0;
146} 299}
147 300
148struct nouveau_oclass 301struct nouveau_oclass
@@ -151,7 +304,7 @@ nv50_therm_oclass = {
151 .ofuncs = &(struct nouveau_ofuncs) { 304 .ofuncs = &(struct nouveau_ofuncs) {
152 .ctor = nv50_therm_ctor, 305 .ctor = nv50_therm_ctor,
153 .dtor = _nouveau_therm_dtor, 306 .dtor = _nouveau_therm_dtor,
154 .init = nouveau_therm_init, 307 .init = _nouveau_therm_init,
155 .fini = nouveau_therm_fini, 308 .fini = _nouveau_therm_fini,
156 }, 309 },
157}; 310};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
new file mode 100644
index 000000000000..2dcc5437116a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <subdev/gpio.h>
26
27#include "priv.h"
28
29struct nva3_therm_priv {
30 struct nouveau_therm_priv base;
31};
32
33int
34nva3_therm_fan_sense(struct nouveau_therm *therm)
35{
36 u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff;
37 u32 ctrl = nv_rd32(therm, 0x00e720);
38 if (ctrl & 0x00000001)
39 return tach * 60;
40 return -ENODEV;
41}
42
43static int
44nva3_therm_init(struct nouveau_object *object)
45{
46 struct nva3_therm_priv *priv = (void *)object;
47 struct dcb_gpio_func *tach = &priv->base.fan->tach;
48 int ret;
49
50 ret = nouveau_therm_init(&priv->base.base);
51 if (ret)
52 return ret;
53
54 /* enable fan tach, count revolutions per-second */
55 nv_mask(priv, 0x00e720, 0x00000003, 0x00000002);
56 if (tach->func != DCB_GPIO_UNUSED) {
57 nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000);
58 nv_mask(priv, 0x00e720, 0x001f0000, tach->line << 16);
59 nv_mask(priv, 0x00e720, 0x00000001, 0x00000001);
60 }
61 nv_mask(priv, 0x00e720, 0x00000002, 0x00000000);
62
63 return 0;
64}
65
66static int
67nva3_therm_ctor(struct nouveau_object *parent,
68 struct nouveau_object *engine,
69 struct nouveau_oclass *oclass, void *data, u32 size,
70 struct nouveau_object **pobject)
71{
72 struct nva3_therm_priv *priv;
73 int ret;
74
75 ret = nouveau_therm_create(parent, engine, oclass, &priv);
76 *pobject = nv_object(priv);
77 if (ret)
78 return ret;
79
80 priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl;
81 priv->base.base.pwm_get = nv50_fan_pwm_get;
82 priv->base.base.pwm_set = nv50_fan_pwm_set;
83 priv->base.base.pwm_clock = nv50_fan_pwm_clock;
84 priv->base.base.temp_get = nv50_temp_get;
85 priv->base.base.fan_sense = nva3_therm_fan_sense;
86 priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling;
87 return nouveau_therm_preinit(&priv->base.base);
88}
89
90struct nouveau_oclass
91nva3_therm_oclass = {
92 .handle = NV_SUBDEV(THERM, 0xa3),
93 .ofuncs = &(struct nouveau_ofuncs) {
94 .ctor = nva3_therm_ctor,
95 .dtor = _nouveau_therm_dtor,
96 .init = nva3_therm_init,
97 .fini = _nouveau_therm_fini,
98 },
99};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
new file mode 100644
index 000000000000..d7d30ee8332e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -0,0 +1,153 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "priv.h"
26
27struct nvd0_therm_priv {
28 struct nouveau_therm_priv base;
29};
30
31static int
32pwm_info(struct nouveau_therm *therm, int line)
33{
34 u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
35 switch (gpio & 0x000000c0) {
36 case 0x00000000: /* normal mode, possibly pwm forced off by us */
37 case 0x00000040: /* nvio special */
38 switch (gpio & 0x0000001f) {
39 case 0x19: return 1;
40 case 0x1c: return 0;
41 default:
42 break;
43 }
44 default:
45 break;
46 }
47
48 nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio);
49 return -ENODEV;
50}
51
52static int
53nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
54{
55 u32 data = enable ? 0x00000040 : 0x00000000;
56 int indx = pwm_info(therm, line);
57 if (indx < 0)
58 return indx;
59
60 nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
61 return 0;
62}
63
64static int
65nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
66{
67 int indx = pwm_info(therm, line);
68 if (indx < 0)
69 return indx;
70
71 if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
72 *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
73 *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
74 return 0;
75 }
76
77 return -EINVAL;
78}
79
80static int
81nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
82{
83 int indx = pwm_info(therm, line);
84 if (indx < 0)
85 return indx;
86
87 nv_wr32(therm, 0x00e114 + (indx * 8), divs);
88 nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
89 return 0;
90}
91
92static int
93nvd0_fan_pwm_clock(struct nouveau_therm *therm)
94{
95 return (nv_device(therm)->crystal * 1000) / 20;
96}
97
98static int
99nvd0_therm_init(struct nouveau_object *object)
100{
101 struct nvd0_therm_priv *priv = (void *)object;
102 int ret;
103
104 ret = nouveau_therm_init(&priv->base.base);
105 if (ret)
106 return ret;
107
108 /* enable fan tach, count revolutions per-second */
109 nv_mask(priv, 0x00e720, 0x00000003, 0x00000002);
110 if (priv->base.fan->tach.func != DCB_GPIO_UNUSED) {
111 nv_mask(priv, 0x00d79c, 0x000000ff, priv->base.fan->tach.line);
112 nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000);
113 nv_mask(priv, 0x00e720, 0x00000001, 0x00000001);
114 }
115 nv_mask(priv, 0x00e720, 0x00000002, 0x00000000);
116
117 return 0;
118}
119
120static int
121nvd0_therm_ctor(struct nouveau_object *parent,
122 struct nouveau_object *engine,
123 struct nouveau_oclass *oclass, void *data, u32 size,
124 struct nouveau_object **pobject)
125{
126 struct nvd0_therm_priv *priv;
127 int ret;
128
129 ret = nouveau_therm_create(parent, engine, oclass, &priv);
130 *pobject = nv_object(priv);
131 if (ret)
132 return ret;
133
134 priv->base.base.pwm_ctrl = nvd0_fan_pwm_ctrl;
135 priv->base.base.pwm_get = nvd0_fan_pwm_get;
136 priv->base.base.pwm_set = nvd0_fan_pwm_set;
137 priv->base.base.pwm_clock = nvd0_fan_pwm_clock;
138 priv->base.base.temp_get = nv50_temp_get;
139 priv->base.base.fan_sense = nva3_therm_fan_sense;
140 priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling;
141 return nouveau_therm_preinit(&priv->base.base);
142}
143
144struct nouveau_oclass
145nvd0_therm_oclass = {
146 .handle = NV_SUBDEV(THERM, 0xd0),
147 .ofuncs = &(struct nouveau_ofuncs) {
148 .ctor = nvd0_therm_ctor,
149 .dtor = _nouveau_therm_dtor,
150 .init = nvd0_therm_init,
151 .fini = _nouveau_therm_fini,
152 },
153};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index 1c3cd6abc36e..06b98706b3fc 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -1,3 +1,6 @@
1#ifndef __NVTHERM_PRIV_H__
2#define __NVTHERM_PRIV_H__
3
1/* 4/*
2 * Copyright 2012 The Nouveau community 5 * Copyright 2012 The Nouveau community
3 * 6 *
@@ -25,33 +28,81 @@
25#include <subdev/therm.h> 28#include <subdev/therm.h>
26 29
27#include <subdev/bios/extdev.h> 30#include <subdev/bios/extdev.h>
31#include <subdev/bios/gpio.h>
28#include <subdev/bios/perf.h> 32#include <subdev/bios/perf.h>
29#include <subdev/bios/therm.h> 33#include <subdev/bios/therm.h>
34#include <subdev/timer.h>
35
36struct nouveau_fan {
37 struct nouveau_therm *parent;
38 const char *type;
39
40 struct nvbios_therm_fan bios;
41 struct nvbios_perf_fan perf;
42
43 struct nouveau_alarm alarm;
44 spinlock_t lock;
45 int percent;
46
47 int (*get)(struct nouveau_therm *therm);
48 int (*set)(struct nouveau_therm *therm, int percent);
49
50 struct dcb_gpio_func tach;
51};
52
53enum nouveau_therm_thrs_direction {
54 NOUVEAU_THERM_THRS_FALLING = 0,
55 NOUVEAU_THERM_THRS_RISING = 1
56};
57
58enum nouveau_therm_thrs_state {
59 NOUVEAU_THERM_THRS_LOWER = 0,
60 NOUVEAU_THERM_THRS_HIGHER = 1
61};
62
63enum nouveau_therm_thrs {
64 NOUVEAU_THERM_THRS_FANBOOST = 0,
65 NOUVEAU_THERM_THRS_DOWNCLOCK = 1,
66 NOUVEAU_THERM_THRS_CRITICAL = 2,
67 NOUVEAU_THERM_THRS_SHUTDOWN = 3,
68 NOUVEAU_THERM_THRS_NR
69};
30 70
31struct nouveau_therm_priv { 71struct nouveau_therm_priv {
32 struct nouveau_therm base; 72 struct nouveau_therm base;
33 73
74 /* automatic thermal management */
75 struct nouveau_alarm alarm;
76 spinlock_t lock;
77 struct nouveau_therm_trip_point *last_trip;
78 int mode;
79 int suspend;
80
34 /* bios */ 81 /* bios */
35 struct nvbios_therm_sensor bios_sensor; 82 struct nvbios_therm_sensor bios_sensor;
36 struct nvbios_therm_fan bios_fan;
37 struct nvbios_perf_fan bios_perf_fan;
38 83
39 /* fan priv */ 84 /* fan priv */
85 struct nouveau_fan *fan;
86
87 /* alarms priv */
40 struct { 88 struct {
41 enum nouveau_therm_fan_mode mode; 89 spinlock_t alarm_program_lock;
42 int percent; 90 struct nouveau_alarm therm_poll_alarm;
91 enum nouveau_therm_thrs_state alarm_state[NOUVEAU_THERM_THRS_NR];
92 void (*program_alarms)(struct nouveau_therm *);
93 } sensor;
43 94
44 int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); 95 /* what should be done if the card overheats */
45 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); 96 struct {
46 int (*pwm_clock)(struct nouveau_therm *); 97 void (*downclock)(struct nouveau_therm *, bool active);
47 } fan; 98 void (*pause)(struct nouveau_therm *, bool active);
99 } emergency;
48 100
49 /* ic */ 101 /* ic */
50 struct i2c_client *ic; 102 struct i2c_client *ic;
51}; 103};
52 104
53int nouveau_therm_init(struct nouveau_object *object); 105int nouveau_therm_mode(struct nouveau_therm *therm, int mode);
54int nouveau_therm_fini(struct nouveau_object *object, bool suspend);
55int nouveau_therm_attr_get(struct nouveau_therm *therm, 106int nouveau_therm_attr_get(struct nouveau_therm *therm,
56 enum nouveau_therm_attr_type type); 107 enum nouveau_therm_attr_type type);
57int nouveau_therm_attr_set(struct nouveau_therm *therm, 108int nouveau_therm_attr_set(struct nouveau_therm *therm,
@@ -63,11 +114,35 @@ int nouveau_therm_sensor_ctor(struct nouveau_therm *therm);
63 114
64int nouveau_therm_fan_ctor(struct nouveau_therm *therm); 115int nouveau_therm_fan_ctor(struct nouveau_therm *therm);
65int nouveau_therm_fan_get(struct nouveau_therm *therm); 116int nouveau_therm_fan_get(struct nouveau_therm *therm);
66int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); 117int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent);
67int nouveau_therm_fan_user_get(struct nouveau_therm *therm); 118int nouveau_therm_fan_user_get(struct nouveau_therm *therm);
68int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent); 119int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent);
69int nouveau_therm_fan_set_mode(struct nouveau_therm *therm,
70 enum nouveau_therm_fan_mode mode);
71
72 120
73int nouveau_therm_fan_sense(struct nouveau_therm *therm); 121int nouveau_therm_fan_sense(struct nouveau_therm *therm);
122
123int nouveau_therm_preinit(struct nouveau_therm *);
124
125void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm,
126 enum nouveau_therm_thrs thrs,
127 enum nouveau_therm_thrs_state st);
128enum nouveau_therm_thrs_state
129nouveau_therm_sensor_get_threshold_state(struct nouveau_therm *therm,
130 enum nouveau_therm_thrs thrs);
131void nouveau_therm_sensor_event(struct nouveau_therm *therm,
132 enum nouveau_therm_thrs thrs,
133 enum nouveau_therm_thrs_direction dir);
134void nouveau_therm_program_alarms_polling(struct nouveau_therm *therm);
135
136int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);
137int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *);
138int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
139int nv50_fan_pwm_clock(struct nouveau_therm *);
140int nv50_temp_get(struct nouveau_therm *therm);
141
142int nva3_therm_fan_sense(struct nouveau_therm *);
143
144int nouveau_fanpwm_create(struct nouveau_therm *, struct dcb_gpio_func *);
145int nouveau_fantog_create(struct nouveau_therm *, struct dcb_gpio_func *);
146int nouveau_fannil_create(struct nouveau_therm *);
147
148#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
index 204282301fb1..b37624af8297 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
@@ -58,11 +58,171 @@ static void
58nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) 58nouveau_therm_temp_safety_checks(struct nouveau_therm *therm)
59{ 59{
60 struct nouveau_therm_priv *priv = (void *)therm; 60 struct nouveau_therm_priv *priv = (void *)therm;
61 struct nvbios_therm_sensor *s = &priv->bios_sensor;
61 62
62 if (!priv->bios_sensor.slope_div) 63 if (!priv->bios_sensor.slope_div)
63 priv->bios_sensor.slope_div = 1; 64 priv->bios_sensor.slope_div = 1;
64 if (!priv->bios_sensor.offset_den) 65 if (!priv->bios_sensor.offset_den)
65 priv->bios_sensor.offset_den = 1; 66 priv->bios_sensor.offset_den = 1;
67
68 /* enforce a minimum hysteresis on thresholds */
69 s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2);
70 s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2);
71 s->thrs_critical.hysteresis = max_t(u8, s->thrs_critical.hysteresis, 2);
72 s->thrs_shutdown.hysteresis = max_t(u8, s->thrs_shutdown.hysteresis, 2);
73}
74
75/* must be called with alarm_program_lock taken ! */
76void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm,
77 enum nouveau_therm_thrs thrs,
78 enum nouveau_therm_thrs_state st)
79{
80 struct nouveau_therm_priv *priv = (void *)therm;
81 priv->sensor.alarm_state[thrs] = st;
82}
83
84/* must be called with alarm_program_lock taken ! */
85enum nouveau_therm_thrs_state
86nouveau_therm_sensor_get_threshold_state(struct nouveau_therm *therm,
87 enum nouveau_therm_thrs thrs)
88{
89 struct nouveau_therm_priv *priv = (void *)therm;
90 return priv->sensor.alarm_state[thrs];
91}
92
93static void
94nv_poweroff_work(struct work_struct *work)
95{
96 orderly_poweroff(true);
97 kfree(work);
98}
99
100void nouveau_therm_sensor_event(struct nouveau_therm *therm,
101 enum nouveau_therm_thrs thrs,
102 enum nouveau_therm_thrs_direction dir)
103{
104 struct nouveau_therm_priv *priv = (void *)therm;
105 bool active;
106 const char *thresolds[] = {
107 "fanboost", "downclock", "critical", "shutdown"
108 };
109 uint8_t temperature = therm->temp_get(therm);
110
111 if (thrs < 0 || thrs > 3)
112 return;
113
114 if (dir == NOUVEAU_THERM_THRS_FALLING)
115 nv_info(therm, "temperature (%u C) went below the '%s' threshold\n",
116 temperature, thresolds[thrs]);
117 else
118 nv_info(therm, "temperature (%u C) hit the '%s' threshold\n",
119 temperature, thresolds[thrs]);
120
121 active = (dir == NOUVEAU_THERM_THRS_RISING);
122 switch (thrs) {
123 case NOUVEAU_THERM_THRS_FANBOOST:
124 if (active) {
125 nouveau_therm_fan_set(therm, true, 100);
126 nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
127 }
128 break;
129 case NOUVEAU_THERM_THRS_DOWNCLOCK:
130 if (priv->emergency.downclock)
131 priv->emergency.downclock(therm, active);
132 break;
133 case NOUVEAU_THERM_THRS_CRITICAL:
134 if (priv->emergency.pause)
135 priv->emergency.pause(therm, active);
136 break;
137 case NOUVEAU_THERM_THRS_SHUTDOWN:
138 if (active) {
139 struct work_struct *work;
140
141 work = kmalloc(sizeof(*work), GFP_ATOMIC);
142 if (work) {
143 INIT_WORK(work, nv_poweroff_work);
144 schedule_work(work);
145 }
146 }
147 break;
148 case NOUVEAU_THERM_THRS_NR:
149 break;
150 }
151
152}
153
154/* must be called with alarm_program_lock taken ! */
155static void
156nouveau_therm_threshold_hyst_polling(struct nouveau_therm *therm,
157 const struct nvbios_therm_threshold *thrs,
158 enum nouveau_therm_thrs thrs_name)
159{
160 enum nouveau_therm_thrs_direction direction;
161 enum nouveau_therm_thrs_state prev_state, new_state;
162 int temp = therm->temp_get(therm);
163
164 prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name);
165
166 if (temp >= thrs->temp && prev_state == NOUVEAU_THERM_THRS_LOWER) {
167 direction = NOUVEAU_THERM_THRS_RISING;
168 new_state = NOUVEAU_THERM_THRS_HIGHER;
169 } else if (temp <= thrs->temp - thrs->hysteresis &&
170 prev_state == NOUVEAU_THERM_THRS_HIGHER) {
171 direction = NOUVEAU_THERM_THRS_FALLING;
172 new_state = NOUVEAU_THERM_THRS_LOWER;
173 } else
174 return; /* nothing to do */
175
176 nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state);
177 nouveau_therm_sensor_event(therm, thrs_name, direction);
178}
179
180static void
181alarm_timer_callback(struct nouveau_alarm *alarm)
182{
183 struct nouveau_therm_priv *priv =
184 container_of(alarm, struct nouveau_therm_priv, sensor.therm_poll_alarm);
185 struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
186 struct nouveau_timer *ptimer = nouveau_timer(priv);
187 struct nouveau_therm *therm = &priv->base;
188 unsigned long flags;
189
190 spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags);
191
192 nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost,
193 NOUVEAU_THERM_THRS_FANBOOST);
194
195 nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_down_clock,
196 NOUVEAU_THERM_THRS_DOWNCLOCK);
197
198 nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_critical,
199 NOUVEAU_THERM_THRS_CRITICAL);
200
201 nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown,
202 NOUVEAU_THERM_THRS_SHUTDOWN);
203
204 /* schedule the next poll in one second */
205 if (list_empty(&alarm->head))
206 ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm);
207
208 spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
209}
210
211void
212nouveau_therm_program_alarms_polling(struct nouveau_therm *therm)
213{
214 struct nouveau_therm_priv *priv = (void *)therm;
215 struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
216
217 nv_info(therm,
218 "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
219 sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis,
220 sensor->thrs_down_clock.temp,
221 sensor->thrs_down_clock.hysteresis,
222 sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis,
223 sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis);
224
225 alarm_timer_callback(&priv->sensor.therm_poll_alarm);
66} 226}
67 227
68int 228int
@@ -71,6 +231,8 @@ nouveau_therm_sensor_ctor(struct nouveau_therm *therm)
71 struct nouveau_therm_priv *priv = (void *)therm; 231 struct nouveau_therm_priv *priv = (void *)therm;
72 struct nouveau_bios *bios = nouveau_bios(therm); 232 struct nouveau_bios *bios = nouveau_bios(therm);
73 233
234 nouveau_alarm_init(&priv->sensor.therm_poll_alarm, alarm_timer_callback);
235
74 nouveau_therm_temp_set_defaults(therm); 236 nouveau_therm_temp_set_defaults(therm);
75 if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, 237 if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE,
76 &priv->bios_sensor)) 238 &priv->bios_sensor))
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
index c26ca9bef671..8e1bae4f12e8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
@@ -79,7 +79,7 @@ nv04_timer_alarm_trigger(struct nouveau_timer *ptimer)
79 79
80 /* execute any pending alarm handlers */ 80 /* execute any pending alarm handlers */
81 list_for_each_entry_safe(alarm, atemp, &exec, head) { 81 list_for_each_entry_safe(alarm, atemp, &exec, head) {
82 list_del(&alarm->head); 82 list_del_init(&alarm->head);
83 alarm->func(alarm); 83 alarm->func(alarm);
84 } 84 }
85} 85}
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h
index d0da230d7706..74acf0f87785 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.h
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h
@@ -3,7 +3,7 @@
3 3
4#define ROM_BIOS_PAGE 4096 4#define ROM_BIOS_PAGE 4096
5 5
6#if defined(CONFIG_ACPI) 6#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
7bool nouveau_is_optimus(void); 7bool nouveau_is_optimus(void);
8bool nouveau_is_v1_dsm(void); 8bool nouveau_is_v1_dsm(void);
9void nouveau_register_dsm_handler(void); 9void nouveau_register_dsm_handler(void);
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index f65b20a375f6..5d940302d2aa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -84,6 +84,8 @@ nv40_backlight_init(struct drm_connector *connector)
84 props.max_brightness = 31; 84 props.max_brightness = 31;
85 bd = backlight_device_register("nv_backlight", &connector->kdev, drm, 85 bd = backlight_device_register("nv_backlight", &connector->kdev, drm,
86 &nv40_bl_ops, &props); 86 &nv40_bl_ops, &props);
87 if (IS_ERR(bd))
88 return PTR_ERR(bd);
87 drm->backlight = bd; 89 drm->backlight = bd;
88 bd->props.brightness = nv40_get_intensity(bd); 90 bd->props.brightness = nv40_get_intensity(bd);
89 backlight_update_status(bd); 91 backlight_update_status(bd);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 865eddfa30a7..50a6dd02f7c5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -678,23 +678,6 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head,
678 return 0; 678 return 0;
679} 679}
680 680
681static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset)
682{
683 /*
684 * offset + 0 (8 bits): Micro version
685 * offset + 1 (8 bits): Minor version
686 * offset + 2 (8 bits): Chip version
687 * offset + 3 (8 bits): Major version
688 */
689 struct nouveau_drm *drm = nouveau_drm(dev);
690
691 bios->major_version = bios->data[offset + 3];
692 bios->chip_version = bios->data[offset + 2];
693 NV_INFO(drm, "Bios version %02x.%02x.%02x.%02x\n",
694 bios->data[offset + 3], bios->data[offset + 2],
695 bios->data[offset + 1], bios->data[offset]);
696}
697
698static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset) 681static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset)
699{ 682{
700 /* 683 /*
@@ -710,12 +693,6 @@ static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset)
710 */ 693 */
711 694
712 bios->init_script_tbls_ptr = ROM16(bios->data[offset]); 695 bios->init_script_tbls_ptr = ROM16(bios->data[offset]);
713 bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]);
714 bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]);
715 bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]);
716 bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]);
717 bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]);
718 bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]);
719} 696}
720 697
721static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) 698static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
@@ -765,25 +742,6 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
765 return 0; 742 return 0;
766} 743}
767 744
768static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
769{
770 /*
771 * offset + 8 (16 bits): PLL limits table pointer
772 *
773 * There's more in here, but that's unknown.
774 */
775 struct nouveau_drm *drm = nouveau_drm(dev);
776
777 if (bitentry->length < 10) {
778 NV_ERROR(drm, "Do not understand BIT C table\n");
779 return -EINVAL;
780 }
781
782 bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]);
783
784 return 0;
785}
786
787static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) 745static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
788{ 746{
789 /* 747 /*
@@ -821,12 +779,6 @@ static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios,
821 } 779 }
822 780
823 parse_script_table_pointers(bios, bitentry->offset); 781 parse_script_table_pointers(bios, bitentry->offset);
824
825 if (bitentry->length >= 16)
826 bios->some_script_ptr = ROM16(bios->data[bitentry->offset + 14]);
827 if (bitentry->length >= 18)
828 bios->init96_tbl_ptr = ROM16(bios->data[bitentry->offset + 16]);
829
830 return 0; 782 return 0;
831} 783}
832 784
@@ -852,8 +804,6 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
852 return -EINVAL; 804 return -EINVAL;
853 } 805 }
854 806
855 parse_bios_version(dev, bios, bitentry->offset);
856
857 /* 807 /*
858 * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's 808 * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's
859 * Quadro identity crisis), other bits possibly as for BMP feature byte 809 * Quadro identity crisis), other bits possibly as for BMP feature byte
@@ -1078,9 +1028,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset)
1078 return ret; 1028 return ret;
1079 if (bios->major_version >= 0x60) /* g80+ */ 1029 if (bios->major_version >= 0x60) /* g80+ */
1080 parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A)); 1030 parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A));
1081 ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('C', C));
1082 if (ret)
1083 return ret;
1084 parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display)); 1031 parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display));
1085 ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init)); 1032 ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init));
1086 if (ret) 1033 if (ret)
@@ -1228,8 +1175,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
1228 */ 1175 */
1229 bios->feature_byte = bmp[9]; 1176 bios->feature_byte = bmp[9];
1230 1177
1231 parse_bios_version(dev, bios, offset + 10);
1232
1233 if (bmp_version_major < 5 || bmp_version_minor < 0x10) 1178 if (bmp_version_major < 5 || bmp_version_minor < 0x10)
1234 bios->old_style_init = true; 1179 bios->old_style_init = true;
1235 legacy_scripts_offset = 18; 1180 legacy_scripts_offset = 18;
@@ -1276,8 +1221,10 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
1276 bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]); 1221 bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]);
1277 bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]); 1222 bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]);
1278 } 1223 }
1224#if 0
1279 if (bmplength > 143) 1225 if (bmplength > 143)
1280 bios->pll_limit_tbl_ptr = ROM16(bmp[142]); 1226 bios->pll_limit_tbl_ptr = ROM16(bmp[142]);
1227#endif
1281 1228
1282 if (bmplength > 157) 1229 if (bmplength > 157)
1283 bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10; 1230 bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10;
@@ -1522,6 +1469,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1522 } 1469 }
1523 case DCB_OUTPUT_DP: 1470 case DCB_OUTPUT_DP:
1524 entry->dpconf.sor.link = (conf & 0x00000030) >> 4; 1471 entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
1472 entry->extdev = (conf & 0x0000ff00) >> 8;
1525 switch ((conf & 0x00e00000) >> 21) { 1473 switch ((conf & 0x00e00000) >> 21) {
1526 case 0: 1474 case 0:
1527 entry->dpconf.link_bw = 162000; 1475 entry->dpconf.link_bw = 162000;
@@ -1543,8 +1491,10 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1543 } 1491 }
1544 break; 1492 break;
1545 case DCB_OUTPUT_TMDS: 1493 case DCB_OUTPUT_TMDS:
1546 if (dcb->version >= 0x40) 1494 if (dcb->version >= 0x40) {
1547 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; 1495 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
1496 entry->extdev = (conf & 0x0000ff00) >> 8;
1497 }
1548 else if (dcb->version >= 0x30) 1498 else if (dcb->version >= 0x30)
1549 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; 1499 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
1550 else if (dcb->version >= 0x22) 1500 else if (dcb->version >= 0x22)
@@ -1937,9 +1887,9 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
1937 if (conn[0] != 0xff) { 1887 if (conn[0] != 0xff) {
1938 NV_INFO(drm, "DCB conn %02d: ", idx); 1888 NV_INFO(drm, "DCB conn %02d: ", idx);
1939 if (olddcb_conntab(dev)[3] < 4) 1889 if (olddcb_conntab(dev)[3] < 4)
1940 printk("%04x\n", ROM16(conn[0])); 1890 pr_cont("%04x\n", ROM16(conn[0]));
1941 else 1891 else
1942 printk("%08x\n", ROM32(conn[0])); 1892 pr_cont("%08x\n", ROM32(conn[0]));
1943 } 1893 }
1944 } 1894 }
1945 dcb_fake_connectors(bios); 1895 dcb_fake_connectors(bios);
@@ -2052,45 +2002,29 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
2052static bool NVInitVBIOS(struct drm_device *dev) 2002static bool NVInitVBIOS(struct drm_device *dev)
2053{ 2003{
2054 struct nouveau_drm *drm = nouveau_drm(dev); 2004 struct nouveau_drm *drm = nouveau_drm(dev);
2055 struct nvbios *bios = &drm->vbios; 2005 struct nouveau_bios *bios = nouveau_bios(drm->device);
2056 2006 struct nvbios *legacy = &drm->vbios;
2057 memset(bios, 0, sizeof(struct nvbios)); 2007
2058 spin_lock_init(&bios->lock); 2008 memset(legacy, 0, sizeof(struct nvbios));
2059 bios->dev = dev; 2009 spin_lock_init(&legacy->lock);
2060 2010 legacy->dev = dev;
2061 bios->data = nouveau_bios(drm->device)->data; 2011
2062 bios->length = nouveau_bios(drm->device)->size; 2012 legacy->data = bios->data;
2063 return true; 2013 legacy->length = bios->size;
2064} 2014 legacy->major_version = bios->version.major;
2015 legacy->chip_version = bios->version.chip;
2016 if (bios->bit_offset) {
2017 legacy->type = NVBIOS_BIT;
2018 legacy->offset = bios->bit_offset;
2019 return !parse_bit_structure(legacy, legacy->offset + 6);
2020 } else
2021 if (bios->bmp_offset) {
2022 legacy->type = NVBIOS_BMP;
2023 legacy->offset = bios->bmp_offset;
2024 return !parse_bmp_structure(dev, legacy, legacy->offset);
2025 }
2065 2026
2066static int nouveau_parse_vbios_struct(struct drm_device *dev) 2027 return false;
2067{
2068 struct nouveau_drm *drm = nouveau_drm(dev);
2069 struct nvbios *bios = &drm->vbios;
2070 const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' };
2071 const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
2072 int offset;
2073
2074 offset = findstr(bios->data, bios->length,
2075 bit_signature, sizeof(bit_signature));
2076 if (offset) {
2077 NV_INFO(drm, "BIT BIOS found\n");
2078 bios->type = NVBIOS_BIT;
2079 bios->offset = offset;
2080 return parse_bit_structure(bios, offset + 6);
2081 }
2082
2083 offset = findstr(bios->data, bios->length,
2084 bmp_signature, sizeof(bmp_signature));
2085 if (offset) {
2086 NV_INFO(drm, "BMP BIOS found\n");
2087 bios->type = NVBIOS_BMP;
2088 bios->offset = offset;
2089 return parse_bmp_structure(dev, bios, offset);
2090 }
2091
2092 NV_ERROR(drm, "No known BIOS signature found\n");
2093 return -ENODEV;
2094} 2028}
2095 2029
2096int 2030int
@@ -2146,10 +2080,6 @@ nouveau_bios_init(struct drm_device *dev)
2146 if (!NVInitVBIOS(dev)) 2080 if (!NVInitVBIOS(dev))
2147 return -ENODEV; 2081 return -ENODEV;
2148 2082
2149 ret = nouveau_parse_vbios_struct(dev);
2150 if (ret)
2151 return ret;
2152
2153 ret = parse_dcb_table(dev, bios); 2083 ret = parse_dcb_table(dev, bios);
2154 if (ret) 2084 if (ret)
2155 return ret; 2085 return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index f68c54ca422f..7ccd28f11adf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -107,20 +107,10 @@ struct nvbios {
107 bool old_style_init; 107 bool old_style_init;
108 uint16_t init_script_tbls_ptr; 108 uint16_t init_script_tbls_ptr;
109 uint16_t extra_init_script_tbl_ptr; 109 uint16_t extra_init_script_tbl_ptr;
110 uint16_t macro_index_tbl_ptr; 110
111 uint16_t macro_tbl_ptr;
112 uint16_t condition_tbl_ptr;
113 uint16_t io_condition_tbl_ptr;
114 uint16_t io_flag_condition_tbl_ptr;
115 uint16_t init_function_tbl_ptr;
116
117 uint16_t pll_limit_tbl_ptr;
118 uint16_t ram_restrict_tbl_ptr; 111 uint16_t ram_restrict_tbl_ptr;
119 uint8_t ram_restrict_group_count; 112 uint8_t ram_restrict_group_count;
120 113
121 uint16_t some_script_ptr; /* BIT I + 14 */
122 uint16_t init96_tbl_ptr; /* BIT I + 16 */
123
124 struct dcb_table dcb; 114 struct dcb_table dcb;
125 115
126 struct { 116 struct {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 2f2741483b51..11ca82148edc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -562,7 +562,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
562 struct nouveau_fence *fence = NULL; 562 struct nouveau_fence *fence = NULL;
563 int ret; 563 int ret;
564 564
565 ret = nouveau_fence_new(chan, &fence); 565 ret = nouveau_fence_new(chan, false, &fence);
566 if (ret) 566 if (ret)
567 return ret; 567 return ret;
568 568
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 174300b6a02e..eaa80a2b81ee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -51,14 +51,15 @@ nouveau_channel_idle(struct nouveau_channel *chan)
51 struct nouveau_fence *fence = NULL; 51 struct nouveau_fence *fence = NULL;
52 int ret; 52 int ret;
53 53
54 ret = nouveau_fence_new(chan, &fence); 54 ret = nouveau_fence_new(chan, false, &fence);
55 if (!ret) { 55 if (!ret) {
56 ret = nouveau_fence_wait(fence, false, false); 56 ret = nouveau_fence_wait(fence, false, false);
57 nouveau_fence_unref(&fence); 57 nouveau_fence_unref(&fence);
58 } 58 }
59 59
60 if (ret) 60 if (ret)
61 NV_ERROR(cli, "failed to idle channel 0x%08x\n", chan->handle); 61 NV_ERROR(cli, "failed to idle channel 0x%08x [%s]\n",
62 chan->handle, cli->base.name);
62 return ret; 63 return ret;
63} 64}
64 65
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index e620ba8271b4..4dd7ae2ac6c6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -55,8 +55,6 @@ MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)");
55static int nouveau_duallink = 1; 55static int nouveau_duallink = 1;
56module_param_named(duallink, nouveau_duallink, int, 0400); 56module_param_named(duallink, nouveau_duallink, int, 0400);
57 57
58static void nouveau_connector_hotplug(void *, int);
59
60struct nouveau_encoder * 58struct nouveau_encoder *
61find_encoder(struct drm_connector *connector, int type) 59find_encoder(struct drm_connector *connector, int type)
62{ 60{
@@ -100,22 +98,6 @@ static void
100nouveau_connector_destroy(struct drm_connector *connector) 98nouveau_connector_destroy(struct drm_connector *connector)
101{ 99{
102 struct nouveau_connector *nv_connector = nouveau_connector(connector); 100 struct nouveau_connector *nv_connector = nouveau_connector(connector);
103 struct nouveau_gpio *gpio;
104 struct nouveau_drm *drm;
105 struct drm_device *dev;
106
107 if (!nv_connector)
108 return;
109
110 dev = nv_connector->base.dev;
111 drm = nouveau_drm(dev);
112 gpio = nouveau_gpio(drm->device);
113
114 if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) {
115 gpio->isr_del(gpio, 0, nv_connector->hpd, 0xff,
116 nouveau_connector_hotplug, connector);
117 }
118
119 kfree(nv_connector->edid); 101 kfree(nv_connector->edid);
120 drm_sysfs_connector_remove(connector); 102 drm_sysfs_connector_remove(connector);
121 drm_connector_cleanup(connector); 103 drm_connector_cleanup(connector);
@@ -130,7 +112,6 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
130 struct nouveau_connector *nv_connector = nouveau_connector(connector); 112 struct nouveau_connector *nv_connector = nouveau_connector(connector);
131 struct nouveau_drm *drm = nouveau_drm(dev); 113 struct nouveau_drm *drm = nouveau_drm(dev);
132 struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 114 struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
133 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
134 struct nouveau_i2c_port *port = NULL; 115 struct nouveau_i2c_port *port = NULL;
135 int i, panel = -ENODEV; 116 int i, panel = -ENODEV;
136 117
@@ -160,8 +141,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
160 continue; 141 continue;
161 nv_encoder = nouveau_encoder(obj_to_encoder(obj)); 142 nv_encoder = nouveau_encoder(obj_to_encoder(obj));
162 143
163 if (nv_encoder->dcb->i2c_index < 0xf) 144 port = nv_encoder->i2c;
164 port = i2c->find(i2c, nv_encoder->dcb->i2c_index);
165 if (port && nv_probe_i2c(port, 0x50)) { 145 if (port && nv_probe_i2c(port, 0x50)) {
166 *pnv_encoder = nv_encoder; 146 *pnv_encoder = nv_encoder;
167 break; 147 break;
@@ -399,9 +379,10 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
399 struct edid *edid = 379 struct edid *edid =
400 (struct edid *)nouveau_bios_embedded_edid(dev); 380 (struct edid *)nouveau_bios_embedded_edid(dev);
401 if (edid) { 381 if (edid) {
402 nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 382 nv_connector->edid =
403 *(nv_connector->edid) = *edid; 383 kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
404 status = connector_status_connected; 384 if (nv_connector->edid)
385 status = connector_status_connected;
405 } 386 }
406 } 387 }
407 388
@@ -911,6 +892,37 @@ nouveau_connector_funcs_lvds = {
911 .force = nouveau_connector_force 892 .force = nouveau_connector_force
912}; 893};
913 894
895static void
896nouveau_connector_hotplug_work(struct work_struct *work)
897{
898 struct nouveau_connector *nv_connector =
899 container_of(work, struct nouveau_connector, hpd_work);
900 struct drm_connector *connector = &nv_connector->base;
901 struct drm_device *dev = connector->dev;
902 struct nouveau_drm *drm = nouveau_drm(dev);
903 struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
904 bool plugged = gpio->get(gpio, 0, nv_connector->hpd.func, 0xff);
905
906 NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un",
907 drm_get_connector_name(connector));
908
909 if (plugged)
910 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
911 else
912 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
913
914 drm_helper_hpd_irq_event(dev);
915}
916
917static int
918nouveau_connector_hotplug(struct nouveau_eventh *event, int index)
919{
920 struct nouveau_connector *nv_connector =
921 container_of(event, struct nouveau_connector, hpd_func);
922 schedule_work(&nv_connector->hpd_work);
923 return NVKM_EVENT_KEEP;
924}
925
914static int 926static int
915drm_conntype_from_dcb(enum dcb_connector_type dcb) 927drm_conntype_from_dcb(enum dcb_connector_type dcb)
916{ 928{
@@ -961,6 +973,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
961 return ERR_PTR(-ENOMEM); 973 return ERR_PTR(-ENOMEM);
962 974
963 connector = &nv_connector->base; 975 connector = &nv_connector->base;
976 INIT_WORK(&nv_connector->hpd_work, nouveau_connector_hotplug_work);
964 nv_connector->index = index; 977 nv_connector->index = index;
965 978
966 /* attempt to parse vbios connector type and hotplug gpio */ 979 /* attempt to parse vbios connector type and hotplug gpio */
@@ -975,8 +988,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
975 if (olddcb_conntab(dev)[3] >= 4) 988 if (olddcb_conntab(dev)[3] >= 4)
976 entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; 989 entry |= (u32)ROM16(nv_connector->dcb[2]) << 16;
977 990
978 nv_connector->hpd = ffs((entry & 0x07033000) >> 12); 991 ret = gpio->find(gpio, 0, hpd[ffs((entry & 0x07033000) >> 12)],
979 nv_connector->hpd = hpd[nv_connector->hpd]; 992 DCB_GPIO_UNUSED, &nv_connector->hpd);
993 nv_connector->hpd_func.func = nouveau_connector_hotplug;
994 if (ret)
995 nv_connector->hpd.func = DCB_GPIO_UNUSED;
980 996
981 nv_connector->type = nv_connector->dcb[0]; 997 nv_connector->type = nv_connector->dcb[0];
982 if (drm_conntype_from_dcb(nv_connector->type) == 998 if (drm_conntype_from_dcb(nv_connector->type) ==
@@ -999,7 +1015,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
999 } 1015 }
1000 } else { 1016 } else {
1001 nv_connector->type = DCB_CONNECTOR_NONE; 1017 nv_connector->type = DCB_CONNECTOR_NONE;
1002 nv_connector->hpd = DCB_GPIO_UNUSED; 1018 nv_connector->hpd.func = DCB_GPIO_UNUSED;
1003 } 1019 }
1004 1020
1005 /* no vbios data, or an unknown dcb connector type - attempt to 1021 /* no vbios data, or an unknown dcb connector type - attempt to
@@ -1126,31 +1142,9 @@ nouveau_connector_create(struct drm_device *dev, int index)
1126 } 1142 }
1127 1143
1128 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1144 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1129 if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { 1145 if (nv_connector->hpd.func != DCB_GPIO_UNUSED)
1130 ret = gpio->isr_add(gpio, 0, nv_connector->hpd, 0xff, 1146 connector->polled = DRM_CONNECTOR_POLL_HPD;
1131 nouveau_connector_hotplug, connector);
1132 if (ret == 0)
1133 connector->polled = DRM_CONNECTOR_POLL_HPD;
1134 }
1135 1147
1136 drm_sysfs_connector_add(connector); 1148 drm_sysfs_connector_add(connector);
1137 return connector; 1149 return connector;
1138} 1150}
1139
1140static void
1141nouveau_connector_hotplug(void *data, int plugged)
1142{
1143 struct drm_connector *connector = data;
1144 struct drm_device *dev = connector->dev;
1145 struct nouveau_drm *drm = nouveau_drm(dev);
1146
1147 NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un",
1148 drm_get_connector_name(connector));
1149
1150 if (plugged)
1151 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
1152 else
1153 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
1154
1155 drm_helper_hpd_irq_event(dev);
1156}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 20eb84cce9e6..6e399aad491a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -30,6 +30,11 @@
30#include <drm/drm_edid.h> 30#include <drm/drm_edid.h>
31#include "nouveau_crtc.h" 31#include "nouveau_crtc.h"
32 32
33#include <core/event.h>
34
35#include <subdev/bios.h>
36#include <subdev/bios/gpio.h>
37
33struct nouveau_i2c_port; 38struct nouveau_i2c_port;
34 39
35enum nouveau_underscan_type { 40enum nouveau_underscan_type {
@@ -61,7 +66,10 @@ struct nouveau_connector {
61 enum dcb_connector_type type; 66 enum dcb_connector_type type;
62 u8 index; 67 u8 index;
63 u8 *dcb; 68 u8 *dcb;
64 u8 hpd; 69
70 struct dcb_gpio_func hpd;
71 struct work_struct hpd_work;
72 struct nouveau_eventh hpd_func;
65 73
66 int dithering_mode; 74 int dithering_mode;
67 int dithering_depth; 75 int dithering_depth;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index d42c9e860c16..4610c3a29bbe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -41,6 +41,8 @@
41#include <subdev/gpio.h> 41#include <subdev/gpio.h>
42#include <engine/disp.h> 42#include <engine/disp.h>
43 43
44#include <core/class.h>
45
44static void 46static void
45nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) 47nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
46{ 48{
@@ -231,8 +233,10 @@ nouveau_display_init(struct drm_device *dev)
231 /* enable hotplug interrupts */ 233 /* enable hotplug interrupts */
232 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 234 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
233 struct nouveau_connector *conn = nouveau_connector(connector); 235 struct nouveau_connector *conn = nouveau_connector(connector);
234 if (gpio) 236 if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) {
235 gpio->irq(gpio, 0, conn->hpd, 0xff, true); 237 nouveau_event_get(gpio->events, conn->hpd.line,
238 &conn->hpd_func);
239 }
236 } 240 }
237 241
238 return ret; 242 return ret;
@@ -249,37 +253,20 @@ nouveau_display_fini(struct drm_device *dev)
249 /* disable hotplug interrupts */ 253 /* disable hotplug interrupts */
250 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 254 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
251 struct nouveau_connector *conn = nouveau_connector(connector); 255 struct nouveau_connector *conn = nouveau_connector(connector);
252 if (gpio) 256 if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) {
253 gpio->irq(gpio, 0, conn->hpd, 0xff, false); 257 nouveau_event_put(gpio->events, conn->hpd.line,
258 &conn->hpd_func);
259 }
254 } 260 }
255 261
256 drm_kms_helper_poll_disable(dev); 262 drm_kms_helper_poll_disable(dev);
257 disp->fini(dev); 263 disp->fini(dev);
258} 264}
259 265
260static void
261nouveau_display_vblank_notify(void *data, int crtc)
262{
263 drm_handle_vblank(data, crtc);
264}
265
266static void
267nouveau_display_vblank_get(void *data, int crtc)
268{
269 drm_vblank_get(data, crtc);
270}
271
272static void
273nouveau_display_vblank_put(void *data, int crtc)
274{
275 drm_vblank_put(data, crtc);
276}
277
278int 266int
279nouveau_display_create(struct drm_device *dev) 267nouveau_display_create(struct drm_device *dev)
280{ 268{
281 struct nouveau_drm *drm = nouveau_drm(dev); 269 struct nouveau_drm *drm = nouveau_drm(dev);
282 struct nouveau_disp *pdisp = nouveau_disp(drm->device);
283 struct nouveau_display *disp; 270 struct nouveau_display *disp;
284 u32 pclass = dev->pdev->class >> 8; 271 u32 pclass = dev->pdev->class >> 8;
285 int ret, gen; 272 int ret, gen;
@@ -288,11 +275,6 @@ nouveau_display_create(struct drm_device *dev)
288 if (!disp) 275 if (!disp)
289 return -ENOMEM; 276 return -ENOMEM;
290 277
291 pdisp->vblank.data = dev;
292 pdisp->vblank.notify = nouveau_display_vblank_notify;
293 pdisp->vblank.get = nouveau_display_vblank_get;
294 pdisp->vblank.put = nouveau_display_vblank_put;
295
296 drm_mode_config_init(dev); 278 drm_mode_config_init(dev);
297 drm_mode_create_scaling_mode_property(dev); 279 drm_mode_create_scaling_mode_property(dev);
298 drm_mode_create_dvi_i_properties(dev); 280 drm_mode_create_dvi_i_properties(dev);
@@ -316,17 +298,13 @@ nouveau_display_create(struct drm_device *dev)
316 drm_property_create_range(dev, 0, "underscan vborder", 0, 128); 298 drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
317 299
318 if (gen >= 1) { 300 if (gen >= 1) {
301 /* -90..+90 */
319 disp->vibrant_hue_property = 302 disp->vibrant_hue_property =
320 drm_property_create(dev, DRM_MODE_PROP_RANGE, 303 drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
321 "vibrant hue", 2);
322 disp->vibrant_hue_property->values[0] = 0;
323 disp->vibrant_hue_property->values[1] = 180; /* -90..+90 */
324 304
305 /* -100..+100 */
325 disp->color_vibrance_property = 306 disp->color_vibrance_property =
326 drm_property_create(dev, DRM_MODE_PROP_RANGE, 307 drm_property_create_range(dev, 0, "color vibrance", 0, 200);
327 "color vibrance", 2);
328 disp->color_vibrance_property->values[0] = 0;
329 disp->color_vibrance_property->values[1] = 200; /* -100..+100 */
330 } 308 }
331 309
332 dev->mode_config.funcs = &nouveau_mode_config_funcs; 310 dev->mode_config.funcs = &nouveau_mode_config_funcs;
@@ -478,39 +456,6 @@ nouveau_display_resume(struct drm_device *dev)
478 } 456 }
479} 457}
480 458
481int
482nouveau_vblank_enable(struct drm_device *dev, int crtc)
483{
484 struct nouveau_device *device = nouveau_dev(dev);
485
486 if (device->card_type >= NV_D0)
487 nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1);
488 else
489 if (device->card_type >= NV_50)
490 nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0,
491 NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
492 else
493 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
494 NV_PCRTC_INTR_0_VBLANK);
495
496 return 0;
497}
498
499void
500nouveau_vblank_disable(struct drm_device *dev, int crtc)
501{
502 struct nouveau_device *device = nouveau_dev(dev);
503
504 if (device->card_type >= NV_D0)
505 nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0);
506 else
507 if (device->card_type >= NV_50)
508 nv_mask(device, NV50_PDISPLAY_INTR_EN_1,
509 NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
510 else
511 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
512}
513
514static int 459static int
515nouveau_page_flip_reserve(struct nouveau_bo *old_bo, 460nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
516 struct nouveau_bo *new_bo) 461 struct nouveau_bo *new_bo)
@@ -595,7 +540,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
595 } 540 }
596 FIRE_RING (chan); 541 FIRE_RING (chan);
597 542
598 ret = nouveau_fence_new(chan, pfence); 543 ret = nouveau_fence_new(chan, false, pfence);
599 if (ret) 544 if (ret)
600 goto fail; 545 goto fail;
601 546
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 722548bb3bd3..1ea3e4734b62 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -59,9 +59,6 @@ void nouveau_display_fini(struct drm_device *dev);
59int nouveau_display_suspend(struct drm_device *dev); 59int nouveau_display_suspend(struct drm_device *dev);
60void nouveau_display_resume(struct drm_device *dev); 60void nouveau_display_resume(struct drm_device *dev);
61 61
62int nouveau_vblank_enable(struct drm_device *dev, int crtc);
63void nouveau_vblank_disable(struct drm_device *dev, int crtc);
64
65int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 62int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
66 struct drm_pending_vblank_event *event); 63 struct drm_pending_vblank_event *event);
67int nouveau_finish_page_flip(struct nouveau_channel *, 64int nouveau_finish_page_flip(struct nouveau_channel *,
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index 5c2e22932d1c..690d5930ce32 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -191,7 +191,7 @@ WIND_RING(struct nouveau_channel *chan)
191#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 191#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002
192#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 192#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004
193#define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 193#define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000
194#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 194#define NV84_SUBCHAN_UEVENT 0x00000020
195#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 195#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024
196#define NV10_SUBCHAN_REF_CNT 0x00000050 196#define NV10_SUBCHAN_REF_CNT 0x00000050
197#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054 197#define NVSW_SUBCHAN_PAGE_FLIP 0x00000054
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 59838651ee8f..36fd22500569 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -35,300 +35,6 @@
35#include <subdev/gpio.h> 35#include <subdev/gpio.h>
36#include <subdev/i2c.h> 36#include <subdev/i2c.h>
37 37
38/******************************************************************************
39 * link training
40 *****************************************************************************/
41struct dp_state {
42 struct nouveau_i2c_port *auxch;
43 struct nouveau_object *core;
44 struct dcb_output *dcb;
45 int crtc;
46 u8 *dpcd;
47 int link_nr;
48 u32 link_bw;
49 u8 stat[6];
50 u8 conf[4];
51};
52
53static void
54dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
55{
56 struct nouveau_drm *drm = nouveau_drm(dev);
57 struct dcb_output *dcb = dp->dcb;
58 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
59 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
60 u8 sink[2];
61 u32 data;
62
63 NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
64
65 /* set desired link configuration on the source */
66 data = ((dp->link_bw / 27000) << 8) | dp->link_nr;
67 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)
68 data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH;
69
70 nv_call(dp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data);
71
72 /* inform the sink of the new configuration */
73 sink[0] = dp->link_bw / 27000;
74 sink[1] = dp->link_nr;
75 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)
76 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
77
78 nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2);
79}
80
81static void
82dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern)
83{
84 struct nouveau_drm *drm = nouveau_drm(dev);
85 struct dcb_output *dcb = dp->dcb;
86 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
87 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
88 u8 sink_tp;
89
90 NV_DEBUG(drm, "training pattern %d\n", pattern);
91
92 nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern);
93
94 nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
95 sink_tp &= ~DP_TRAINING_PATTERN_MASK;
96 sink_tp |= pattern;
97 nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
98}
99
100static int
101dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
102{
103 struct nouveau_drm *drm = nouveau_drm(dev);
104 struct dcb_output *dcb = dp->dcb;
105 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
106 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
107 int i;
108
109 for (i = 0; i < dp->link_nr; i++) {
110 u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
111 u8 lpre = (lane & 0x0c) >> 2;
112 u8 lvsw = (lane & 0x03) >> 0;
113
114 dp->conf[i] = (lpre << 3) | lvsw;
115 if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200)
116 dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED;
117 if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5)
118 dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
119
120 NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]);
121
122 nv_call(dp->core, NV94_DISP_SOR_DP_DRVCTL(i) + moff, (lvsw << 8) | lpre);
123 }
124
125 return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4);
126}
127
128static int
129dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
130{
131 struct nouveau_drm *drm = nouveau_drm(dev);
132 int ret;
133
134 udelay(delay);
135
136 ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6);
137 if (ret)
138 return ret;
139
140 NV_DEBUG(drm, "status %*ph\n", 6, dp->stat);
141 return 0;
142}
143
144static int
145dp_link_train_cr(struct drm_device *dev, struct dp_state *dp)
146{
147 bool cr_done = false, abort = false;
148 int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
149 int tries = 0, i;
150
151 dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1);
152
153 do {
154 if (dp_link_train_commit(dev, dp) ||
155 dp_link_train_update(dev, dp, 100))
156 break;
157
158 cr_done = true;
159 for (i = 0; i < dp->link_nr; i++) {
160 u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
161 if (!(lane & DP_LANE_CR_DONE)) {
162 cr_done = false;
163 if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED)
164 abort = true;
165 break;
166 }
167 }
168
169 if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
170 voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
171 tries = 0;
172 }
173 } while (!cr_done && !abort && ++tries < 5);
174
175 return cr_done ? 0 : -1;
176}
177
178static int
179dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
180{
181 bool eq_done, cr_done = true;
182 int tries = 0, i;
183
184 dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2);
185
186 do {
187 if (dp_link_train_update(dev, dp, 400))
188 break;
189
190 eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE);
191 for (i = 0; i < dp->link_nr && eq_done; i++) {
192 u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
193 if (!(lane & DP_LANE_CR_DONE))
194 cr_done = false;
195 if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
196 !(lane & DP_LANE_SYMBOL_LOCKED))
197 eq_done = false;
198 }
199
200 if (dp_link_train_commit(dev, dp))
201 break;
202 } while (!eq_done && cr_done && ++tries <= 5);
203
204 return eq_done ? 0 : -1;
205}
206
207static void
208dp_link_train_init(struct drm_device *dev, struct dp_state *dp, bool spread)
209{
210 struct dcb_output *dcb = dp->dcb;
211 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
212 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
213
214 nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, (spread ?
215 NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON :
216 NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF) |
217 NV94_DISP_SOR_DP_TRAIN_OP_INIT);
218}
219
220static void
221dp_link_train_fini(struct drm_device *dev, struct dp_state *dp)
222{
223 struct dcb_output *dcb = dp->dcb;
224 const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
225 const u32 moff = (dp->crtc << 3) | (link << 2) | or;
226
227 nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff,
228 NV94_DISP_SOR_DP_TRAIN_OP_FINI);
229}
230
231static bool
232nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
233 struct nouveau_object *core)
234{
235 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
236 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
237 struct nouveau_connector *nv_connector =
238 nouveau_encoder_connector_get(nv_encoder);
239 struct drm_device *dev = encoder->dev;
240 struct nouveau_drm *drm = nouveau_drm(dev);
241 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
242 struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
243 const u32 bw_list[] = { 270000, 162000, 0 };
244 const u32 *link_bw = bw_list;
245 struct dp_state dp;
246
247 dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
248 if (!dp.auxch)
249 return false;
250
251 dp.core = core;
252 dp.dcb = nv_encoder->dcb;
253 dp.crtc = nv_crtc->index;
254 dp.dpcd = nv_encoder->dp.dpcd;
255
256 /* adjust required bandwidth for 8B/10B coding overhead */
257 datarate = (datarate / 8) * 10;
258
259 /* some sinks toggle hotplug in response to some of the actions
260 * we take during link training (DP_SET_POWER is one), we need
261 * to ignore them for the moment to avoid races.
262 */
263 gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false);
264
265 /* enable down-spreading and execute pre-train script from vbios */
266 dp_link_train_init(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
267
268 /* start off at highest link rate supported by encoder and display */
269 while (*link_bw > nv_encoder->dp.link_bw)
270 link_bw++;
271
272 while (link_bw[0]) {
273 /* find minimum required lane count at this link rate */
274 dp.link_nr = nv_encoder->dp.link_nr;
275 while ((dp.link_nr >> 1) * link_bw[0] > datarate)
276 dp.link_nr >>= 1;
277
278 /* drop link rate to minimum with this lane count */
279 while ((link_bw[1] * dp.link_nr) > datarate)
280 link_bw++;
281 dp.link_bw = link_bw[0];
282
283 /* program selected link configuration */
284 dp_set_link_config(dev, &dp);
285
286 /* attempt to train the link at this configuration */
287 memset(dp.stat, 0x00, sizeof(dp.stat));
288 if (!dp_link_train_cr(dev, &dp) &&
289 !dp_link_train_eq(dev, &dp))
290 break;
291
292 /* retry at lower rate */
293 link_bw++;
294 }
295
296 /* finish link training */
297 dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE);
298
299 /* execute post-train script from vbios */
300 dp_link_train_fini(dev, &dp);
301
302 /* re-enable hotplug detect */
303 gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true);
304 return true;
305}
306
307void
308nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
309 struct nouveau_object *core)
310{
311 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
312 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
313 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
314 struct nouveau_i2c_port *auxch;
315 u8 status;
316
317 auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
318 if (!auxch)
319 return;
320
321 if (mode == DRM_MODE_DPMS_ON)
322 status = DP_SET_POWER_D0;
323 else
324 status = DP_SET_POWER_D3;
325
326 nv_wraux(auxch, DP_SET_POWER, &status, 1);
327
328 if (mode == DRM_MODE_DPMS_ON)
329 nouveau_dp_link_train(encoder, datarate, core);
330}
331
332static void 38static void
333nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, 39nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
334 u8 *dpcd) 40 u8 *dpcd)
@@ -355,12 +61,11 @@ nouveau_dp_detect(struct drm_encoder *encoder)
355 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 61 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
356 struct drm_device *dev = encoder->dev; 62 struct drm_device *dev = encoder->dev;
357 struct nouveau_drm *drm = nouveau_drm(dev); 63 struct nouveau_drm *drm = nouveau_drm(dev);
358 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
359 struct nouveau_i2c_port *auxch; 64 struct nouveau_i2c_port *auxch;
360 u8 *dpcd = nv_encoder->dp.dpcd; 65 u8 *dpcd = nv_encoder->dp.dpcd;
361 int ret; 66 int ret;
362 67
363 auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); 68 auxch = nv_encoder->i2c;
364 if (!auxch) 69 if (!auxch)
365 return false; 70 return false;
366 71
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 8e8e8ce75528..ccfe2be3ae38 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -34,6 +34,8 @@
34#include <subdev/device.h> 34#include <subdev/device.h>
35#include <subdev/vm.h> 35#include <subdev/vm.h>
36 36
37#include <engine/disp.h>
38
37#include "nouveau_drm.h" 39#include "nouveau_drm.h"
38#include "nouveau_irq.h" 40#include "nouveau_irq.h"
39#include "nouveau_dma.h" 41#include "nouveau_dma.h"
@@ -68,6 +70,32 @@ module_param_named(modeset, nouveau_modeset, int, 0400);
68 70
69static struct drm_driver driver; 71static struct drm_driver driver;
70 72
73static int
74nouveau_drm_vblank_enable(struct drm_device *dev, int head)
75{
76 struct nouveau_drm *drm = nouveau_drm(dev);
77 struct nouveau_disp *pdisp = nouveau_disp(drm->device);
78 nouveau_event_get(pdisp->vblank, head, &drm->vblank);
79 return 0;
80}
81
82static void
83nouveau_drm_vblank_disable(struct drm_device *dev, int head)
84{
85 struct nouveau_drm *drm = nouveau_drm(dev);
86 struct nouveau_disp *pdisp = nouveau_disp(drm->device);
87 nouveau_event_put(pdisp->vblank, head, &drm->vblank);
88}
89
90static int
91nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
92{
93 struct nouveau_drm *drm =
94 container_of(event, struct nouveau_drm, vblank);
95 drm_handle_vblank(drm->dev, head);
96 return NVKM_EVENT_KEEP;
97}
98
71static u64 99static u64
72nouveau_name(struct pci_dev *pdev) 100nouveau_name(struct pci_dev *pdev)
73{ 101{
@@ -132,7 +160,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
132 160
133 /* initialise synchronisation routines */ 161 /* initialise synchronisation routines */
134 if (device->card_type < NV_10) ret = nv04_fence_create(drm); 162 if (device->card_type < NV_10) ret = nv04_fence_create(drm);
135 else if (device->card_type < NV_50) ret = nv10_fence_create(drm); 163 else if (device->chipset < 0x17) ret = nv10_fence_create(drm);
164 else if (device->card_type < NV_50) ret = nv17_fence_create(drm);
136 else if (device->chipset < 0x84) ret = nv50_fence_create(drm); 165 else if (device->chipset < 0x84) ret = nv50_fence_create(drm);
137 else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); 166 else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
138 else ret = nvc0_fence_create(drm); 167 else ret = nvc0_fence_create(drm);
@@ -259,6 +288,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
259 288
260 dev->dev_private = drm; 289 dev->dev_private = drm;
261 drm->dev = dev; 290 drm->dev = dev;
291 drm->vblank.func = nouveau_drm_vblank_handler;
262 292
263 INIT_LIST_HEAD(&drm->clients); 293 INIT_LIST_HEAD(&drm->clients);
264 spin_lock_init(&drm->tile.lock); 294 spin_lock_init(&drm->tile.lock);
@@ -398,7 +428,7 @@ nouveau_drm_remove(struct pci_dev *pdev)
398 nouveau_object_debug(); 428 nouveau_object_debug();
399} 429}
400 430
401int 431static int
402nouveau_do_suspend(struct drm_device *dev) 432nouveau_do_suspend(struct drm_device *dev)
403{ 433{
404 struct nouveau_drm *drm = nouveau_drm(dev); 434 struct nouveau_drm *drm = nouveau_drm(dev);
@@ -469,7 +499,7 @@ int nouveau_pmops_suspend(struct device *dev)
469 return 0; 499 return 0;
470} 500}
471 501
472int 502static int
473nouveau_do_resume(struct drm_device *dev) 503nouveau_do_resume(struct drm_device *dev)
474{ 504{
475 struct nouveau_drm *drm = nouveau_drm(dev); 505 struct nouveau_drm *drm = nouveau_drm(dev);
@@ -543,10 +573,11 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
543 struct pci_dev *pdev = dev->pdev; 573 struct pci_dev *pdev = dev->pdev;
544 struct nouveau_drm *drm = nouveau_drm(dev); 574 struct nouveau_drm *drm = nouveau_drm(dev);
545 struct nouveau_cli *cli; 575 struct nouveau_cli *cli;
546 char name[16]; 576 char name[32], tmpname[TASK_COMM_LEN];
547 int ret; 577 int ret;
548 578
549 snprintf(name, sizeof(name), "%d", pid_nr(fpriv->pid)); 579 get_task_comm(tmpname, current);
580 snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
550 581
551 ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); 582 ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli);
552 if (ret) 583 if (ret)
@@ -642,8 +673,8 @@ driver = {
642 .irq_handler = nouveau_irq_handler, 673 .irq_handler = nouveau_irq_handler,
643 674
644 .get_vblank_counter = drm_vblank_count, 675 .get_vblank_counter = drm_vblank_count,
645 .enable_vblank = nouveau_vblank_enable, 676 .enable_vblank = nouveau_drm_vblank_enable,
646 .disable_vblank = nouveau_vblank_disable, 677 .disable_vblank = nouveau_drm_vblank_disable,
647 678
648 .ioctls = nouveau_ioctls, 679 .ioctls = nouveau_ioctls,
649 .fops = &nouveau_driver_fops, 680 .fops = &nouveau_driver_fops,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index aa89eb938b47..b25df374c901 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -13,6 +13,7 @@
13#define DRIVER_PATCHLEVEL 0 13#define DRIVER_PATCHLEVEL 0
14 14
15#include <core/client.h> 15#include <core/client.h>
16#include <core/event.h>
16 17
17#include <subdev/vm.h> 18#include <subdev/vm.h>
18 19
@@ -112,6 +113,7 @@ struct nouveau_drm {
112 struct nvbios vbios; 113 struct nvbios vbios;
113 struct nouveau_display *display; 114 struct nouveau_display *display;
114 struct backlight_device *backlight; 115 struct backlight_device *backlight;
116 struct nouveau_eventh vblank;
115 117
116 /* power management */ 118 /* power management */
117 struct nouveau_pm *pm; 119 struct nouveau_pm *pm;
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index d0d95bd511ab..e24341229d5e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -36,19 +36,12 @@
36 36
37struct nouveau_i2c_port; 37struct nouveau_i2c_port;
38 38
39struct dp_train_func {
40 void (*link_set)(struct drm_device *, struct dcb_output *, int crtc,
41 int nr, u32 bw, bool enhframe);
42 void (*train_set)(struct drm_device *, struct dcb_output *, u8 pattern);
43 void (*train_adj)(struct drm_device *, struct dcb_output *,
44 u8 lane, u8 swing, u8 preem);
45};
46
47struct nouveau_encoder { 39struct nouveau_encoder {
48 struct drm_encoder_slave base; 40 struct drm_encoder_slave base;
49 41
50 struct dcb_output *dcb; 42 struct dcb_output *dcb;
51 int or; 43 int or;
44 struct nouveau_i2c_port *i2c;
52 45
53 /* different to drm_encoder.crtc, this reflects what's 46 /* different to drm_encoder.crtc, this reflects what's
54 * actually programmed on the hw, not the proposed crtc */ 47 * actually programmed on the hw, not the proposed crtc */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 1d049be79f74..6c946837a0aa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -33,14 +33,14 @@
33#include "nouveau_dma.h" 33#include "nouveau_dma.h"
34#include "nouveau_fence.h" 34#include "nouveau_fence.h"
35 35
36#include <engine/fifo.h>
37
36void 38void
37nouveau_fence_context_del(struct nouveau_fence_chan *fctx) 39nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
38{ 40{
39 struct nouveau_fence *fence, *fnext; 41 struct nouveau_fence *fence, *fnext;
40 spin_lock(&fctx->lock); 42 spin_lock(&fctx->lock);
41 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { 43 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) {
42 if (fence->work)
43 fence->work(fence->priv, false);
44 fence->channel = NULL; 44 fence->channel = NULL;
45 list_del(&fence->head); 45 list_del(&fence->head);
46 nouveau_fence_unref(&fence); 46 nouveau_fence_unref(&fence);
@@ -59,17 +59,14 @@ nouveau_fence_context_new(struct nouveau_fence_chan *fctx)
59static void 59static void
60nouveau_fence_update(struct nouveau_channel *chan) 60nouveau_fence_update(struct nouveau_channel *chan)
61{ 61{
62 struct nouveau_fence_priv *priv = chan->drm->fence;
63 struct nouveau_fence_chan *fctx = chan->fence; 62 struct nouveau_fence_chan *fctx = chan->fence;
64 struct nouveau_fence *fence, *fnext; 63 struct nouveau_fence *fence, *fnext;
65 64
66 spin_lock(&fctx->lock); 65 spin_lock(&fctx->lock);
67 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { 66 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) {
68 if (priv->read(chan) < fence->sequence) 67 if (fctx->read(chan) < fence->sequence)
69 break; 68 break;
70 69
71 if (fence->work)
72 fence->work(fence->priv, true);
73 fence->channel = NULL; 70 fence->channel = NULL;
74 list_del(&fence->head); 71 list_del(&fence->head);
75 nouveau_fence_unref(&fence); 72 nouveau_fence_unref(&fence);
@@ -80,7 +77,6 @@ nouveau_fence_update(struct nouveau_channel *chan)
80int 77int
81nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) 78nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
82{ 79{
83 struct nouveau_fence_priv *priv = chan->drm->fence;
84 struct nouveau_fence_chan *fctx = chan->fence; 80 struct nouveau_fence_chan *fctx = chan->fence;
85 int ret; 81 int ret;
86 82
@@ -88,7 +84,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
88 fence->timeout = jiffies + (3 * DRM_HZ); 84 fence->timeout = jiffies + (3 * DRM_HZ);
89 fence->sequence = ++fctx->sequence; 85 fence->sequence = ++fctx->sequence;
90 86
91 ret = priv->emit(fence); 87 ret = fctx->emit(fence);
92 if (!ret) { 88 if (!ret) {
93 kref_get(&fence->kref); 89 kref_get(&fence->kref);
94 spin_lock(&fctx->lock); 90 spin_lock(&fctx->lock);
@@ -107,13 +103,87 @@ nouveau_fence_done(struct nouveau_fence *fence)
107 return !fence->channel; 103 return !fence->channel;
108} 104}
109 105
106struct nouveau_fence_uevent {
107 struct nouveau_eventh handler;
108 struct nouveau_fence_priv *priv;
109};
110
111static int
112nouveau_fence_wait_uevent_handler(struct nouveau_eventh *event, int index)
113{
114 struct nouveau_fence_uevent *uevent =
115 container_of(event, struct nouveau_fence_uevent, handler);
116 wake_up_all(&uevent->priv->waiting);
117 return NVKM_EVENT_KEEP;
118}
119
120static int
121nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
122
123{
124 struct nouveau_channel *chan = fence->channel;
125 struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device);
126 struct nouveau_fence_priv *priv = chan->drm->fence;
127 struct nouveau_fence_uevent uevent = {
128 .handler.func = nouveau_fence_wait_uevent_handler,
129 .priv = priv,
130 };
131 int ret = 0;
132
133 nouveau_event_get(pfifo->uevent, 0, &uevent.handler);
134
135 if (fence->timeout) {
136 unsigned long timeout = fence->timeout - jiffies;
137
138 if (time_before(jiffies, fence->timeout)) {
139 if (intr) {
140 ret = wait_event_interruptible_timeout(
141 priv->waiting,
142 nouveau_fence_done(fence),
143 timeout);
144 } else {
145 ret = wait_event_timeout(priv->waiting,
146 nouveau_fence_done(fence),
147 timeout);
148 }
149 }
150
151 if (ret >= 0) {
152 fence->timeout = jiffies + ret;
153 if (time_after_eq(jiffies, fence->timeout))
154 ret = -EBUSY;
155 }
156 } else {
157 if (intr) {
158 ret = wait_event_interruptible(priv->waiting,
159 nouveau_fence_done(fence));
160 } else {
161 wait_event(priv->waiting, nouveau_fence_done(fence));
162 }
163 }
164
165 nouveau_event_put(pfifo->uevent, 0, &uevent.handler);
166 if (unlikely(ret < 0))
167 return ret;
168
169 return 0;
170}
171
110int 172int
111nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) 173nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
112{ 174{
175 struct nouveau_channel *chan = fence->channel;
176 struct nouveau_fence_priv *priv = chan ? chan->drm->fence : NULL;
113 unsigned long sleep_time = NSEC_PER_MSEC / 1000; 177 unsigned long sleep_time = NSEC_PER_MSEC / 1000;
114 ktime_t t; 178 ktime_t t;
115 int ret = 0; 179 int ret = 0;
116 180
181 while (priv && priv->uevent && lazy && !nouveau_fence_done(fence)) {
182 ret = nouveau_fence_wait_uevent(fence, intr);
183 if (ret < 0)
184 return ret;
185 }
186
117 while (!nouveau_fence_done(fence)) { 187 while (!nouveau_fence_done(fence)) {
118 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) { 188 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
119 ret = -EBUSY; 189 ret = -EBUSY;
@@ -143,14 +213,14 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
143int 213int
144nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan) 214nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan)
145{ 215{
146 struct nouveau_fence_priv *priv = chan->drm->fence; 216 struct nouveau_fence_chan *fctx = chan->fence;
147 struct nouveau_channel *prev; 217 struct nouveau_channel *prev;
148 int ret = 0; 218 int ret = 0;
149 219
150 prev = fence ? fence->channel : NULL; 220 prev = fence ? fence->channel : NULL;
151 if (prev) { 221 if (prev) {
152 if (unlikely(prev != chan && !nouveau_fence_done(fence))) { 222 if (unlikely(prev != chan && !nouveau_fence_done(fence))) {
153 ret = priv->sync(fence, prev, chan); 223 ret = fctx->sync(fence, prev, chan);
154 if (unlikely(ret)) 224 if (unlikely(ret))
155 ret = nouveau_fence_wait(fence, true, false); 225 ret = nouveau_fence_wait(fence, true, false);
156 } 226 }
@@ -182,7 +252,8 @@ nouveau_fence_ref(struct nouveau_fence *fence)
182} 252}
183 253
184int 254int
185nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence) 255nouveau_fence_new(struct nouveau_channel *chan, bool sysmem,
256 struct nouveau_fence **pfence)
186{ 257{
187 struct nouveau_fence *fence; 258 struct nouveau_fence *fence;
188 int ret = 0; 259 int ret = 0;
@@ -193,13 +264,13 @@ nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence)
193 fence = kzalloc(sizeof(*fence), GFP_KERNEL); 264 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
194 if (!fence) 265 if (!fence)
195 return -ENOMEM; 266 return -ENOMEM;
267
268 fence->sysmem = sysmem;
196 kref_init(&fence->kref); 269 kref_init(&fence->kref);
197 270
198 if (chan) { 271 ret = nouveau_fence_emit(fence, chan);
199 ret = nouveau_fence_emit(fence, chan); 272 if (ret)
200 if (ret) 273 nouveau_fence_unref(&fence);
201 nouveau_fence_unref(&fence);
202 }
203 274
204 *pfence = fence; 275 *pfence = fence;
205 return ret; 276 return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index cdb83acdffe2..c89943407b52 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -7,15 +7,15 @@ struct nouveau_fence {
7 struct list_head head; 7 struct list_head head;
8 struct kref kref; 8 struct kref kref;
9 9
10 bool sysmem;
11
10 struct nouveau_channel *channel; 12 struct nouveau_channel *channel;
11 unsigned long timeout; 13 unsigned long timeout;
12 u32 sequence; 14 u32 sequence;
13
14 void (*work)(void *priv, bool signalled);
15 void *priv;
16}; 15};
17 16
18int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); 17int nouveau_fence_new(struct nouveau_channel *, bool sysmem,
18 struct nouveau_fence **);
19struct nouveau_fence * 19struct nouveau_fence *
20nouveau_fence_ref(struct nouveau_fence *); 20nouveau_fence_ref(struct nouveau_fence *);
21void nouveau_fence_unref(struct nouveau_fence **); 21void nouveau_fence_unref(struct nouveau_fence **);
@@ -29,6 +29,13 @@ struct nouveau_fence_chan {
29 struct list_head pending; 29 struct list_head pending;
30 struct list_head flip; 30 struct list_head flip;
31 31
32 int (*emit)(struct nouveau_fence *);
33 int (*sync)(struct nouveau_fence *, struct nouveau_channel *,
34 struct nouveau_channel *);
35 u32 (*read)(struct nouveau_channel *);
36 int (*emit32)(struct nouveau_channel *, u64, u32);
37 int (*sync32)(struct nouveau_channel *, u64, u32);
38
32 spinlock_t lock; 39 spinlock_t lock;
33 u32 sequence; 40 u32 sequence;
34}; 41};
@@ -39,10 +46,9 @@ struct nouveau_fence_priv {
39 void (*resume)(struct nouveau_drm *); 46 void (*resume)(struct nouveau_drm *);
40 int (*context_new)(struct nouveau_channel *); 47 int (*context_new)(struct nouveau_channel *);
41 void (*context_del)(struct nouveau_channel *); 48 void (*context_del)(struct nouveau_channel *);
42 int (*emit)(struct nouveau_fence *); 49
43 int (*sync)(struct nouveau_fence *, struct nouveau_channel *, 50 wait_queue_head_t waiting;
44 struct nouveau_channel *); 51 bool uevent;
45 u32 (*read)(struct nouveau_channel *);
46}; 52};
47 53
48#define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence) 54#define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence)
@@ -60,13 +66,31 @@ u32 nv10_fence_read(struct nouveau_channel *);
60void nv10_fence_context_del(struct nouveau_channel *); 66void nv10_fence_context_del(struct nouveau_channel *);
61void nv10_fence_destroy(struct nouveau_drm *); 67void nv10_fence_destroy(struct nouveau_drm *);
62int nv10_fence_create(struct nouveau_drm *); 68int nv10_fence_create(struct nouveau_drm *);
69
70int nv17_fence_create(struct nouveau_drm *);
63void nv17_fence_resume(struct nouveau_drm *drm); 71void nv17_fence_resume(struct nouveau_drm *drm);
64 72
65int nv50_fence_create(struct nouveau_drm *); 73int nv50_fence_create(struct nouveau_drm *);
66int nv84_fence_create(struct nouveau_drm *); 74int nv84_fence_create(struct nouveau_drm *);
67int nvc0_fence_create(struct nouveau_drm *); 75int nvc0_fence_create(struct nouveau_drm *);
68u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc);
69 76
70int nouveau_flip_complete(void *chan); 77int nouveau_flip_complete(void *chan);
71 78
79struct nv84_fence_chan {
80 struct nouveau_fence_chan base;
81 struct nouveau_vma vma;
82 struct nouveau_vma vma_gart;
83 struct nouveau_vma dispc_vma[4];
84};
85
86struct nv84_fence_priv {
87 struct nouveau_fence_priv base;
88 struct nouveau_bo *bo;
89 struct nouveau_bo *bo_gart;
90 u32 *suspend;
91};
92
93u64 nv84_fence_crtc(struct nouveau_channel *, int);
94int nv84_fence_context_new(struct nouveau_channel *);
95
72#endif 96#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index d98bee012cab..b4b4d0c1f4af 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -203,6 +203,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
203 struct drm_file *file_priv) 203 struct drm_file *file_priv)
204{ 204{
205 struct nouveau_drm *drm = nouveau_drm(dev); 205 struct nouveau_drm *drm = nouveau_drm(dev);
206 struct nouveau_cli *cli = nouveau_cli(file_priv);
206 struct nouveau_fb *pfb = nouveau_fb(drm->device); 207 struct nouveau_fb *pfb = nouveau_fb(drm->device);
207 struct drm_nouveau_gem_new *req = data; 208 struct drm_nouveau_gem_new *req = data;
208 struct nouveau_bo *nvbo = NULL; 209 struct nouveau_bo *nvbo = NULL;
@@ -211,7 +212,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
211 drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; 212 drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping;
212 213
213 if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { 214 if (!pfb->memtype_valid(pfb, req->info.tile_flags)) {
214 NV_ERROR(drm, "bad page flags: 0x%08x\n", req->info.tile_flags); 215 NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
215 return -EINVAL; 216 return -EINVAL;
216 } 217 }
217 218
@@ -313,6 +314,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
313 struct drm_nouveau_gem_pushbuf_bo *pbbo, 314 struct drm_nouveau_gem_pushbuf_bo *pbbo,
314 int nr_buffers, struct validate_op *op) 315 int nr_buffers, struct validate_op *op)
315{ 316{
317 struct nouveau_cli *cli = nouveau_cli(file_priv);
316 struct drm_device *dev = chan->drm->dev; 318 struct drm_device *dev = chan->drm->dev;
317 struct nouveau_drm *drm = nouveau_drm(dev); 319 struct nouveau_drm *drm = nouveau_drm(dev);
318 uint32_t sequence; 320 uint32_t sequence;
@@ -323,7 +325,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
323 sequence = atomic_add_return(1, &drm->ttm.validate_sequence); 325 sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
324retry: 326retry:
325 if (++trycnt > 100000) { 327 if (++trycnt > 100000) {
326 NV_ERROR(drm, "%s failed and gave up.\n", __func__); 328 NV_ERROR(cli, "%s failed and gave up.\n", __func__);
327 return -EINVAL; 329 return -EINVAL;
328 } 330 }
329 331
@@ -334,7 +336,7 @@ retry:
334 336
335 gem = drm_gem_object_lookup(dev, file_priv, b->handle); 337 gem = drm_gem_object_lookup(dev, file_priv, b->handle);
336 if (!gem) { 338 if (!gem) {
337 NV_ERROR(drm, "Unknown handle 0x%08x\n", b->handle); 339 NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
338 validate_fini(op, NULL); 340 validate_fini(op, NULL);
339 return -ENOENT; 341 return -ENOENT;
340 } 342 }
@@ -346,7 +348,7 @@ retry:
346 } 348 }
347 349
348 if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { 350 if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
349 NV_ERROR(drm, "multiple instances of buffer %d on " 351 NV_ERROR(cli, "multiple instances of buffer %d on "
350 "validation list\n", b->handle); 352 "validation list\n", b->handle);
351 drm_gem_object_unreference_unlocked(gem); 353 drm_gem_object_unreference_unlocked(gem);
352 validate_fini(op, NULL); 354 validate_fini(op, NULL);
@@ -366,7 +368,7 @@ retry:
366 if (unlikely(ret)) { 368 if (unlikely(ret)) {
367 drm_gem_object_unreference_unlocked(gem); 369 drm_gem_object_unreference_unlocked(gem);
368 if (ret != -ERESTARTSYS) 370 if (ret != -ERESTARTSYS)
369 NV_ERROR(drm, "fail reserve\n"); 371 NV_ERROR(cli, "fail reserve\n");
370 return ret; 372 return ret;
371 } 373 }
372 } 374 }
@@ -384,7 +386,7 @@ retry:
384 if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) 386 if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)
385 list_add_tail(&nvbo->entry, &op->gart_list); 387 list_add_tail(&nvbo->entry, &op->gart_list);
386 else { 388 else {
387 NV_ERROR(drm, "invalid valid domains: 0x%08x\n", 389 NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
388 b->valid_domains); 390 b->valid_domains);
389 list_add_tail(&nvbo->entry, &op->both_list); 391 list_add_tail(&nvbo->entry, &op->both_list);
390 validate_fini(op, NULL); 392 validate_fini(op, NULL);
@@ -417,8 +419,9 @@ validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
417} 419}
418 420
419static int 421static int
420validate_list(struct nouveau_channel *chan, struct list_head *list, 422validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
421 struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) 423 struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo,
424 uint64_t user_pbbo_ptr)
422{ 425{
423 struct nouveau_drm *drm = chan->drm; 426 struct nouveau_drm *drm = chan->drm;
424 struct drm_nouveau_gem_pushbuf_bo __user *upbbo = 427 struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
@@ -431,7 +434,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
431 434
432 ret = validate_sync(chan, nvbo); 435 ret = validate_sync(chan, nvbo);
433 if (unlikely(ret)) { 436 if (unlikely(ret)) {
434 NV_ERROR(drm, "fail pre-validate sync\n"); 437 NV_ERROR(cli, "fail pre-validate sync\n");
435 return ret; 438 return ret;
436 } 439 }
437 440
@@ -439,20 +442,20 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
439 b->write_domains, 442 b->write_domains,
440 b->valid_domains); 443 b->valid_domains);
441 if (unlikely(ret)) { 444 if (unlikely(ret)) {
442 NV_ERROR(drm, "fail set_domain\n"); 445 NV_ERROR(cli, "fail set_domain\n");
443 return ret; 446 return ret;
444 } 447 }
445 448
446 ret = nouveau_bo_validate(nvbo, true, false); 449 ret = nouveau_bo_validate(nvbo, true, false);
447 if (unlikely(ret)) { 450 if (unlikely(ret)) {
448 if (ret != -ERESTARTSYS) 451 if (ret != -ERESTARTSYS)
449 NV_ERROR(drm, "fail ttm_validate\n"); 452 NV_ERROR(cli, "fail ttm_validate\n");
450 return ret; 453 return ret;
451 } 454 }
452 455
453 ret = validate_sync(chan, nvbo); 456 ret = validate_sync(chan, nvbo);
454 if (unlikely(ret)) { 457 if (unlikely(ret)) {
455 NV_ERROR(drm, "fail post-validate sync\n"); 458 NV_ERROR(cli, "fail post-validate sync\n");
456 return ret; 459 return ret;
457 } 460 }
458 461
@@ -488,7 +491,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
488 uint64_t user_buffers, int nr_buffers, 491 uint64_t user_buffers, int nr_buffers,
489 struct validate_op *op, int *apply_relocs) 492 struct validate_op *op, int *apply_relocs)
490{ 493{
491 struct nouveau_drm *drm = chan->drm; 494 struct nouveau_cli *cli = nouveau_cli(file_priv);
492 int ret, relocs = 0; 495 int ret, relocs = 0;
493 496
494 INIT_LIST_HEAD(&op->vram_list); 497 INIT_LIST_HEAD(&op->vram_list);
@@ -501,32 +504,32 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
501 ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); 504 ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
502 if (unlikely(ret)) { 505 if (unlikely(ret)) {
503 if (ret != -ERESTARTSYS) 506 if (ret != -ERESTARTSYS)
504 NV_ERROR(drm, "validate_init\n"); 507 NV_ERROR(cli, "validate_init\n");
505 return ret; 508 return ret;
506 } 509 }
507 510
508 ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); 511 ret = validate_list(chan, cli, &op->vram_list, pbbo, user_buffers);
509 if (unlikely(ret < 0)) { 512 if (unlikely(ret < 0)) {
510 if (ret != -ERESTARTSYS) 513 if (ret != -ERESTARTSYS)
511 NV_ERROR(drm, "validate vram_list\n"); 514 NV_ERROR(cli, "validate vram_list\n");
512 validate_fini(op, NULL); 515 validate_fini(op, NULL);
513 return ret; 516 return ret;
514 } 517 }
515 relocs += ret; 518 relocs += ret;
516 519
517 ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); 520 ret = validate_list(chan, cli, &op->gart_list, pbbo, user_buffers);
518 if (unlikely(ret < 0)) { 521 if (unlikely(ret < 0)) {
519 if (ret != -ERESTARTSYS) 522 if (ret != -ERESTARTSYS)
520 NV_ERROR(drm, "validate gart_list\n"); 523 NV_ERROR(cli, "validate gart_list\n");
521 validate_fini(op, NULL); 524 validate_fini(op, NULL);
522 return ret; 525 return ret;
523 } 526 }
524 relocs += ret; 527 relocs += ret;
525 528
526 ret = validate_list(chan, &op->both_list, pbbo, user_buffers); 529 ret = validate_list(chan, cli, &op->both_list, pbbo, user_buffers);
527 if (unlikely(ret < 0)) { 530 if (unlikely(ret < 0)) {
528 if (ret != -ERESTARTSYS) 531 if (ret != -ERESTARTSYS)
529 NV_ERROR(drm, "validate both_list\n"); 532 NV_ERROR(cli, "validate both_list\n");
530 validate_fini(op, NULL); 533 validate_fini(op, NULL);
531 return ret; 534 return ret;
532 } 535 }
@@ -555,11 +558,10 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
555} 558}
556 559
557static int 560static int
558nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, 561nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
559 struct drm_nouveau_gem_pushbuf *req, 562 struct drm_nouveau_gem_pushbuf *req,
560 struct drm_nouveau_gem_pushbuf_bo *bo) 563 struct drm_nouveau_gem_pushbuf_bo *bo)
561{ 564{
562 struct nouveau_drm *drm = nouveau_drm(dev);
563 struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; 565 struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
564 int ret = 0; 566 int ret = 0;
565 unsigned i; 567 unsigned i;
@@ -575,7 +577,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
575 uint32_t data; 577 uint32_t data;
576 578
577 if (unlikely(r->bo_index > req->nr_buffers)) { 579 if (unlikely(r->bo_index > req->nr_buffers)) {
578 NV_ERROR(drm, "reloc bo index invalid\n"); 580 NV_ERROR(cli, "reloc bo index invalid\n");
579 ret = -EINVAL; 581 ret = -EINVAL;
580 break; 582 break;
581 } 583 }
@@ -585,7 +587,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
585 continue; 587 continue;
586 588
587 if (unlikely(r->reloc_bo_index > req->nr_buffers)) { 589 if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
588 NV_ERROR(drm, "reloc container bo index invalid\n"); 590 NV_ERROR(cli, "reloc container bo index invalid\n");
589 ret = -EINVAL; 591 ret = -EINVAL;
590 break; 592 break;
591 } 593 }
@@ -593,7 +595,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
593 595
594 if (unlikely(r->reloc_bo_offset + 4 > 596 if (unlikely(r->reloc_bo_offset + 4 >
595 nvbo->bo.mem.num_pages << PAGE_SHIFT)) { 597 nvbo->bo.mem.num_pages << PAGE_SHIFT)) {
596 NV_ERROR(drm, "reloc outside of bo\n"); 598 NV_ERROR(cli, "reloc outside of bo\n");
597 ret = -EINVAL; 599 ret = -EINVAL;
598 break; 600 break;
599 } 601 }
@@ -602,7 +604,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
602 ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, 604 ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
603 &nvbo->kmap); 605 &nvbo->kmap);
604 if (ret) { 606 if (ret) {
605 NV_ERROR(drm, "failed kmap for reloc\n"); 607 NV_ERROR(cli, "failed kmap for reloc\n");
606 break; 608 break;
607 } 609 }
608 nvbo->validate_mapped = true; 610 nvbo->validate_mapped = true;
@@ -627,7 +629,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
627 ret = ttm_bo_wait(&nvbo->bo, false, false, false); 629 ret = ttm_bo_wait(&nvbo->bo, false, false, false);
628 spin_unlock(&nvbo->bo.bdev->fence_lock); 630 spin_unlock(&nvbo->bo.bdev->fence_lock);
629 if (ret) { 631 if (ret) {
630 NV_ERROR(drm, "reloc wait_idle failed: %d\n", ret); 632 NV_ERROR(cli, "reloc wait_idle failed: %d\n", ret);
631 break; 633 break;
632 } 634 }
633 635
@@ -643,6 +645,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
643 struct drm_file *file_priv) 645 struct drm_file *file_priv)
644{ 646{
645 struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); 647 struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
648 struct nouveau_cli *cli = nouveau_cli(file_priv);
646 struct nouveau_abi16_chan *temp; 649 struct nouveau_abi16_chan *temp;
647 struct nouveau_drm *drm = nouveau_drm(dev); 650 struct nouveau_drm *drm = nouveau_drm(dev);
648 struct drm_nouveau_gem_pushbuf *req = data; 651 struct drm_nouveau_gem_pushbuf *req = data;
@@ -672,19 +675,19 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
672 goto out_next; 675 goto out_next;
673 676
674 if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { 677 if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
675 NV_ERROR(drm, "pushbuf push count exceeds limit: %d max %d\n", 678 NV_ERROR(cli, "pushbuf push count exceeds limit: %d max %d\n",
676 req->nr_push, NOUVEAU_GEM_MAX_PUSH); 679 req->nr_push, NOUVEAU_GEM_MAX_PUSH);
677 return nouveau_abi16_put(abi16, -EINVAL); 680 return nouveau_abi16_put(abi16, -EINVAL);
678 } 681 }
679 682
680 if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { 683 if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
681 NV_ERROR(drm, "pushbuf bo count exceeds limit: %d max %d\n", 684 NV_ERROR(cli, "pushbuf bo count exceeds limit: %d max %d\n",
682 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); 685 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
683 return nouveau_abi16_put(abi16, -EINVAL); 686 return nouveau_abi16_put(abi16, -EINVAL);
684 } 687 }
685 688
686 if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { 689 if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
687 NV_ERROR(drm, "pushbuf reloc count exceeds limit: %d max %d\n", 690 NV_ERROR(cli, "pushbuf reloc count exceeds limit: %d max %d\n",
688 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); 691 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
689 return nouveau_abi16_put(abi16, -EINVAL); 692 return nouveau_abi16_put(abi16, -EINVAL);
690 } 693 }
@@ -702,7 +705,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
702 /* Ensure all push buffers are on validate list */ 705 /* Ensure all push buffers are on validate list */
703 for (i = 0; i < req->nr_push; i++) { 706 for (i = 0; i < req->nr_push; i++) {
704 if (push[i].bo_index >= req->nr_buffers) { 707 if (push[i].bo_index >= req->nr_buffers) {
705 NV_ERROR(drm, "push %d buffer not in list\n", i); 708 NV_ERROR(cli, "push %d buffer not in list\n", i);
706 ret = -EINVAL; 709 ret = -EINVAL;
707 goto out_prevalid; 710 goto out_prevalid;
708 } 711 }
@@ -713,15 +716,15 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
713 req->nr_buffers, &op, &do_reloc); 716 req->nr_buffers, &op, &do_reloc);
714 if (ret) { 717 if (ret) {
715 if (ret != -ERESTARTSYS) 718 if (ret != -ERESTARTSYS)
716 NV_ERROR(drm, "validate: %d\n", ret); 719 NV_ERROR(cli, "validate: %d\n", ret);
717 goto out_prevalid; 720 goto out_prevalid;
718 } 721 }
719 722
720 /* Apply any relocations that are required */ 723 /* Apply any relocations that are required */
721 if (do_reloc) { 724 if (do_reloc) {
722 ret = nouveau_gem_pushbuf_reloc_apply(dev, req, bo); 725 ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo);
723 if (ret) { 726 if (ret) {
724 NV_ERROR(drm, "reloc apply: %d\n", ret); 727 NV_ERROR(cli, "reloc apply: %d\n", ret);
725 goto out; 728 goto out;
726 } 729 }
727 } 730 }
@@ -729,7 +732,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
729 if (chan->dma.ib_max) { 732 if (chan->dma.ib_max) {
730 ret = nouveau_dma_wait(chan, req->nr_push + 1, 16); 733 ret = nouveau_dma_wait(chan, req->nr_push + 1, 16);
731 if (ret) { 734 if (ret) {
732 NV_ERROR(drm, "nv50cal_space: %d\n", ret); 735 NV_ERROR(cli, "nv50cal_space: %d\n", ret);
733 goto out; 736 goto out;
734 } 737 }
735 738
@@ -744,7 +747,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
744 if (nv_device(drm->device)->chipset >= 0x25) { 747 if (nv_device(drm->device)->chipset >= 0x25) {
745 ret = RING_SPACE(chan, req->nr_push * 2); 748 ret = RING_SPACE(chan, req->nr_push * 2);
746 if (ret) { 749 if (ret) {
747 NV_ERROR(drm, "cal_space: %d\n", ret); 750 NV_ERROR(cli, "cal_space: %d\n", ret);
748 goto out; 751 goto out;
749 } 752 }
750 753
@@ -758,7 +761,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
758 } else { 761 } else {
759 ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); 762 ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
760 if (ret) { 763 if (ret) {
761 NV_ERROR(drm, "jmp_space: %d\n", ret); 764 NV_ERROR(cli, "jmp_space: %d\n", ret);
762 goto out; 765 goto out;
763 } 766 }
764 767
@@ -794,9 +797,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
794 } 797 }
795 } 798 }
796 799
797 ret = nouveau_fence_new(chan, &fence); 800 ret = nouveau_fence_new(chan, false, &fence);
798 if (ret) { 801 if (ret) {
799 NV_ERROR(drm, "error fencing pushbuf: %d\n", ret); 802 NV_ERROR(cli, "error fencing pushbuf: %d\n", ret);
800 WIND_RING(chan); 803 WIND_RING(chan);
801 goto out; 804 goto out;
802 } 805 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index a701ff5ffa5b..bb54098c6d97 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -409,6 +409,81 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
409 NULL, 0); 409 NULL, 0);
410 410
411static ssize_t 411static ssize_t
412nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,
413 struct device_attribute *a, char *buf)
414{
415 return snprintf(buf, PAGE_SIZE, "%d\n", 100);
416}
417static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO,
418 nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
419
420static ssize_t
421nouveau_hwmon_temp1_auto_point1_temp(struct device *d,
422 struct device_attribute *a, char *buf)
423{
424 struct drm_device *dev = dev_get_drvdata(d);
425 struct nouveau_drm *drm = nouveau_drm(dev);
426 struct nouveau_therm *therm = nouveau_therm(drm->device);
427
428 return snprintf(buf, PAGE_SIZE, "%d\n",
429 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST) * 1000);
430}
431static ssize_t
432nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
433 struct device_attribute *a,
434 const char *buf, size_t count)
435{
436 struct drm_device *dev = dev_get_drvdata(d);
437 struct nouveau_drm *drm = nouveau_drm(dev);
438 struct nouveau_therm *therm = nouveau_therm(drm->device);
439 long value;
440
441 if (kstrtol(buf, 10, &value) == -EINVAL)
442 return count;
443
444 therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST,
445 value / 1000);
446
447 return count;
448}
449static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IRUGO | S_IWUSR,
450 nouveau_hwmon_temp1_auto_point1_temp,
451 nouveau_hwmon_set_temp1_auto_point1_temp, 0);
452
453static ssize_t
454nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
455 struct device_attribute *a, char *buf)
456{
457 struct drm_device *dev = dev_get_drvdata(d);
458 struct nouveau_drm *drm = nouveau_drm(dev);
459 struct nouveau_therm *therm = nouveau_therm(drm->device);
460
461 return snprintf(buf, PAGE_SIZE, "%d\n",
462 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
463}
464static ssize_t
465nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
466 struct device_attribute *a,
467 const char *buf, size_t count)
468{
469 struct drm_device *dev = dev_get_drvdata(d);
470 struct nouveau_drm *drm = nouveau_drm(dev);
471 struct nouveau_therm *therm = nouveau_therm(drm->device);
472 long value;
473
474 if (kstrtol(buf, 10, &value) == -EINVAL)
475 return count;
476
477 therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST,
478 value / 1000);
479
480 return count;
481}
482static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
483 nouveau_hwmon_temp1_auto_point1_temp_hyst,
484 nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0);
485
486static ssize_t
412nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) 487nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
413{ 488{
414 struct drm_device *dev = dev_get_drvdata(d); 489 struct drm_device *dev = dev_get_drvdata(d);
@@ -439,6 +514,38 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
439 0); 514 0);
440 515
441static ssize_t 516static ssize_t
517nouveau_hwmon_max_temp_hyst(struct device *d, struct device_attribute *a,
518 char *buf)
519{
520 struct drm_device *dev = dev_get_drvdata(d);
521 struct nouveau_drm *drm = nouveau_drm(dev);
522 struct nouveau_therm *therm = nouveau_therm(drm->device);
523
524 return snprintf(buf, PAGE_SIZE, "%d\n",
525 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000);
526}
527static ssize_t
528nouveau_hwmon_set_max_temp_hyst(struct device *d, struct device_attribute *a,
529 const char *buf, size_t count)
530{
531 struct drm_device *dev = dev_get_drvdata(d);
532 struct nouveau_drm *drm = nouveau_drm(dev);
533 struct nouveau_therm *therm = nouveau_therm(drm->device);
534 long value;
535
536 if (kstrtol(buf, 10, &value) == -EINVAL)
537 return count;
538
539 therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST,
540 value / 1000);
541
542 return count;
543}
544static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
545 nouveau_hwmon_max_temp_hyst,
546 nouveau_hwmon_set_max_temp_hyst, 0);
547
548static ssize_t
442nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, 549nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a,
443 char *buf) 550 char *buf)
444{ 551{
@@ -471,6 +578,107 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
471 nouveau_hwmon_set_critical_temp, 578 nouveau_hwmon_set_critical_temp,
472 0); 579 0);
473 580
581static ssize_t
582nouveau_hwmon_critical_temp_hyst(struct device *d, struct device_attribute *a,
583 char *buf)
584{
585 struct drm_device *dev = dev_get_drvdata(d);
586 struct nouveau_drm *drm = nouveau_drm(dev);
587 struct nouveau_therm *therm = nouveau_therm(drm->device);
588
589 return snprintf(buf, PAGE_SIZE, "%d\n",
590 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST) * 1000);
591}
592static ssize_t
593nouveau_hwmon_set_critical_temp_hyst(struct device *d,
594 struct device_attribute *a,
595 const char *buf,
596 size_t count)
597{
598 struct drm_device *dev = dev_get_drvdata(d);
599 struct nouveau_drm *drm = nouveau_drm(dev);
600 struct nouveau_therm *therm = nouveau_therm(drm->device);
601 long value;
602
603 if (kstrtol(buf, 10, &value) == -EINVAL)
604 return count;
605
606 therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST,
607 value / 1000);
608
609 return count;
610}
611static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,
612 nouveau_hwmon_critical_temp_hyst,
613 nouveau_hwmon_set_critical_temp_hyst, 0);
614static ssize_t
615nouveau_hwmon_emergency_temp(struct device *d, struct device_attribute *a,
616 char *buf)
617{
618 struct drm_device *dev = dev_get_drvdata(d);
619 struct nouveau_drm *drm = nouveau_drm(dev);
620 struct nouveau_therm *therm = nouveau_therm(drm->device);
621
622 return snprintf(buf, PAGE_SIZE, "%d\n",
623 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN) * 1000);
624}
625static ssize_t
626nouveau_hwmon_set_emergency_temp(struct device *d, struct device_attribute *a,
627 const char *buf,
628 size_t count)
629{
630 struct drm_device *dev = dev_get_drvdata(d);
631 struct nouveau_drm *drm = nouveau_drm(dev);
632 struct nouveau_therm *therm = nouveau_therm(drm->device);
633 long value;
634
635 if (kstrtol(buf, 10, &value) == -EINVAL)
636 return count;
637
638 therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN, value / 1000);
639
640 return count;
641}
642static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR,
643 nouveau_hwmon_emergency_temp,
644 nouveau_hwmon_set_emergency_temp,
645 0);
646
647static ssize_t
648nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a,
649 char *buf)
650{
651 struct drm_device *dev = dev_get_drvdata(d);
652 struct nouveau_drm *drm = nouveau_drm(dev);
653 struct nouveau_therm *therm = nouveau_therm(drm->device);
654
655 return snprintf(buf, PAGE_SIZE, "%d\n",
656 therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
657}
658static ssize_t
659nouveau_hwmon_set_emergency_temp_hyst(struct device *d,
660 struct device_attribute *a,
661 const char *buf,
662 size_t count)
663{
664 struct drm_device *dev = dev_get_drvdata(d);
665 struct nouveau_drm *drm = nouveau_drm(dev);
666 struct nouveau_therm *therm = nouveau_therm(drm->device);
667 long value;
668
669 if (kstrtol(buf, 10, &value) == -EINVAL)
670 return count;
671
672 therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST,
673 value / 1000);
674
675 return count;
676}
677static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO | S_IWUSR,
678 nouveau_hwmon_emergency_temp_hyst,
679 nouveau_hwmon_set_emergency_temp_hyst,
680 0);
681
474static ssize_t nouveau_hwmon_show_name(struct device *dev, 682static ssize_t nouveau_hwmon_show_name(struct device *dev,
475 struct device_attribute *attr, 683 struct device_attribute *attr,
476 char *buf) 684 char *buf)
@@ -490,7 +698,7 @@ static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
490 NULL, 0); 698 NULL, 0);
491 699
492static ssize_t 700static ssize_t
493nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, 701nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr,
494 char *buf) 702 char *buf)
495{ 703{
496 struct drm_device *dev = dev_get_drvdata(d); 704 struct drm_device *dev = dev_get_drvdata(d);
@@ -499,7 +707,7 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr,
499 707
500 return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm)); 708 return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm));
501} 709}
502static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, 710static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input,
503 NULL, 0); 711 NULL, 0);
504 712
505 static ssize_t 713 static ssize_t
@@ -665,14 +873,21 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
665 873
666static struct attribute *hwmon_attributes[] = { 874static struct attribute *hwmon_attributes[] = {
667 &sensor_dev_attr_temp1_input.dev_attr.attr, 875 &sensor_dev_attr_temp1_input.dev_attr.attr,
876 &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
877 &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
878 &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
668 &sensor_dev_attr_temp1_max.dev_attr.attr, 879 &sensor_dev_attr_temp1_max.dev_attr.attr,
880 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
669 &sensor_dev_attr_temp1_crit.dev_attr.attr, 881 &sensor_dev_attr_temp1_crit.dev_attr.attr,
882 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
883 &sensor_dev_attr_temp1_emergency.dev_attr.attr,
884 &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
670 &sensor_dev_attr_name.dev_attr.attr, 885 &sensor_dev_attr_name.dev_attr.attr,
671 &sensor_dev_attr_update_rate.dev_attr.attr, 886 &sensor_dev_attr_update_rate.dev_attr.attr,
672 NULL 887 NULL
673}; 888};
674static struct attribute *hwmon_fan_rpm_attributes[] = { 889static struct attribute *hwmon_fan_rpm_attributes[] = {
675 &sensor_dev_attr_fan0_input.dev_attr.attr, 890 &sensor_dev_attr_fan1_input.dev_attr.attr,
676 NULL 891 NULL
677}; 892};
678static struct attribute *hwmon_pwm_fan_attributes[] = { 893static struct attribute *hwmon_pwm_fan_attributes[] = {
@@ -717,7 +932,7 @@ nouveau_hwmon_init(struct drm_device *dev)
717 dev_set_drvdata(hwmon_dev, dev); 932 dev_set_drvdata(hwmon_dev, dev);
718 933
719 /* default sysfs entries */ 934 /* default sysfs entries */
720 ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); 935 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup);
721 if (ret) { 936 if (ret) {
722 if (ret) 937 if (ret)
723 goto error; 938 goto error;
@@ -728,7 +943,7 @@ nouveau_hwmon_init(struct drm_device *dev)
728 * the gpio entries for pwm fan control even when there's no 943 * the gpio entries for pwm fan control even when there's no
729 * actual fan connected to it... therm table? */ 944 * actual fan connected to it... therm table? */
730 if (therm->fan_get && therm->fan_get(therm) >= 0) { 945 if (therm->fan_get && therm->fan_get(therm) >= 0) {
731 ret = sysfs_create_group(&dev->pdev->dev.kobj, 946 ret = sysfs_create_group(&hwmon_dev->kobj,
732 &hwmon_pwm_fan_attrgroup); 947 &hwmon_pwm_fan_attrgroup);
733 if (ret) 948 if (ret)
734 goto error; 949 goto error;
@@ -736,7 +951,7 @@ nouveau_hwmon_init(struct drm_device *dev)
736 951
737 /* if the card can read the fan rpm */ 952 /* if the card can read the fan rpm */
738 if (therm->fan_sense(therm) >= 0) { 953 if (therm->fan_sense(therm) >= 0) {
739 ret = sysfs_create_group(&dev->pdev->dev.kobj, 954 ret = sysfs_create_group(&hwmon_dev->kobj,
740 &hwmon_fan_rpm_attrgroup); 955 &hwmon_fan_rpm_attrgroup);
741 if (ret) 956 if (ret)
742 goto error; 957 goto error;
@@ -764,10 +979,10 @@ nouveau_hwmon_fini(struct drm_device *dev)
764 struct nouveau_pm *pm = nouveau_pm(dev); 979 struct nouveau_pm *pm = nouveau_pm(dev);
765 980
766 if (pm->hwmon) { 981 if (pm->hwmon) {
767 sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); 982 sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup);
768 sysfs_remove_group(&dev->pdev->dev.kobj, 983 sysfs_remove_group(&pm->hwmon->kobj,
769 &hwmon_pwm_fan_attrgroup); 984 &hwmon_pwm_fan_attrgroup);
770 sysfs_remove_group(&dev->pdev->dev.kobj, 985 sysfs_remove_group(&pm->hwmon->kobj,
771 &hwmon_fan_rpm_attrgroup); 986 &hwmon_fan_rpm_attrgroup);
772 987
773 hwmon_device_unregister(pm->hwmon); 988 hwmon_device_unregister(pm->hwmon);
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index 39ffc07f906b..7e24cdf1cb39 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -490,8 +490,8 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
490 /* BIOS scripts usually take care of the backlight, thanks 490 /* BIOS scripts usually take care of the backlight, thanks
491 * Apple for your consistency. 491 * Apple for your consistency.
492 */ 492 */
493 if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || 493 if (dev->pci_device == 0x0174 || dev->pci_device == 0x0179 ||
494 dev->pci_device == 0x0329) { 494 dev->pci_device == 0x0189 || dev->pci_device == 0x0329) {
495 if (mode == DRM_MODE_DPMS_ON) { 495 if (mode == DRM_MODE_DPMS_ON) {
496 nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); 496 nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31);
497 nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1); 497 nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1);
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c
index 4c6e9f83fe82..ad48444c385c 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -22,6 +22,9 @@
22 * Author: Ben Skeggs 22 * Author: Ben Skeggs
23 */ 23 */
24 24
25#include <core/object.h>
26#include <core/class.h>
27
25#include <drm/drmP.h> 28#include <drm/drmP.h>
26#include <drm/drm_crtc_helper.h> 29#include <drm/drm_crtc_helper.h>
27 30
@@ -31,6 +34,8 @@
31#include "nouveau_encoder.h" 34#include "nouveau_encoder.h"
32#include "nouveau_connector.h" 35#include "nouveau_connector.h"
33 36
37#include <subdev/i2c.h>
38
34int 39int
35nv04_display_early_init(struct drm_device *dev) 40nv04_display_early_init(struct drm_device *dev)
36{ 41{
@@ -53,6 +58,7 @@ int
53nv04_display_create(struct drm_device *dev) 58nv04_display_create(struct drm_device *dev)
54{ 59{
55 struct nouveau_drm *drm = nouveau_drm(dev); 60 struct nouveau_drm *drm = nouveau_drm(dev);
61 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
56 struct dcb_table *dcb = &drm->vbios.dcb; 62 struct dcb_table *dcb = &drm->vbios.dcb;
57 struct drm_connector *connector, *ct; 63 struct drm_connector *connector, *ct;
58 struct drm_encoder *encoder; 64 struct drm_encoder *encoder;
@@ -71,6 +77,11 @@ nv04_display_create(struct drm_device *dev)
71 77
72 nouveau_hw_save_vga_fonts(dev, 1); 78 nouveau_hw_save_vga_fonts(dev, 1);
73 79
80 ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000,
81 NV04_DISP_CLASS, NULL, 0, &disp->core);
82 if (ret)
83 return ret;
84
74 nv04_crtc_create(dev, 0); 85 nv04_crtc_create(dev, 0);
75 if (nv_two_heads(dev)) 86 if (nv_two_heads(dev))
76 nv04_crtc_create(dev, 1); 87 nv04_crtc_create(dev, 1);
@@ -114,6 +125,11 @@ nv04_display_create(struct drm_device *dev)
114 } 125 }
115 } 126 }
116 127
128 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
129 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
130 nv_encoder->i2c = i2c->find(i2c, nv_encoder->dcb->i2c_index);
131 }
132
117 /* Save previous state */ 133 /* Save previous state */
118 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 134 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
119 crtc->funcs->save(crtc); 135 crtc->funcs->save(crtc);
diff --git a/drivers/gpu/drm/nouveau/nv04_display.h b/drivers/gpu/drm/nouveau/nv04_display.h
index 45322802e37d..a0a031dad13f 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.h
+++ b/drivers/gpu/drm/nouveau/nv04_display.h
@@ -80,6 +80,7 @@ struct nv04_display {
80 struct nv04_mode_state saved_reg; 80 struct nv04_mode_state saved_reg;
81 uint32_t saved_vga_font[4][16384]; 81 uint32_t saved_vga_font[4][16384];
82 uint32_t dac_users[4]; 82 uint32_t dac_users[4];
83 struct nouveau_object *core;
83}; 84};
84 85
85static inline struct nv04_display * 86static inline struct nv04_display *
diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c
index a220b94ba9f2..94eadd1dd10a 100644
--- a/drivers/gpu/drm/nouveau/nv04_fence.c
+++ b/drivers/gpu/drm/nouveau/nv04_fence.c
@@ -78,6 +78,9 @@ nv04_fence_context_new(struct nouveau_channel *chan)
78 struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); 78 struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
79 if (fctx) { 79 if (fctx) {
80 nouveau_fence_context_new(&fctx->base); 80 nouveau_fence_context_new(&fctx->base);
81 fctx->base.emit = nv04_fence_emit;
82 fctx->base.sync = nv04_fence_sync;
83 fctx->base.read = nv04_fence_read;
81 chan->fence = fctx; 84 chan->fence = fctx;
82 return 0; 85 return 0;
83 } 86 }
@@ -104,8 +107,5 @@ nv04_fence_create(struct nouveau_drm *drm)
104 priv->base.dtor = nv04_fence_destroy; 107 priv->base.dtor = nv04_fence_destroy;
105 priv->base.context_new = nv04_fence_context_new; 108 priv->base.context_new = nv04_fence_context_new;
106 priv->base.context_del = nv04_fence_context_del; 109 priv->base.context_del = nv04_fence_context_del;
107 priv->base.emit = nv04_fence_emit;
108 priv->base.sync = nv04_fence_sync;
109 priv->base.read = nv04_fence_read;
110 return 0; 110 return 0;
111} 111}
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c
index 03017f24d593..06f434f03fba 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.c
+++ b/drivers/gpu/drm/nouveau/nv10_fence.c
@@ -27,18 +27,7 @@
27 27
28#include "nouveau_drm.h" 28#include "nouveau_drm.h"
29#include "nouveau_dma.h" 29#include "nouveau_dma.h"
30#include "nouveau_fence.h" 30#include "nv10_fence.h"
31
32struct nv10_fence_chan {
33 struct nouveau_fence_chan base;
34};
35
36struct nv10_fence_priv {
37 struct nouveau_fence_priv base;
38 struct nouveau_bo *bo;
39 spinlock_t lock;
40 u32 sequence;
41};
42 31
43int 32int
44nv10_fence_emit(struct nouveau_fence *fence) 33nv10_fence_emit(struct nouveau_fence *fence)
@@ -61,45 +50,6 @@ nv10_fence_sync(struct nouveau_fence *fence,
61 return -ENODEV; 50 return -ENODEV;
62} 51}
63 52
64int
65nv17_fence_sync(struct nouveau_fence *fence,
66 struct nouveau_channel *prev, struct nouveau_channel *chan)
67{
68 struct nv10_fence_priv *priv = chan->drm->fence;
69 u32 value;
70 int ret;
71
72 if (!mutex_trylock(&prev->cli->mutex))
73 return -EBUSY;
74
75 spin_lock(&priv->lock);
76 value = priv->sequence;
77 priv->sequence += 2;
78 spin_unlock(&priv->lock);
79
80 ret = RING_SPACE(prev, 5);
81 if (!ret) {
82 BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
83 OUT_RING (prev, NvSema);
84 OUT_RING (prev, 0);
85 OUT_RING (prev, value + 0);
86 OUT_RING (prev, value + 1);
87 FIRE_RING (prev);
88 }
89
90 if (!ret && !(ret = RING_SPACE(chan, 5))) {
91 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
92 OUT_RING (chan, NvSema);
93 OUT_RING (chan, 0);
94 OUT_RING (chan, value + 1);
95 OUT_RING (chan, value + 2);
96 FIRE_RING (chan);
97 }
98
99 mutex_unlock(&prev->cli->mutex);
100 return 0;
101}
102
103u32 53u32
104nv10_fence_read(struct nouveau_channel *chan) 54nv10_fence_read(struct nouveau_channel *chan)
105{ 55{
@@ -115,39 +65,20 @@ nv10_fence_context_del(struct nouveau_channel *chan)
115 kfree(fctx); 65 kfree(fctx);
116} 66}
117 67
118static int 68int
119nv10_fence_context_new(struct nouveau_channel *chan) 69nv10_fence_context_new(struct nouveau_channel *chan)
120{ 70{
121 struct nv10_fence_priv *priv = chan->drm->fence;
122 struct nv10_fence_chan *fctx; 71 struct nv10_fence_chan *fctx;
123 int ret = 0;
124 72
125 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 73 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
126 if (!fctx) 74 if (!fctx)
127 return -ENOMEM; 75 return -ENOMEM;
128 76
129 nouveau_fence_context_new(&fctx->base); 77 nouveau_fence_context_new(&fctx->base);
130 78 fctx->base.emit = nv10_fence_emit;
131 if (priv->bo) { 79 fctx->base.read = nv10_fence_read;
132 struct ttm_mem_reg *mem = &priv->bo->bo.mem; 80 fctx->base.sync = nv10_fence_sync;
133 struct nouveau_object *object; 81 return 0;
134 u32 start = mem->start * PAGE_SIZE;
135 u32 limit = mem->start + mem->size - 1;
136
137 ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
138 NvSema, 0x0002,
139 &(struct nv_dma_class) {
140 .flags = NV_DMA_TARGET_VRAM |
141 NV_DMA_ACCESS_RDWR,
142 .start = start,
143 .limit = limit,
144 }, sizeof(struct nv_dma_class),
145 &object);
146 }
147
148 if (ret)
149 nv10_fence_context_del(chan);
150 return ret;
151} 82}
152 83
153void 84void
@@ -162,18 +93,10 @@ nv10_fence_destroy(struct nouveau_drm *drm)
162 kfree(priv); 93 kfree(priv);
163} 94}
164 95
165void nv17_fence_resume(struct nouveau_drm *drm)
166{
167 struct nv10_fence_priv *priv = drm->fence;
168
169 nouveau_bo_wr32(priv->bo, 0, priv->sequence);
170}
171
172int 96int
173nv10_fence_create(struct nouveau_drm *drm) 97nv10_fence_create(struct nouveau_drm *drm)
174{ 98{
175 struct nv10_fence_priv *priv; 99 struct nv10_fence_priv *priv;
176 int ret = 0;
177 100
178 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); 101 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
179 if (!priv) 102 if (!priv)
@@ -182,33 +105,6 @@ nv10_fence_create(struct nouveau_drm *drm)
182 priv->base.dtor = nv10_fence_destroy; 105 priv->base.dtor = nv10_fence_destroy;
183 priv->base.context_new = nv10_fence_context_new; 106 priv->base.context_new = nv10_fence_context_new;
184 priv->base.context_del = nv10_fence_context_del; 107 priv->base.context_del = nv10_fence_context_del;
185 priv->base.emit = nv10_fence_emit;
186 priv->base.read = nv10_fence_read;
187 priv->base.sync = nv10_fence_sync;
188 spin_lock_init(&priv->lock); 108 spin_lock_init(&priv->lock);
189 109 return 0;
190 if (nv_device(drm->device)->chipset >= 0x17) {
191 ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
192 0, 0x0000, NULL, &priv->bo);
193 if (!ret) {
194 ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
195 if (!ret) {
196 ret = nouveau_bo_map(priv->bo);
197 if (ret)
198 nouveau_bo_unpin(priv->bo);
199 }
200 if (ret)
201 nouveau_bo_ref(NULL, &priv->bo);
202 }
203
204 if (ret == 0) {
205 nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
206 priv->base.sync = nv17_fence_sync;
207 priv->base.resume = nv17_fence_resume;
208 }
209 }
210
211 if (ret)
212 nv10_fence_destroy(drm);
213 return ret;
214} 110}
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.h b/drivers/gpu/drm/nouveau/nv10_fence.h
new file mode 100644
index 000000000000..e5d9204826c2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv10_fence.h
@@ -0,0 +1,19 @@
1#ifndef __NV10_FENCE_H_
2#define __NV10_FENCE_H_
3
4#include <core/os.h>
5#include "nouveau_fence.h"
6#include "nouveau_bo.h"
7
8struct nv10_fence_chan {
9 struct nouveau_fence_chan base;
10};
11
12struct nv10_fence_priv {
13 struct nouveau_fence_priv base;
14 struct nouveau_bo *bo;
15 spinlock_t lock;
16 u32 sequence;
17};
18
19#endif
diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c
new file mode 100644
index 000000000000..8e47a9bae8c3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv17_fence.c
@@ -0,0 +1,149 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */
24
25#include <core/object.h>
26#include <core/class.h>
27
28#include "nouveau_drm.h"
29#include "nouveau_dma.h"
30#include "nv10_fence.h"
31
32int
33nv17_fence_sync(struct nouveau_fence *fence,
34 struct nouveau_channel *prev, struct nouveau_channel *chan)
35{
36 struct nv10_fence_priv *priv = chan->drm->fence;
37 u32 value;
38 int ret;
39
40 if (!mutex_trylock(&prev->cli->mutex))
41 return -EBUSY;
42
43 spin_lock(&priv->lock);
44 value = priv->sequence;
45 priv->sequence += 2;
46 spin_unlock(&priv->lock);
47
48 ret = RING_SPACE(prev, 5);
49 if (!ret) {
50 BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
51 OUT_RING (prev, NvSema);
52 OUT_RING (prev, 0);
53 OUT_RING (prev, value + 0);
54 OUT_RING (prev, value + 1);
55 FIRE_RING (prev);
56 }
57
58 if (!ret && !(ret = RING_SPACE(chan, 5))) {
59 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
60 OUT_RING (chan, NvSema);
61 OUT_RING (chan, 0);
62 OUT_RING (chan, value + 1);
63 OUT_RING (chan, value + 2);
64 FIRE_RING (chan);
65 }
66
67 mutex_unlock(&prev->cli->mutex);
68 return 0;
69}
70
71static int
72nv17_fence_context_new(struct nouveau_channel *chan)
73{
74 struct nv10_fence_priv *priv = chan->drm->fence;
75 struct nv10_fence_chan *fctx;
76 struct ttm_mem_reg *mem = &priv->bo->bo.mem;
77 struct nouveau_object *object;
78 u32 start = mem->start * PAGE_SIZE;
79 u32 limit = mem->start + mem->size - 1;
80 int ret = 0;
81
82 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
83 if (!fctx)
84 return -ENOMEM;
85
86 nouveau_fence_context_new(&fctx->base);
87 fctx->base.emit = nv10_fence_emit;
88 fctx->base.read = nv10_fence_read;
89 fctx->base.sync = nv17_fence_sync;
90
91 ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
92 NvSema, 0x0002,
93 &(struct nv_dma_class) {
94 .flags = NV_DMA_TARGET_VRAM |
95 NV_DMA_ACCESS_RDWR,
96 .start = start,
97 .limit = limit,
98 }, sizeof(struct nv_dma_class),
99 &object);
100 if (ret)
101 nv10_fence_context_del(chan);
102 return ret;
103}
104
105void
106nv17_fence_resume(struct nouveau_drm *drm)
107{
108 struct nv10_fence_priv *priv = drm->fence;
109
110 nouveau_bo_wr32(priv->bo, 0, priv->sequence);
111}
112
113int
114nv17_fence_create(struct nouveau_drm *drm)
115{
116 struct nv10_fence_priv *priv;
117 int ret = 0;
118
119 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
120 if (!priv)
121 return -ENOMEM;
122
123 priv->base.dtor = nv10_fence_destroy;
124 priv->base.resume = nv17_fence_resume;
125 priv->base.context_new = nv17_fence_context_new;
126 priv->base.context_del = nv10_fence_context_del;
127 spin_lock_init(&priv->lock);
128
129 ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
130 0, 0x0000, NULL, &priv->bo);
131 if (!ret) {
132 ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
133 if (!ret) {
134 ret = nouveau_bo_map(priv->bo);
135 if (ret)
136 nouveau_bo_unpin(priv->bo);
137 }
138 if (ret)
139 nouveau_bo_ref(NULL, &priv->bo);
140 }
141
142 if (ret) {
143 nv10_fence_destroy(drm);
144 return ret;
145 }
146
147 nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
148 return ret;
149}
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index d4cbea19b890..45624c37e29f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -43,6 +43,7 @@
43#include <subdev/timer.h> 43#include <subdev/timer.h>
44#include <subdev/bar.h> 44#include <subdev/bar.h>
45#include <subdev/fb.h> 45#include <subdev/fb.h>
46#include <subdev/i2c.h>
46 47
47#define EVO_DMA_NR 9 48#define EVO_DMA_NR 9
48 49
@@ -433,7 +434,10 @@ evo_kick(u32 *push, void *evoc)
433static bool 434static bool
434evo_sync_wait(void *data) 435evo_sync_wait(void *data)
435{ 436{
436 return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; 437 if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000)
438 return true;
439 usleep_range(1, 2);
440 return false;
437} 441}
438 442
439static int 443static int
@@ -512,7 +516,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
512 if (ret) 516 if (ret)
513 return ret; 517 return ret;
514 518
515 if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { 519 if (nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) {
516 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); 520 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
517 OUT_RING (chan, NvEvoSema0 + nv_crtc->index); 521 OUT_RING (chan, NvEvoSema0 + nv_crtc->index);
518 OUT_RING (chan, sync->sem.offset); 522 OUT_RING (chan, sync->sem.offset);
@@ -522,24 +526,36 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
522 OUT_RING (chan, sync->sem.offset ^ 0x10); 526 OUT_RING (chan, sync->sem.offset ^ 0x10);
523 OUT_RING (chan, 0x74b1e000); 527 OUT_RING (chan, 0x74b1e000);
524 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 528 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
525 if (nv_mclass(chan->object) < NV84_CHANNEL_DMA_CLASS) 529 OUT_RING (chan, NvSema);
526 OUT_RING (chan, NvSema); 530 } else
527 else 531 if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
528 OUT_RING (chan, chan->vram); 532 u64 offset = nv84_fence_crtc(chan, nv_crtc->index);
533 offset += sync->sem.offset;
534
535 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
536 OUT_RING (chan, upper_32_bits(offset));
537 OUT_RING (chan, lower_32_bits(offset));
538 OUT_RING (chan, 0xf00d0000 | sync->sem.value);
539 OUT_RING (chan, 0x00000002);
540 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
541 OUT_RING (chan, upper_32_bits(offset));
542 OUT_RING (chan, lower_32_bits(offset ^ 0x10));
543 OUT_RING (chan, 0x74b1e000);
544 OUT_RING (chan, 0x00000001);
529 } else { 545 } else {
530 u64 offset = nvc0_fence_crtc(chan, nv_crtc->index); 546 u64 offset = nv84_fence_crtc(chan, nv_crtc->index);
531 offset += sync->sem.offset; 547 offset += sync->sem.offset;
532 548
533 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 549 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
534 OUT_RING (chan, upper_32_bits(offset)); 550 OUT_RING (chan, upper_32_bits(offset));
535 OUT_RING (chan, lower_32_bits(offset)); 551 OUT_RING (chan, lower_32_bits(offset));
536 OUT_RING (chan, 0xf00d0000 | sync->sem.value); 552 OUT_RING (chan, 0xf00d0000 | sync->sem.value);
537 OUT_RING (chan, 0x1002); 553 OUT_RING (chan, 0x00001002);
538 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 554 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
539 OUT_RING (chan, upper_32_bits(offset)); 555 OUT_RING (chan, upper_32_bits(offset));
540 OUT_RING (chan, lower_32_bits(offset ^ 0x10)); 556 OUT_RING (chan, lower_32_bits(offset ^ 0x10));
541 OUT_RING (chan, 0x74b1e000); 557 OUT_RING (chan, 0x74b1e000);
542 OUT_RING (chan, 0x1001); 558 OUT_RING (chan, 0x00001001);
543 } 559 }
544 560
545 FIRE_RING (chan); 561 FIRE_RING (chan);
@@ -1552,20 +1568,23 @@ static const struct drm_encoder_funcs nv50_dac_func = {
1552static int 1568static int
1553nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) 1569nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
1554{ 1570{
1555 struct drm_device *dev = connector->dev; 1571 struct nouveau_drm *drm = nouveau_drm(connector->dev);
1572 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
1556 struct nouveau_encoder *nv_encoder; 1573 struct nouveau_encoder *nv_encoder;
1557 struct drm_encoder *encoder; 1574 struct drm_encoder *encoder;
1575 int type = DRM_MODE_ENCODER_DAC;
1558 1576
1559 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 1577 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
1560 if (!nv_encoder) 1578 if (!nv_encoder)
1561 return -ENOMEM; 1579 return -ENOMEM;
1562 nv_encoder->dcb = dcbe; 1580 nv_encoder->dcb = dcbe;
1563 nv_encoder->or = ffs(dcbe->or) - 1; 1581 nv_encoder->or = ffs(dcbe->or) - 1;
1582 nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index);
1564 1583
1565 encoder = to_drm_encoder(nv_encoder); 1584 encoder = to_drm_encoder(nv_encoder);
1566 encoder->possible_crtcs = dcbe->heads; 1585 encoder->possible_crtcs = dcbe->heads;
1567 encoder->possible_clones = 0; 1586 encoder->possible_clones = 0;
1568 drm_encoder_init(dev, encoder, &nv50_dac_func, DRM_MODE_ENCODER_DAC); 1587 drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type);
1569 drm_encoder_helper_add(encoder, &nv50_dac_hfunc); 1588 drm_encoder_helper_add(encoder, &nv50_dac_hfunc);
1570 1589
1571 drm_mode_connector_attach_encoder(connector, encoder); 1590 drm_mode_connector_attach_encoder(connector, encoder);
@@ -1674,9 +1693,6 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
1674 } 1693 }
1675 1694
1676 nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); 1695 nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
1677
1678 if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
1679 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, disp->core);
1680} 1696}
1681 1697
1682static bool 1698static bool
@@ -1733,14 +1749,6 @@ nv50_sor_disconnect(struct drm_encoder *encoder)
1733} 1749}
1734 1750
1735static void 1751static void
1736nv50_sor_prepare(struct drm_encoder *encoder)
1737{
1738 nv50_sor_disconnect(encoder);
1739 if (nouveau_encoder(encoder)->dcb->type == DCB_OUTPUT_DP)
1740 evo_sync(encoder->dev);
1741}
1742
1743static void
1744nv50_sor_commit(struct drm_encoder *encoder) 1752nv50_sor_commit(struct drm_encoder *encoder)
1745{ 1753{
1746} 1754}
@@ -1835,8 +1843,13 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1835 push = evo_wait(nv50_mast(dev), 8); 1843 push = evo_wait(nv50_mast(dev), 8);
1836 if (push) { 1844 if (push) {
1837 if (nv50_vers(mast) < NVD0_DISP_CLASS) { 1845 if (nv50_vers(mast) < NVD0_DISP_CLASS) {
1846 u32 ctrl = (depth << 16) | (proto << 8) | owner;
1847 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1848 ctrl |= 0x00001000;
1849 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1850 ctrl |= 0x00002000;
1838 evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1); 1851 evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1);
1839 evo_data(push, (depth << 16) | (proto << 8) | owner); 1852 evo_data(push, ctrl);
1840 } else { 1853 } else {
1841 u32 magic = 0x31ec6000 | (nv_crtc->index << 25); 1854 u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
1842 u32 syncs = 0x00000001; 1855 u32 syncs = 0x00000001;
@@ -1872,7 +1885,7 @@ nv50_sor_destroy(struct drm_encoder *encoder)
1872static const struct drm_encoder_helper_funcs nv50_sor_hfunc = { 1885static const struct drm_encoder_helper_funcs nv50_sor_hfunc = {
1873 .dpms = nv50_sor_dpms, 1886 .dpms = nv50_sor_dpms,
1874 .mode_fixup = nv50_sor_mode_fixup, 1887 .mode_fixup = nv50_sor_mode_fixup,
1875 .prepare = nv50_sor_prepare, 1888 .prepare = nv50_sor_disconnect,
1876 .commit = nv50_sor_commit, 1889 .commit = nv50_sor_commit,
1877 .mode_set = nv50_sor_mode_set, 1890 .mode_set = nv50_sor_mode_set,
1878 .disable = nv50_sor_disconnect, 1891 .disable = nv50_sor_disconnect,
@@ -1886,21 +1899,33 @@ static const struct drm_encoder_funcs nv50_sor_func = {
1886static int 1899static int
1887nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) 1900nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
1888{ 1901{
1889 struct drm_device *dev = connector->dev; 1902 struct nouveau_drm *drm = nouveau_drm(connector->dev);
1903 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
1890 struct nouveau_encoder *nv_encoder; 1904 struct nouveau_encoder *nv_encoder;
1891 struct drm_encoder *encoder; 1905 struct drm_encoder *encoder;
1906 int type;
1907
1908 switch (dcbe->type) {
1909 case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; break;
1910 case DCB_OUTPUT_TMDS:
1911 case DCB_OUTPUT_DP:
1912 default:
1913 type = DRM_MODE_ENCODER_TMDS;
1914 break;
1915 }
1892 1916
1893 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 1917 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
1894 if (!nv_encoder) 1918 if (!nv_encoder)
1895 return -ENOMEM; 1919 return -ENOMEM;
1896 nv_encoder->dcb = dcbe; 1920 nv_encoder->dcb = dcbe;
1897 nv_encoder->or = ffs(dcbe->or) - 1; 1921 nv_encoder->or = ffs(dcbe->or) - 1;
1922 nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index);
1898 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 1923 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
1899 1924
1900 encoder = to_drm_encoder(nv_encoder); 1925 encoder = to_drm_encoder(nv_encoder);
1901 encoder->possible_crtcs = dcbe->heads; 1926 encoder->possible_crtcs = dcbe->heads;
1902 encoder->possible_clones = 0; 1927 encoder->possible_clones = 0;
1903 drm_encoder_init(dev, encoder, &nv50_sor_func, DRM_MODE_ENCODER_TMDS); 1928 drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type);
1904 drm_encoder_helper_add(encoder, &nv50_sor_hfunc); 1929 drm_encoder_helper_add(encoder, &nv50_sor_hfunc);
1905 1930
1906 drm_mode_connector_attach_encoder(connector, encoder); 1931 drm_mode_connector_attach_encoder(connector, encoder);
@@ -1908,6 +1933,184 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
1908} 1933}
1909 1934
1910/****************************************************************************** 1935/******************************************************************************
1936 * PIOR
1937 *****************************************************************************/
1938
1939static void
1940nv50_pior_dpms(struct drm_encoder *encoder, int mode)
1941{
1942 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1943 struct nv50_disp *disp = nv50_disp(encoder->dev);
1944 u32 mthd = (nv_encoder->dcb->type << 12) | nv_encoder->or;
1945 u32 ctrl = (mode == DRM_MODE_DPMS_ON);
1946 nv_call(disp->core, NV50_DISP_PIOR_PWR + mthd, ctrl);
1947}
1948
1949static bool
1950nv50_pior_mode_fixup(struct drm_encoder *encoder,
1951 const struct drm_display_mode *mode,
1952 struct drm_display_mode *adjusted_mode)
1953{
1954 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1955 struct nouveau_connector *nv_connector;
1956
1957 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1958 if (nv_connector && nv_connector->native_mode) {
1959 if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
1960 int id = adjusted_mode->base.id;
1961 *adjusted_mode = *nv_connector->native_mode;
1962 adjusted_mode->base.id = id;
1963 }
1964 }
1965
1966 adjusted_mode->clock *= 2;
1967 return true;
1968}
1969
1970static void
1971nv50_pior_commit(struct drm_encoder *encoder)
1972{
1973}
1974
1975static void
1976nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
1977 struct drm_display_mode *adjusted_mode)
1978{
1979 struct nv50_mast *mast = nv50_mast(encoder->dev);
1980 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1981 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
1982 struct nouveau_connector *nv_connector;
1983 u8 owner = 1 << nv_crtc->index;
1984 u8 proto, depth;
1985 u32 *push;
1986
1987 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1988 switch (nv_connector->base.display_info.bpc) {
1989 case 10: depth = 0x6; break;
1990 case 8: depth = 0x5; break;
1991 case 6: depth = 0x2; break;
1992 default: depth = 0x0; break;
1993 }
1994
1995 switch (nv_encoder->dcb->type) {
1996 case DCB_OUTPUT_TMDS:
1997 case DCB_OUTPUT_DP:
1998 proto = 0x0;
1999 break;
2000 default:
2001 BUG_ON(1);
2002 break;
2003 }
2004
2005 nv50_pior_dpms(encoder, DRM_MODE_DPMS_ON);
2006
2007 push = evo_wait(mast, 8);
2008 if (push) {
2009 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
2010 u32 ctrl = (depth << 16) | (proto << 8) | owner;
2011 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
2012 ctrl |= 0x00001000;
2013 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
2014 ctrl |= 0x00002000;
2015 evo_mthd(push, 0x0700 + (nv_encoder->or * 0x040), 1);
2016 evo_data(push, ctrl);
2017 }
2018
2019 evo_kick(push, mast);
2020 }
2021
2022 nv_encoder->crtc = encoder->crtc;
2023}
2024
2025static void
2026nv50_pior_disconnect(struct drm_encoder *encoder)
2027{
2028 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
2029 struct nv50_mast *mast = nv50_mast(encoder->dev);
2030 const int or = nv_encoder->or;
2031 u32 *push;
2032
2033 if (nv_encoder->crtc) {
2034 nv50_crtc_prepare(nv_encoder->crtc);
2035
2036 push = evo_wait(mast, 4);
2037 if (push) {
2038 if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
2039 evo_mthd(push, 0x0700 + (or * 0x040), 1);
2040 evo_data(push, 0x00000000);
2041 }
2042
2043 evo_mthd(push, 0x0080, 1);
2044 evo_data(push, 0x00000000);
2045 evo_kick(push, mast);
2046 }
2047 }
2048
2049 nv_encoder->crtc = NULL;
2050}
2051
2052static void
2053nv50_pior_destroy(struct drm_encoder *encoder)
2054{
2055 drm_encoder_cleanup(encoder);
2056 kfree(encoder);
2057}
2058
2059static const struct drm_encoder_helper_funcs nv50_pior_hfunc = {
2060 .dpms = nv50_pior_dpms,
2061 .mode_fixup = nv50_pior_mode_fixup,
2062 .prepare = nv50_pior_disconnect,
2063 .commit = nv50_pior_commit,
2064 .mode_set = nv50_pior_mode_set,
2065 .disable = nv50_pior_disconnect,
2066 .get_crtc = nv50_display_crtc_get,
2067};
2068
2069static const struct drm_encoder_funcs nv50_pior_func = {
2070 .destroy = nv50_pior_destroy,
2071};
2072
2073static int
2074nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
2075{
2076 struct nouveau_drm *drm = nouveau_drm(connector->dev);
2077 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
2078 struct nouveau_i2c_port *ddc = NULL;
2079 struct nouveau_encoder *nv_encoder;
2080 struct drm_encoder *encoder;
2081 int type;
2082
2083 switch (dcbe->type) {
2084 case DCB_OUTPUT_TMDS:
2085 ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(dcbe->extdev));
2086 type = DRM_MODE_ENCODER_TMDS;
2087 break;
2088 case DCB_OUTPUT_DP:
2089 ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(dcbe->extdev));
2090 type = DRM_MODE_ENCODER_TMDS;
2091 break;
2092 default:
2093 return -ENODEV;
2094 }
2095
2096 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
2097 if (!nv_encoder)
2098 return -ENOMEM;
2099 nv_encoder->dcb = dcbe;
2100 nv_encoder->or = ffs(dcbe->or) - 1;
2101 nv_encoder->i2c = ddc;
2102
2103 encoder = to_drm_encoder(nv_encoder);
2104 encoder->possible_crtcs = dcbe->heads;
2105 encoder->possible_clones = 0;
2106 drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type);
2107 drm_encoder_helper_add(encoder, &nv50_pior_hfunc);
2108
2109 drm_mode_connector_attach_encoder(connector, encoder);
2110 return 0;
2111}
2112
2113/******************************************************************************
1911 * Init 2114 * Init
1912 *****************************************************************************/ 2115 *****************************************************************************/
1913void 2116void
@@ -1923,7 +2126,7 @@ nv50_display_init(struct drm_device *dev)
1923 evo_mthd(push, 0x0088, 1); 2126 evo_mthd(push, 0x0088, 1);
1924 evo_data(push, NvEvoSync); 2127 evo_data(push, NvEvoSync);
1925 evo_kick(push, nv50_mast(dev)); 2128 evo_kick(push, nv50_mast(dev));
1926 return evo_sync(dev); 2129 return 0;
1927 } 2130 }
1928 2131
1929 return -EBUSY; 2132 return -EBUSY;
@@ -2029,25 +2232,28 @@ nv50_display_create(struct drm_device *dev)
2029 if (IS_ERR(connector)) 2232 if (IS_ERR(connector))
2030 continue; 2233 continue;
2031 2234
2032 if (dcbe->location != DCB_LOC_ON_CHIP) { 2235 if (dcbe->location == DCB_LOC_ON_CHIP) {
2033 NV_WARN(drm, "skipping off-chip encoder %d/%d\n", 2236 switch (dcbe->type) {
2034 dcbe->type, ffs(dcbe->or) - 1); 2237 case DCB_OUTPUT_TMDS:
2035 continue; 2238 case DCB_OUTPUT_LVDS:
2239 case DCB_OUTPUT_DP:
2240 ret = nv50_sor_create(connector, dcbe);
2241 break;
2242 case DCB_OUTPUT_ANALOG:
2243 ret = nv50_dac_create(connector, dcbe);
2244 break;
2245 default:
2246 ret = -ENODEV;
2247 break;
2248 }
2249 } else {
2250 ret = nv50_pior_create(connector, dcbe);
2036 } 2251 }
2037 2252
2038 switch (dcbe->type) { 2253 if (ret) {
2039 case DCB_OUTPUT_TMDS: 2254 NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n",
2040 case DCB_OUTPUT_LVDS: 2255 dcbe->location, dcbe->type,
2041 case DCB_OUTPUT_DP: 2256 ffs(dcbe->or) - 1, ret);
2042 nv50_sor_create(connector, dcbe);
2043 break;
2044 case DCB_OUTPUT_ANALOG:
2045 nv50_dac_create(connector, dcbe);
2046 break;
2047 default:
2048 NV_WARN(drm, "skipping unsupported encoder %d/%d\n",
2049 dcbe->type, ffs(dcbe->or) - 1);
2050 continue;
2051 } 2257 }
2052 } 2258 }
2053 2259
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
index d889f3ac0d41..f9701e567db8 100644
--- a/drivers/gpu/drm/nouveau/nv50_fence.c
+++ b/drivers/gpu/drm/nouveau/nv50_fence.c
@@ -27,27 +27,16 @@
27 27
28#include "nouveau_drm.h" 28#include "nouveau_drm.h"
29#include "nouveau_dma.h" 29#include "nouveau_dma.h"
30#include "nouveau_fence.h" 30#include "nv10_fence.h"
31 31
32#include "nv50_display.h" 32#include "nv50_display.h"
33 33
34struct nv50_fence_chan {
35 struct nouveau_fence_chan base;
36};
37
38struct nv50_fence_priv {
39 struct nouveau_fence_priv base;
40 struct nouveau_bo *bo;
41 spinlock_t lock;
42 u32 sequence;
43};
44
45static int 34static int
46nv50_fence_context_new(struct nouveau_channel *chan) 35nv50_fence_context_new(struct nouveau_channel *chan)
47{ 36{
48 struct drm_device *dev = chan->drm->dev; 37 struct drm_device *dev = chan->drm->dev;
49 struct nv50_fence_priv *priv = chan->drm->fence; 38 struct nv10_fence_priv *priv = chan->drm->fence;
50 struct nv50_fence_chan *fctx; 39 struct nv10_fence_chan *fctx;
51 struct ttm_mem_reg *mem = &priv->bo->bo.mem; 40 struct ttm_mem_reg *mem = &priv->bo->bo.mem;
52 struct nouveau_object *object; 41 struct nouveau_object *object;
53 int ret, i; 42 int ret, i;
@@ -57,6 +46,9 @@ nv50_fence_context_new(struct nouveau_channel *chan)
57 return -ENOMEM; 46 return -ENOMEM;
58 47
59 nouveau_fence_context_new(&fctx->base); 48 nouveau_fence_context_new(&fctx->base);
49 fctx->base.emit = nv10_fence_emit;
50 fctx->base.read = nv10_fence_read;
51 fctx->base.sync = nv17_fence_sync;
60 52
61 ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 53 ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
62 NvSema, 0x0002, 54 NvSema, 0x0002,
@@ -91,7 +83,7 @@ nv50_fence_context_new(struct nouveau_channel *chan)
91int 83int
92nv50_fence_create(struct nouveau_drm *drm) 84nv50_fence_create(struct nouveau_drm *drm)
93{ 85{
94 struct nv50_fence_priv *priv; 86 struct nv10_fence_priv *priv;
95 int ret = 0; 87 int ret = 0;
96 88
97 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); 89 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -99,11 +91,9 @@ nv50_fence_create(struct nouveau_drm *drm)
99 return -ENOMEM; 91 return -ENOMEM;
100 92
101 priv->base.dtor = nv10_fence_destroy; 93 priv->base.dtor = nv10_fence_destroy;
94 priv->base.resume = nv17_fence_resume;
102 priv->base.context_new = nv50_fence_context_new; 95 priv->base.context_new = nv50_fence_context_new;
103 priv->base.context_del = nv10_fence_context_del; 96 priv->base.context_del = nv10_fence_context_del;
104 priv->base.emit = nv10_fence_emit;
105 priv->base.read = nv10_fence_read;
106 priv->base.sync = nv17_fence_sync;
107 spin_lock_init(&priv->lock); 97 spin_lock_init(&priv->lock);
108 98
109 ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 99 ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -119,13 +109,11 @@ nv50_fence_create(struct nouveau_drm *drm)
119 nouveau_bo_ref(NULL, &priv->bo); 109 nouveau_bo_ref(NULL, &priv->bo);
120 } 110 }
121 111
122 if (ret == 0) { 112 if (ret) {
123 nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); 113 nv10_fence_destroy(drm);
124 priv->base.sync = nv17_fence_sync; 114 return ret;
125 priv->base.resume = nv17_fence_resume;
126 } 115 }
127 116
128 if (ret) 117 nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
129 nv10_fence_destroy(drm);
130 return ret; 118 return ret;
131} 119}
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index c686650584b6..9fd475c89820 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include <core/object.h> 25#include <core/object.h>
26#include <core/client.h>
26#include <core/class.h> 27#include <core/class.h>
27 28
28#include <engine/fifo.h> 29#include <engine/fifo.h>
@@ -33,79 +34,115 @@
33 34
34#include "nv50_display.h" 35#include "nv50_display.h"
35 36
36struct nv84_fence_chan { 37u64
37 struct nouveau_fence_chan base; 38nv84_fence_crtc(struct nouveau_channel *chan, int crtc)
38}; 39{
39 40 struct nv84_fence_chan *fctx = chan->fence;
40struct nv84_fence_priv { 41 return fctx->dispc_vma[crtc].offset;
41 struct nouveau_fence_priv base; 42}
42 struct nouveau_gpuobj *mem;
43};
44 43
45static int 44static int
46nv84_fence_emit(struct nouveau_fence *fence) 45nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
47{ 46{
48 struct nouveau_channel *chan = fence->channel; 47 int ret = RING_SPACE(chan, 8);
49 struct nouveau_fifo_chan *fifo = (void *)chan->object;
50 int ret = RING_SPACE(chan, 7);
51 if (ret == 0) { 48 if (ret == 0) {
52 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 49 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
53 OUT_RING (chan, NvSema); 50 OUT_RING (chan, chan->vram);
54 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 51 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
55 OUT_RING (chan, upper_32_bits(fifo->chid * 16)); 52 OUT_RING (chan, upper_32_bits(virtual));
56 OUT_RING (chan, lower_32_bits(fifo->chid * 16)); 53 OUT_RING (chan, lower_32_bits(virtual));
57 OUT_RING (chan, fence->sequence); 54 OUT_RING (chan, sequence);
58 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 55 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
56 OUT_RING (chan, 0x00000000);
59 FIRE_RING (chan); 57 FIRE_RING (chan);
60 } 58 }
61 return ret; 59 return ret;
62} 60}
63 61
64
65static int 62static int
66nv84_fence_sync(struct nouveau_fence *fence, 63nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
67 struct nouveau_channel *prev, struct nouveau_channel *chan)
68{ 64{
69 struct nouveau_fifo_chan *fifo = (void *)prev->object;
70 int ret = RING_SPACE(chan, 7); 65 int ret = RING_SPACE(chan, 7);
71 if (ret == 0) { 66 if (ret == 0) {
72 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 67 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
73 OUT_RING (chan, NvSema); 68 OUT_RING (chan, chan->vram);
74 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 69 BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
75 OUT_RING (chan, upper_32_bits(fifo->chid * 16)); 70 OUT_RING (chan, upper_32_bits(virtual));
76 OUT_RING (chan, lower_32_bits(fifo->chid * 16)); 71 OUT_RING (chan, lower_32_bits(virtual));
77 OUT_RING (chan, fence->sequence); 72 OUT_RING (chan, sequence);
78 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL); 73 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL);
79 FIRE_RING (chan); 74 FIRE_RING (chan);
80 } 75 }
81 return ret; 76 return ret;
82} 77}
83 78
79static int
80nv84_fence_emit(struct nouveau_fence *fence)
81{
82 struct nouveau_channel *chan = fence->channel;
83 struct nv84_fence_chan *fctx = chan->fence;
84 struct nouveau_fifo_chan *fifo = (void *)chan->object;
85 u64 addr = fifo->chid * 16;
86
87 if (fence->sysmem)
88 addr += fctx->vma_gart.offset;
89 else
90 addr += fctx->vma.offset;
91
92 return fctx->base.emit32(chan, addr, fence->sequence);
93}
94
95static int
96nv84_fence_sync(struct nouveau_fence *fence,
97 struct nouveau_channel *prev, struct nouveau_channel *chan)
98{
99 struct nv84_fence_chan *fctx = chan->fence;
100 struct nouveau_fifo_chan *fifo = (void *)prev->object;
101 u64 addr = fifo->chid * 16;
102
103 if (fence->sysmem)
104 addr += fctx->vma_gart.offset;
105 else
106 addr += fctx->vma.offset;
107
108 return fctx->base.sync32(chan, addr, fence->sequence);
109}
110
84static u32 111static u32
85nv84_fence_read(struct nouveau_channel *chan) 112nv84_fence_read(struct nouveau_channel *chan)
86{ 113{
87 struct nouveau_fifo_chan *fifo = (void *)chan->object; 114 struct nouveau_fifo_chan *fifo = (void *)chan->object;
88 struct nv84_fence_priv *priv = chan->drm->fence; 115 struct nv84_fence_priv *priv = chan->drm->fence;
89 return nv_ro32(priv->mem, fifo->chid * 16); 116 return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4);
90} 117}
91 118
92static void 119static void
93nv84_fence_context_del(struct nouveau_channel *chan) 120nv84_fence_context_del(struct nouveau_channel *chan)
94{ 121{
122 struct drm_device *dev = chan->drm->dev;
123 struct nv84_fence_priv *priv = chan->drm->fence;
95 struct nv84_fence_chan *fctx = chan->fence; 124 struct nv84_fence_chan *fctx = chan->fence;
125 int i;
126
127 for (i = 0; i < dev->mode_config.num_crtc; i++) {
128 struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
129 nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
130 }
131
132 nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
133 nouveau_bo_vma_del(priv->bo, &fctx->vma);
96 nouveau_fence_context_del(&fctx->base); 134 nouveau_fence_context_del(&fctx->base);
97 chan->fence = NULL; 135 chan->fence = NULL;
98 kfree(fctx); 136 kfree(fctx);
99} 137}
100 138
101static int 139int
102nv84_fence_context_new(struct nouveau_channel *chan) 140nv84_fence_context_new(struct nouveau_channel *chan)
103{ 141{
104 struct drm_device *dev = chan->drm->dev;
105 struct nouveau_fifo_chan *fifo = (void *)chan->object; 142 struct nouveau_fifo_chan *fifo = (void *)chan->object;
143 struct nouveau_client *client = nouveau_client(fifo);
106 struct nv84_fence_priv *priv = chan->drm->fence; 144 struct nv84_fence_priv *priv = chan->drm->fence;
107 struct nv84_fence_chan *fctx; 145 struct nv84_fence_chan *fctx;
108 struct nouveau_object *object;
109 int ret, i; 146 int ret, i;
110 147
111 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 148 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
@@ -113,44 +150,74 @@ nv84_fence_context_new(struct nouveau_channel *chan)
113 return -ENOMEM; 150 return -ENOMEM;
114 151
115 nouveau_fence_context_new(&fctx->base); 152 nouveau_fence_context_new(&fctx->base);
153 fctx->base.emit = nv84_fence_emit;
154 fctx->base.sync = nv84_fence_sync;
155 fctx->base.read = nv84_fence_read;
156 fctx->base.emit32 = nv84_fence_emit32;
157 fctx->base.sync32 = nv84_fence_sync32;
116 158
117 ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 159 ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
118 NvSema, 0x0002, 160 if (ret == 0) {
119 &(struct nv_dma_class) { 161 ret = nouveau_bo_vma_add(priv->bo_gart, client->vm,
120 .flags = NV_DMA_TARGET_VRAM | 162 &fctx->vma_gart);
121 NV_DMA_ACCESS_RDWR, 163 }
122 .start = priv->mem->addr,
123 .limit = priv->mem->addr +
124 priv->mem->size - 1,
125 }, sizeof(struct nv_dma_class),
126 &object);
127
128 /* dma objects for display sync channel semaphore blocks */
129 for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
130 struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
131 164
132 ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 165 /* map display semaphore buffers into channel's vm */
133 NvEvoSema0 + i, 0x003d, 166 for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
134 &(struct nv_dma_class) { 167 struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
135 .flags = NV_DMA_TARGET_VRAM | 168 ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]);
136 NV_DMA_ACCESS_RDWR,
137 .start = bo->bo.offset,
138 .limit = bo->bo.offset + 0xfff,
139 }, sizeof(struct nv_dma_class),
140 &object);
141 } 169 }
142 170
171 nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);
172
143 if (ret) 173 if (ret)
144 nv84_fence_context_del(chan); 174 nv84_fence_context_del(chan);
145 nv_wo32(priv->mem, fifo->chid * 16, 0x00000000);
146 return ret; 175 return ret;
147} 176}
148 177
178static bool
179nv84_fence_suspend(struct nouveau_drm *drm)
180{
181 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
182 struct nv84_fence_priv *priv = drm->fence;
183 int i;
184
185 priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32));
186 if (priv->suspend) {
187 for (i = 0; i <= pfifo->max; i++)
188 priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
189 }
190
191 return priv->suspend != NULL;
192}
193
194static void
195nv84_fence_resume(struct nouveau_drm *drm)
196{
197 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
198 struct nv84_fence_priv *priv = drm->fence;
199 int i;
200
201 if (priv->suspend) {
202 for (i = 0; i <= pfifo->max; i++)
203 nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
204 vfree(priv->suspend);
205 priv->suspend = NULL;
206 }
207}
208
149static void 209static void
150nv84_fence_destroy(struct nouveau_drm *drm) 210nv84_fence_destroy(struct nouveau_drm *drm)
151{ 211{
152 struct nv84_fence_priv *priv = drm->fence; 212 struct nv84_fence_priv *priv = drm->fence;
153 nouveau_gpuobj_ref(NULL, &priv->mem); 213 nouveau_bo_unmap(priv->bo_gart);
214 if (priv->bo_gart)
215 nouveau_bo_unpin(priv->bo_gart);
216 nouveau_bo_ref(NULL, &priv->bo_gart);
217 nouveau_bo_unmap(priv->bo);
218 if (priv->bo)
219 nouveau_bo_unpin(priv->bo);
220 nouveau_bo_ref(NULL, &priv->bo);
154 drm->fence = NULL; 221 drm->fence = NULL;
155 kfree(priv); 222 kfree(priv);
156} 223}
@@ -160,7 +227,6 @@ nv84_fence_create(struct nouveau_drm *drm)
160{ 227{
161 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 228 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
162 struct nv84_fence_priv *priv; 229 struct nv84_fence_priv *priv;
163 u32 chan = pfifo->max + 1;
164 int ret; 230 int ret;
165 231
166 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); 232 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -168,14 +234,42 @@ nv84_fence_create(struct nouveau_drm *drm)
168 return -ENOMEM; 234 return -ENOMEM;
169 235
170 priv->base.dtor = nv84_fence_destroy; 236 priv->base.dtor = nv84_fence_destroy;
237 priv->base.suspend = nv84_fence_suspend;
238 priv->base.resume = nv84_fence_resume;
171 priv->base.context_new = nv84_fence_context_new; 239 priv->base.context_new = nv84_fence_context_new;
172 priv->base.context_del = nv84_fence_context_del; 240 priv->base.context_del = nv84_fence_context_del;
173 priv->base.emit = nv84_fence_emit;
174 priv->base.sync = nv84_fence_sync;
175 priv->base.read = nv84_fence_read;
176 241
177 ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, 242 init_waitqueue_head(&priv->base.waiting);
178 &priv->mem); 243 priv->base.uevent = true;
244
245 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
246 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);
247 if (ret == 0) {
248 ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
249 if (ret == 0) {
250 ret = nouveau_bo_map(priv->bo);
251 if (ret)
252 nouveau_bo_unpin(priv->bo);
253 }
254 if (ret)
255 nouveau_bo_ref(NULL, &priv->bo);
256 }
257
258 if (ret == 0)
259 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
260 TTM_PL_FLAG_TT, 0, 0, NULL,
261 &priv->bo_gart);
262 if (ret == 0) {
263 ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT);
264 if (ret == 0) {
265 ret = nouveau_bo_map(priv->bo_gart);
266 if (ret)
267 nouveau_bo_unpin(priv->bo_gart);
268 }
269 if (ret)
270 nouveau_bo_ref(NULL, &priv->bo_gart);
271 }
272
179 if (ret) 273 if (ret)
180 nv84_fence_destroy(drm); 274 nv84_fence_destroy(drm);
181 return ret; 275 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c
index 2a56b1b551cb..9566267fbc42 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fence.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fence.c
@@ -34,203 +34,57 @@
34 34
35#include "nv50_display.h" 35#include "nv50_display.h"
36 36
37struct nvc0_fence_priv {
38 struct nouveau_fence_priv base;
39 struct nouveau_bo *bo;
40 u32 *suspend;
41};
42
43struct nvc0_fence_chan {
44 struct nouveau_fence_chan base;
45 struct nouveau_vma vma;
46 struct nouveau_vma dispc_vma[4];
47};
48
49u64
50nvc0_fence_crtc(struct nouveau_channel *chan, int crtc)
51{
52 struct nvc0_fence_chan *fctx = chan->fence;
53 return fctx->dispc_vma[crtc].offset;
54}
55
56static int 37static int
57nvc0_fence_emit(struct nouveau_fence *fence) 38nvc0_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
58{ 39{
59 struct nouveau_channel *chan = fence->channel; 40 int ret = RING_SPACE(chan, 6);
60 struct nvc0_fence_chan *fctx = chan->fence;
61 struct nouveau_fifo_chan *fifo = (void *)chan->object;
62 u64 addr = fctx->vma.offset + fifo->chid * 16;
63 int ret;
64
65 ret = RING_SPACE(chan, 5);
66 if (ret == 0) { 41 if (ret == 0) {
67 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 42 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
68 OUT_RING (chan, upper_32_bits(addr)); 43 OUT_RING (chan, upper_32_bits(virtual));
69 OUT_RING (chan, lower_32_bits(addr)); 44 OUT_RING (chan, lower_32_bits(virtual));
70 OUT_RING (chan, fence->sequence); 45 OUT_RING (chan, sequence);
71 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 46 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
47 OUT_RING (chan, 0x00000000);
72 FIRE_RING (chan); 48 FIRE_RING (chan);
73 } 49 }
74
75 return ret; 50 return ret;
76} 51}
77 52
78static int 53static int
79nvc0_fence_sync(struct nouveau_fence *fence, 54nvc0_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
80 struct nouveau_channel *prev, struct nouveau_channel *chan)
81{ 55{
82 struct nvc0_fence_chan *fctx = chan->fence; 56 int ret = RING_SPACE(chan, 5);
83 struct nouveau_fifo_chan *fifo = (void *)prev->object;
84 u64 addr = fctx->vma.offset + fifo->chid * 16;
85 int ret;
86
87 ret = RING_SPACE(chan, 5);
88 if (ret == 0) { 57 if (ret == 0) {
89 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 58 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
90 OUT_RING (chan, upper_32_bits(addr)); 59 OUT_RING (chan, upper_32_bits(virtual));
91 OUT_RING (chan, lower_32_bits(addr)); 60 OUT_RING (chan, lower_32_bits(virtual));
92 OUT_RING (chan, fence->sequence); 61 OUT_RING (chan, sequence);
93 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL | 62 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL |
94 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD); 63 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
95 FIRE_RING (chan); 64 FIRE_RING (chan);
96 } 65 }
97
98 return ret; 66 return ret;
99} 67}
100 68
101static u32
102nvc0_fence_read(struct nouveau_channel *chan)
103{
104 struct nouveau_fifo_chan *fifo = (void *)chan->object;
105 struct nvc0_fence_priv *priv = chan->drm->fence;
106 return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4);
107}
108
109static void
110nvc0_fence_context_del(struct nouveau_channel *chan)
111{
112 struct drm_device *dev = chan->drm->dev;
113 struct nvc0_fence_priv *priv = chan->drm->fence;
114 struct nvc0_fence_chan *fctx = chan->fence;
115 int i;
116
117 for (i = 0; i < dev->mode_config.num_crtc; i++) {
118 struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
119 nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
120 }
121
122 nouveau_bo_vma_del(priv->bo, &fctx->vma);
123 nouveau_fence_context_del(&fctx->base);
124 chan->fence = NULL;
125 kfree(fctx);
126}
127
128static int 69static int
129nvc0_fence_context_new(struct nouveau_channel *chan) 70nvc0_fence_context_new(struct nouveau_channel *chan)
130{ 71{
131 struct nouveau_fifo_chan *fifo = (void *)chan->object; 72 int ret = nv84_fence_context_new(chan);
132 struct nouveau_client *client = nouveau_client(fifo); 73 if (ret == 0) {
133 struct nvc0_fence_priv *priv = chan->drm->fence; 74 struct nv84_fence_chan *fctx = chan->fence;
134 struct nvc0_fence_chan *fctx; 75 fctx->base.emit32 = nvc0_fence_emit32;
135 int ret, i; 76 fctx->base.sync32 = nvc0_fence_sync32;
136
137 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
138 if (!fctx)
139 return -ENOMEM;
140
141 nouveau_fence_context_new(&fctx->base);
142
143 ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
144 if (ret)
145 nvc0_fence_context_del(chan);
146
147 /* map display semaphore buffers into channel's vm */
148 for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
149 struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
150 ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]);
151 } 77 }
152
153 nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);
154 return ret; 78 return ret;
155} 79}
156 80
157static bool
158nvc0_fence_suspend(struct nouveau_drm *drm)
159{
160 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
161 struct nvc0_fence_priv *priv = drm->fence;
162 int i;
163
164 priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32));
165 if (priv->suspend) {
166 for (i = 0; i <= pfifo->max; i++)
167 priv->suspend[i] = nouveau_bo_rd32(priv->bo, i);
168 }
169
170 return priv->suspend != NULL;
171}
172
173static void
174nvc0_fence_resume(struct nouveau_drm *drm)
175{
176 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
177 struct nvc0_fence_priv *priv = drm->fence;
178 int i;
179
180 if (priv->suspend) {
181 for (i = 0; i <= pfifo->max; i++)
182 nouveau_bo_wr32(priv->bo, i, priv->suspend[i]);
183 vfree(priv->suspend);
184 priv->suspend = NULL;
185 }
186}
187
188static void
189nvc0_fence_destroy(struct nouveau_drm *drm)
190{
191 struct nvc0_fence_priv *priv = drm->fence;
192 nouveau_bo_unmap(priv->bo);
193 if (priv->bo)
194 nouveau_bo_unpin(priv->bo);
195 nouveau_bo_ref(NULL, &priv->bo);
196 drm->fence = NULL;
197 kfree(priv);
198}
199
200int 81int
201nvc0_fence_create(struct nouveau_drm *drm) 82nvc0_fence_create(struct nouveau_drm *drm)
202{ 83{
203 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 84 int ret = nv84_fence_create(drm);
204 struct nvc0_fence_priv *priv;
205 int ret;
206
207 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
208 if (!priv)
209 return -ENOMEM;
210
211 priv->base.dtor = nvc0_fence_destroy;
212 priv->base.suspend = nvc0_fence_suspend;
213 priv->base.resume = nvc0_fence_resume;
214 priv->base.context_new = nvc0_fence_context_new;
215 priv->base.context_del = nvc0_fence_context_del;
216 priv->base.emit = nvc0_fence_emit;
217 priv->base.sync = nvc0_fence_sync;
218 priv->base.read = nvc0_fence_read;
219
220 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,
221 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);
222 if (ret == 0) { 85 if (ret == 0) {
223 ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 86 struct nv84_fence_priv *priv = drm->fence;
224 if (ret == 0) { 87 priv->base.context_new = nvc0_fence_context_new;
225 ret = nouveau_bo_map(priv->bo);
226 if (ret)
227 nouveau_bo_unpin(priv->bo);
228 }
229 if (ret)
230 nouveau_bo_ref(NULL, &priv->bo);
231 } 88 }
232
233 if (ret)
234 nvc0_fence_destroy(drm);
235 return ret; 89 return ret;
236} 90}