aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
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 /drivers/gpu
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. ...
Diffstat (limited to 'drivers/gpu')
-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
148 files changed, 6923 insertions, 2740 deletions
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}