aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c61
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h6
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c)6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c)4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c)12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c37
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c)29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c46
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c)12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c37
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c)4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c)22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c17
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c (renamed from drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c)6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c227
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c43
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c217
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h14
55 files changed, 778 insertions, 377 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
index e6e9537537cf..82235f30277c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
@@ -52,7 +52,7 @@
52#define GM107_DISP /* cl5070.h */ 0x00009470 52#define GM107_DISP /* cl5070.h */ 0x00009470
53#define GM200_DISP /* cl5070.h */ 0x00009570 53#define GM200_DISP /* cl5070.h */ 0x00009570
54#define GP100_DISP /* cl5070.h */ 0x00009770 54#define GP100_DISP /* cl5070.h */ 0x00009770
55#define GP104_DISP /* cl5070.h */ 0x00009870 55#define GP102_DISP /* cl5070.h */ 0x00009870
56 56
57#define NV31_MPEG 0x00003174 57#define NV31_MPEG 0x00003174
58#define G82_MPEG 0x00008274 58#define G82_MPEG 0x00008274
@@ -90,7 +90,7 @@
90#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d 90#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d
91#define GM200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d 91#define GM200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d
92#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d 92#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d
93#define GP104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d 93#define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d
94 94
95#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e 95#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e
96#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e 96#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
index d3d26a1e215d..b93f4c1a95e5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
@@ -8,5 +8,5 @@ int gk104_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
8int gm107_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 8int gm107_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
9int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 9int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
10int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 10int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
11int gp104_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 11int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
12#endif 12#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
index e82049667ce4..970ae753968a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
@@ -33,5 +33,5 @@ int gk110_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
33int gm107_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 33int gm107_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
34int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 34int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
35int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 35int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
36int gp104_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 36int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
37#endif 37#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
index 65ce79a85d37..794e432578b2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
@@ -95,7 +95,7 @@ int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
95int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **); 95int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
96int gm20b_fb_new(struct nvkm_device *, int, struct nvkm_fb **); 96int gm20b_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
97int gp100_fb_new(struct nvkm_device *, int, struct nvkm_fb **); 97int gp100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
98int gp104_fb_new(struct nvkm_device *, int, struct nvkm_fb **); 98int gp102_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
99 99
100#include <subdev/bios.h> 100#include <subdev/bios.h>
101#include <subdev/bios/ramcfg.h> 101#include <subdev/bios/ramcfg.h>
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
index e61923d5e49c..f37538eb1fe5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
@@ -35,6 +35,8 @@ int gk110_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
35int gk208_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); 35int gk208_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
36int gk20a_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); 36int gk20a_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
37int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); 37int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
38int gp100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
39int gp102_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
38 40
39/* interface to MEMX process running on PMU */ 41/* interface to MEMX process running on PMU */
40struct nvkm_memx; 42struct nvkm_memx;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 5698687bc197..bd37ae127582 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -24,6 +24,7 @@
24 * 24 *
25 */ 25 */
26 26
27#include <acpi/video.h>
27#include <drm/drmP.h> 28#include <drm/drmP.h>
28#include <drm/drm_atomic.h> 29#include <drm/drm_atomic.h>
29#include <drm/drm_atomic_helper.h> 30#include <drm/drm_atomic_helper.h>
@@ -348,6 +349,55 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {
348 } \ 349 } \
349} while(0) 350} while(0)
350 351
352#ifdef CONFIG_ACPI
353
354/*
355 * Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch
356 * to the acpi subsys to move it there from drivers/acpi/acpi_video.c .
357 * This should be dropped once that is merged.
358 */
359#ifndef ACPI_VIDEO_NOTIFY_PROBE
360#define ACPI_VIDEO_NOTIFY_PROBE 0x81
361#endif
362
363static void
364nouveau_display_acpi_work(struct work_struct *work)
365{
366 struct nouveau_drm *drm = container_of(work, typeof(*drm), acpi_work);
367
368 pm_runtime_get_sync(drm->dev->dev);
369
370 drm_helper_hpd_irq_event(drm->dev);
371
372 pm_runtime_mark_last_busy(drm->dev->dev);
373 pm_runtime_put_sync(drm->dev->dev);
374}
375
376static int
377nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
378 void *data)
379{
380 struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
381 struct acpi_bus_event *info = data;
382
383 if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
384 if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
385 /*
386 * This may be the only indication we receive of a
387 * connector hotplug on a runtime suspended GPU,
388 * schedule acpi_work to check.
389 */
390 schedule_work(&drm->acpi_work);
391
392 /* acpi-video should not generate keypresses for this */
393 return NOTIFY_BAD;
394 }
395 }
396
397 return NOTIFY_DONE;
398}
399#endif
400
351int 401int
352nouveau_display_init(struct drm_device *dev) 402nouveau_display_init(struct drm_device *dev)
353{ 403{
@@ -488,7 +538,7 @@ nouveau_display_create(struct drm_device *dev)
488 538
489 if (nouveau_modeset != 2 && drm->vbios.dcb.entries) { 539 if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
490 static const u16 oclass[] = { 540 static const u16 oclass[] = {
491 GP104_DISP, 541 GP102_DISP,
492 GP100_DISP, 542 GP100_DISP,
493 GM200_DISP, 543 GM200_DISP,
494 GM107_DISP, 544 GM107_DISP,
@@ -532,6 +582,12 @@ nouveau_display_create(struct drm_device *dev)
532 } 582 }
533 583
534 nouveau_backlight_init(dev); 584 nouveau_backlight_init(dev);
585#ifdef CONFIG_ACPI
586 INIT_WORK(&drm->acpi_work, nouveau_display_acpi_work);
587 drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
588 register_acpi_notifier(&drm->acpi_nb);
589#endif
590
535 return 0; 591 return 0;
536 592
537vblank_err: 593vblank_err:
@@ -547,6 +603,9 @@ nouveau_display_destroy(struct drm_device *dev)
547{ 603{
548 struct nouveau_display *disp = nouveau_display(dev); 604 struct nouveau_display *disp = nouveau_display(dev);
549 605
606#ifdef CONFIG_ACPI
607 unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
608#endif
550 nouveau_backlight_exit(dev); 609 nouveau_backlight_exit(dev);
551 nouveau_display_vblank_fini(dev); 610 nouveau_display_vblank_fini(dev);
552 611
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 4cd47bae73c7..ae1fd641c96e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -37,6 +37,8 @@
37 * - implemented limited ABI16/NVIF interop 37 * - implemented limited ABI16/NVIF interop
38 */ 38 */
39 39
40#include <linux/notifier.h>
41
40#include <nvif/client.h> 42#include <nvif/client.h>
41#include <nvif/device.h> 43#include <nvif/device.h>
42#include <nvif/ioctl.h> 44#include <nvif/ioctl.h>
@@ -161,6 +163,10 @@ struct nouveau_drm {
161 struct nvbios vbios; 163 struct nvbios vbios;
162 struct nouveau_display *display; 164 struct nouveau_display *display;
163 struct backlight_device *backlight; 165 struct backlight_device *backlight;
166#ifdef CONFIG_ACPI
167 struct notifier_block acpi_nb;
168 struct work_struct acpi_work;
169#endif
164 170
165 /* power management */ 171 /* power management */
166 struct nouveau_hwmon *hwmon; 172 struct nouveau_hwmon *hwmon;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index a9855a4ec532..22a8b70a4d1e 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -574,7 +574,7 @@ nv50_core_create(struct nvif_device *device, struct nvif_object *disp,
574 .pushbuf = 0xb0007d00, 574 .pushbuf = 0xb0007d00,
575 }; 575 };
576 static const s32 oclass[] = { 576 static const s32 oclass[] = {
577 GP104_DISP_CORE_CHANNEL_DMA, 577 GP102_DISP_CORE_CHANNEL_DMA,
578 GP100_DISP_CORE_CHANNEL_DMA, 578 GP100_DISP_CORE_CHANNEL_DMA,
579 GM200_DISP_CORE_CHANNEL_DMA, 579 GM200_DISP_CORE_CHANNEL_DMA,
580 GM107_DISP_CORE_CHANNEL_DMA, 580 GM107_DISP_CORE_CHANNEL_DMA,
@@ -3343,12 +3343,15 @@ nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow)
3343 if (!mstm) 3343 if (!mstm)
3344 return 0; 3344 return 0;
3345 3345
3346 if (dpcd[0] >= 0x12 && allow) { 3346 if (dpcd[0] >= 0x12) {
3347 ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]); 3347 ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]);
3348 if (ret < 0) 3348 if (ret < 0)
3349 return ret; 3349 return ret;
3350 3350
3351 state = dpcd[1] & DP_MST_CAP; 3351 if (!(dpcd[1] & DP_MST_CAP))
3352 dpcd[0] = 0x11;
3353 else
3354 state = allow;
3352 } 3355 }
3353 3356
3354 ret = nv50_mstm_enable(mstm, dpcd[0], state); 3357 ret = nv50_mstm_enable(mstm, dpcd[0], state);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
index a4458a8eb30a..255d81ccf916 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
@@ -4,4 +4,4 @@ nvkm-y += nvkm/engine/ce/gk104.o
4nvkm-y += nvkm/engine/ce/gm107.o 4nvkm-y += nvkm/engine/ce/gm107.o
5nvkm-y += nvkm/engine/ce/gm200.o 5nvkm-y += nvkm/engine/ce/gm200.o
6nvkm-y += nvkm/engine/ce/gp100.o 6nvkm-y += nvkm/engine/ce/gp100.o
7nvkm-y += nvkm/engine/ce/gp104.o 7nvkm-y += nvkm/engine/ce/gp102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c
index 20e019788a53..985c8f653874 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c
@@ -27,7 +27,7 @@
27#include <nvif/class.h> 27#include <nvif/class.h>
28 28
29static const struct nvkm_engine_func 29static const struct nvkm_engine_func
30gp104_ce = { 30gp102_ce = {
31 .intr = gp100_ce_intr, 31 .intr = gp100_ce_intr,
32 .sclass = { 32 .sclass = {
33 { -1, -1, PASCAL_DMA_COPY_B }, 33 { -1, -1, PASCAL_DMA_COPY_B },
@@ -37,8 +37,8 @@ gp104_ce = {
37}; 37};
38 38
39int 39int
40gp104_ce_new(struct nvkm_device *device, int index, 40gp102_ce_new(struct nvkm_device *device, int index,
41 struct nvkm_engine **pengine) 41 struct nvkm_engine **pengine)
42{ 42{
43 return nvkm_engine_new_(&gp104_ce, device, index, true, pengine); 43 return nvkm_engine_new_(&gp102_ce, device, index, true, pengine);
44} 44}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index bd22526edb0b..2cbcffe78c3e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2167,6 +2167,7 @@ nv130_chipset = {
2167 .mmu = gf100_mmu_new, 2167 .mmu = gf100_mmu_new,
2168 .secboot = gm200_secboot_new, 2168 .secboot = gm200_secboot_new,
2169 .pci = gp100_pci_new, 2169 .pci = gp100_pci_new,
2170 .pmu = gp100_pmu_new,
2170 .timer = gk20a_timer_new, 2171 .timer = gk20a_timer_new,
2171 .top = gk104_top_new, 2172 .top = gk104_top_new,
2172 .ce[0] = gp100_ce_new, 2173 .ce[0] = gp100_ce_new,
@@ -2183,13 +2184,42 @@ nv130_chipset = {
2183}; 2184};
2184 2185
2185static const struct nvkm_device_chip 2186static const struct nvkm_device_chip
2187nv132_chipset = {
2188 .name = "GP102",
2189 .bar = gf100_bar_new,
2190 .bios = nvkm_bios_new,
2191 .bus = gf100_bus_new,
2192 .devinit = gm200_devinit_new,
2193 .fb = gp102_fb_new,
2194 .fuse = gm107_fuse_new,
2195 .gpio = gk104_gpio_new,
2196 .i2c = gm200_i2c_new,
2197 .ibus = gm200_ibus_new,
2198 .imem = nv50_instmem_new,
2199 .ltc = gp100_ltc_new,
2200 .mc = gp100_mc_new,
2201 .mmu = gf100_mmu_new,
2202 .pci = gp100_pci_new,
2203 .pmu = gp102_pmu_new,
2204 .timer = gk20a_timer_new,
2205 .top = gk104_top_new,
2206 .ce[0] = gp102_ce_new,
2207 .ce[1] = gp102_ce_new,
2208 .ce[2] = gp102_ce_new,
2209 .ce[3] = gp102_ce_new,
2210 .disp = gp102_disp_new,
2211 .dma = gf119_dma_new,
2212 .fifo = gp100_fifo_new,
2213};
2214
2215static const struct nvkm_device_chip
2186nv134_chipset = { 2216nv134_chipset = {
2187 .name = "GP104", 2217 .name = "GP104",
2188 .bar = gf100_bar_new, 2218 .bar = gf100_bar_new,
2189 .bios = nvkm_bios_new, 2219 .bios = nvkm_bios_new,
2190 .bus = gf100_bus_new, 2220 .bus = gf100_bus_new,
2191 .devinit = gm200_devinit_new, 2221 .devinit = gm200_devinit_new,
2192 .fb = gp104_fb_new, 2222 .fb = gp102_fb_new,
2193 .fuse = gm107_fuse_new, 2223 .fuse = gm107_fuse_new,
2194 .gpio = gk104_gpio_new, 2224 .gpio = gk104_gpio_new,
2195 .i2c = gm200_i2c_new, 2225 .i2c = gm200_i2c_new,
@@ -2199,13 +2229,14 @@ nv134_chipset = {
2199 .mc = gp100_mc_new, 2229 .mc = gp100_mc_new,
2200 .mmu = gf100_mmu_new, 2230 .mmu = gf100_mmu_new,
2201 .pci = gp100_pci_new, 2231 .pci = gp100_pci_new,
2232 .pmu = gp102_pmu_new,
2202 .timer = gk20a_timer_new, 2233 .timer = gk20a_timer_new,
2203 .top = gk104_top_new, 2234 .top = gk104_top_new,
2204 .ce[0] = gp104_ce_new, 2235 .ce[0] = gp102_ce_new,
2205 .ce[1] = gp104_ce_new, 2236 .ce[1] = gp102_ce_new,
2206 .ce[2] = gp104_ce_new, 2237 .ce[2] = gp102_ce_new,
2207 .ce[3] = gp104_ce_new, 2238 .ce[3] = gp102_ce_new,
2208 .disp = gp104_disp_new, 2239 .disp = gp102_disp_new,
2209 .dma = gf119_dma_new, 2240 .dma = gf119_dma_new,
2210 .fifo = gp100_fifo_new, 2241 .fifo = gp100_fifo_new,
2211}; 2242};
@@ -2644,6 +2675,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
2644 case 0x126: device->chip = &nv126_chipset; break; 2675 case 0x126: device->chip = &nv126_chipset; break;
2645 case 0x12b: device->chip = &nv12b_chipset; break; 2676 case 0x12b: device->chip = &nv12b_chipset; break;
2646 case 0x130: device->chip = &nv130_chipset; break; 2677 case 0x130: device->chip = &nv130_chipset; break;
2678 case 0x132: device->chip = &nv132_chipset; break;
2647 case 0x134: device->chip = &nv134_chipset; break; 2679 case 0x134: device->chip = &nv134_chipset; break;
2648 default: 2680 default:
2649 nvdev_error(device, "unknown chipset (%08x)\n", boot0); 2681 nvdev_error(device, "unknown chipset (%08x)\n", boot0);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index 0030cd9543b2..74a1ffa425f7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -1687,7 +1687,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
1687 * This is necessary for platforms where the default DMA mask of 32 1687 * This is necessary for platforms where the default DMA mask of 32
1688 * does not cover any system memory, i.e., when all RAM is > 4 GB. 1688 * does not cover any system memory, i.e., when all RAM is > 4 GB.
1689 */ 1689 */
1690 if (subdev_mask & BIT(NVKM_SUBDEV_MMU)) 1690 if (pdev->device.mmu)
1691 dma_set_mask_and_coherent(&pci_dev->dev, 1691 dma_set_mask_and_coherent(&pci_dev->dev,
1692 DMA_BIT_MASK(pdev->device.mmu->dma_bits)); 1692 DMA_BIT_MASK(pdev->device.mmu->dma_bits));
1693 1693
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
index 77a52b54a31e..fa05d16ae948 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -11,7 +11,7 @@ nvkm-y += nvkm/engine/disp/gk110.o
11nvkm-y += nvkm/engine/disp/gm107.o 11nvkm-y += nvkm/engine/disp/gm107.o
12nvkm-y += nvkm/engine/disp/gm200.o 12nvkm-y += nvkm/engine/disp/gm200.o
13nvkm-y += nvkm/engine/disp/gp100.o 13nvkm-y += nvkm/engine/disp/gp100.o
14nvkm-y += nvkm/engine/disp/gp104.o 14nvkm-y += nvkm/engine/disp/gp102.o
15 15
16nvkm-y += nvkm/engine/disp/outp.o 16nvkm-y += nvkm/engine/disp/outp.o
17nvkm-y += nvkm/engine/disp/outpdp.o 17nvkm-y += nvkm/engine/disp/outpdp.o
@@ -48,14 +48,14 @@ nvkm-y += nvkm/engine/disp/rootgk110.o
48nvkm-y += nvkm/engine/disp/rootgm107.o 48nvkm-y += nvkm/engine/disp/rootgm107.o
49nvkm-y += nvkm/engine/disp/rootgm200.o 49nvkm-y += nvkm/engine/disp/rootgm200.o
50nvkm-y += nvkm/engine/disp/rootgp100.o 50nvkm-y += nvkm/engine/disp/rootgp100.o
51nvkm-y += nvkm/engine/disp/rootgp104.o 51nvkm-y += nvkm/engine/disp/rootgp102.o
52 52
53nvkm-y += nvkm/engine/disp/channv50.o 53nvkm-y += nvkm/engine/disp/channv50.o
54nvkm-y += nvkm/engine/disp/changf119.o 54nvkm-y += nvkm/engine/disp/changf119.o
55 55
56nvkm-y += nvkm/engine/disp/dmacnv50.o 56nvkm-y += nvkm/engine/disp/dmacnv50.o
57nvkm-y += nvkm/engine/disp/dmacgf119.o 57nvkm-y += nvkm/engine/disp/dmacgf119.o
58nvkm-y += nvkm/engine/disp/dmacgp104.o 58nvkm-y += nvkm/engine/disp/dmacgp102.o
59 59
60nvkm-y += nvkm/engine/disp/basenv50.o 60nvkm-y += nvkm/engine/disp/basenv50.o
61nvkm-y += nvkm/engine/disp/baseg84.o 61nvkm-y += nvkm/engine/disp/baseg84.o
@@ -64,7 +64,7 @@ nvkm-y += nvkm/engine/disp/basegt215.o
64nvkm-y += nvkm/engine/disp/basegf119.o 64nvkm-y += nvkm/engine/disp/basegf119.o
65nvkm-y += nvkm/engine/disp/basegk104.o 65nvkm-y += nvkm/engine/disp/basegk104.o
66nvkm-y += nvkm/engine/disp/basegk110.o 66nvkm-y += nvkm/engine/disp/basegk110.o
67nvkm-y += nvkm/engine/disp/basegp104.o 67nvkm-y += nvkm/engine/disp/basegp102.o
68 68
69nvkm-y += nvkm/engine/disp/corenv50.o 69nvkm-y += nvkm/engine/disp/corenv50.o
70nvkm-y += nvkm/engine/disp/coreg84.o 70nvkm-y += nvkm/engine/disp/coreg84.o
@@ -77,7 +77,7 @@ nvkm-y += nvkm/engine/disp/coregk110.o
77nvkm-y += nvkm/engine/disp/coregm107.o 77nvkm-y += nvkm/engine/disp/coregm107.o
78nvkm-y += nvkm/engine/disp/coregm200.o 78nvkm-y += nvkm/engine/disp/coregm200.o
79nvkm-y += nvkm/engine/disp/coregp100.o 79nvkm-y += nvkm/engine/disp/coregp100.o
80nvkm-y += nvkm/engine/disp/coregp104.o 80nvkm-y += nvkm/engine/disp/coregp102.o
81 81
82nvkm-y += nvkm/engine/disp/ovlynv50.o 82nvkm-y += nvkm/engine/disp/ovlynv50.o
83nvkm-y += nvkm/engine/disp/ovlyg84.o 83nvkm-y += nvkm/engine/disp/ovlyg84.o
@@ -85,7 +85,7 @@ nvkm-y += nvkm/engine/disp/ovlygt200.o
85nvkm-y += nvkm/engine/disp/ovlygt215.o 85nvkm-y += nvkm/engine/disp/ovlygt215.o
86nvkm-y += nvkm/engine/disp/ovlygf119.o 86nvkm-y += nvkm/engine/disp/ovlygf119.o
87nvkm-y += nvkm/engine/disp/ovlygk104.o 87nvkm-y += nvkm/engine/disp/ovlygk104.o
88nvkm-y += nvkm/engine/disp/ovlygp104.o 88nvkm-y += nvkm/engine/disp/ovlygp102.o
89 89
90nvkm-y += nvkm/engine/disp/piocnv50.o 90nvkm-y += nvkm/engine/disp/piocnv50.o
91nvkm-y += nvkm/engine/disp/piocgf119.o 91nvkm-y += nvkm/engine/disp/piocgf119.o
@@ -95,9 +95,11 @@ nvkm-y += nvkm/engine/disp/cursg84.o
95nvkm-y += nvkm/engine/disp/cursgt215.o 95nvkm-y += nvkm/engine/disp/cursgt215.o
96nvkm-y += nvkm/engine/disp/cursgf119.o 96nvkm-y += nvkm/engine/disp/cursgf119.o
97nvkm-y += nvkm/engine/disp/cursgk104.o 97nvkm-y += nvkm/engine/disp/cursgk104.o
98nvkm-y += nvkm/engine/disp/cursgp102.o
98 99
99nvkm-y += nvkm/engine/disp/oimmnv50.o 100nvkm-y += nvkm/engine/disp/oimmnv50.o
100nvkm-y += nvkm/engine/disp/oimmg84.o 101nvkm-y += nvkm/engine/disp/oimmg84.o
101nvkm-y += nvkm/engine/disp/oimmgt215.o 102nvkm-y += nvkm/engine/disp/oimmgt215.o
102nvkm-y += nvkm/engine/disp/oimmgf119.o 103nvkm-y += nvkm/engine/disp/oimmgf119.o
103nvkm-y += nvkm/engine/disp/oimmgk104.o 104nvkm-y += nvkm/engine/disp/oimmgk104.o
105nvkm-y += nvkm/engine/disp/oimmgp102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c
index 51688e37c54e..8a3cdeef8d2c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c
@@ -27,12 +27,12 @@
27#include <nvif/class.h> 27#include <nvif/class.h>
28 28
29const struct nv50_disp_dmac_oclass 29const struct nv50_disp_dmac_oclass
30gp104_disp_base_oclass = { 30gp102_disp_base_oclass = {
31 .base.oclass = GK110_DISP_BASE_CHANNEL_DMA, 31 .base.oclass = GK110_DISP_BASE_CHANNEL_DMA,
32 .base.minver = 0, 32 .base.minver = 0,
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_base_new, 34 .ctor = nv50_disp_base_new,
35 .func = &gp104_disp_dmac_func, 35 .func = &gp102_disp_dmac_func,
36 .mthd = &gf119_disp_base_chan_mthd, 36 .mthd = &gf119_disp_base_chan_mthd,
37 .chid = 1, 37 .chid = 1,
38}; 38};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
index 26990d44ae75..524a24eae1a0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
@@ -82,7 +82,7 @@ nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug)
82 82
83 if (mthd->addr) { 83 if (mthd->addr) {
84 snprintf(cname_, sizeof(cname_), "%s %d", 84 snprintf(cname_, sizeof(cname_), "%s %d",
85 mthd->name, chan->chid); 85 mthd->name, chan->chid.user);
86 cname = cname_; 86 cname = cname_;
87 } 87 }
88 88
@@ -139,7 +139,7 @@ nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size,
139 if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { 139 if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
140 notify->size = sizeof(struct nvif_notify_uevent_rep); 140 notify->size = sizeof(struct nvif_notify_uevent_rep);
141 notify->types = 1; 141 notify->types = 1;
142 notify->index = chan->chid; 142 notify->index = chan->chid.user;
143 return 0; 143 return 0;
144 } 144 }
145 145
@@ -159,7 +159,7 @@ nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
159 struct nv50_disp_chan *chan = nv50_disp_chan(object); 159 struct nv50_disp_chan *chan = nv50_disp_chan(object);
160 struct nv50_disp *disp = chan->root->disp; 160 struct nv50_disp *disp = chan->root->disp;
161 struct nvkm_device *device = disp->base.engine.subdev.device; 161 struct nvkm_device *device = disp->base.engine.subdev.device;
162 *data = nvkm_rd32(device, 0x640000 + (chan->chid * 0x1000) + addr); 162 *data = nvkm_rd32(device, 0x640000 + (chan->chid.user * 0x1000) + addr);
163 return 0; 163 return 0;
164} 164}
165 165
@@ -169,7 +169,7 @@ nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
169 struct nv50_disp_chan *chan = nv50_disp_chan(object); 169 struct nv50_disp_chan *chan = nv50_disp_chan(object);
170 struct nv50_disp *disp = chan->root->disp; 170 struct nv50_disp *disp = chan->root->disp;
171 struct nvkm_device *device = disp->base.engine.subdev.device; 171 struct nvkm_device *device = disp->base.engine.subdev.device;
172 nvkm_wr32(device, 0x640000 + (chan->chid * 0x1000) + addr, data); 172 nvkm_wr32(device, 0x640000 + (chan->chid.user * 0x1000) + addr, data);
173 return 0; 173 return 0;
174} 174}
175 175
@@ -196,7 +196,7 @@ nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
196 struct nv50_disp *disp = chan->root->disp; 196 struct nv50_disp *disp = chan->root->disp;
197 struct nvkm_device *device = disp->base.engine.subdev.device; 197 struct nvkm_device *device = disp->base.engine.subdev.device;
198 *addr = device->func->resource_addr(device, 0) + 198 *addr = device->func->resource_addr(device, 0) +
199 0x640000 + (chan->chid * 0x1000); 199 0x640000 + (chan->chid.user * 0x1000);
200 *size = 0x001000; 200 *size = 0x001000;
201 return 0; 201 return 0;
202} 202}
@@ -243,8 +243,8 @@ nv50_disp_chan_dtor(struct nvkm_object *object)
243{ 243{
244 struct nv50_disp_chan *chan = nv50_disp_chan(object); 244 struct nv50_disp_chan *chan = nv50_disp_chan(object);
245 struct nv50_disp *disp = chan->root->disp; 245 struct nv50_disp *disp = chan->root->disp;
246 if (chan->chid >= 0) 246 if (chan->chid.user >= 0)
247 disp->chan[chan->chid] = NULL; 247 disp->chan[chan->chid.user] = NULL;
248 return chan->func->dtor ? chan->func->dtor(chan) : chan; 248 return chan->func->dtor ? chan->func->dtor(chan) : chan;
249} 249}
250 250
@@ -263,7 +263,7 @@ nv50_disp_chan = {
263int 263int
264nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func, 264nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func,
265 const struct nv50_disp_chan_mthd *mthd, 265 const struct nv50_disp_chan_mthd *mthd,
266 struct nv50_disp_root *root, int chid, int head, 266 struct nv50_disp_root *root, int ctrl, int user, int head,
267 const struct nvkm_oclass *oclass, 267 const struct nvkm_oclass *oclass,
268 struct nv50_disp_chan *chan) 268 struct nv50_disp_chan *chan)
269{ 269{
@@ -273,21 +273,22 @@ nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func,
273 chan->func = func; 273 chan->func = func;
274 chan->mthd = mthd; 274 chan->mthd = mthd;
275 chan->root = root; 275 chan->root = root;
276 chan->chid = chid; 276 chan->chid.ctrl = ctrl;
277 chan->chid.user = user;
277 chan->head = head; 278 chan->head = head;
278 279
279 if (disp->chan[chan->chid]) { 280 if (disp->chan[chan->chid.user]) {
280 chan->chid = -1; 281 chan->chid.user = -1;
281 return -EBUSY; 282 return -EBUSY;
282 } 283 }
283 disp->chan[chan->chid] = chan; 284 disp->chan[chan->chid.user] = chan;
284 return 0; 285 return 0;
285} 286}
286 287
287int 288int
288nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, 289nv50_disp_chan_new_(const struct nv50_disp_chan_func *func,
289 const struct nv50_disp_chan_mthd *mthd, 290 const struct nv50_disp_chan_mthd *mthd,
290 struct nv50_disp_root *root, int chid, int head, 291 struct nv50_disp_root *root, int ctrl, int user, int head,
291 const struct nvkm_oclass *oclass, 292 const struct nvkm_oclass *oclass,
292 struct nvkm_object **pobject) 293 struct nvkm_object **pobject)
293{ 294{
@@ -297,5 +298,6 @@ nv50_disp_chan_new_(const struct nv50_disp_chan_func *func,
297 return -ENOMEM; 298 return -ENOMEM;
298 *pobject = &chan->object; 299 *pobject = &chan->object;
299 300
300 return nv50_disp_chan_ctor(func, mthd, root, chid, head, oclass, chan); 301 return nv50_disp_chan_ctor(func, mthd, root, ctrl, user,
302 head, oclass, chan);
301} 303}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
index f5f683d9fd20..737b38f6fbd2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
@@ -7,7 +7,11 @@ struct nv50_disp_chan {
7 const struct nv50_disp_chan_func *func; 7 const struct nv50_disp_chan_func *func;
8 const struct nv50_disp_chan_mthd *mthd; 8 const struct nv50_disp_chan_mthd *mthd;
9 struct nv50_disp_root *root; 9 struct nv50_disp_root *root;
10 int chid; 10
11 struct {
12 int ctrl;
13 int user;
14 } chid;
11 int head; 15 int head;
12 16
13 struct nvkm_object object; 17 struct nvkm_object object;
@@ -25,11 +29,11 @@ struct nv50_disp_chan_func {
25 29
26int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *, 30int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *,
27 const struct nv50_disp_chan_mthd *, 31 const struct nv50_disp_chan_mthd *,
28 struct nv50_disp_root *, int chid, int head, 32 struct nv50_disp_root *, int ctrl, int user, int head,
29 const struct nvkm_oclass *, struct nv50_disp_chan *); 33 const struct nvkm_oclass *, struct nv50_disp_chan *);
30int nv50_disp_chan_new_(const struct nv50_disp_chan_func *, 34int nv50_disp_chan_new_(const struct nv50_disp_chan_func *,
31 const struct nv50_disp_chan_mthd *, 35 const struct nv50_disp_chan_mthd *,
32 struct nv50_disp_root *, int chid, int head, 36 struct nv50_disp_root *, int ctrl, int user, int head,
33 const struct nvkm_oclass *, struct nvkm_object **); 37 const struct nvkm_oclass *, struct nvkm_object **);
34 38
35extern const struct nv50_disp_chan_func nv50_disp_pioc_func; 39extern const struct nv50_disp_chan_func nv50_disp_pioc_func;
@@ -90,13 +94,16 @@ extern const struct nv50_disp_chan_mthd gk104_disp_ovly_chan_mthd;
90struct nv50_disp_pioc_oclass { 94struct nv50_disp_pioc_oclass {
91 int (*ctor)(const struct nv50_disp_chan_func *, 95 int (*ctor)(const struct nv50_disp_chan_func *,
92 const struct nv50_disp_chan_mthd *, 96 const struct nv50_disp_chan_mthd *,
93 struct nv50_disp_root *, int chid, 97 struct nv50_disp_root *, int ctrl, int user,
94 const struct nvkm_oclass *, void *data, u32 size, 98 const struct nvkm_oclass *, void *data, u32 size,
95 struct nvkm_object **); 99 struct nvkm_object **);
96 struct nvkm_sclass base; 100 struct nvkm_sclass base;
97 const struct nv50_disp_chan_func *func; 101 const struct nv50_disp_chan_func *func;
98 const struct nv50_disp_chan_mthd *mthd; 102 const struct nv50_disp_chan_mthd *mthd;
99 int chid; 103 struct {
104 int ctrl;
105 int user;
106 } chid;
100}; 107};
101 108
102extern const struct nv50_disp_pioc_oclass nv50_disp_oimm_oclass; 109extern const struct nv50_disp_pioc_oclass nv50_disp_oimm_oclass;
@@ -114,15 +121,17 @@ extern const struct nv50_disp_pioc_oclass gf119_disp_curs_oclass;
114extern const struct nv50_disp_pioc_oclass gk104_disp_oimm_oclass; 121extern const struct nv50_disp_pioc_oclass gk104_disp_oimm_oclass;
115extern const struct nv50_disp_pioc_oclass gk104_disp_curs_oclass; 122extern const struct nv50_disp_pioc_oclass gk104_disp_curs_oclass;
116 123
124extern const struct nv50_disp_pioc_oclass gp102_disp_oimm_oclass;
125extern const struct nv50_disp_pioc_oclass gp102_disp_curs_oclass;
117 126
118int nv50_disp_curs_new(const struct nv50_disp_chan_func *, 127int nv50_disp_curs_new(const struct nv50_disp_chan_func *,
119 const struct nv50_disp_chan_mthd *, 128 const struct nv50_disp_chan_mthd *,
120 struct nv50_disp_root *, int chid, 129 struct nv50_disp_root *, int ctrl, int user,
121 const struct nvkm_oclass *, void *data, u32 size, 130 const struct nvkm_oclass *, void *data, u32 size,
122 struct nvkm_object **); 131 struct nvkm_object **);
123int nv50_disp_oimm_new(const struct nv50_disp_chan_func *, 132int nv50_disp_oimm_new(const struct nv50_disp_chan_func *,
124 const struct nv50_disp_chan_mthd *, 133 const struct nv50_disp_chan_mthd *,
125 struct nv50_disp_root *, int chid, 134 struct nv50_disp_root *, int ctrl, int user,
126 const struct nvkm_oclass *, void *data, u32 size, 135 const struct nvkm_oclass *, void *data, u32 size,
127 struct nvkm_object **); 136 struct nvkm_object **);
128#endif 137#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c
index e356f87fbe60..b0df4b752b8c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c
@@ -29,7 +29,7 @@
29#include <nvif/class.h> 29#include <nvif/class.h>
30 30
31static int 31static int
32gp104_disp_core_init(struct nv50_disp_dmac *chan) 32gp102_disp_core_init(struct nv50_disp_dmac *chan)
33{ 33{
34 struct nv50_disp *disp = chan->base.root->disp; 34 struct nv50_disp *disp = chan->base.root->disp;
35 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 35 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
@@ -60,19 +60,19 @@ gp104_disp_core_init(struct nv50_disp_dmac *chan)
60} 60}
61 61
62static const struct nv50_disp_dmac_func 62static const struct nv50_disp_dmac_func
63gp104_disp_core_func = { 63gp102_disp_core_func = {
64 .init = gp104_disp_core_init, 64 .init = gp102_disp_core_init,
65 .fini = gf119_disp_core_fini, 65 .fini = gf119_disp_core_fini,
66 .bind = gf119_disp_dmac_bind, 66 .bind = gf119_disp_dmac_bind,
67}; 67};
68 68
69const struct nv50_disp_dmac_oclass 69const struct nv50_disp_dmac_oclass
70gp104_disp_core_oclass = { 70gp102_disp_core_oclass = {
71 .base.oclass = GP104_DISP_CORE_CHANNEL_DMA, 71 .base.oclass = GP102_DISP_CORE_CHANNEL_DMA,
72 .base.minver = 0, 72 .base.minver = 0,
73 .base.maxver = 0, 73 .base.maxver = 0,
74 .ctor = nv50_disp_core_new, 74 .ctor = nv50_disp_core_new,
75 .func = &gp104_disp_core_func, 75 .func = &gp102_disp_core_func,
76 .mthd = &gk104_disp_core_chan_mthd, 76 .mthd = &gk104_disp_core_chan_mthd,
77 .chid = 0, 77 .chid = 0,
78}; 78};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
index dd99fc7060b1..fa781b5a7e07 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
@@ -33,5 +33,5 @@ g84_disp_curs_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_curs_new, 34 .ctor = nv50_disp_curs_new,
35 .func = &nv50_disp_pioc_func, 35 .func = &nv50_disp_pioc_func,
36 .chid = 7, 36 .chid = { 7, 7 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
index 2a1574e06ad6..2be6fb052c65 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
@@ -33,5 +33,5 @@ gf119_disp_curs_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_curs_new, 34 .ctor = nv50_disp_curs_new,
35 .func = &gf119_disp_pioc_func, 35 .func = &gf119_disp_pioc_func,
36 .chid = 13, 36 .chid = { 13, 13 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
index 28e8f06c9472..2a99db4bf8f8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
@@ -33,5 +33,5 @@ gk104_disp_curs_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_curs_new, 34 .ctor = nv50_disp_curs_new,
35 .func = &gf119_disp_pioc_func, 35 .func = &gf119_disp_pioc_func,
36 .chid = 13, 36 .chid = { 13, 13 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c
new file mode 100644
index 000000000000..e958210d8105
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c
@@ -0,0 +1,37 @@
1/*
2 * Copyright 2016 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#include "channv50.h"
25#include "rootnv50.h"
26
27#include <nvif/class.h>
28
29const struct nv50_disp_pioc_oclass
30gp102_disp_curs_oclass = {
31 .base.oclass = GK104_DISP_CURSOR,
32 .base.minver = 0,
33 .base.maxver = 0,
34 .ctor = nv50_disp_curs_new,
35 .func = &gf119_disp_pioc_func,
36 .chid = { 13, 17 },
37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
index d8a4b9ca139c..00a7f3564450 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
@@ -33,5 +33,5 @@ gt215_disp_curs_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_curs_new, 34 .ctor = nv50_disp_curs_new,
35 .func = &nv50_disp_pioc_func, 35 .func = &nv50_disp_pioc_func,
36 .chid = 7, 36 .chid = { 7, 7 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
index 8b1320499a0f..82ff82d8c1ab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
@@ -33,7 +33,7 @@
33int 33int
34nv50_disp_curs_new(const struct nv50_disp_chan_func *func, 34nv50_disp_curs_new(const struct nv50_disp_chan_func *func,
35 const struct nv50_disp_chan_mthd *mthd, 35 const struct nv50_disp_chan_mthd *mthd,
36 struct nv50_disp_root *root, int chid, 36 struct nv50_disp_root *root, int ctrl, int user,
37 const struct nvkm_oclass *oclass, void *data, u32 size, 37 const struct nvkm_oclass *oclass, void *data, u32 size,
38 struct nvkm_object **pobject) 38 struct nvkm_object **pobject)
39{ 39{
@@ -54,7 +54,7 @@ nv50_disp_curs_new(const struct nv50_disp_chan_func *func,
54 } else 54 } else
55 return ret; 55 return ret;
56 56
57 return nv50_disp_chan_new_(func, mthd, root, chid + head, 57 return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head,
58 head, oclass, pobject); 58 head, oclass, pobject);
59} 59}
60 60
@@ -65,5 +65,5 @@ nv50_disp_curs_oclass = {
65 .base.maxver = 0, 65 .base.maxver = 0,
66 .ctor = nv50_disp_curs_new, 66 .ctor = nv50_disp_curs_new,
67 .func = &nv50_disp_pioc_func, 67 .func = &nv50_disp_pioc_func,
68 .chid = 7, 68 .chid = { 7, 7 },
69}; 69};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
index a57f7cef307a..ce7cd74fbd5d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
@@ -32,8 +32,8 @@ gf119_disp_dmac_bind(struct nv50_disp_dmac *chan,
32 struct nvkm_object *object, u32 handle) 32 struct nvkm_object *object, u32 handle)
33{ 33{
34 return nvkm_ramht_insert(chan->base.root->ramht, object, 34 return nvkm_ramht_insert(chan->base.root->ramht, object,
35 chan->base.chid, -9, handle, 35 chan->base.chid.user, -9, handle,
36 chan->base.chid << 27 | 0x00000001); 36 chan->base.chid.user << 27 | 0x00000001);
37} 37}
38 38
39void 39void
@@ -42,22 +42,23 @@ gf119_disp_dmac_fini(struct nv50_disp_dmac *chan)
42 struct nv50_disp *disp = chan->base.root->disp; 42 struct nv50_disp *disp = chan->base.root->disp;
43 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 43 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
44 struct nvkm_device *device = subdev->device; 44 struct nvkm_device *device = subdev->device;
45 int chid = chan->base.chid; 45 int ctrl = chan->base.chid.ctrl;
46 int user = chan->base.chid.user;
46 47
47 /* deactivate channel */ 48 /* deactivate channel */
48 nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000); 49 nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000);
49 nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000); 50 nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000);
50 if (nvkm_msec(device, 2000, 51 if (nvkm_msec(device, 2000,
51 if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x001e0000)) 52 if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000))
52 break; 53 break;
53 ) < 0) { 54 ) < 0) {
54 nvkm_error(subdev, "ch %d fini: %08x\n", chid, 55 nvkm_error(subdev, "ch %d fini: %08x\n", user,
55 nvkm_rd32(device, 0x610490 + (chid * 0x10))); 56 nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
56 } 57 }
57 58
58 /* disable error reporting and completion notification */ 59 /* disable error reporting and completion notification */
59 nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000); 60 nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
60 nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000); 61 nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
61} 62}
62 63
63static int 64static int
@@ -66,26 +67,27 @@ gf119_disp_dmac_init(struct nv50_disp_dmac *chan)
66 struct nv50_disp *disp = chan->base.root->disp; 67 struct nv50_disp *disp = chan->base.root->disp;
67 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 68 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
68 struct nvkm_device *device = subdev->device; 69 struct nvkm_device *device = subdev->device;
69 int chid = chan->base.chid; 70 int ctrl = chan->base.chid.ctrl;
71 int user = chan->base.chid.user;
70 72
71 /* enable error reporting */ 73 /* enable error reporting */
72 nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); 74 nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
73 75
74 /* initialise channel for dma command submission */ 76 /* initialise channel for dma command submission */
75 nvkm_wr32(device, 0x610494 + (chid * 0x0010), chan->push); 77 nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push);
76 nvkm_wr32(device, 0x610498 + (chid * 0x0010), 0x00010000); 78 nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000);
77 nvkm_wr32(device, 0x61049c + (chid * 0x0010), 0x00000001); 79 nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001);
78 nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010); 80 nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
79 nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000); 81 nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
80 nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013); 82 nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
81 83
82 /* wait for it to go inactive */ 84 /* wait for it to go inactive */
83 if (nvkm_msec(device, 2000, 85 if (nvkm_msec(device, 2000,
84 if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000)) 86 if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
85 break; 87 break;
86 ) < 0) { 88 ) < 0) {
87 nvkm_error(subdev, "ch %d init: %08x\n", chid, 89 nvkm_error(subdev, "ch %d init: %08x\n", user,
88 nvkm_rd32(device, 0x610490 + (chid * 0x10))); 90 nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
89 return -EBUSY; 91 return -EBUSY;
90 } 92 }
91 93
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c
index ad24c2c57696..cdead9500343 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c
@@ -27,31 +27,32 @@
27#include <subdev/timer.h> 27#include <subdev/timer.h>
28 28
29static int 29static int
30gp104_disp_dmac_init(struct nv50_disp_dmac *chan) 30gp102_disp_dmac_init(struct nv50_disp_dmac *chan)
31{ 31{
32 struct nv50_disp *disp = chan->base.root->disp; 32 struct nv50_disp *disp = chan->base.root->disp;
33 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 33 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
34 struct nvkm_device *device = subdev->device; 34 struct nvkm_device *device = subdev->device;
35 int chid = chan->base.chid; 35 int ctrl = chan->base.chid.ctrl;
36 int user = chan->base.chid.user;
36 37
37 /* enable error reporting */ 38 /* enable error reporting */
38 nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); 39 nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
39 40
40 /* initialise channel for dma command submission */ 41 /* initialise channel for dma command submission */
41 nvkm_wr32(device, 0x611494 + (chid * 0x0010), chan->push); 42 nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push);
42 nvkm_wr32(device, 0x611498 + (chid * 0x0010), 0x00010000); 43 nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000);
43 nvkm_wr32(device, 0x61149c + (chid * 0x0010), 0x00000001); 44 nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001);
44 nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010); 45 nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
45 nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000); 46 nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
46 nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013); 47 nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
47 48
48 /* wait for it to go inactive */ 49 /* wait for it to go inactive */
49 if (nvkm_msec(device, 2000, 50 if (nvkm_msec(device, 2000,
50 if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000)) 51 if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
51 break; 52 break;
52 ) < 0) { 53 ) < 0) {
53 nvkm_error(subdev, "ch %d init: %08x\n", chid, 54 nvkm_error(subdev, "ch %d init: %08x\n", user,
54 nvkm_rd32(device, 0x610490 + (chid * 0x10))); 55 nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
55 return -EBUSY; 56 return -EBUSY;
56 } 57 }
57 58
@@ -59,8 +60,8 @@ gp104_disp_dmac_init(struct nv50_disp_dmac *chan)
59} 60}
60 61
61const struct nv50_disp_dmac_func 62const struct nv50_disp_dmac_func
62gp104_disp_dmac_func = { 63gp102_disp_dmac_func = {
63 .init = gp104_disp_dmac_init, 64 .init = gp102_disp_dmac_init,
64 .fini = gf119_disp_dmac_fini, 65 .fini = gf119_disp_dmac_fini,
65 .bind = gf119_disp_dmac_bind, 66 .bind = gf119_disp_dmac_bind,
66}; 67};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
index 9c6645a357b9..0a1381a84552 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
@@ -149,7 +149,7 @@ nv50_disp_dmac_new_(const struct nv50_disp_dmac_func *func,
149 chan->func = func; 149 chan->func = func;
150 150
151 ret = nv50_disp_chan_ctor(&nv50_disp_dmac_func_, mthd, root, 151 ret = nv50_disp_chan_ctor(&nv50_disp_dmac_func_, mthd, root,
152 chid, head, oclass, &chan->base); 152 chid, chid, head, oclass, &chan->base);
153 if (ret) 153 if (ret)
154 return ret; 154 return ret;
155 155
@@ -179,9 +179,9 @@ nv50_disp_dmac_bind(struct nv50_disp_dmac *chan,
179 struct nvkm_object *object, u32 handle) 179 struct nvkm_object *object, u32 handle)
180{ 180{
181 return nvkm_ramht_insert(chan->base.root->ramht, object, 181 return nvkm_ramht_insert(chan->base.root->ramht, object,
182 chan->base.chid, -10, handle, 182 chan->base.chid.user, -10, handle,
183 chan->base.chid << 28 | 183 chan->base.chid.user << 28 |
184 chan->base.chid); 184 chan->base.chid.user);
185} 185}
186 186
187static void 187static void
@@ -190,21 +190,22 @@ nv50_disp_dmac_fini(struct nv50_disp_dmac *chan)
190 struct nv50_disp *disp = chan->base.root->disp; 190 struct nv50_disp *disp = chan->base.root->disp;
191 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 191 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
192 struct nvkm_device *device = subdev->device; 192 struct nvkm_device *device = subdev->device;
193 int chid = chan->base.chid; 193 int ctrl = chan->base.chid.ctrl;
194 int user = chan->base.chid.user;
194 195
195 /* deactivate channel */ 196 /* deactivate channel */
196 nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000); 197 nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000);
197 nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000); 198 nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000);
198 if (nvkm_msec(device, 2000, 199 if (nvkm_msec(device, 2000,
199 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x001e0000)) 200 if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000))
200 break; 201 break;
201 ) < 0) { 202 ) < 0) {
202 nvkm_error(subdev, "ch %d fini timeout, %08x\n", chid, 203 nvkm_error(subdev, "ch %d fini timeout, %08x\n", user,
203 nvkm_rd32(device, 0x610200 + (chid * 0x10))); 204 nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
204 } 205 }
205 206
206 /* disable error reporting and completion notifications */ 207 /* disable error reporting and completion notifications */
207 nvkm_mask(device, 0x610028, 0x00010001 << chid, 0x00000000 << chid); 208 nvkm_mask(device, 0x610028, 0x00010001 << user, 0x00000000 << user);
208} 209}
209 210
210static int 211static int
@@ -213,26 +214,27 @@ nv50_disp_dmac_init(struct nv50_disp_dmac *chan)
213 struct nv50_disp *disp = chan->base.root->disp; 214 struct nv50_disp *disp = chan->base.root->disp;
214 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 215 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
215 struct nvkm_device *device = subdev->device; 216 struct nvkm_device *device = subdev->device;
216 int chid = chan->base.chid; 217 int ctrl = chan->base.chid.ctrl;
218 int user = chan->base.chid.user;
217 219
218 /* enable error reporting */ 220 /* enable error reporting */
219 nvkm_mask(device, 0x610028, 0x00010000 << chid, 0x00010000 << chid); 221 nvkm_mask(device, 0x610028, 0x00010000 << user, 0x00010000 << user);
220 222
221 /* initialise channel for dma command submission */ 223 /* initialise channel for dma command submission */
222 nvkm_wr32(device, 0x610204 + (chid * 0x0010), chan->push); 224 nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push);
223 nvkm_wr32(device, 0x610208 + (chid * 0x0010), 0x00010000); 225 nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000);
224 nvkm_wr32(device, 0x61020c + (chid * 0x0010), chid); 226 nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl);
225 nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010); 227 nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010);
226 nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000); 228 nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
227 nvkm_wr32(device, 0x610200 + (chid * 0x0010), 0x00000013); 229 nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013);
228 230
229 /* wait for it to go inactive */ 231 /* wait for it to go inactive */
230 if (nvkm_msec(device, 2000, 232 if (nvkm_msec(device, 2000,
231 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x80000000)) 233 if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000))
232 break; 234 break;
233 ) < 0) { 235 ) < 0) {
234 nvkm_error(subdev, "ch %d init timeout, %08x\n", chid, 236 nvkm_error(subdev, "ch %d init timeout, %08x\n", user,
235 nvkm_rd32(device, 0x610200 + (chid * 0x10))); 237 nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
236 return -EBUSY; 238 return -EBUSY;
237 } 239 }
238 240
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
index 43ac05857853..ea4a0d062e31 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
@@ -30,7 +30,7 @@ int gf119_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32);
30extern const struct nv50_disp_dmac_func gf119_disp_core_func; 30extern const struct nv50_disp_dmac_func gf119_disp_core_func;
31void gf119_disp_core_fini(struct nv50_disp_dmac *); 31void gf119_disp_core_fini(struct nv50_disp_dmac *);
32 32
33extern const struct nv50_disp_dmac_func gp104_disp_dmac_func; 33extern const struct nv50_disp_dmac_func gp102_disp_dmac_func;
34 34
35struct nv50_disp_dmac_oclass { 35struct nv50_disp_dmac_oclass {
36 int (*ctor)(const struct nv50_disp_dmac_func *, 36 int (*ctor)(const struct nv50_disp_dmac_func *,
@@ -95,7 +95,7 @@ extern const struct nv50_disp_dmac_oclass gm200_disp_core_oclass;
95 95
96extern const struct nv50_disp_dmac_oclass gp100_disp_core_oclass; 96extern const struct nv50_disp_dmac_oclass gp100_disp_core_oclass;
97 97
98extern const struct nv50_disp_dmac_oclass gp104_disp_core_oclass; 98extern const struct nv50_disp_dmac_oclass gp102_disp_core_oclass;
99extern const struct nv50_disp_dmac_oclass gp104_disp_base_oclass; 99extern const struct nv50_disp_dmac_oclass gp102_disp_base_oclass;
100extern const struct nv50_disp_dmac_oclass gp104_disp_ovly_oclass; 100extern const struct nv50_disp_dmac_oclass gp102_disp_ovly_oclass;
101#endif 101#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
index 3bf3380336e4..f5d613f82709 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
@@ -25,7 +25,7 @@
25#include "rootnv50.h" 25#include "rootnv50.h"
26 26
27static void 27static void
28gp104_disp_intr_error(struct nv50_disp *disp, int chid) 28gp102_disp_intr_error(struct nv50_disp *disp, int chid)
29{ 29{
30 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 30 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
31 struct nvkm_device *device = subdev->device; 31 struct nvkm_device *device = subdev->device;
@@ -51,12 +51,12 @@ gp104_disp_intr_error(struct nv50_disp *disp, int chid)
51} 51}
52 52
53static const struct nv50_disp_func 53static const struct nv50_disp_func
54gp104_disp = { 54gp102_disp = {
55 .intr = gf119_disp_intr, 55 .intr = gf119_disp_intr,
56 .intr_error = gp104_disp_intr_error, 56 .intr_error = gp102_disp_intr_error,
57 .uevent = &gf119_disp_chan_uevent, 57 .uevent = &gf119_disp_chan_uevent,
58 .super = gf119_disp_intr_supervisor, 58 .super = gf119_disp_intr_supervisor,
59 .root = &gp104_disp_root_oclass, 59 .root = &gp102_disp_root_oclass,
60 .head.vblank_init = gf119_disp_vblank_init, 60 .head.vblank_init = gf119_disp_vblank_init,
61 .head.vblank_fini = gf119_disp_vblank_fini, 61 .head.vblank_fini = gf119_disp_vblank_fini,
62 .head.scanoutpos = gf119_disp_root_scanoutpos, 62 .head.scanoutpos = gf119_disp_root_scanoutpos,
@@ -75,7 +75,7 @@ gp104_disp = {
75}; 75};
76 76
77int 77int
78gp104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) 78gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
79{ 79{
80 return gf119_disp_new_(&gp104_disp, device, index, pdisp); 80 return gf119_disp_new_(&gp102_disp, device, index, pdisp);
81} 81}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
index 54a4ae8d66c6..5ad5d0f5db05 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
@@ -33,5 +33,5 @@ g84_disp_oimm_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_oimm_new, 34 .ctor = nv50_disp_oimm_new,
35 .func = &nv50_disp_pioc_func, 35 .func = &nv50_disp_pioc_func,
36 .chid = 5, 36 .chid = { 5, 5 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
index c658db54afc5..1f9fd3403f07 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
@@ -33,5 +33,5 @@ gf119_disp_oimm_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_oimm_new, 34 .ctor = nv50_disp_oimm_new,
35 .func = &gf119_disp_pioc_func, 35 .func = &gf119_disp_pioc_func,
36 .chid = 9, 36 .chid = { 9, 9 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
index b1fde8c125d6..0c09fe85e952 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
@@ -33,5 +33,5 @@ gk104_disp_oimm_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_oimm_new, 34 .ctor = nv50_disp_oimm_new,
35 .func = &gf119_disp_pioc_func, 35 .func = &gf119_disp_pioc_func,
36 .chid = 9, 36 .chid = { 9, 9 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c
new file mode 100644
index 000000000000..abf82365c671
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c
@@ -0,0 +1,37 @@
1/*
2 * Copyright 2016 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#include "channv50.h"
25#include "rootnv50.h"
26
27#include <nvif/class.h>
28
29const struct nv50_disp_pioc_oclass
30gp102_disp_oimm_oclass = {
31 .base.oclass = GK104_DISP_OVERLAY,
32 .base.minver = 0,
33 .base.maxver = 0,
34 .ctor = nv50_disp_oimm_new,
35 .func = &gf119_disp_pioc_func,
36 .chid = { 9, 13 },
37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
index f4e7eb3d1177..1281db28aebd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
@@ -33,5 +33,5 @@ gt215_disp_oimm_oclass = {
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_oimm_new, 34 .ctor = nv50_disp_oimm_new,
35 .func = &nv50_disp_pioc_func, 35 .func = &nv50_disp_pioc_func,
36 .chid = 5, 36 .chid = { 5, 5 },
37}; 37};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
index 3940b9c966ec..07540f3d32dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
@@ -33,7 +33,7 @@
33int 33int
34nv50_disp_oimm_new(const struct nv50_disp_chan_func *func, 34nv50_disp_oimm_new(const struct nv50_disp_chan_func *func,
35 const struct nv50_disp_chan_mthd *mthd, 35 const struct nv50_disp_chan_mthd *mthd,
36 struct nv50_disp_root *root, int chid, 36 struct nv50_disp_root *root, int ctrl, int user,
37 const struct nvkm_oclass *oclass, void *data, u32 size, 37 const struct nvkm_oclass *oclass, void *data, u32 size,
38 struct nvkm_object **pobject) 38 struct nvkm_object **pobject)
39{ 39{
@@ -54,7 +54,7 @@ nv50_disp_oimm_new(const struct nv50_disp_chan_func *func,
54 } else 54 } else
55 return ret; 55 return ret;
56 56
57 return nv50_disp_chan_new_(func, mthd, root, chid + head, 57 return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head,
58 head, oclass, pobject); 58 head, oclass, pobject);
59} 59}
60 60
@@ -65,5 +65,5 @@ nv50_disp_oimm_oclass = {
65 .base.maxver = 0, 65 .base.maxver = 0,
66 .ctor = nv50_disp_oimm_new, 66 .ctor = nv50_disp_oimm_new,
67 .func = &nv50_disp_pioc_func, 67 .func = &nv50_disp_pioc_func,
68 .chid = 5, 68 .chid = { 5, 5 },
69}; 69};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c
index 97e2dd2d908e..589bd2f12b41 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c
@@ -27,12 +27,12 @@
27#include <nvif/class.h> 27#include <nvif/class.h>
28 28
29const struct nv50_disp_dmac_oclass 29const struct nv50_disp_dmac_oclass
30gp104_disp_ovly_oclass = { 30gp102_disp_ovly_oclass = {
31 .base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA, 31 .base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA,
32 .base.minver = 0, 32 .base.minver = 0,
33 .base.maxver = 0, 33 .base.maxver = 0,
34 .ctor = nv50_disp_ovly_new, 34 .ctor = nv50_disp_ovly_new,
35 .func = &gp104_disp_dmac_func, 35 .func = &gp102_disp_dmac_func,
36 .mthd = &gk104_disp_ovly_chan_mthd, 36 .mthd = &gk104_disp_ovly_chan_mthd,
37 .chid = 5, 37 .chid = 5,
38}; 38};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
index a625a9876e34..0abaa6431943 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
@@ -32,20 +32,21 @@ gf119_disp_pioc_fini(struct nv50_disp_chan *chan)
32 struct nv50_disp *disp = chan->root->disp; 32 struct nv50_disp *disp = chan->root->disp;
33 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 33 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
34 struct nvkm_device *device = subdev->device; 34 struct nvkm_device *device = subdev->device;
35 int chid = chan->chid; 35 int ctrl = chan->chid.ctrl;
36 int user = chan->chid.user;
36 37
37 nvkm_mask(device, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000); 38 nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000);
38 if (nvkm_msec(device, 2000, 39 if (nvkm_msec(device, 2000,
39 if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x00030000)) 40 if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000))
40 break; 41 break;
41 ) < 0) { 42 ) < 0) {
42 nvkm_error(subdev, "ch %d fini: %08x\n", chid, 43 nvkm_error(subdev, "ch %d fini: %08x\n", user,
43 nvkm_rd32(device, 0x610490 + (chid * 0x10))); 44 nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
44 } 45 }
45 46
46 /* disable error reporting and completion notification */ 47 /* disable error reporting and completion notification */
47 nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000); 48 nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
48 nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000); 49 nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
49} 50}
50 51
51static int 52static int
@@ -54,20 +55,21 @@ gf119_disp_pioc_init(struct nv50_disp_chan *chan)
54 struct nv50_disp *disp = chan->root->disp; 55 struct nv50_disp *disp = chan->root->disp;
55 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 56 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
56 struct nvkm_device *device = subdev->device; 57 struct nvkm_device *device = subdev->device;
57 int chid = chan->chid; 58 int ctrl = chan->chid.ctrl;
59 int user = chan->chid.user;
58 60
59 /* enable error reporting */ 61 /* enable error reporting */
60 nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); 62 nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
61 63
62 /* activate channel */ 64 /* activate channel */
63 nvkm_wr32(device, 0x610490 + (chid * 0x10), 0x00000001); 65 nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001);
64 if (nvkm_msec(device, 2000, 66 if (nvkm_msec(device, 2000,
65 u32 tmp = nvkm_rd32(device, 0x610490 + (chid * 0x10)); 67 u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10));
66 if ((tmp & 0x00030000) == 0x00010000) 68 if ((tmp & 0x00030000) == 0x00010000)
67 break; 69 break;
68 ) < 0) { 70 ) < 0) {
69 nvkm_error(subdev, "ch %d init: %08x\n", chid, 71 nvkm_error(subdev, "ch %d init: %08x\n", user,
70 nvkm_rd32(device, 0x610490 + (chid * 0x10))); 72 nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
71 return -EBUSY; 73 return -EBUSY;
72 } 74 }
73 75
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
index 9d2618dacf20..0211e0e8a35f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
@@ -32,15 +32,16 @@ nv50_disp_pioc_fini(struct nv50_disp_chan *chan)
32 struct nv50_disp *disp = chan->root->disp; 32 struct nv50_disp *disp = chan->root->disp;
33 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 33 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
34 struct nvkm_device *device = subdev->device; 34 struct nvkm_device *device = subdev->device;
35 int chid = chan->chid; 35 int ctrl = chan->chid.ctrl;
36 int user = chan->chid.user;
36 37
37 nvkm_mask(device, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000); 38 nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000);
38 if (nvkm_msec(device, 2000, 39 if (nvkm_msec(device, 2000,
39 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000)) 40 if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000))
40 break; 41 break;
41 ) < 0) { 42 ) < 0) {
42 nvkm_error(subdev, "ch %d timeout: %08x\n", chid, 43 nvkm_error(subdev, "ch %d timeout: %08x\n", user,
43 nvkm_rd32(device, 0x610200 + (chid * 0x10))); 44 nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
44 } 45 }
45} 46}
46 47
@@ -50,26 +51,27 @@ nv50_disp_pioc_init(struct nv50_disp_chan *chan)
50 struct nv50_disp *disp = chan->root->disp; 51 struct nv50_disp *disp = chan->root->disp;
51 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 52 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
52 struct nvkm_device *device = subdev->device; 53 struct nvkm_device *device = subdev->device;
53 int chid = chan->chid; 54 int ctrl = chan->chid.ctrl;
55 int user = chan->chid.user;
54 56
55 nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00002000); 57 nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000);
56 if (nvkm_msec(device, 2000, 58 if (nvkm_msec(device, 2000,
57 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000)) 59 if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000))
58 break; 60 break;
59 ) < 0) { 61 ) < 0) {
60 nvkm_error(subdev, "ch %d timeout0: %08x\n", chid, 62 nvkm_error(subdev, "ch %d timeout0: %08x\n", user,
61 nvkm_rd32(device, 0x610200 + (chid * 0x10))); 63 nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
62 return -EBUSY; 64 return -EBUSY;
63 } 65 }
64 66
65 nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00000001); 67 nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001);
66 if (nvkm_msec(device, 2000, 68 if (nvkm_msec(device, 2000,
67 u32 tmp = nvkm_rd32(device, 0x610200 + (chid * 0x10)); 69 u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10));
68 if ((tmp & 0x00030000) == 0x00010000) 70 if ((tmp & 0x00030000) == 0x00010000)
69 break; 71 break;
70 ) < 0) { 72 ) < 0) {
71 nvkm_error(subdev, "ch %d timeout1: %08x\n", chid, 73 nvkm_error(subdev, "ch %d timeout1: %08x\n", user,
72 nvkm_rd32(device, 0x610200 + (chid * 0x10))); 74 nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
73 return -EBUSY; 75 return -EBUSY;
74 } 76 }
75 77
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c
index 8443e04dc626..37122ca579ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c
@@ -27,32 +27,32 @@
27#include <nvif/class.h> 27#include <nvif/class.h>
28 28
29static const struct nv50_disp_root_func 29static const struct nv50_disp_root_func
30gp104_disp_root = { 30gp102_disp_root = {
31 .init = gf119_disp_root_init, 31 .init = gf119_disp_root_init,
32 .fini = gf119_disp_root_fini, 32 .fini = gf119_disp_root_fini,
33 .dmac = { 33 .dmac = {
34 &gp104_disp_core_oclass, 34 &gp102_disp_core_oclass,
35 &gp104_disp_base_oclass, 35 &gp102_disp_base_oclass,
36 &gp104_disp_ovly_oclass, 36 &gp102_disp_ovly_oclass,
37 }, 37 },
38 .pioc = { 38 .pioc = {
39 &gk104_disp_oimm_oclass, 39 &gp102_disp_oimm_oclass,
40 &gk104_disp_curs_oclass, 40 &gp102_disp_curs_oclass,
41 }, 41 },
42}; 42};
43 43
44static int 44static int
45gp104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, 45gp102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
46 void *data, u32 size, struct nvkm_object **pobject) 46 void *data, u32 size, struct nvkm_object **pobject)
47{ 47{
48 return nv50_disp_root_new_(&gp104_disp_root, disp, oclass, 48 return nv50_disp_root_new_(&gp102_disp_root, disp, oclass,
49 data, size, pobject); 49 data, size, pobject);
50} 50}
51 51
52const struct nvkm_disp_oclass 52const struct nvkm_disp_oclass
53gp104_disp_root_oclass = { 53gp102_disp_root_oclass = {
54 .base.oclass = GP104_DISP, 54 .base.oclass = GP102_DISP,
55 .base.minver = -1, 55 .base.minver = -1,
56 .base.maxver = -1, 56 .base.maxver = -1,
57 .ctor = gp104_disp_root_new, 57 .ctor = gp102_disp_root_new,
58}; 58};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index c1158b22a721..e70dc6a9ff7d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -250,8 +250,8 @@ nv50_disp_root_pioc_new_(const struct nvkm_oclass *oclass,
250{ 250{
251 const struct nv50_disp_pioc_oclass *sclass = oclass->priv; 251 const struct nv50_disp_pioc_oclass *sclass = oclass->priv;
252 struct nv50_disp_root *root = nv50_disp_root(oclass->parent); 252 struct nv50_disp_root *root = nv50_disp_root(oclass->parent);
253 return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid, 253 return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid.ctrl,
254 oclass, data, size, pobject); 254 sclass->chid.user, oclass, data, size, pobject);
255} 255}
256 256
257static int 257static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
index ad00f1724b72..b147cf5b3518 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
@@ -41,5 +41,5 @@ extern const struct nvkm_disp_oclass gk110_disp_root_oclass;
41extern const struct nvkm_disp_oclass gm107_disp_root_oclass; 41extern const struct nvkm_disp_oclass gm107_disp_root_oclass;
42extern const struct nvkm_disp_oclass gm200_disp_root_oclass; 42extern const struct nvkm_disp_oclass gm200_disp_root_oclass;
43extern const struct nvkm_disp_oclass gp100_disp_root_oclass; 43extern const struct nvkm_disp_oclass gp100_disp_root_oclass;
44extern const struct nvkm_disp_oclass gp104_disp_root_oclass; 44extern const struct nvkm_disp_oclass gp102_disp_root_oclass;
45#endif 45#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
index a410c0db8a08..42d94731655a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
@@ -26,6 +26,7 @@
26#include <subdev/bios.h> 26#include <subdev/bios.h>
27#include <subdev/bios/bit.h> 27#include <subdev/bios/bit.h>
28#include <subdev/bios/pmu.h> 28#include <subdev/bios/pmu.h>
29#include <subdev/timer.h>
29 30
30static void 31static void
31pmu_code(struct nv50_devinit *init, u32 pmu, u32 img, u32 len, bool sec) 32pmu_code(struct nv50_devinit *init, u32 pmu, u32 img, u32 len, bool sec)
@@ -123,15 +124,6 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
123 return -EINVAL; 124 return -EINVAL;
124 } 125 }
125 126
126 /* reset PMU and load init table parser ucode */
127 if (post) {
128 nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
129 nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
130 nvkm_rd32(device, 0x000200);
131 while (nvkm_rd32(device, 0x10a10c) & 0x00000006) {
132 }
133 }
134
135 ret = pmu_load(init, 0x04, post, &exec, &args); 127 ret = pmu_load(init, 0x04, post, &exec, &args);
136 if (ret) 128 if (ret)
137 return ret; 129 return ret;
@@ -156,8 +148,11 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
156 if (post) { 148 if (post) {
157 nvkm_wr32(device, 0x10a040, 0x00005000); 149 nvkm_wr32(device, 0x10a040, 0x00005000);
158 pmu_exec(init, exec); 150 pmu_exec(init, exec);
159 while (!(nvkm_rd32(device, 0x10a040) & 0x00002000)) { 151 if (nvkm_msec(device, 2000,
160 } 152 if (nvkm_rd32(device, 0x10a040) & 0x00002000)
153 break;
154 ) < 0)
155 return -ETIMEDOUT;
161 } 156 }
162 157
163 /* load and execute some other ucode image (bios therm?) */ 158 /* load and execute some other ucode image (bios therm?) */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
index ef47d57fcb87..63566ba12fbb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
@@ -26,7 +26,7 @@ nvkm-y += nvkm/subdev/fb/gm107.o
26nvkm-y += nvkm/subdev/fb/gm200.o 26nvkm-y += nvkm/subdev/fb/gm200.o
27nvkm-y += nvkm/subdev/fb/gm20b.o 27nvkm-y += nvkm/subdev/fb/gm20b.o
28nvkm-y += nvkm/subdev/fb/gp100.o 28nvkm-y += nvkm/subdev/fb/gp100.o
29nvkm-y += nvkm/subdev/fb/gp104.o 29nvkm-y += nvkm/subdev/fb/gp102.o
30 30
31nvkm-y += nvkm/subdev/fb/ram.o 31nvkm-y += nvkm/subdev/fb/ram.o
32nvkm-y += nvkm/subdev/fb/ramnv04.o 32nvkm-y += nvkm/subdev/fb/ramnv04.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
index 92cb71861bec..73b4ae1c73dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
@@ -27,7 +27,7 @@
27#include <core/memory.h> 27#include <core/memory.h>
28 28
29static const struct nvkm_fb_func 29static const struct nvkm_fb_func
30gp104_fb = { 30gp102_fb = {
31 .dtor = gf100_fb_dtor, 31 .dtor = gf100_fb_dtor,
32 .oneinit = gf100_fb_oneinit, 32 .oneinit = gf100_fb_oneinit,
33 .init = gp100_fb_init, 33 .init = gp100_fb_init,
@@ -37,7 +37,7 @@ gp104_fb = {
37}; 37};
38 38
39int 39int
40gp104_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) 40gp102_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
41{ 41{
42 return gf100_fb_new_(&gp104_fb, device, index, pfb); 42 return gf100_fb_new_(&gp102_fb, device, index, pfb);
43} 43}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
index 88b643b8664e..51fb4bf94a44 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
@@ -8,3 +8,5 @@ nvkm-y += nvkm/subdev/pmu/gk110.o
8nvkm-y += nvkm/subdev/pmu/gk208.o 8nvkm-y += nvkm/subdev/pmu/gk208.o
9nvkm-y += nvkm/subdev/pmu/gk20a.o 9nvkm-y += nvkm/subdev/pmu/gk20a.o
10nvkm-y += nvkm/subdev/pmu/gm107.o 10nvkm-y += nvkm/subdev/pmu/gm107.o
11nvkm-y += nvkm/subdev/pmu/gp100.o
12nvkm-y += nvkm/subdev/pmu/gp102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index 8dd164d13043..e611ce80f8ef 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -32,225 +32,85 @@ nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
32 pmu->func->pgob(pmu, enable); 32 pmu->func->pgob(pmu, enable);
33} 33}
34 34
35int
36nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
37 u32 process, u32 message, u32 data0, u32 data1)
38{
39 struct nvkm_subdev *subdev = &pmu->subdev;
40 struct nvkm_device *device = subdev->device;
41 u32 addr;
42
43 mutex_lock(&subdev->mutex);
44 /* wait for a free slot in the fifo */
45 addr = nvkm_rd32(device, 0x10a4a0);
46 if (nvkm_msec(device, 2000,
47 u32 tmp = nvkm_rd32(device, 0x10a4b0);
48 if (tmp != (addr ^ 8))
49 break;
50 ) < 0) {
51 mutex_unlock(&subdev->mutex);
52 return -EBUSY;
53 }
54
55 /* we currently only support a single process at a time waiting
56 * on a synchronous reply, take the PMU mutex and tell the
57 * receive handler what we're waiting for
58 */
59 if (reply) {
60 pmu->recv.message = message;
61 pmu->recv.process = process;
62 }
63
64 /* acquire data segment access */
65 do {
66 nvkm_wr32(device, 0x10a580, 0x00000001);
67 } while (nvkm_rd32(device, 0x10a580) != 0x00000001);
68
69 /* write the packet */
70 nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
71 pmu->send.base));
72 nvkm_wr32(device, 0x10a1c4, process);
73 nvkm_wr32(device, 0x10a1c4, message);
74 nvkm_wr32(device, 0x10a1c4, data0);
75 nvkm_wr32(device, 0x10a1c4, data1);
76 nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f);
77
78 /* release data segment access */
79 nvkm_wr32(device, 0x10a580, 0x00000000);
80
81 /* wait for reply, if requested */
82 if (reply) {
83 wait_event(pmu->recv.wait, (pmu->recv.process == 0));
84 reply[0] = pmu->recv.data[0];
85 reply[1] = pmu->recv.data[1];
86 }
87
88 mutex_unlock(&subdev->mutex);
89 return 0;
90}
91
92static void 35static void
93nvkm_pmu_recv(struct work_struct *work) 36nvkm_pmu_recv(struct work_struct *work)
94{ 37{
95 struct nvkm_pmu *pmu = container_of(work, struct nvkm_pmu, recv.work); 38 struct nvkm_pmu *pmu = container_of(work, typeof(*pmu), recv.work);
96 struct nvkm_subdev *subdev = &pmu->subdev; 39 return pmu->func->recv(pmu);
97 struct nvkm_device *device = subdev->device; 40}
98 u32 process, message, data0, data1;
99
100 /* nothing to do if GET == PUT */
101 u32 addr = nvkm_rd32(device, 0x10a4cc);
102 if (addr == nvkm_rd32(device, 0x10a4c8))
103 return;
104
105 /* acquire data segment access */
106 do {
107 nvkm_wr32(device, 0x10a580, 0x00000002);
108 } while (nvkm_rd32(device, 0x10a580) != 0x00000002);
109
110 /* read the packet */
111 nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
112 pmu->recv.base));
113 process = nvkm_rd32(device, 0x10a1c4);
114 message = nvkm_rd32(device, 0x10a1c4);
115 data0 = nvkm_rd32(device, 0x10a1c4);
116 data1 = nvkm_rd32(device, 0x10a1c4);
117 nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f);
118
119 /* release data segment access */
120 nvkm_wr32(device, 0x10a580, 0x00000000);
121
122 /* wake process if it's waiting on a synchronous reply */
123 if (pmu->recv.process) {
124 if (process == pmu->recv.process &&
125 message == pmu->recv.message) {
126 pmu->recv.data[0] = data0;
127 pmu->recv.data[1] = data1;
128 pmu->recv.process = 0;
129 wake_up(&pmu->recv.wait);
130 return;
131 }
132 }
133 41
134 /* right now there's no other expected responses from the engine, 42int
135 * so assume that any unexpected message is an error. 43nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
136 */ 44 u32 process, u32 message, u32 data0, u32 data1)
137 nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n", 45{
138 (char)((process & 0x000000ff) >> 0), 46 if (!pmu || !pmu->func->send)
139 (char)((process & 0x0000ff00) >> 8), 47 return -ENODEV;
140 (char)((process & 0x00ff0000) >> 16), 48 return pmu->func->send(pmu, reply, process, message, data0, data1);
141 (char)((process & 0xff000000) >> 24),
142 process, message, data0, data1);
143} 49}
144 50
145static void 51static void
146nvkm_pmu_intr(struct nvkm_subdev *subdev) 52nvkm_pmu_intr(struct nvkm_subdev *subdev)
147{ 53{
148 struct nvkm_pmu *pmu = nvkm_pmu(subdev); 54 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
149 struct nvkm_device *device = pmu->subdev.device; 55 if (!pmu->func->intr)
150 u32 disp = nvkm_rd32(device, 0x10a01c); 56 return;
151 u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16); 57 pmu->func->intr(pmu);
152
153 if (intr & 0x00000020) {
154 u32 stat = nvkm_rd32(device, 0x10a16c);
155 if (stat & 0x80000000) {
156 nvkm_error(subdev, "UAS fault at %06x addr %08x\n",
157 stat & 0x00ffffff,
158 nvkm_rd32(device, 0x10a168));
159 nvkm_wr32(device, 0x10a16c, 0x00000000);
160 intr &= ~0x00000020;
161 }
162 }
163
164 if (intr & 0x00000040) {
165 schedule_work(&pmu->recv.work);
166 nvkm_wr32(device, 0x10a004, 0x00000040);
167 intr &= ~0x00000040;
168 }
169
170 if (intr & 0x00000080) {
171 nvkm_info(subdev, "wr32 %06x %08x\n",
172 nvkm_rd32(device, 0x10a7a0),
173 nvkm_rd32(device, 0x10a7a4));
174 nvkm_wr32(device, 0x10a004, 0x00000080);
175 intr &= ~0x00000080;
176 }
177
178 if (intr) {
179 nvkm_error(subdev, "intr %08x\n", intr);
180 nvkm_wr32(device, 0x10a004, intr);
181 }
182} 58}
183 59
184static int 60static int
185nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) 61nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
186{ 62{
187 struct nvkm_pmu *pmu = nvkm_pmu(subdev); 63 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
188 struct nvkm_device *device = pmu->subdev.device;
189 64
190 nvkm_wr32(device, 0x10a014, 0x00000060); 65 if (pmu->func->fini)
66 pmu->func->fini(pmu);
67
191 flush_work(&pmu->recv.work); 68 flush_work(&pmu->recv.work);
192 return 0; 69 return 0;
193} 70}
194 71
195static int 72static int
196nvkm_pmu_init(struct nvkm_subdev *subdev) 73nvkm_pmu_reset(struct nvkm_pmu *pmu)
197{ 74{
198 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
199 struct nvkm_device *device = pmu->subdev.device; 75 struct nvkm_device *device = pmu->subdev.device;
200 int i;
201 76
202 /* prevent previous ucode from running, wait for idle, reset */ 77 if (!(nvkm_rd32(device, 0x000200) & 0x00002000))
203 nvkm_wr32(device, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */ 78 return 0;
79
80 /* Inhibit interrupts, and wait for idle. */
81 nvkm_wr32(device, 0x10a014, 0x0000ffff);
204 nvkm_msec(device, 2000, 82 nvkm_msec(device, 2000,
205 if (!nvkm_rd32(device, 0x10a04c)) 83 if (!nvkm_rd32(device, 0x10a04c))
206 break; 84 break;
207 ); 85 );
208 nvkm_mask(device, 0x000200, 0x00002000, 0x00000000); 86
209 nvkm_mask(device, 0x000200, 0x00002000, 0x00002000); 87 /* Reset. */
210 nvkm_rd32(device, 0x000200); 88 pmu->func->reset(pmu);
89
90 /* Wait for IMEM/DMEM scrubbing to be complete. */
211 nvkm_msec(device, 2000, 91 nvkm_msec(device, 2000,
212 if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) 92 if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
213 break; 93 break;
214 ); 94 );
215 95
216 /* upload data segment */ 96 return 0;
217 nvkm_wr32(device, 0x10a1c0, 0x01000000); 97}
218 for (i = 0; i < pmu->func->data.size / 4; i++)
219 nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]);
220
221 /* upload code segment */
222 nvkm_wr32(device, 0x10a180, 0x01000000);
223 for (i = 0; i < pmu->func->code.size / 4; i++) {
224 if ((i & 0x3f) == 0)
225 nvkm_wr32(device, 0x10a188, i >> 6);
226 nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]);
227 }
228
229 /* start it running */
230 nvkm_wr32(device, 0x10a10c, 0x00000000);
231 nvkm_wr32(device, 0x10a104, 0x00000000);
232 nvkm_wr32(device, 0x10a100, 0x00000002);
233
234 /* wait for valid host->pmu ring configuration */
235 if (nvkm_msec(device, 2000,
236 if (nvkm_rd32(device, 0x10a4d0))
237 break;
238 ) < 0)
239 return -EBUSY;
240 pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff;
241 pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16;
242 98
243 /* wait for valid pmu->host ring configuration */ 99static int
244 if (nvkm_msec(device, 2000, 100nvkm_pmu_preinit(struct nvkm_subdev *subdev)
245 if (nvkm_rd32(device, 0x10a4dc)) 101{
246 break; 102 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
247 ) < 0) 103 return nvkm_pmu_reset(pmu);
248 return -EBUSY; 104}
249 pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff;
250 pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16;
251 105
252 nvkm_wr32(device, 0x10a010, 0x000000e0); 106static int
253 return 0; 107nvkm_pmu_init(struct nvkm_subdev *subdev)
108{
109 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
110 int ret = nvkm_pmu_reset(pmu);
111 if (ret == 0 && pmu->func->init)
112 ret = pmu->func->init(pmu);
113 return ret;
254} 114}
255 115
256static void * 116static void *
@@ -262,6 +122,7 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev)
262static const struct nvkm_subdev_func 122static const struct nvkm_subdev_func
263nvkm_pmu = { 123nvkm_pmu = {
264 .dtor = nvkm_pmu_dtor, 124 .dtor = nvkm_pmu_dtor,
125 .preinit = nvkm_pmu_preinit,
265 .init = nvkm_pmu_init, 126 .init = nvkm_pmu_init,
266 .fini = nvkm_pmu_fini, 127 .fini = nvkm_pmu_fini,
267 .intr = nvkm_pmu_intr, 128 .intr = nvkm_pmu_intr,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
index aeb8ccd891fc..0e36d4cb7201 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
@@ -30,6 +30,12 @@ gf100_pmu = {
30 .code.size = sizeof(gf100_pmu_code), 30 .code.size = sizeof(gf100_pmu_code),
31 .data.data = gf100_pmu_data, 31 .data.data = gf100_pmu_data,
32 .data.size = sizeof(gf100_pmu_data), 32 .data.size = sizeof(gf100_pmu_data),
33 .reset = gt215_pmu_reset,
34 .init = gt215_pmu_init,
35 .fini = gt215_pmu_fini,
36 .intr = gt215_pmu_intr,
37 .send = gt215_pmu_send,
38 .recv = gt215_pmu_recv,
33}; 39};
34 40
35int 41int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
index fbc88d8ecd4d..0e4ba4248b15 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
@@ -30,6 +30,12 @@ gf119_pmu = {
30 .code.size = sizeof(gf119_pmu_code), 30 .code.size = sizeof(gf119_pmu_code),
31 .data.data = gf119_pmu_data, 31 .data.data = gf119_pmu_data,
32 .data.size = sizeof(gf119_pmu_data), 32 .data.size = sizeof(gf119_pmu_data),
33 .reset = gt215_pmu_reset,
34 .init = gt215_pmu_init,
35 .fini = gt215_pmu_fini,
36 .intr = gt215_pmu_intr,
37 .send = gt215_pmu_send,
38 .recv = gt215_pmu_recv,
33}; 39};
34 40
35int 41int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
index 86f9f3b13f71..2ad858d825ac 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
@@ -109,6 +109,12 @@ gk104_pmu = {
109 .code.size = sizeof(gk104_pmu_code), 109 .code.size = sizeof(gk104_pmu_code),
110 .data.data = gk104_pmu_data, 110 .data.data = gk104_pmu_data,
111 .data.size = sizeof(gk104_pmu_data), 111 .data.size = sizeof(gk104_pmu_data),
112 .reset = gt215_pmu_reset,
113 .init = gt215_pmu_init,
114 .fini = gt215_pmu_fini,
115 .intr = gt215_pmu_intr,
116 .send = gt215_pmu_send,
117 .recv = gt215_pmu_recv,
112 .pgob = gk104_pmu_pgob, 118 .pgob = gk104_pmu_pgob,
113}; 119};
114 120
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
index ae255247c9d1..fc4b8ecfdaeb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
@@ -88,6 +88,12 @@ gk110_pmu = {
88 .code.size = sizeof(gk110_pmu_code), 88 .code.size = sizeof(gk110_pmu_code),
89 .data.data = gk110_pmu_data, 89 .data.data = gk110_pmu_data,
90 .data.size = sizeof(gk110_pmu_data), 90 .data.size = sizeof(gk110_pmu_data),
91 .reset = gt215_pmu_reset,
92 .init = gt215_pmu_init,
93 .fini = gt215_pmu_fini,
94 .intr = gt215_pmu_intr,
95 .send = gt215_pmu_send,
96 .recv = gt215_pmu_recv,
91 .pgob = gk110_pmu_pgob, 97 .pgob = gk110_pmu_pgob,
92}; 98};
93 99
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
index 3b4917637902..e9a91277683a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
@@ -30,6 +30,12 @@ gk208_pmu = {
30 .code.size = sizeof(gk208_pmu_code), 30 .code.size = sizeof(gk208_pmu_code),
31 .data.data = gk208_pmu_data, 31 .data.data = gk208_pmu_data,
32 .data.size = sizeof(gk208_pmu_data), 32 .data.size = sizeof(gk208_pmu_data),
33 .reset = gt215_pmu_reset,
34 .init = gt215_pmu_init,
35 .fini = gt215_pmu_fini,
36 .intr = gt215_pmu_intr,
37 .send = gt215_pmu_send,
38 .recv = gt215_pmu_recv,
33 .pgob = gk110_pmu_pgob, 39 .pgob = gk110_pmu_pgob,
34}; 40};
35 41
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
index 31b8692b4641..9a248ed75f09 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
@@ -32,6 +32,12 @@ gm107_pmu = {
32 .code.size = sizeof(gm107_pmu_code), 32 .code.size = sizeof(gm107_pmu_code),
33 .data.data = gm107_pmu_data, 33 .data.data = gm107_pmu_data,
34 .data.size = sizeof(gm107_pmu_data), 34 .data.size = sizeof(gm107_pmu_data),
35 .reset = gt215_pmu_reset,
36 .init = gt215_pmu_init,
37 .fini = gt215_pmu_fini,
38 .intr = gt215_pmu_intr,
39 .send = gt215_pmu_send,
40 .recv = gt215_pmu_recv,
35}; 41};
36 42
37int 43int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c
new file mode 100644
index 000000000000..6c41c20c85a7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c
@@ -0,0 +1,35 @@
1/*
2 * Copyright 2016 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#include "priv.h"
25
26static const struct nvkm_pmu_func
27gp100_pmu = {
28 .reset = gt215_pmu_reset,
29};
30
31int
32gp100_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu)
33{
34 return nvkm_pmu_new_(&gp100_pmu, device, index, ppmu);
35}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
new file mode 100644
index 000000000000..f017352206c9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
@@ -0,0 +1,43 @@
1/*
2 * Copyright 2016 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#include "priv.h"
25
26static void
27gp102_pmu_reset(struct nvkm_pmu *pmu)
28{
29 struct nvkm_device *device = pmu->subdev.device;
30 nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000001);
31 nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000);
32}
33
34static const struct nvkm_pmu_func
35gp102_pmu = {
36 .reset = gp102_pmu_reset,
37};
38
39int
40gp102_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu)
41{
42 return nvkm_pmu_new_(&gp102_pmu, device, index, ppmu);
43}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
index dcf9eaf274aa..90d428b3be97 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
@@ -24,12 +24,229 @@
24#include "priv.h" 24#include "priv.h"
25#include "fuc/gt215.fuc3.h" 25#include "fuc/gt215.fuc3.h"
26 26
27#include <subdev/timer.h>
28
29int
30gt215_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
31 u32 process, u32 message, u32 data0, u32 data1)
32{
33 struct nvkm_subdev *subdev = &pmu->subdev;
34 struct nvkm_device *device = subdev->device;
35 u32 addr;
36
37 mutex_lock(&subdev->mutex);
38 /* wait for a free slot in the fifo */
39 addr = nvkm_rd32(device, 0x10a4a0);
40 if (nvkm_msec(device, 2000,
41 u32 tmp = nvkm_rd32(device, 0x10a4b0);
42 if (tmp != (addr ^ 8))
43 break;
44 ) < 0) {
45 mutex_unlock(&subdev->mutex);
46 return -EBUSY;
47 }
48
49 /* we currently only support a single process at a time waiting
50 * on a synchronous reply, take the PMU mutex and tell the
51 * receive handler what we're waiting for
52 */
53 if (reply) {
54 pmu->recv.message = message;
55 pmu->recv.process = process;
56 }
57
58 /* acquire data segment access */
59 do {
60 nvkm_wr32(device, 0x10a580, 0x00000001);
61 } while (nvkm_rd32(device, 0x10a580) != 0x00000001);
62
63 /* write the packet */
64 nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
65 pmu->send.base));
66 nvkm_wr32(device, 0x10a1c4, process);
67 nvkm_wr32(device, 0x10a1c4, message);
68 nvkm_wr32(device, 0x10a1c4, data0);
69 nvkm_wr32(device, 0x10a1c4, data1);
70 nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f);
71
72 /* release data segment access */
73 nvkm_wr32(device, 0x10a580, 0x00000000);
74
75 /* wait for reply, if requested */
76 if (reply) {
77 wait_event(pmu->recv.wait, (pmu->recv.process == 0));
78 reply[0] = pmu->recv.data[0];
79 reply[1] = pmu->recv.data[1];
80 }
81
82 mutex_unlock(&subdev->mutex);
83 return 0;
84}
85
86void
87gt215_pmu_recv(struct nvkm_pmu *pmu)
88{
89 struct nvkm_subdev *subdev = &pmu->subdev;
90 struct nvkm_device *device = subdev->device;
91 u32 process, message, data0, data1;
92
93 /* nothing to do if GET == PUT */
94 u32 addr = nvkm_rd32(device, 0x10a4cc);
95 if (addr == nvkm_rd32(device, 0x10a4c8))
96 return;
97
98 /* acquire data segment access */
99 do {
100 nvkm_wr32(device, 0x10a580, 0x00000002);
101 } while (nvkm_rd32(device, 0x10a580) != 0x00000002);
102
103 /* read the packet */
104 nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
105 pmu->recv.base));
106 process = nvkm_rd32(device, 0x10a1c4);
107 message = nvkm_rd32(device, 0x10a1c4);
108 data0 = nvkm_rd32(device, 0x10a1c4);
109 data1 = nvkm_rd32(device, 0x10a1c4);
110 nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f);
111
112 /* release data segment access */
113 nvkm_wr32(device, 0x10a580, 0x00000000);
114
115 /* wake process if it's waiting on a synchronous reply */
116 if (pmu->recv.process) {
117 if (process == pmu->recv.process &&
118 message == pmu->recv.message) {
119 pmu->recv.data[0] = data0;
120 pmu->recv.data[1] = data1;
121 pmu->recv.process = 0;
122 wake_up(&pmu->recv.wait);
123 return;
124 }
125 }
126
127 /* right now there's no other expected responses from the engine,
128 * so assume that any unexpected message is an error.
129 */
130 nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n",
131 (char)((process & 0x000000ff) >> 0),
132 (char)((process & 0x0000ff00) >> 8),
133 (char)((process & 0x00ff0000) >> 16),
134 (char)((process & 0xff000000) >> 24),
135 process, message, data0, data1);
136}
137
138void
139gt215_pmu_intr(struct nvkm_pmu *pmu)
140{
141 struct nvkm_subdev *subdev = &pmu->subdev;
142 struct nvkm_device *device = subdev->device;
143 u32 disp = nvkm_rd32(device, 0x10a01c);
144 u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16);
145
146 if (intr & 0x00000020) {
147 u32 stat = nvkm_rd32(device, 0x10a16c);
148 if (stat & 0x80000000) {
149 nvkm_error(subdev, "UAS fault at %06x addr %08x\n",
150 stat & 0x00ffffff,
151 nvkm_rd32(device, 0x10a168));
152 nvkm_wr32(device, 0x10a16c, 0x00000000);
153 intr &= ~0x00000020;
154 }
155 }
156
157 if (intr & 0x00000040) {
158 schedule_work(&pmu->recv.work);
159 nvkm_wr32(device, 0x10a004, 0x00000040);
160 intr &= ~0x00000040;
161 }
162
163 if (intr & 0x00000080) {
164 nvkm_info(subdev, "wr32 %06x %08x\n",
165 nvkm_rd32(device, 0x10a7a0),
166 nvkm_rd32(device, 0x10a7a4));
167 nvkm_wr32(device, 0x10a004, 0x00000080);
168 intr &= ~0x00000080;
169 }
170
171 if (intr) {
172 nvkm_error(subdev, "intr %08x\n", intr);
173 nvkm_wr32(device, 0x10a004, intr);
174 }
175}
176
177void
178gt215_pmu_fini(struct nvkm_pmu *pmu)
179{
180 nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060);
181}
182
183void
184gt215_pmu_reset(struct nvkm_pmu *pmu)
185{
186 struct nvkm_device *device = pmu->subdev.device;
187 nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
188 nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
189 nvkm_rd32(device, 0x000200);
190}
191
192int
193gt215_pmu_init(struct nvkm_pmu *pmu)
194{
195 struct nvkm_device *device = pmu->subdev.device;
196 int i;
197
198 /* upload data segment */
199 nvkm_wr32(device, 0x10a1c0, 0x01000000);
200 for (i = 0; i < pmu->func->data.size / 4; i++)
201 nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]);
202
203 /* upload code segment */
204 nvkm_wr32(device, 0x10a180, 0x01000000);
205 for (i = 0; i < pmu->func->code.size / 4; i++) {
206 if ((i & 0x3f) == 0)
207 nvkm_wr32(device, 0x10a188, i >> 6);
208 nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]);
209 }
210
211 /* start it running */
212 nvkm_wr32(device, 0x10a10c, 0x00000000);
213 nvkm_wr32(device, 0x10a104, 0x00000000);
214 nvkm_wr32(device, 0x10a100, 0x00000002);
215
216 /* wait for valid host->pmu ring configuration */
217 if (nvkm_msec(device, 2000,
218 if (nvkm_rd32(device, 0x10a4d0))
219 break;
220 ) < 0)
221 return -EBUSY;
222 pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff;
223 pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16;
224
225 /* wait for valid pmu->host ring configuration */
226 if (nvkm_msec(device, 2000,
227 if (nvkm_rd32(device, 0x10a4dc))
228 break;
229 ) < 0)
230 return -EBUSY;
231 pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff;
232 pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16;
233
234 nvkm_wr32(device, 0x10a010, 0x000000e0);
235 return 0;
236}
237
27static const struct nvkm_pmu_func 238static const struct nvkm_pmu_func
28gt215_pmu = { 239gt215_pmu = {
29 .code.data = gt215_pmu_code, 240 .code.data = gt215_pmu_code,
30 .code.size = sizeof(gt215_pmu_code), 241 .code.size = sizeof(gt215_pmu_code),
31 .data.data = gt215_pmu_data, 242 .data.data = gt215_pmu_data,
32 .data.size = sizeof(gt215_pmu_data), 243 .data.size = sizeof(gt215_pmu_data),
244 .reset = gt215_pmu_reset,
245 .init = gt215_pmu_init,
246 .fini = gt215_pmu_fini,
247 .intr = gt215_pmu_intr,
248 .send = gt215_pmu_send,
249 .recv = gt215_pmu_recv,
33}; 250};
34 251
35int 252int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
index 73b811ccc2d5..2e2179a4ad17 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
@@ -18,8 +18,22 @@ struct nvkm_pmu_func {
18 u32 size; 18 u32 size;
19 } data; 19 } data;
20 20
21 void (*reset)(struct nvkm_pmu *);
22 int (*init)(struct nvkm_pmu *);
23 void (*fini)(struct nvkm_pmu *);
24 void (*intr)(struct nvkm_pmu *);
25 int (*send)(struct nvkm_pmu *, u32 reply[2], u32 process,
26 u32 message, u32 data0, u32 data1);
27 void (*recv)(struct nvkm_pmu *);
21 void (*pgob)(struct nvkm_pmu *, bool); 28 void (*pgob)(struct nvkm_pmu *, bool);
22}; 29};
23 30
31void gt215_pmu_reset(struct nvkm_pmu *);
32int gt215_pmu_init(struct nvkm_pmu *);
33void gt215_pmu_fini(struct nvkm_pmu *);
34void gt215_pmu_intr(struct nvkm_pmu *);
35void gt215_pmu_recv(struct nvkm_pmu *);
36int gt215_pmu_send(struct nvkm_pmu *, u32[2], u32, u32, u32, u32);
37
24void gk110_pmu_pgob(struct nvkm_pmu *, bool); 38void gk110_pmu_pgob(struct nvkm_pmu *, bool);
25#endif 39#endif