aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2018-05-08 06:39:48 -0400
committerBen Skeggs <bskeggs@redhat.com>2018-05-18 01:01:46 -0400
commitfacaed62b4cba3a6334fc1798fa8f51ea6a1962d (patch)
tree5c05fb78990e9a0b920312974c8d2ab61411b3bb
parent290ffeafcc1a953aa287c8a7bf7f6d9af25b7e77 (diff)
drm/nouveau/kms/gv100: initial support
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/Kbuild8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/atom.h8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/core.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/core.h3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/corec37d.c110
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs.c1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs.h1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/cursc37a.c50
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.h4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c13
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.h4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head917d.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/headc37d.c212
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/sorc37d.c39
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wimm.c47
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wimm.h8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c86
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c38
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.h6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c278
21 files changed, 918 insertions, 7 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/Kbuild b/drivers/gpu/drm/nouveau/dispnv50/Kbuild
index ebd18cb9feda..849b0f45afb8 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/Kbuild
+++ b/drivers/gpu/drm/nouveau/dispnv50/Kbuild
@@ -6,6 +6,7 @@ nouveau-y += dispnv50/core507d.o
6nouveau-y += dispnv50/core827d.o 6nouveau-y += dispnv50/core827d.o
7nouveau-y += dispnv50/core907d.o 7nouveau-y += dispnv50/core907d.o
8nouveau-y += dispnv50/core917d.o 8nouveau-y += dispnv50/core917d.o
9nouveau-y += dispnv50/corec37d.o
9 10
10nouveau-y += dispnv50/dac507d.o 11nouveau-y += dispnv50/dac507d.o
11nouveau-y += dispnv50/dac907d.o 12nouveau-y += dispnv50/dac907d.o
@@ -14,14 +15,20 @@ nouveau-y += dispnv50/pior507d.o
14 15
15nouveau-y += dispnv50/sor507d.o 16nouveau-y += dispnv50/sor507d.o
16nouveau-y += dispnv50/sor907d.o 17nouveau-y += dispnv50/sor907d.o
18nouveau-y += dispnv50/sorc37d.o
17 19
18nouveau-y += dispnv50/head.o 20nouveau-y += dispnv50/head.o
19nouveau-y += dispnv50/head507d.o 21nouveau-y += dispnv50/head507d.o
20nouveau-y += dispnv50/head827d.o 22nouveau-y += dispnv50/head827d.o
21nouveau-y += dispnv50/head907d.o 23nouveau-y += dispnv50/head907d.o
22nouveau-y += dispnv50/head917d.o 24nouveau-y += dispnv50/head917d.o
25nouveau-y += dispnv50/headc37d.o
26
27nouveau-y += dispnv50/wimm.o
28nouveau-y += dispnv50/wimmc37b.o
23 29
24nouveau-y += dispnv50/wndw.o 30nouveau-y += dispnv50/wndw.o
31nouveau-y += dispnv50/wndwc37e.o
25 32
26nouveau-y += dispnv50/base.o 33nouveau-y += dispnv50/base.o
27nouveau-y += dispnv50/base507c.o 34nouveau-y += dispnv50/base507c.o
@@ -32,6 +39,7 @@ nouveau-y += dispnv50/base917c.o
32nouveau-y += dispnv50/curs.o 39nouveau-y += dispnv50/curs.o
33nouveau-y += dispnv50/curs507a.o 40nouveau-y += dispnv50/curs507a.o
34nouveau-y += dispnv50/curs907a.o 41nouveau-y += dispnv50/curs907a.o
42nouveau-y += dispnv50/cursc37a.o
35 43
36nouveau-y += dispnv50/oimm.o 44nouveau-y += dispnv50/oimm.o
37nouveau-y += dispnv50/oimm507b.o 45nouveau-y += dispnv50/oimm507b.o
diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
index d8337e7996e8..908feb1fc60f 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
@@ -54,6 +54,9 @@ struct nv50_head_atom {
54 u64 offset:40; 54 u64 offset:40;
55 u8 buffer:1; 55 u8 buffer:1;
56 u8 mode:4; 56 u8 mode:4;
57 u8 size:2;
58 u8 range:2;
59 u8 output_mode:2;
57 } olut; 60 } olut;
58 61
59 struct { 62 struct {
@@ -77,7 +80,7 @@ struct nv50_head_atom {
77 u32 handle; 80 u32 handle;
78 u64 offset:40; 81 u64 offset:40;
79 u8 layout:2; 82 u8 layout:2;
80 u8 format:1; 83 u8 format:8;
81 } curs; 84 } curs;
82 85
83 struct { 86 struct {
@@ -166,6 +169,9 @@ struct nv50_wndw_atom {
166 u8 buffer:1; 169 u8 buffer:1;
167 u8 enable:2; 170 u8 enable:2;
168 u8 mode:4; 171 u8 mode:4;
172 u8 size:2;
173 u8 range:2;
174 u8 output_mode:2;
169 } i; 175 } i;
170 } xlut; 176 } xlut;
171 177
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core.c b/drivers/gpu/drm/nouveau/dispnv50/core.c
index f87cbaa4f8ec..f3c49adb1bdb 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/core.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/core.c
@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
42 int version; 42 int version;
43 int (*new)(struct nouveau_drm *, s32, struct nv50_core **); 43 int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
44 } cores[] = { 44 } cores[] = {
45 { GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new },
45 { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, 46 { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
46 { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, 47 { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
47 { GM200_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, 48 { GM200_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core.h b/drivers/gpu/drm/nouveau/dispnv50/core.h
index c490d7d497b2..8470df9dd13d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/core.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/core.h
@@ -44,4 +44,7 @@ extern const struct nv50_outp_func dac907d;
44extern const struct nv50_outp_func sor907d; 44extern const struct nv50_outp_func sor907d;
45 45
46int core917d_new(struct nouveau_drm *, s32, struct nv50_core **); 46int core917d_new(struct nouveau_drm *, s32, struct nv50_core **);
47
48int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **);
49extern const struct nv50_outp_func sorc37d;
47#endif 50#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
new file mode 100644
index 000000000000..b5c17c948918
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2018 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#include "core.h"
23#include "head.h"
24
25#include <nouveau_bo.h>
26
27static void
28corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
29{
30 u32 *push;
31 if ((push = evo_wait(&core->chan, 9))) {
32 if (ntfy) {
33 evo_mthd(push, 0x020c, 1);
34 evo_data(push, 0x00001000 | NV50_DISP_CORE_NTFY);
35 }
36
37 evo_mthd(push, 0x0218, 2);
38 evo_data(push, interlock[NV50_DISP_INTERLOCK_CURS]);
39 evo_data(push, interlock[NV50_DISP_INTERLOCK_WNDW]);
40 evo_mthd(push, 0x0200, 1);
41 evo_data(push, 0x00000001);
42
43 if (ntfy) {
44 evo_mthd(push, 0x020c, 1);
45 evo_data(push, 0x00000000);
46 }
47 evo_kick(push, &core->chan);
48 }
49}
50
51int
52corec37d_ntfy_wait_done(struct nouveau_bo *bo, u32 offset,
53 struct nvif_device *device)
54{
55 u32 data;
56 s64 time = nvif_msec(device, 2000ULL,
57 data = nouveau_bo_rd32(bo, offset / 4 + 0);
58 if ((data & 0xc0000000) == 0x80000000)
59 break;
60 usleep_range(1, 2);
61 );
62 return time < 0 ? time : 0;
63}
64
65void
66corec37d_ntfy_init(struct nouveau_bo *bo, u32 offset)
67{
68 nouveau_bo_wr32(bo, offset / 4 + 0, 0x00000000);
69 nouveau_bo_wr32(bo, offset / 4 + 1, 0x00000000);
70 nouveau_bo_wr32(bo, offset / 4 + 2, 0x00000000);
71 nouveau_bo_wr32(bo, offset / 4 + 3, 0x00000000);
72}
73
74void
75corec37d_init(struct nv50_core *core)
76{
77 const u32 windows = 8; /*XXX*/
78 u32 *push, i;
79 if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) {
80 evo_mthd(push, 0x0208, 1);
81 evo_data(push, core->chan.sync.handle);
82 for (i = 0; i < windows; i++) {
83 evo_mthd(push, 0x1000 + (i * 0x080), 3);
84 evo_data(push, i >> 1);
85 evo_data(push, 0x00000017);
86 evo_data(push, 0x00000000);
87 evo_mthd(push, 0x1010 + (i * 0x080), 1);
88 evo_data(push, 0x00127fff);
89 }
90 evo_mthd(push, 0x0200, 1);
91 evo_data(push, 0x00000001);
92 evo_kick(push, &core->chan);
93 }
94}
95
96static const struct nv50_core_func
97corec37d = {
98 .init = corec37d_init,
99 .ntfy_init = corec37d_ntfy_init,
100 .ntfy_wait_done = corec37d_ntfy_wait_done,
101 .update = corec37d_update,
102 .head = &headc37d,
103 .sor = &sorc37d,
104};
105
106int
107corec37d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
108{
109 return core507d_new_(&corec37d, drm, oclass, pcore);
110}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs.c b/drivers/gpu/drm/nouveau/dispnv50/curs.c
index fb842ed2592f..f592087338c4 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs.c
@@ -31,6 +31,7 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
31 int version; 31 int version;
32 int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); 32 int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
33 } curses[] = { 33 } curses[] = {
34 { GV100_DISP_CURSOR, 0, cursc37a_new },
34 { GK104_DISP_CURSOR, 0, curs907a_new }, 35 { GK104_DISP_CURSOR, 0, curs907a_new },
35 { GF110_DISP_CURSOR, 0, curs907a_new }, 36 { GF110_DISP_CURSOR, 0, curs907a_new },
36 { GT214_DISP_CURSOR, 0, curs507a_new }, 37 { GT214_DISP_CURSOR, 0, curs507a_new },
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs.h b/drivers/gpu/drm/nouveau/dispnv50/curs.h
index 8edac4507ec8..23aff5fd6747 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs.h
@@ -8,6 +8,7 @@ int curs507a_new_(const struct nv50_wimm_func *, struct nouveau_drm *,
8 struct nv50_wndw **); 8 struct nv50_wndw **);
9 9
10int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); 10int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
11int cursc37a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
11 12
12int nv50_curs_new(struct nouveau_drm *, int head, struct nv50_wndw **); 13int nv50_curs_new(struct nouveau_drm *, int head, struct nv50_wndw **);
13#endif 14#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/cursc37a.c b/drivers/gpu/drm/nouveau/dispnv50/cursc37a.c
new file mode 100644
index 000000000000..23fb29d41efe
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/cursc37a.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2018 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#include "curs.h"
23#include "atom.h"
24
25static void
26cursc37a_update(struct nv50_wndw *wndw, u32 *interlock)
27{
28 nvif_wr32(&wndw->wimm.base.user, 0x0200, 0x00000001);
29}
30
31static void
32cursc37a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
33{
34 nvif_wr32(&wndw->wimm.base.user, 0x0208, asyw->point.y << 16 |
35 asyw->point.x);
36}
37
38static const struct nv50_wimm_func
39cursc37a = {
40 .point = cursc37a_point,
41 .update = cursc37a_update,
42};
43
44int
45cursc37a_new(struct nouveau_drm *drm, int head, s32 oclass,
46 struct nv50_wndw **pwndw)
47{
48 return curs507a_new_(&cursc37a, drm, head, oclass,
49 0x00000001 << head, pwndw);
50}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 6c860e8b1b16..b83465ae7c1b 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -154,6 +154,9 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
154 if (ret) 154 if (ret)
155 return ret; 155 return ret;
156 156
157 if (!syncbuf)
158 return 0;
159
157 ret = nvif_object_init(&dmac->base.user, 0xf0000000, NV_DMA_IN_MEMORY, 160 ret = nvif_object_init(&dmac->base.user, 0xf0000000, NV_DMA_IN_MEMORY,
158 &(struct nv_dma_v0) { 161 &(struct nv_dma_v0) {
159 .target = NV_DMA_V0_TARGET_VRAM, 162 .target = NV_DMA_V0_TARGET_VRAM,
@@ -2170,6 +2173,9 @@ nv50_display_create(struct drm_device *dev)
2170 goto out; 2173 goto out;
2171 2174
2172 /* create crtc objects to represent the hw heads */ 2175 /* create crtc objects to represent the hw heads */
2176 if (disp->disp->object.oclass >= GV100_DISP)
2177 crtcs = nvif_rd32(&device->object, 0x610060) & 0xff;
2178 else
2173 if (disp->disp->object.oclass >= GF110_DISP) 2179 if (disp->disp->object.oclass >= GF110_DISP)
2174 crtcs = nvif_rd32(&device->object, 0x612004) & 0xf; 2180 crtcs = nvif_rd32(&device->object, 0x612004) & 0xf;
2175 else 2181 else
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h
index a89b83f95187..e48c5eb35b49 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h
@@ -36,11 +36,15 @@ struct nv50_disp_interlock {
36 NV50_DISP_INTERLOCK_CURS, 36 NV50_DISP_INTERLOCK_CURS,
37 NV50_DISP_INTERLOCK_BASE, 37 NV50_DISP_INTERLOCK_BASE,
38 NV50_DISP_INTERLOCK_OVLY, 38 NV50_DISP_INTERLOCK_OVLY,
39 NV50_DISP_INTERLOCK_WNDW,
40 NV50_DISP_INTERLOCK_WIMM,
39 NV50_DISP_INTERLOCK__SIZE 41 NV50_DISP_INTERLOCK__SIZE
40 } type; 42 } type;
41 u32 data; 43 u32 data;
42}; 44};
43 45
46void corec37d_ntfy_init(struct nouveau_bo *, u32);
47
44struct nv50_chan { 48struct nv50_chan {
45 struct nvif_object user; 49 struct nvif_object user;
46 struct nvif_device *device; 50 struct nvif_device *device;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index ca83006510b7..4f57e5379796 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -475,7 +475,16 @@ nv50_head_create(struct drm_device *dev, int index)
475 475
476 head->func = disp->core->func->head; 476 head->func = disp->core->func->head;
477 head->base.index = index; 477 head->base.index = index;
478 ret = nv50_base_new(drm, head->base.index, &wndw); 478
479 if (disp->disp->object.oclass < GV100_DISP) {
480 ret = nv50_ovly_new(drm, head->base.index, &wndw);
481 ret = nv50_base_new(drm, head->base.index, &wndw);
482 } else {
483 ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY,
484 head->base.index * 2 + 1, &wndw);
485 ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_PRIMARY,
486 head->base.index * 2 + 0, &wndw);
487 }
479 if (ret == 0) 488 if (ret == 0)
480 ret = nv50_curs_new(drm, head->base.index, &curs); 489 ret = nv50_curs_new(drm, head->base.index, &curs);
481 if (ret) { 490 if (ret) {
@@ -495,8 +504,6 @@ nv50_head_create(struct drm_device *dev, int index)
495 goto out; 504 goto out;
496 } 505 }
497 506
498 /* allocate overlay resources */
499 ret = nv50_ovly_new(drm, head->base.index, &wndw);
500out: 507out:
501 if (ret) 508 if (ret)
502 nv50_head_destroy(crtc); 509 nv50_head_destroy(crtc);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h b/drivers/gpu/drm/nouveau/dispnv50/head.h
index 8f2c3ffa4e61..37b3248c6dae 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.h
@@ -71,4 +71,8 @@ void head907d_procamp(struct nv50_head *, struct nv50_head_atom *);
71void head907d_or(struct nv50_head *, struct nv50_head_atom *); 71void head907d_or(struct nv50_head *, struct nv50_head_atom *);
72 72
73extern const struct nv50_head_func head917d; 73extern const struct nv50_head_func head917d;
74int head917d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *,
75 struct nv50_head_atom *);
76
77extern const struct nv50_head_func headc37d;
74#endif 78#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c
index 4c019a4417ea..303df8459ca8 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head917d.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head917d.c
@@ -63,7 +63,7 @@ head917d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
63 } 63 }
64} 64}
65 65
66static int 66int
67head917d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw, 67head917d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw,
68 struct nv50_head_atom *asyh) 68 struct nv50_head_atom *asyh)
69{ 69{
diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c
new file mode 100644
index 000000000000..989c14083066
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c
@@ -0,0 +1,212 @@
1/*
2 * Copyright 2018 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#include "head.h"
23#include "atom.h"
24#include "core.h"
25
26static void
27headc37d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
28{
29 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
30 u32 *push;
31 if ((push = evo_wait(core, 2))) {
32 /*XXX: This is a dirty hack until OR depth handling is
33 * improved later for deep colour etc.
34 */
35 switch (asyh->or.depth) {
36 case 6: asyh->or.depth = 5; break;
37 case 5: asyh->or.depth = 4; break;
38 case 2: asyh->or.depth = 1; break;
39 case 0: asyh->or.depth = 4; break;
40 default:
41 WARN_ON(1);
42 break;
43 }
44
45 evo_mthd(push, 0x2004 + (head->base.index * 0x400), 1);
46 evo_data(push, 0x00000001 |
47 asyh->or.depth << 4 |
48 asyh->or.nvsync << 3 |
49 asyh->or.nhsync << 2);
50 evo_kick(push, core);
51 }
52}
53
54static void
55headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
56{
57 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
58 u32 *push;
59 if ((push = evo_wait(core, 2))) {
60 evo_mthd(push, 0x2000 + (head->base.index * 0x400), 1);
61 evo_data(push, 0x80000000 |
62 asyh->procamp.sat.sin << 16 |
63 asyh->procamp.sat.cos << 4);
64 evo_kick(push, core);
65 }
66}
67
68static void
69headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
70{
71 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
72 u32 *push;
73 if ((push = evo_wait(core, 2))) {
74 evo_mthd(push, 0x2018 + (head->base.index * 0x0400), 1);
75 evo_data(push, asyh->dither.mode << 8 |
76 asyh->dither.bits << 4 |
77 asyh->dither.enable);
78 evo_kick(push, core);
79 }
80}
81
82static void
83headc37d_curs_clr(struct nv50_head *head)
84{
85 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
86 u32 *push;
87 if ((push = evo_wait(core, 4))) {
88 evo_mthd(push, 0x209c + head->base.index * 0x400, 1);
89 evo_data(push, 0x000000cf);
90 evo_mthd(push, 0x2088 + head->base.index * 0x400, 1);
91 evo_data(push, 0x00000000);
92 evo_kick(push, core);
93 }
94}
95
96static void
97headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
98{
99 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
100 u32 *push;
101 if ((push = evo_wait(core, 7))) {
102 evo_mthd(push, 0x209c + head->base.index * 0x400, 2);
103 evo_data(push, 0x80000000 |
104 asyh->curs.layout << 8 |
105 asyh->curs.format << 0);
106 evo_data(push, 0x000072ff);
107 evo_mthd(push, 0x2088 + head->base.index * 0x400, 1);
108 evo_data(push, asyh->curs.handle);
109 evo_mthd(push, 0x2090 + head->base.index * 0x400, 1);
110 evo_data(push, asyh->curs.offset >> 8);
111 evo_kick(push, core);
112 }
113}
114
115static int
116headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw,
117 struct nv50_head_atom *asyh)
118{
119 asyh->curs.format = asyw->image.format;
120 return 0;
121}
122
123static void
124headc37d_olut_clr(struct nv50_head *head)
125{
126 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
127 u32 *push;
128 if ((push = evo_wait(core, 2))) {
129 evo_mthd(push, 0x20ac + (head->base.index * 0x400), 1);
130 evo_data(push, 0x00000000);
131 evo_kick(push, core);
132 }
133}
134
135static void
136headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
137{
138 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
139 u32 *push;
140 if ((push = evo_wait(core, 4))) {
141 evo_mthd(push, 0x20a4 + (head->base.index * 0x400), 3);
142 evo_data(push, asyh->olut.output_mode << 8 |
143 asyh->olut.range << 4 |
144 asyh->olut.size);
145 evo_data(push, asyh->olut.offset >> 8);
146 evo_data(push, asyh->olut.handle);
147 evo_kick(push, core);
148 }
149}
150
151static void
152headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
153{
154 asyh->olut.mode = 2;
155 asyh->olut.size = 0;
156 asyh->olut.range = 0;
157 asyh->olut.output_mode = 1;
158}
159
160static void
161headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
162{
163 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
164 struct nv50_head_mode *m = &asyh->mode;
165 u32 *push;
166 if ((push = evo_wait(core, 12))) {
167 evo_mthd(push, 0x2064 + (head->base.index * 0x400), 5);
168 evo_data(push, (m->v.active << 16) | m->h.active );
169 evo_data(push, (m->v.synce << 16) | m->h.synce );
170 evo_data(push, (m->v.blanke << 16) | m->h.blanke );
171 evo_data(push, (m->v.blanks << 16) | m->h.blanks );
172 evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
173 evo_mthd(push, 0x200c + (head->base.index * 0x400), 1);
174 evo_data(push, m->clock * 1000);
175 evo_mthd(push, 0x2028 + (head->base.index * 0x400), 1);
176 evo_data(push, m->clock * 1000);
177 /*XXX: HEAD_USAGE_BOUNDS, doesn't belong here. */
178 evo_mthd(push, 0x2030 + (head->base.index * 0x400), 1);
179 evo_data(push, 0x00000124);
180 evo_kick(push, core);
181 }
182}
183
184static void
185headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
186{
187 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
188 u32 *push;
189 if ((push = evo_wait(core, 4))) {
190 evo_mthd(push, 0x204c + (head->base.index * 0x400), 1);
191 evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
192 evo_mthd(push, 0x2058 + (head->base.index * 0x400), 1);
193 evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
194 evo_kick(push, core);
195 }
196}
197
198const struct nv50_head_func
199headc37d = {
200 .view = headc37d_view,
201 .mode = headc37d_mode,
202 .olut = headc37d_olut,
203 .olut_set = headc37d_olut_set,
204 .olut_clr = headc37d_olut_clr,
205 .curs_layout = head917d_curs_layout,
206 .curs_format = headc37d_curs_format,
207 .curs_set = headc37d_curs_set,
208 .curs_clr = headc37d_curs_clr,
209 .dither = headc37d_dither,
210 .procamp = headc37d_procamp,
211 .or = headc37d_or,
212};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c b/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c
new file mode 100644
index 000000000000..dff059241c5d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c
@@ -0,0 +1,39 @@
1/*
2 * Copyright 2018 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#include "core.h"
23
24static void
25sorc37d_ctrl(struct nv50_core *core, int or, u32 ctrl,
26 struct nv50_head_atom *asyh)
27{
28 u32 *push;
29 if ((push = evo_wait(&core->chan, 2))) {
30 evo_mthd(push, 0x0300 + (or * 0x20), 1);
31 evo_data(push, ctrl);
32 evo_kick(push, &core->chan);
33 }
34}
35
36const struct nv50_outp_func
37sorc37d = {
38 .ctrl = sorc37d_ctrl,
39};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimm.c b/drivers/gpu/drm/nouveau/dispnv50/wimm.c
new file mode 100644
index 000000000000..fc36e0696407
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/wimm.c
@@ -0,0 +1,47 @@
1/*
2 * Copyright 2018 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#include "wimm.h"
23
24#include <nvif/class.h>
25
26int
27nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw)
28{
29 struct {
30 s32 oclass;
31 int version;
32 int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *);
33 } wimms[] = {
34 { GV100_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
35 {}
36 };
37 struct nv50_disp *disp = nv50_disp(drm->dev);
38 int cid;
39
40 cid = nvif_mclass(&disp->disp->object, wimms);
41 if (cid < 0) {
42 NV_ERROR(drm, "No supported window immediate class\n");
43 return cid;
44 }
45
46 return wimms[cid].init(drm, wimms[cid].oclass, wndw);
47}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimm.h b/drivers/gpu/drm/nouveau/dispnv50/wimm.h
new file mode 100644
index 000000000000..363052309be9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/wimm.h
@@ -0,0 +1,8 @@
1#ifndef __NV50_KMS_WIMM_H__
2#define __NV50_KMS_WIMM_H__
3#include "wndw.h"
4
5int nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *);
6
7int wimmc37b_init(struct nouveau_drm *, s32, struct nv50_wndw *);
8#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c
new file mode 100644
index 000000000000..9103b8494279
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright 2018 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#include "wimm.h"
23#include "atom.h"
24#include "wndw.h"
25
26#include <nvif/clc37b.h>
27
28static void
29wimmc37b_update(struct nv50_wndw *wndw, u32 *interlock)
30{
31 u32 *push;
32 if ((push = evo_wait(&wndw->wimm, 2))) {
33 evo_mthd(push, 0x0200, 1);
34 if (interlock[NV50_DISP_INTERLOCK_WNDW] & wndw->interlock.data)
35 evo_data(push, 0x00000003);
36 else
37 evo_data(push, 0x00000001);
38 evo_kick(push, &wndw->wimm);
39 }
40}
41
42static void
43wimmc37b_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
44{
45 u32 *push;
46 if ((push = evo_wait(&wndw->wimm, 2))) {
47 evo_mthd(push, 0x0208, 1);
48 evo_data(push, asyw->point.y << 16 | asyw->point.x);
49 evo_kick(push, &wndw->wimm);
50 }
51}
52
53static const struct nv50_wimm_func
54wimmc37b = {
55 .point = wimmc37b_point,
56 .update = wimmc37b_update,
57};
58
59static int
60wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
61 s32 oclass, struct nv50_wndw *wndw)
62{
63 struct nvc37b_window_imm_channel_dma_v0 args = {
64 .pushbuf = 0xb0007b00 | wndw->id,
65 .index = wndw->id,
66 };
67 struct nv50_disp *disp = nv50_disp(drm->dev);
68 int ret;
69
70 ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
71 &oclass, 0, &args, sizeof(args), 0,
72 &wndw->wimm);
73 if (ret) {
74 NV_ERROR(drm, "wimm%04x allocation failed: %d\n", oclass, ret);
75 return ret;
76 }
77
78 wndw->immd = func;
79 return 0;
80}
81
82int
83wimmc37b_init(struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw)
84{
85 return wimmc37b_init_(&wimmc37b, drm, oclass, wndw);
86}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index c7c08fae383f..224963b533a6 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -20,6 +20,7 @@
20 * OTHER DEALINGS IN THE SOFTWARE. 20 * OTHER DEALINGS IN THE SOFTWARE.
21 */ 21 */
22#include "wndw.h" 22#include "wndw.h"
23#include "wimm.h"
23 24
24#include <nvif/class.h> 25#include <nvif/class.h>
25#include <nvif/cl0002.h> 26#include <nvif/cl0002.h>
@@ -148,11 +149,15 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
148 149
149 if (asyw->set.scale) wndw->func->scale_set(wndw, asyw); 150 if (asyw->set.scale) wndw->func->scale_set(wndw, asyw);
150 if (asyw->set.point) { 151 if (asyw->set.point) {
152 if (asyw->set.point = false, asyw->set.mask)
153 interlock[wndw->interlock.type] |= wndw->interlock.data;
154 interlock[NV50_DISP_INTERLOCK_WIMM] |= wndw->interlock.data;
155
151 wndw->immd->point(wndw, asyw); 156 wndw->immd->point(wndw, asyw);
152 wndw->immd->update(wndw, interlock); 157 wndw->immd->update(wndw, interlock);
158 } else {
159 interlock[wndw->interlock.type] |= wndw->interlock.data;
153 } 160 }
154
155 interlock[wndw->interlock.type] |= wndw->interlock.data;
156} 161}
157 162
158void 163void
@@ -605,3 +610,32 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
605 wndw->notify.func = nv50_wndw_notify; 610 wndw->notify.func = nv50_wndw_notify;
606 return 0; 611 return 0;
607} 612}
613
614int
615nv50_wndw_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
616 struct nv50_wndw **pwndw)
617{
618 struct {
619 s32 oclass;
620 int version;
621 int (*new)(struct nouveau_drm *, enum drm_plane_type,
622 int, s32, struct nv50_wndw **);
623 } wndws[] = {
624 { GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new },
625 {}
626 };
627 struct nv50_disp *disp = nv50_disp(drm->dev);
628 int cid, ret;
629
630 cid = nvif_mclass(&disp->disp->object, wndws);
631 if (cid < 0) {
632 NV_ERROR(drm, "No supported window class\n");
633 return cid;
634 }
635
636 ret = wndws[cid].new(drm, type, index, wndws[cid].oclass, pwndw);
637 if (ret)
638 return ret;
639
640 return nv50_wimm_init(drm, *pwndw);
641}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
index 745304d06af1..b0b6428034b0 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
@@ -87,4 +87,10 @@ struct nv50_wimm_func {
87}; 87};
88 88
89extern const struct nv50_wimm_func curs507a; 89extern const struct nv50_wimm_func curs507a;
90
91int wndwc37e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
92 struct nv50_wndw **);
93
94int nv50_wndw_new(struct nouveau_drm *, enum drm_plane_type, int index,
95 struct nv50_wndw **);
90#endif 96#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
new file mode 100644
index 000000000000..44afb0f069a5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
@@ -0,0 +1,278 @@
1/*
2 * Copyright 2018 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#include "wndw.h"
23#include "atom.h"
24
25#include <drm/drm_atomic_helper.h>
26#include <drm/drm_plane_helper.h>
27#include <nouveau_bo.h>
28
29#include <nvif/clc37e.h>
30
31static void
32wndwc37e_ilut_clr(struct nv50_wndw *wndw)
33{
34 u32 *push;
35 if ((push = evo_wait(&wndw->wndw, 2))) {
36 evo_mthd(push, 0x02b8, 1);
37 evo_data(push, 0x00000000);
38 evo_kick(push, &wndw->wndw);
39 }
40}
41
42static void
43wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
44{
45 u32 *push;
46 if ((push = evo_wait(&wndw->wndw, 4))) {
47 evo_mthd(push, 0x02b0, 3);
48 evo_data(push, asyw->xlut.i.output_mode << 8 |
49 asyw->xlut.i.range << 4 |
50 asyw->xlut.i.size);
51 evo_data(push, asyw->xlut.i.offset >> 8);
52 evo_data(push, asyw->xlut.handle);
53 evo_kick(push, &wndw->wndw);
54 }
55}
56
57static void
58wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
59{
60 asyw->xlut.i.mode = 2;
61 asyw->xlut.i.size = 0;
62 asyw->xlut.i.range = 0;
63 asyw->xlut.i.output_mode = 1;
64}
65
66static void
67wndwc37e_image_clr(struct nv50_wndw *wndw)
68{
69 u32 *push;
70 if ((push = evo_wait(&wndw->wndw, 4))) {
71 evo_mthd(push, 0x0308, 1);
72 evo_data(push, 0x00000000);
73 evo_mthd(push, 0x0240, 1);
74 evo_data(push, 0x00000000);
75 evo_kick(push, &wndw->wndw);
76 }
77}
78
79static void
80wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
81{
82 u32 *push;
83
84 if (!(push = evo_wait(&wndw->wndw, 25)))
85 return;
86
87 evo_mthd(push, 0x0308, 1);
88 evo_data(push, asyw->image.mode << 4 | asyw->image.interval);
89 evo_mthd(push, 0x0224, 4);
90 evo_data(push, asyw->image.h << 16 | asyw->image.w);
91 evo_data(push, asyw->image.layout << 4 | asyw->image.blockh);
92 evo_data(push, asyw->image.colorspace << 8 | asyw->image.format);
93 evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6));
94 evo_mthd(push, 0x0240, 1);
95 evo_data(push, asyw->image.handle[0]);
96 evo_mthd(push, 0x0260, 1);
97 evo_data(push, asyw->image.offset[0] >> 8);
98 evo_mthd(push, 0x0290, 1);
99 evo_data(push, (asyw->state.src_y >> 16) << 16 |
100 (asyw->state.src_x >> 16));
101 evo_mthd(push, 0x0298, 1);
102 evo_data(push, (asyw->state.src_h >> 16) << 16 |
103 (asyw->state.src_w >> 16));
104 evo_mthd(push, 0x02a4, 1);
105 evo_data(push, asyw->state.crtc_h << 16 |
106 asyw->state.crtc_w);
107
108 /*XXX: Composition-related stuff. Need to implement properly. */
109 evo_mthd(push, 0x02ec, 1);
110 evo_data(push, (2 - (wndw->id & 1)) << 4);
111 evo_mthd(push, 0x02f4, 5);
112 evo_data(push, 0x00000011);
113 evo_data(push, 0xffff0000);
114 evo_data(push, 0xffff0000);
115 evo_data(push, 0xffff0000);
116 evo_data(push, 0xffff0000);
117 evo_kick(push, &wndw->wndw);
118}
119
120static void
121wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
122{
123 u32 *push;
124 if ((push = evo_wait(&wndw->wndw, 2))) {
125 evo_mthd(push, 0x021c, 1);
126 evo_data(push, 0x00000000);
127 evo_kick(push, &wndw->wndw);
128 }
129}
130
131static void
132wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
133{
134 u32 *push;
135 if ((push = evo_wait(&wndw->wndw, 3))) {
136 evo_mthd(push, 0x021c, 2);
137 evo_data(push, asyw->ntfy.handle);
138 evo_data(push, asyw->ntfy.offset | asyw->ntfy.awaken);
139 evo_kick(push, &wndw->wndw);
140 }
141}
142
143static void
144wndwc37e_sema_clr(struct nv50_wndw *wndw)
145{
146 u32 *push;
147 if ((push = evo_wait(&wndw->wndw, 2))) {
148 evo_mthd(push, 0x0218, 1);
149 evo_data(push, 0x00000000);
150 evo_kick(push, &wndw->wndw);
151 }
152}
153
154static void
155wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
156{
157 u32 *push;
158 if ((push = evo_wait(&wndw->wndw, 5))) {
159 evo_mthd(push, 0x020c, 4);
160 evo_data(push, asyw->sema.offset);
161 evo_data(push, asyw->sema.acquire);
162 evo_data(push, asyw->sema.release);
163 evo_data(push, asyw->sema.handle);
164 evo_kick(push, &wndw->wndw);
165 }
166}
167
168static void
169wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
170{
171 u32 *push;
172 if ((push = evo_wait(&wndw->wndw, 5))) {
173 evo_mthd(push, 0x0370, 2);
174 evo_data(push, interlock[NV50_DISP_INTERLOCK_CURS] << 1 |
175 interlock[NV50_DISP_INTERLOCK_CORE]);
176 evo_data(push, interlock[NV50_DISP_INTERLOCK_WNDW]);
177 evo_mthd(push, 0x0200, 1);
178 if (interlock[NV50_DISP_INTERLOCK_WIMM] & wndw->interlock.data)
179 evo_data(push, 0x00001001);
180 else
181 evo_data(push, 0x00000001);
182 evo_kick(push, &wndw->wndw);
183 }
184}
185
186static void
187wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
188 struct nv50_head_atom *asyh)
189{
190}
191
192static int
193wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
194 struct nv50_head_atom *asyh)
195{
196 return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
197 DRM_PLANE_HELPER_NO_SCALING,
198 DRM_PLANE_HELPER_NO_SCALING,
199 true, true);
200}
201
202static const u32
203wndwc37e_format[] = {
204 DRM_FORMAT_C8,
205 DRM_FORMAT_YUYV,
206 DRM_FORMAT_UYVY,
207 DRM_FORMAT_XRGB8888,
208 DRM_FORMAT_ARGB8888,
209 DRM_FORMAT_RGB565,
210 DRM_FORMAT_XRGB1555,
211 DRM_FORMAT_ARGB1555,
212 DRM_FORMAT_XBGR2101010,
213 DRM_FORMAT_ABGR2101010,
214 DRM_FORMAT_XBGR8888,
215 DRM_FORMAT_ABGR8888,
216 DRM_FORMAT_XRGB2101010,
217 DRM_FORMAT_ARGB2101010,
218 0
219};
220
221static const struct nv50_wndw_func
222wndwc37e = {
223 .acquire = wndwc37e_acquire,
224 .release = wndwc37e_release,
225 .sema_set = wndwc37e_sema_set,
226 .sema_clr = wndwc37e_sema_clr,
227 .ntfy_set = wndwc37e_ntfy_set,
228 .ntfy_clr = wndwc37e_ntfy_clr,
229 .ntfy_reset = corec37d_ntfy_init,
230 .ntfy_wait_begun = base507c_ntfy_wait_begun,
231 .ilut = wndwc37e_ilut,
232 .xlut_set = wndwc37e_ilut_set,
233 .xlut_clr = wndwc37e_ilut_clr,
234 .image_set = wndwc37e_image_set,
235 .image_clr = wndwc37e_image_clr,
236 .update = wndwc37e_update,
237};
238
239static int
240wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
241 enum drm_plane_type type, int index, s32 oclass, u32 heads,
242 struct nv50_wndw **pwndw)
243{
244 struct nvc37e_window_channel_dma_v0 args = {
245 .pushbuf = 0xb0007e00 | index,
246 .index = index,
247 };
248 struct nv50_disp *disp = nv50_disp(drm->dev);
249 struct nv50_wndw *wndw;
250 int ret;
251
252 ret = nv50_wndw_new_(func, drm->dev, type, "wndw", index,
253 wndwc37e_format, heads, NV50_DISP_INTERLOCK_WNDW,
254 BIT(index), &wndw);
255 if (*pwndw = wndw, ret)
256 return ret;
257
258 ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
259 &oclass, 0, &args, sizeof(args),
260 disp->sync->bo.offset, &wndw->wndw);
261 if (ret) {
262 NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret);
263 return ret;
264 }
265
266 wndw->ntfy = NV50_DISP_WNDW_NTFY(wndw->id);
267 wndw->sema = NV50_DISP_WNDW_SEM0(wndw->id);
268 wndw->data = 0x00000000;
269 return 0;
270}
271
272int
273wndwc37e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
274 s32 oclass, struct nv50_wndw **pwndw)
275{
276 return wndwc37e_new_(&wndwc37e, drm, type, index, oclass,
277 BIT(index >> 1), pwndw);
278}