diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2014-08-11 00:38:10 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2014-09-15 08:22:12 -0400 |
| commit | b38a2322df62dbcd423d3e329f401eb14c1f0e4a (patch) | |
| tree | 077c38ef3ea2c1d446e2e7961c96ed3d15c92c2e | |
| parent | 996f5a08235b27a7adcd01fe2b3f79e2f0f20ced (diff) | |
drm/nv50-/disp: add support for completion events
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/gm107.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 89 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv84.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva0.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 49 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvif/class.h | 9 |
11 files changed, 173 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c index d54da8b5f87e..c8e4e60b86f1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c | |||
| @@ -68,6 +68,10 @@ gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 68 | if (ret) | 68 | if (ret) |
| 69 | return ret; | 69 | return ret; |
| 70 | 70 | ||
| 71 | ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent); | ||
| 72 | if (ret) | ||
| 73 | return ret; | ||
| 74 | |||
| 71 | nv_engine(priv)->sclass = gm107_disp_base_oclass; | 75 | nv_engine(priv)->sclass = gm107_disp_base_oclass; |
| 72 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 76 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 73 | nv_subdev(priv)->intr = nvd0_disp_intr; | 77 | nv_subdev(priv)->intr = nvd0_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 4b5bb5d58a54..86fda5d51ed4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <core/enum.h> | 29 | #include <core/enum.h> |
| 30 | #include <nvif/unpack.h> | 30 | #include <nvif/unpack.h> |
| 31 | #include <nvif/class.h> | 31 | #include <nvif/class.h> |
| 32 | #include <nvif/event.h> | ||
| 32 | 33 | ||
| 33 | #include <subdev/bios.h> | 34 | #include <subdev/bios.h> |
| 34 | #include <subdev/bios/dcb.h> | 35 | #include <subdev/bios/dcb.h> |
| @@ -82,6 +83,71 @@ nv50_disp_chan_destroy(struct nv50_disp_chan *chan) | |||
| 82 | nouveau_namedb_destroy(&chan->base); | 83 | nouveau_namedb_destroy(&chan->base); |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 86 | static void | ||
| 87 | nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) | ||
| 88 | { | ||
| 89 | struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); | ||
| 90 | nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000000 << index); | ||
| 91 | } | ||
| 92 | |||
| 93 | static void | ||
| 94 | nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) | ||
| 95 | { | ||
| 96 | struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); | ||
| 97 | nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000001 << index); | ||
| 98 | } | ||
| 99 | |||
| 100 | void | ||
| 101 | nv50_disp_chan_uevent_send(struct nv50_disp_priv *priv, int chid) | ||
| 102 | { | ||
| 103 | struct nvif_notify_uevent_rep { | ||
| 104 | } rep; | ||
| 105 | |||
| 106 | nvkm_event_send(&priv->uevent, 1, chid, &rep, sizeof(rep)); | ||
| 107 | } | ||
| 108 | |||
| 109 | int | ||
| 110 | nv50_disp_chan_uevent_ctor(struct nouveau_object *object, void *data, u32 size, | ||
| 111 | struct nvkm_notify *notify) | ||
| 112 | { | ||
| 113 | struct nv50_disp_dmac *dmac = (void *)object; | ||
| 114 | union { | ||
| 115 | struct nvif_notify_uevent_req none; | ||
| 116 | } *args = data; | ||
| 117 | int ret; | ||
| 118 | |||
| 119 | if (nvif_unvers(args->none)) { | ||
| 120 | notify->size = sizeof(struct nvif_notify_uevent_rep); | ||
| 121 | notify->types = 1; | ||
| 122 | notify->index = dmac->base.chid; | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | return ret; | ||
| 127 | } | ||
| 128 | |||
| 129 | const struct nvkm_event_func | ||
| 130 | nv50_disp_chan_uevent = { | ||
| 131 | .ctor = nv50_disp_chan_uevent_ctor, | ||
| 132 | .init = nv50_disp_chan_uevent_init, | ||
| 133 | .fini = nv50_disp_chan_uevent_fini, | ||
| 134 | }; | ||
| 135 | |||
| 136 | int | ||
| 137 | nv50_disp_chan_ntfy(struct nouveau_object *object, u32 type, | ||
| 138 | struct nvkm_event **pevent) | ||
| 139 | { | ||
| 140 | struct nv50_disp_priv *priv = (void *)object->engine; | ||
| 141 | switch (type) { | ||
| 142 | case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: | ||
| 143 | *pevent = &priv->uevent; | ||
| 144 | return 0; | ||
| 145 | default: | ||
| 146 | break; | ||
| 147 | } | ||
| 148 | return -EINVAL; | ||
| 149 | } | ||
| 150 | |||
| 85 | int | 151 | int |
| 86 | nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size) | 152 | nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size) |
| 87 | { | 153 | { |
| @@ -195,7 +261,7 @@ nv50_disp_dmac_init(struct nouveau_object *object) | |||
| 195 | return ret; | 261 | return ret; |
| 196 | 262 | ||
| 197 | /* enable error reporting */ | 263 | /* enable error reporting */ |
| 198 | nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00010001 << chid); | 264 | nv_mask(priv, 0x610028, 0x00010000 << chid, 0x00010000 << chid); |
| 199 | 265 | ||
| 200 | /* initialise channel for dma command submission */ | 266 | /* initialise channel for dma command submission */ |
| 201 | nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push); | 267 | nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push); |
| @@ -232,7 +298,7 @@ nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend) | |||
| 232 | return -EBUSY; | 298 | return -EBUSY; |
| 233 | } | 299 | } |
| 234 | 300 | ||
| 235 | /* disable error reporting */ | 301 | /* disable error reporting and completion notifications */ |
| 236 | nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid); | 302 | nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid); |
| 237 | 303 | ||
| 238 | return nv50_disp_chan_fini(&dmac->base, suspend); | 304 | return nv50_disp_chan_fini(&dmac->base, suspend); |
| @@ -454,7 +520,7 @@ nv50_disp_mast_init(struct nouveau_object *object) | |||
| 454 | return ret; | 520 | return ret; |
| 455 | 521 | ||
| 456 | /* enable error reporting */ | 522 | /* enable error reporting */ |
| 457 | nv_mask(priv, 0x610028, 0x00010001, 0x00010001); | 523 | nv_mask(priv, 0x610028, 0x00010000, 0x00010000); |
| 458 | 524 | ||
| 459 | /* attempt to unstick channel from some unknown state */ | 525 | /* attempt to unstick channel from some unknown state */ |
| 460 | if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000) | 526 | if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000) |
| @@ -494,7 +560,7 @@ nv50_disp_mast_fini(struct nouveau_object *object, bool suspend) | |||
| 494 | return -EBUSY; | 560 | return -EBUSY; |
| 495 | } | 561 | } |
| 496 | 562 | ||
| 497 | /* disable error reporting */ | 563 | /* disable error reporting and completion notifications */ |
| 498 | nv_mask(priv, 0x610028, 0x00010001, 0x00000000); | 564 | nv_mask(priv, 0x610028, 0x00010001, 0x00000000); |
| 499 | 565 | ||
| 500 | return nv50_disp_chan_fini(&mast->base, suspend); | 566 | return nv50_disp_chan_fini(&mast->base, suspend); |
| @@ -507,6 +573,7 @@ nv50_disp_mast_ofuncs = { | |||
| 507 | .base.init = nv50_disp_mast_init, | 573 | .base.init = nv50_disp_mast_init, |
| 508 | .base.fini = nv50_disp_mast_fini, | 574 | .base.fini = nv50_disp_mast_fini, |
| 509 | .base.map = nv50_disp_chan_map, | 575 | .base.map = nv50_disp_chan_map, |
| 576 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 510 | .base.rd32 = nv50_disp_chan_rd32, | 577 | .base.rd32 = nv50_disp_chan_rd32, |
| 511 | .base.wr32 = nv50_disp_chan_wr32, | 578 | .base.wr32 = nv50_disp_chan_wr32, |
| 512 | .chid = 0, | 579 | .chid = 0, |
| @@ -607,6 +674,7 @@ nv50_disp_sync_ofuncs = { | |||
| 607 | .base.dtor = nv50_disp_dmac_dtor, | 674 | .base.dtor = nv50_disp_dmac_dtor, |
| 608 | .base.init = nv50_disp_dmac_init, | 675 | .base.init = nv50_disp_dmac_init, |
| 609 | .base.fini = nv50_disp_dmac_fini, | 676 | .base.fini = nv50_disp_dmac_fini, |
| 677 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 610 | .base.map = nv50_disp_chan_map, | 678 | .base.map = nv50_disp_chan_map, |
| 611 | .base.rd32 = nv50_disp_chan_rd32, | 679 | .base.rd32 = nv50_disp_chan_rd32, |
| 612 | .base.wr32 = nv50_disp_chan_wr32, | 680 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -696,6 +764,7 @@ nv50_disp_ovly_ofuncs = { | |||
| 696 | .base.dtor = nv50_disp_dmac_dtor, | 764 | .base.dtor = nv50_disp_dmac_dtor, |
| 697 | .base.init = nv50_disp_dmac_init, | 765 | .base.init = nv50_disp_dmac_init, |
| 698 | .base.fini = nv50_disp_dmac_fini, | 766 | .base.fini = nv50_disp_dmac_fini, |
| 767 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 699 | .base.map = nv50_disp_chan_map, | 768 | .base.map = nv50_disp_chan_map, |
| 700 | .base.rd32 = nv50_disp_chan_rd32, | 769 | .base.rd32 = nv50_disp_chan_rd32, |
| 701 | .base.wr32 = nv50_disp_chan_wr32, | 770 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -813,6 +882,7 @@ nv50_disp_oimm_ofuncs = { | |||
| 813 | .base.dtor = nv50_disp_pioc_dtor, | 882 | .base.dtor = nv50_disp_pioc_dtor, |
| 814 | .base.init = nv50_disp_pioc_init, | 883 | .base.init = nv50_disp_pioc_init, |
| 815 | .base.fini = nv50_disp_pioc_fini, | 884 | .base.fini = nv50_disp_pioc_fini, |
| 885 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 816 | .base.map = nv50_disp_chan_map, | 886 | .base.map = nv50_disp_chan_map, |
| 817 | .base.rd32 = nv50_disp_chan_rd32, | 887 | .base.rd32 = nv50_disp_chan_rd32, |
| 818 | .base.wr32 = nv50_disp_chan_wr32, | 888 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -860,6 +930,7 @@ nv50_disp_curs_ofuncs = { | |||
| 860 | .base.dtor = nv50_disp_pioc_dtor, | 930 | .base.dtor = nv50_disp_pioc_dtor, |
| 861 | .base.init = nv50_disp_pioc_init, | 931 | .base.init = nv50_disp_pioc_init, |
| 862 | .base.fini = nv50_disp_pioc_fini, | 932 | .base.fini = nv50_disp_pioc_fini, |
| 933 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 863 | .base.map = nv50_disp_chan_map, | 934 | .base.map = nv50_disp_chan_map, |
| 864 | .base.rd32 = nv50_disp_chan_rd32, | 935 | .base.rd32 = nv50_disp_chan_rd32, |
| 865 | .base.wr32 = nv50_disp_chan_wr32, | 936 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -1846,6 +1917,12 @@ nv50_disp_intr(struct nouveau_subdev *subdev) | |||
| 1846 | intr0 &= ~(0x00010000 << chid); | 1917 | intr0 &= ~(0x00010000 << chid); |
| 1847 | } | 1918 | } |
| 1848 | 1919 | ||
| 1920 | while (intr0 & 0x0000001f) { | ||
| 1921 | u32 chid = __ffs(intr0 & 0x0000001f); | ||
| 1922 | nv50_disp_chan_uevent_send(priv, chid); | ||
| 1923 | intr0 &= ~(0x00000001 << chid); | ||
| 1924 | } | ||
| 1925 | |||
| 1849 | if (intr1 & 0x00000004) { | 1926 | if (intr1 & 0x00000004) { |
| 1850 | nouveau_disp_vblank(&priv->base, 0); | 1927 | nouveau_disp_vblank(&priv->base, 0); |
| 1851 | nv_wr32(priv, 0x610024, 0x00000004); | 1928 | nv_wr32(priv, 0x610024, 0x00000004); |
| @@ -1880,6 +1957,10 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 1880 | if (ret) | 1957 | if (ret) |
| 1881 | return ret; | 1958 | return ret; |
| 1882 | 1959 | ||
| 1960 | ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); | ||
| 1961 | if (ret) | ||
| 1962 | return ret; | ||
| 1963 | |||
| 1883 | nv_engine(priv)->sclass = nv50_disp_base_oclass; | 1964 | nv_engine(priv)->sclass = nv50_disp_base_oclass; |
| 1884 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 1965 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 1885 | nv_subdev(priv)->intr = nv50_disp_intr; | 1966 | nv_subdev(priv)->intr = nv50_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index 8ab14461f70c..a288a7f454aa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | |||
| @@ -26,6 +26,8 @@ struct nv50_disp_priv { | |||
| 26 | struct work_struct supervisor; | 26 | struct work_struct supervisor; |
| 27 | u32 super; | 27 | u32 super; |
| 28 | 28 | ||
| 29 | struct nvkm_event uevent; | ||
| 30 | |||
| 29 | struct { | 31 | struct { |
| 30 | int nr; | 32 | int nr; |
| 31 | } head; | 33 | } head; |
| @@ -116,9 +118,16 @@ struct nv50_disp_chan { | |||
| 116 | int chid; | 118 | int chid; |
| 117 | }; | 119 | }; |
| 118 | 120 | ||
| 121 | int nv50_disp_chan_ntfy(struct nouveau_object *, u32, struct nvkm_event **); | ||
| 119 | int nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *); | 122 | int nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *); |
| 120 | u32 nv50_disp_chan_rd32(struct nouveau_object *, u64); | 123 | u32 nv50_disp_chan_rd32(struct nouveau_object *, u64); |
| 121 | void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32); | 124 | void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32); |
| 125 | extern const struct nvkm_event_func nv50_disp_chan_uevent; | ||
| 126 | int nv50_disp_chan_uevent_ctor(struct nouveau_object *, void *, u32, | ||
| 127 | struct nvkm_notify *); | ||
| 128 | void nv50_disp_chan_uevent_send(struct nv50_disp_priv *, int); | ||
| 129 | |||
| 130 | extern const struct nvkm_event_func nvd0_disp_chan_uevent; | ||
| 122 | 131 | ||
| 123 | #define nv50_disp_chan_init(a) \ | 132 | #define nv50_disp_chan_init(a) \ |
| 124 | nouveau_namedb_init(&(a)->base) | 133 | nouveau_namedb_init(&(a)->base) |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index 788ced1b6182..d36284715b2a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c | |||
| @@ -236,6 +236,10 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 236 | if (ret) | 236 | if (ret) |
| 237 | return ret; | 237 | return ret; |
| 238 | 238 | ||
| 239 | ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); | ||
| 240 | if (ret) | ||
| 241 | return ret; | ||
| 242 | |||
| 239 | nv_engine(priv)->sclass = nv84_disp_base_oclass; | 243 | nv_engine(priv)->sclass = nv84_disp_base_oclass; |
| 240 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 244 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 241 | nv_subdev(priv)->intr = nv50_disp_intr; | 245 | nv_subdev(priv)->intr = nv50_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index fa79de906eae..a117064002b1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | |||
| @@ -95,6 +95,10 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 95 | if (ret) | 95 | if (ret) |
| 96 | return ret; | 96 | return ret; |
| 97 | 97 | ||
| 98 | ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); | ||
| 99 | if (ret) | ||
| 100 | return ret; | ||
| 101 | |||
| 98 | nv_engine(priv)->sclass = nv94_disp_base_oclass; | 102 | nv_engine(priv)->sclass = nv94_disp_base_oclass; |
| 99 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 103 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 100 | nv_subdev(priv)->intr = nv50_disp_intr; | 104 | nv_subdev(priv)->intr = nv50_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c index 7af15f5d48dc..c67e68aadd45 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c | |||
| @@ -112,6 +112,10 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 112 | if (ret) | 112 | if (ret) |
| 113 | return ret; | 113 | return ret; |
| 114 | 114 | ||
| 115 | ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); | ||
| 116 | if (ret) | ||
| 117 | return ret; | ||
| 118 | |||
| 115 | nv_engine(priv)->sclass = nva0_disp_base_oclass; | 119 | nv_engine(priv)->sclass = nva0_disp_base_oclass; |
| 116 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 120 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 117 | nv_subdev(priv)->intr = nv50_disp_intr; | 121 | nv_subdev(priv)->intr = nv50_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index 6bd39448f8da..22969f355aae 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | |||
| @@ -67,6 +67,10 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 67 | if (ret) | 67 | if (ret) |
| 68 | return ret; | 68 | return ret; |
| 69 | 69 | ||
| 70 | ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent); | ||
| 71 | if (ret) | ||
| 72 | return ret; | ||
| 73 | |||
| 70 | nv_engine(priv)->sclass = nva3_disp_base_oclass; | 74 | nv_engine(priv)->sclass = nva3_disp_base_oclass; |
| 71 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 75 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 72 | nv_subdev(priv)->intr = nv50_disp_intr; | 76 | nv_subdev(priv)->intr = nv50_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index a4bb3c774ee1..a571c4fd6d53 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | |||
| @@ -43,6 +43,31 @@ | |||
| 43 | #include "nv50.h" | 43 | #include "nv50.h" |
| 44 | 44 | ||
| 45 | /******************************************************************************* | 45 | /******************************************************************************* |
| 46 | * EVO channel base class | ||
| 47 | ******************************************************************************/ | ||
| 48 | |||
| 49 | static void | ||
| 50 | nvd0_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) | ||
| 51 | { | ||
| 52 | struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); | ||
| 53 | nv_mask(priv, 0x610090, 0x00000001 << index, 0x00000000 << index); | ||
| 54 | } | ||
| 55 | |||
| 56 | static void | ||
| 57 | nvd0_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) | ||
| 58 | { | ||
| 59 | struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent); | ||
| 60 | nv_mask(priv, 0x610090, 0x00000001 << index, 0x00000001 << index); | ||
| 61 | } | ||
| 62 | |||
| 63 | const struct nvkm_event_func | ||
| 64 | nvd0_disp_chan_uevent = { | ||
| 65 | .ctor = nv50_disp_chan_uevent_ctor, | ||
| 66 | .init = nvd0_disp_chan_uevent_init, | ||
| 67 | .fini = nvd0_disp_chan_uevent_fini, | ||
| 68 | }; | ||
| 69 | |||
| 70 | /******************************************************************************* | ||
| 46 | * EVO DMA channel base class | 71 | * EVO DMA channel base class |
| 47 | ******************************************************************************/ | 72 | ******************************************************************************/ |
| 48 | 73 | ||
| @@ -77,7 +102,6 @@ nvd0_disp_dmac_init(struct nouveau_object *object) | |||
| 77 | return ret; | 102 | return ret; |
| 78 | 103 | ||
| 79 | /* enable error reporting */ | 104 | /* enable error reporting */ |
| 80 | nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid); | ||
| 81 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); | 105 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); |
| 82 | 106 | ||
| 83 | /* initialise channel for dma command submission */ | 107 | /* initialise channel for dma command submission */ |
| @@ -115,7 +139,7 @@ nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend) | |||
| 115 | return -EBUSY; | 139 | return -EBUSY; |
| 116 | } | 140 | } |
| 117 | 141 | ||
| 118 | /* disable error reporting */ | 142 | /* disable error reporting and completion notification */ |
| 119 | nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); | 143 | nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); |
| 120 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); | 144 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); |
| 121 | 145 | ||
| @@ -278,7 +302,6 @@ nvd0_disp_mast_init(struct nouveau_object *object) | |||
| 278 | return ret; | 302 | return ret; |
| 279 | 303 | ||
| 280 | /* enable error reporting */ | 304 | /* enable error reporting */ |
| 281 | nv_mask(priv, 0x610090, 0x00000001, 0x00000001); | ||
| 282 | nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001); | 305 | nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001); |
| 283 | 306 | ||
| 284 | /* initialise channel for dma command submission */ | 307 | /* initialise channel for dma command submission */ |
| @@ -313,7 +336,7 @@ nvd0_disp_mast_fini(struct nouveau_object *object, bool suspend) | |||
| 313 | return -EBUSY; | 336 | return -EBUSY; |
| 314 | } | 337 | } |
| 315 | 338 | ||
| 316 | /* disable error reporting */ | 339 | /* disable error reporting and completion notification */ |
| 317 | nv_mask(priv, 0x610090, 0x00000001, 0x00000000); | 340 | nv_mask(priv, 0x610090, 0x00000001, 0x00000000); |
| 318 | nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000); | 341 | nv_mask(priv, 0x6100a0, 0x00000001, 0x00000000); |
| 319 | 342 | ||
| @@ -326,6 +349,7 @@ nvd0_disp_mast_ofuncs = { | |||
| 326 | .base.dtor = nv50_disp_dmac_dtor, | 349 | .base.dtor = nv50_disp_dmac_dtor, |
| 327 | .base.init = nvd0_disp_mast_init, | 350 | .base.init = nvd0_disp_mast_init, |
| 328 | .base.fini = nvd0_disp_mast_fini, | 351 | .base.fini = nvd0_disp_mast_fini, |
| 352 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 329 | .base.map = nv50_disp_chan_map, | 353 | .base.map = nv50_disp_chan_map, |
| 330 | .base.rd32 = nv50_disp_chan_rd32, | 354 | .base.rd32 = nv50_disp_chan_rd32, |
| 331 | .base.wr32 = nv50_disp_chan_wr32, | 355 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -419,6 +443,7 @@ nvd0_disp_sync_ofuncs = { | |||
| 419 | .base.dtor = nv50_disp_dmac_dtor, | 443 | .base.dtor = nv50_disp_dmac_dtor, |
| 420 | .base.init = nvd0_disp_dmac_init, | 444 | .base.init = nvd0_disp_dmac_init, |
| 421 | .base.fini = nvd0_disp_dmac_fini, | 445 | .base.fini = nvd0_disp_dmac_fini, |
| 446 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 422 | .base.map = nv50_disp_chan_map, | 447 | .base.map = nv50_disp_chan_map, |
| 423 | .base.rd32 = nv50_disp_chan_rd32, | 448 | .base.rd32 = nv50_disp_chan_rd32, |
| 424 | .base.wr32 = nv50_disp_chan_wr32, | 449 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -499,6 +524,7 @@ nvd0_disp_ovly_ofuncs = { | |||
| 499 | .base.dtor = nv50_disp_dmac_dtor, | 524 | .base.dtor = nv50_disp_dmac_dtor, |
| 500 | .base.init = nvd0_disp_dmac_init, | 525 | .base.init = nvd0_disp_dmac_init, |
| 501 | .base.fini = nvd0_disp_dmac_fini, | 526 | .base.fini = nvd0_disp_dmac_fini, |
| 527 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 502 | .base.map = nv50_disp_chan_map, | 528 | .base.map = nv50_disp_chan_map, |
| 503 | .base.rd32 = nv50_disp_chan_rd32, | 529 | .base.rd32 = nv50_disp_chan_rd32, |
| 504 | .base.wr32 = nv50_disp_chan_wr32, | 530 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -524,7 +550,6 @@ nvd0_disp_pioc_init(struct nouveau_object *object) | |||
| 524 | return ret; | 550 | return ret; |
| 525 | 551 | ||
| 526 | /* enable error reporting */ | 552 | /* enable error reporting */ |
| 527 | nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid); | ||
| 528 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); | 553 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid); |
| 529 | 554 | ||
| 530 | /* activate channel */ | 555 | /* activate channel */ |
| @@ -553,7 +578,7 @@ nvd0_disp_pioc_fini(struct nouveau_object *object, bool suspend) | |||
| 553 | return -EBUSY; | 578 | return -EBUSY; |
| 554 | } | 579 | } |
| 555 | 580 | ||
| 556 | /* disable error reporting */ | 581 | /* disable error reporting and completion notification */ |
| 557 | nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); | 582 | nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000000); |
| 558 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); | 583 | nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000000); |
| 559 | 584 | ||
| @@ -570,6 +595,7 @@ nvd0_disp_oimm_ofuncs = { | |||
| 570 | .base.dtor = nv50_disp_pioc_dtor, | 595 | .base.dtor = nv50_disp_pioc_dtor, |
| 571 | .base.init = nvd0_disp_pioc_init, | 596 | .base.init = nvd0_disp_pioc_init, |
| 572 | .base.fini = nvd0_disp_pioc_fini, | 597 | .base.fini = nvd0_disp_pioc_fini, |
| 598 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 573 | .base.map = nv50_disp_chan_map, | 599 | .base.map = nv50_disp_chan_map, |
| 574 | .base.rd32 = nv50_disp_chan_rd32, | 600 | .base.rd32 = nv50_disp_chan_rd32, |
| 575 | .base.wr32 = nv50_disp_chan_wr32, | 601 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -586,6 +612,7 @@ nvd0_disp_curs_ofuncs = { | |||
| 586 | .base.dtor = nv50_disp_pioc_dtor, | 612 | .base.dtor = nv50_disp_pioc_dtor, |
| 587 | .base.init = nvd0_disp_pioc_init, | 613 | .base.init = nvd0_disp_pioc_init, |
| 588 | .base.fini = nvd0_disp_pioc_fini, | 614 | .base.fini = nvd0_disp_pioc_fini, |
| 615 | .base.ntfy = nv50_disp_chan_ntfy, | ||
| 589 | .base.map = nv50_disp_chan_map, | 616 | .base.map = nv50_disp_chan_map, |
| 590 | .base.rd32 = nv50_disp_chan_rd32, | 617 | .base.rd32 = nv50_disp_chan_rd32, |
| 591 | .base.wr32 = nv50_disp_chan_wr32, | 618 | .base.wr32 = nv50_disp_chan_wr32, |
| @@ -1153,7 +1180,11 @@ nvd0_disp_intr(struct nouveau_subdev *subdev) | |||
| 1153 | 1180 | ||
| 1154 | if (intr & 0x00000001) { | 1181 | if (intr & 0x00000001) { |
| 1155 | u32 stat = nv_rd32(priv, 0x61008c); | 1182 | u32 stat = nv_rd32(priv, 0x61008c); |
| 1156 | nv_wr32(priv, 0x61008c, stat); | 1183 | while (stat) { |
| 1184 | int chid = __ffs(stat); stat &= ~(1 << chid); | ||
| 1185 | nv50_disp_chan_uevent_send(priv, chid); | ||
| 1186 | nv_wr32(priv, 0x61008c, 1 << chid); | ||
| 1187 | } | ||
| 1157 | intr &= ~0x00000001; | 1188 | intr &= ~0x00000001; |
| 1158 | } | 1189 | } |
| 1159 | 1190 | ||
| @@ -1209,6 +1240,10 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 1209 | if (ret) | 1240 | if (ret) |
| 1210 | return ret; | 1241 | return ret; |
| 1211 | 1242 | ||
| 1243 | ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent); | ||
| 1244 | if (ret) | ||
| 1245 | return ret; | ||
| 1246 | |||
| 1212 | nv_engine(priv)->sclass = nvd0_disp_base_oclass; | 1247 | nv_engine(priv)->sclass = nvd0_disp_base_oclass; |
| 1213 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 1248 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 1214 | nv_subdev(priv)->intr = nvd0_disp_intr; | 1249 | nv_subdev(priv)->intr = nvd0_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index 47fef1e398c4..3ed47e187f89 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | |||
| @@ -233,6 +233,10 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 233 | if (ret) | 233 | if (ret) |
| 234 | return ret; | 234 | return ret; |
| 235 | 235 | ||
| 236 | ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent); | ||
| 237 | if (ret) | ||
| 238 | return ret; | ||
| 239 | |||
| 236 | nv_engine(priv)->sclass = nve0_disp_base_oclass; | 240 | nv_engine(priv)->sclass = nve0_disp_base_oclass; |
| 237 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 241 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 238 | nv_subdev(priv)->intr = nvd0_disp_intr; | 242 | nv_subdev(priv)->intr = nvd0_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c index 04bda4ac4ed3..07f337695007 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c | |||
| @@ -68,6 +68,10 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 68 | if (ret) | 68 | if (ret) |
| 69 | return ret; | 69 | return ret; |
| 70 | 70 | ||
| 71 | ret = nvkm_event_init(&nvd0_disp_chan_uevent, 1, 17, &priv->uevent); | ||
| 72 | if (ret) | ||
| 73 | return ret; | ||
| 74 | |||
| 71 | nv_engine(priv)->sclass = nvf0_disp_base_oclass; | 75 | nv_engine(priv)->sclass = nvf0_disp_base_oclass; |
| 72 | nv_engine(priv)->cclass = &nv50_disp_cclass; | 76 | nv_engine(priv)->cclass = &nv50_disp_cclass; |
| 73 | nv_subdev(priv)->intr = nvd0_disp_intr; | 77 | nv_subdev(priv)->intr = nvd0_disp_intr; |
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h index 573491f84792..e5a27df0672b 100644 --- a/drivers/gpu/drm/nouveau/nvif/class.h +++ b/drivers/gpu/drm/nouveau/nvif/class.h | |||
| @@ -479,6 +479,8 @@ struct nv50_disp_core_channel_dma_v0 { | |||
| 479 | __u32 pushbuf; | 479 | __u32 pushbuf; |
| 480 | }; | 480 | }; |
| 481 | 481 | ||
| 482 | #define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 | ||
| 483 | |||
| 482 | /* cursor immediate */ | 484 | /* cursor immediate */ |
| 483 | struct nv50_disp_cursor_v0 { | 485 | struct nv50_disp_cursor_v0 { |
| 484 | __u8 version; | 486 | __u8 version; |
| @@ -486,6 +488,8 @@ struct nv50_disp_cursor_v0 { | |||
| 486 | __u8 pad02[6]; | 488 | __u8 pad02[6]; |
| 487 | }; | 489 | }; |
| 488 | 490 | ||
| 491 | #define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00 | ||
| 492 | |||
| 489 | /* base */ | 493 | /* base */ |
| 490 | struct nv50_disp_base_channel_dma_v0 { | 494 | struct nv50_disp_base_channel_dma_v0 { |
| 491 | __u8 version; | 495 | __u8 version; |
| @@ -494,6 +498,8 @@ struct nv50_disp_base_channel_dma_v0 { | |||
| 494 | __u32 pushbuf; | 498 | __u32 pushbuf; |
| 495 | }; | 499 | }; |
| 496 | 500 | ||
| 501 | #define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 | ||
| 502 | |||
| 497 | /* overlay */ | 503 | /* overlay */ |
| 498 | struct nv50_disp_overlay_channel_dma_v0 { | 504 | struct nv50_disp_overlay_channel_dma_v0 { |
| 499 | __u8 version; | 505 | __u8 version; |
| @@ -502,6 +508,8 @@ struct nv50_disp_overlay_channel_dma_v0 { | |||
| 502 | __u32 pushbuf; | 508 | __u32 pushbuf; |
| 503 | }; | 509 | }; |
| 504 | 510 | ||
| 511 | #define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 | ||
| 512 | |||
| 505 | /* overlay immediate */ | 513 | /* overlay immediate */ |
| 506 | struct nv50_disp_overlay_v0 { | 514 | struct nv50_disp_overlay_v0 { |
| 507 | __u8 version; | 515 | __u8 version; |
| @@ -509,6 +517,7 @@ struct nv50_disp_overlay_v0 { | |||
| 509 | __u8 pad02[6]; | 517 | __u8 pad02[6]; |
| 510 | }; | 518 | }; |
| 511 | 519 | ||
| 520 | #define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00 | ||
| 512 | 521 | ||
| 513 | /******************************************************************************* | 522 | /******************************************************************************* |
| 514 | * fermi | 523 | * fermi |
