aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2017-05-19 09:59:35 -0400
committerBen Skeggs <bskeggs@redhat.com>2017-06-16 00:04:59 -0400
commit327c5581d303183e9e56b50238034f419dcca3ce (patch)
tree3c085b9391d0a5360cef45f8ab69113d95f71928
parent99a845a30f62b926818412f337ad15218fb121ba (diff)
drm/nouveau/disp/nv50-: implement a common supervisor 1.0
This makes use of all the additional routing and state added in previous commits, making it possible to deal with GM20x macro link routing, while also sharing code between the NV50 and GF119 implementations. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c71
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h2
3 files changed, 70 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index 7a8dff7b8c95..e8bfb6ee89ae 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -177,12 +177,6 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
177} 177}
178 178
179static void 179static void
180gf119_disp_intr_unk1_0(struct nv50_disp *disp, int head)
181{
182 exec_script(disp, head, 1);
183}
184
185static void
186gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head) 180gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
187{ 181{
188 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 182 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
@@ -363,8 +357,7 @@ gf119_disp_super(struct work_struct *work)
363 list_for_each_entry(head, &disp->base.head, head) { 357 list_for_each_entry(head, &disp->base.head, head) {
364 if (!(mask[head->id] & 0x00001000)) 358 if (!(mask[head->id] & 0x00001000))
365 continue; 359 continue;
366 nvkm_debug(subdev, "supervisor 1.0 - head %d\n", head->id); 360 nv50_disp_super_1_0(disp, head);
367 gf119_disp_intr_unk1_0(disp, head->id);
368 } 361 }
369 } else 362 } else
370 if (disp->super & 0x00000002) { 363 if (disp->super & 0x00000002) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index c018dbdb121d..96d281568765 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -114,6 +114,60 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
114 return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent); 114 return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
115} 115}
116 116
117static u32
118nv50_disp_super_iedt(struct nvkm_head *head, struct nvkm_outp *outp,
119 u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
120 struct nvbios_outp *iedt)
121{
122 struct nvkm_bios *bios = head->disp->engine.subdev.device->bios;
123 const u8 l = ffs(outp->info.link);
124 const u16 t = outp->info.hasht;
125 const u16 m = (0x0100 << head->id) | (l << 6) | outp->info.or;
126 u32 data = nvbios_outp_match(bios, t, m, ver, hdr, cnt, len, iedt);
127 if (!data)
128 OUTP_DBG(outp, "missing IEDT for %04x:%04x", t, m);
129 return data;
130}
131
132static void
133nv50_disp_super_ied_off(struct nvkm_head *head, struct nvkm_ior *ior, int id)
134{
135 struct nvkm_outp *outp = ior->arm.outp;
136 struct nvbios_outp iedt;
137 u8 ver, hdr, cnt, len;
138 u32 data;
139
140 if (!outp) {
141 IOR_DBG(ior, "nothing attached");
142 return;
143 }
144
145 data = nv50_disp_super_iedt(head, outp, &ver, &hdr, &cnt, &len, &iedt);
146 if (!data)
147 return;
148
149 nvbios_init(&head->disp->engine.subdev, iedt.script[id],
150 init.outp = &outp->info;
151 init.or = ior->id;
152 init.link = ior->arm.link;
153 init.head = head->id;
154 );
155}
156
157static struct nvkm_ior *
158nv50_disp_super_ior_arm(struct nvkm_head *head)
159{
160 struct nvkm_ior *ior;
161 list_for_each_entry(ior, &head->disp->ior, head) {
162 if (ior->arm.head & (1 << head->id)) {
163 HEAD_DBG(head, "on %s", ior->name);
164 return ior;
165 }
166 }
167 HEAD_DBG(head, "nothing attached");
168 return NULL;
169}
170
117static struct nvkm_output * 171static struct nvkm_output *
118exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl, 172exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
119 u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 173 u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
@@ -582,10 +636,19 @@ nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
582 } 636 }
583} 637}
584 638
585static void 639void
586nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head) 640nv50_disp_super_1_0(struct nv50_disp *disp, struct nvkm_head *head)
587{ 641{
588 exec_script(disp, head, 1); 642 struct nvkm_ior *ior;
643
644 /* Determine which OR, if any, we're detaching from the head. */
645 HEAD_DBG(head, "supervisor 1.0");
646 ior = nv50_disp_super_ior_arm(head);
647 if (!ior)
648 return;
649
650 /* Execute OffInt1 IED script. */
651 nv50_disp_super_ied_off(head, ior, 1);
589} 652}
590 653
591void 654void
@@ -625,7 +688,7 @@ nv50_disp_super(struct work_struct *work)
625 continue; 688 continue;
626 if (!(super & (0x00000080 << head->id))) 689 if (!(super & (0x00000080 << head->id)))
627 continue; 690 continue;
628 nv50_disp_intr_unk10_0(disp, head->id); 691 nv50_disp_super_1_0(disp, head);
629 } 692 }
630 } else 693 } else
631 if (disp->super & 0x00000020) { 694 if (disp->super & 0x00000020) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
index 65d445687038..921ed0fa87f3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
@@ -3,6 +3,7 @@
3#define nv50_disp(p) container_of((p), struct nv50_disp, base) 3#define nv50_disp(p) container_of((p), struct nv50_disp, base)
4#include "priv.h" 4#include "priv.h"
5#include "dp.h" 5#include "dp.h"
6struct nvkm_head;
6 7
7struct nv50_disp { 8struct nv50_disp {
8 const struct nv50_disp_func *func; 9 const struct nv50_disp_func *func;
@@ -26,6 +27,7 @@ struct nv50_disp {
26}; 27};
27 28
28void nv50_disp_super_1(struct nv50_disp *); 29void nv50_disp_super_1(struct nv50_disp *);
30void nv50_disp_super_1_0(struct nv50_disp *, struct nvkm_head *);
29 31
30int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, 32int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *,
31 int index, int heads, struct nvkm_disp **); 33 int index, int heads, struct nvkm_disp **);