diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2018-05-08 06:39:48 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2018-05-18 01:01:46 -0400 |
commit | facaed62b4cba3a6334fc1798fa8f51ea6a1962d (patch) | |
tree | 5c05fb78990e9a0b920312974c8d2ab61411b3bb | |
parent | 290ffeafcc1a953aa287c8a7bf7f6d9af25b7e77 (diff) |
drm/nouveau/kms/gv100: initial support
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
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 | |||
6 | nouveau-y += dispnv50/core827d.o | 6 | nouveau-y += dispnv50/core827d.o |
7 | nouveau-y += dispnv50/core907d.o | 7 | nouveau-y += dispnv50/core907d.o |
8 | nouveau-y += dispnv50/core917d.o | 8 | nouveau-y += dispnv50/core917d.o |
9 | nouveau-y += dispnv50/corec37d.o | ||
9 | 10 | ||
10 | nouveau-y += dispnv50/dac507d.o | 11 | nouveau-y += dispnv50/dac507d.o |
11 | nouveau-y += dispnv50/dac907d.o | 12 | nouveau-y += dispnv50/dac907d.o |
@@ -14,14 +15,20 @@ nouveau-y += dispnv50/pior507d.o | |||
14 | 15 | ||
15 | nouveau-y += dispnv50/sor507d.o | 16 | nouveau-y += dispnv50/sor507d.o |
16 | nouveau-y += dispnv50/sor907d.o | 17 | nouveau-y += dispnv50/sor907d.o |
18 | nouveau-y += dispnv50/sorc37d.o | ||
17 | 19 | ||
18 | nouveau-y += dispnv50/head.o | 20 | nouveau-y += dispnv50/head.o |
19 | nouveau-y += dispnv50/head507d.o | 21 | nouveau-y += dispnv50/head507d.o |
20 | nouveau-y += dispnv50/head827d.o | 22 | nouveau-y += dispnv50/head827d.o |
21 | nouveau-y += dispnv50/head907d.o | 23 | nouveau-y += dispnv50/head907d.o |
22 | nouveau-y += dispnv50/head917d.o | 24 | nouveau-y += dispnv50/head917d.o |
25 | nouveau-y += dispnv50/headc37d.o | ||
26 | |||
27 | nouveau-y += dispnv50/wimm.o | ||
28 | nouveau-y += dispnv50/wimmc37b.o | ||
23 | 29 | ||
24 | nouveau-y += dispnv50/wndw.o | 30 | nouveau-y += dispnv50/wndw.o |
31 | nouveau-y += dispnv50/wndwc37e.o | ||
25 | 32 | ||
26 | nouveau-y += dispnv50/base.o | 33 | nouveau-y += dispnv50/base.o |
27 | nouveau-y += dispnv50/base507c.o | 34 | nouveau-y += dispnv50/base507c.o |
@@ -32,6 +39,7 @@ nouveau-y += dispnv50/base917c.o | |||
32 | nouveau-y += dispnv50/curs.o | 39 | nouveau-y += dispnv50/curs.o |
33 | nouveau-y += dispnv50/curs507a.o | 40 | nouveau-y += dispnv50/curs507a.o |
34 | nouveau-y += dispnv50/curs907a.o | 41 | nouveau-y += dispnv50/curs907a.o |
42 | nouveau-y += dispnv50/cursc37a.o | ||
35 | 43 | ||
36 | nouveau-y += dispnv50/oimm.o | 44 | nouveau-y += dispnv50/oimm.o |
37 | nouveau-y += dispnv50/oimm507b.o | 45 | nouveau-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; | |||
44 | extern const struct nv50_outp_func sor907d; | 44 | extern const struct nv50_outp_func sor907d; |
45 | 45 | ||
46 | int core917d_new(struct nouveau_drm *, s32, struct nv50_core **); | 46 | int core917d_new(struct nouveau_drm *, s32, struct nv50_core **); |
47 | |||
48 | int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **); | ||
49 | extern 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 | |||
27 | static void | ||
28 | corec37d_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 | |||
51 | int | ||
52 | corec37d_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 | |||
65 | void | ||
66 | corec37d_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 | |||
74 | void | ||
75 | corec37d_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 | |||
96 | static const struct nv50_core_func | ||
97 | corec37d = { | ||
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 | |||
106 | int | ||
107 | corec37d_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 | ||
10 | int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); | 10 | int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); |
11 | int cursc37a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); | ||
11 | 12 | ||
12 | int nv50_curs_new(struct nouveau_drm *, int head, struct nv50_wndw **); | 13 | int 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 | |||
25 | static void | ||
26 | cursc37a_update(struct nv50_wndw *wndw, u32 *interlock) | ||
27 | { | ||
28 | nvif_wr32(&wndw->wimm.base.user, 0x0200, 0x00000001); | ||
29 | } | ||
30 | |||
31 | static void | ||
32 | cursc37a_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 | |||
38 | static const struct nv50_wimm_func | ||
39 | cursc37a = { | ||
40 | .point = cursc37a_point, | ||
41 | .update = cursc37a_update, | ||
42 | }; | ||
43 | |||
44 | int | ||
45 | cursc37a_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 | ||
46 | void corec37d_ntfy_init(struct nouveau_bo *, u32); | ||
47 | |||
44 | struct nv50_chan { | 48 | struct 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); | ||
500 | out: | 507 | out: |
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 *); | |||
71 | void head907d_or(struct nv50_head *, struct nv50_head_atom *); | 71 | void head907d_or(struct nv50_head *, struct nv50_head_atom *); |
72 | 72 | ||
73 | extern const struct nv50_head_func head917d; | 73 | extern const struct nv50_head_func head917d; |
74 | int head917d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *, | ||
75 | struct nv50_head_atom *); | ||
76 | |||
77 | extern 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 | ||
66 | static int | 66 | int |
67 | head917d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw, | 67 | head917d_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 | |||
26 | static void | ||
27 | headc37d_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 | |||
54 | static void | ||
55 | headc37d_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 | |||
68 | static void | ||
69 | headc37d_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 | |||
82 | static void | ||
83 | headc37d_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 | |||
96 | static void | ||
97 | headc37d_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 | |||
115 | static int | ||
116 | headc37d_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 | |||
123 | static void | ||
124 | headc37d_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 | |||
135 | static void | ||
136 | headc37d_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 | |||
151 | static void | ||
152 | headc37d_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 | |||
160 | static void | ||
161 | headc37d_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 | |||
184 | static void | ||
185 | headc37d_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 | |||
198 | const struct nv50_head_func | ||
199 | headc37d = { | ||
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 | |||
24 | static void | ||
25 | sorc37d_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 | |||
36 | const struct nv50_outp_func | ||
37 | sorc37d = { | ||
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 | |||
26 | int | ||
27 | nv50_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 | |||
5 | int nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *); | ||
6 | |||
7 | int 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 | |||
28 | static void | ||
29 | wimmc37b_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 | |||
42 | static void | ||
43 | wimmc37b_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 | |||
53 | static const struct nv50_wimm_func | ||
54 | wimmc37b = { | ||
55 | .point = wimmc37b_point, | ||
56 | .update = wimmc37b_update, | ||
57 | }; | ||
58 | |||
59 | static int | ||
60 | wimmc37b_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 | |||
82 | int | ||
83 | wimmc37b_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 | ||
158 | void | 163 | void |
@@ -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 | |||
614 | int | ||
615 | nv50_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 | ||
89 | extern const struct nv50_wimm_func curs507a; | 89 | extern const struct nv50_wimm_func curs507a; |
90 | |||
91 | int wndwc37e_new(struct nouveau_drm *, enum drm_plane_type, int, s32, | ||
92 | struct nv50_wndw **); | ||
93 | |||
94 | int 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 | |||
31 | static void | ||
32 | wndwc37e_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 | |||
42 | static void | ||
43 | wndwc37e_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 | |||
57 | static void | ||
58 | wndwc37e_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 | |||
66 | static void | ||
67 | wndwc37e_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 | |||
79 | static void | ||
80 | wndwc37e_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 | |||
120 | static void | ||
121 | wndwc37e_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 | |||
131 | static void | ||
132 | wndwc37e_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 | |||
143 | static void | ||
144 | wndwc37e_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 | |||
154 | static void | ||
155 | wndwc37e_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 | |||
168 | static void | ||
169 | wndwc37e_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 | |||
186 | static void | ||
187 | wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, | ||
188 | struct nv50_head_atom *asyh) | ||
189 | { | ||
190 | } | ||
191 | |||
192 | static int | ||
193 | wndwc37e_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 | |||
202 | static const u32 | ||
203 | wndwc37e_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 | |||
221 | static const struct nv50_wndw_func | ||
222 | wndwc37e = { | ||
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 | |||
239 | static int | ||
240 | wndwc37e_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 | |||
272 | int | ||
273 | wndwc37e_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 | } | ||