Commit f7b2ece3 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/disp/nv50-: fetch mask of available heads during oneinit

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 3b9ba66a
...@@ -32,7 +32,7 @@ g84_disp = { ...@@ -32,7 +32,7 @@ g84_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &g84_disp_root_oclass, .root = &g84_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 2, .new = g84_sor_new }, .sor = { .nr = 2, .new = g84_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -41,5 +41,5 @@ g84_disp = { ...@@ -41,5 +41,5 @@ g84_disp = {
int int
g84_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) g84_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&g84_disp, device, index, 2, pdisp); return nv50_disp_new_(&g84_disp, device, index, pdisp);
} }
...@@ -32,7 +32,7 @@ g94_disp = { ...@@ -32,7 +32,7 @@ g94_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &g94_disp_root_oclass, .root = &g94_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = g94_sor_new }, .sor = { .nr = 4, .new = g94_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -41,5 +41,5 @@ g94_disp = { ...@@ -41,5 +41,5 @@ g94_disp = {
int int
g94_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) g94_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&g94_disp, device, index, 2, pdisp); return nv50_disp_new_(&g94_disp, device, index, pdisp);
} }
...@@ -164,14 +164,6 @@ gf119_disp_intr(struct nv50_disp *disp) ...@@ -164,14 +164,6 @@ gf119_disp_intr(struct nv50_disp *disp)
} }
} }
int
gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
int index, struct nvkm_disp **pdisp)
{
u32 heads = nvkm_rd32(device, 0x022448);
return nv50_disp_new_(func, device, index, heads, pdisp);
}
static const struct nv50_disp_func static const struct nv50_disp_func
gf119_disp = { gf119_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
...@@ -179,7 +171,7 @@ gf119_disp = { ...@@ -179,7 +171,7 @@ gf119_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gf119_disp_root_oclass, .root = &gf119_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.dac = { .nr = 3, .new = gf119_dac_new }, .dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gf119_sor_new }, .sor = { .nr = 4, .new = gf119_sor_new },
}; };
...@@ -187,5 +179,5 @@ gf119_disp = { ...@@ -187,5 +179,5 @@ gf119_disp = {
int int
gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gf119_disp, device, index, pdisp); return nv50_disp_new_(&gf119_disp, device, index, pdisp);
} }
...@@ -33,7 +33,7 @@ gk104_disp = { ...@@ -33,7 +33,7 @@ gk104_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gk104_disp_root_oclass, .root = &gk104_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.dac = { .nr = 3, .new = gf119_dac_new }, .dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gk104_sor_new }, .sor = { .nr = 4, .new = gk104_sor_new },
}; };
...@@ -41,5 +41,5 @@ gk104_disp = { ...@@ -41,5 +41,5 @@ gk104_disp = {
int int
gk104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gk104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gk104_disp, device, index, pdisp); return nv50_disp_new_(&gk104_disp, device, index, pdisp);
} }
...@@ -33,7 +33,7 @@ gk110_disp = { ...@@ -33,7 +33,7 @@ gk110_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gk110_disp_root_oclass, .root = &gk110_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.dac = { .nr = 3, .new = gf119_dac_new }, .dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gk104_sor_new }, .sor = { .nr = 4, .new = gk104_sor_new },
}; };
...@@ -41,5 +41,5 @@ gk110_disp = { ...@@ -41,5 +41,5 @@ gk110_disp = {
int int
gk110_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gk110_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gk110_disp, device, index, pdisp); return nv50_disp_new_(&gk110_disp, device, index, pdisp);
} }
...@@ -33,7 +33,7 @@ gm107_disp = { ...@@ -33,7 +33,7 @@ gm107_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gm107_disp_root_oclass, .root = &gm107_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.dac = { .nr = 3, .new = gf119_dac_new }, .dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gm107_sor_new }, .sor = { .nr = 4, .new = gm107_sor_new },
}; };
...@@ -41,5 +41,5 @@ gm107_disp = { ...@@ -41,5 +41,5 @@ gm107_disp = {
int int
gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gm107_disp, device, index, pdisp); return nv50_disp_new_(&gm107_disp, device, index, pdisp);
} }
...@@ -33,7 +33,7 @@ gm200_disp = { ...@@ -33,7 +33,7 @@ gm200_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gm200_disp_root_oclass, .root = &gm200_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.dac = { .nr = 3, .new = gf119_dac_new }, .dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gm200_sor_new }, .sor = { .nr = 4, .new = gm200_sor_new },
}; };
...@@ -41,5 +41,5 @@ gm200_disp = { ...@@ -41,5 +41,5 @@ gm200_disp = {
int int
gm200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gm200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gm200_disp, device, index, pdisp); return nv50_disp_new_(&gm200_disp, device, index, pdisp);
} }
...@@ -33,12 +33,12 @@ gp100_disp = { ...@@ -33,12 +33,12 @@ gp100_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gp100_disp_root_oclass, .root = &gp100_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.sor = { .nr = 4, .new = gm200_sor_new }, .sor = { .nr = 4, .new = gm200_sor_new },
}; };
int int
gp100_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gp100_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gp100_disp, device, index, pdisp); return nv50_disp_new_(&gp100_disp, device, index, pdisp);
} }
...@@ -59,12 +59,12 @@ gp102_disp = { ...@@ -59,12 +59,12 @@ gp102_disp = {
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_super, .super = gf119_disp_super,
.root = &gp102_disp_root_oclass, .root = &gp102_disp_root_oclass,
.head.new = gf119_head_new, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
.sor = { .nr = 4, .new = gm200_sor_new }, .sor = { .nr = 4, .new = gm200_sor_new },
}; };
int int
gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return gf119_disp_new_(&gp102_disp, device, index, pdisp); return nv50_disp_new_(&gp102_disp, device, index, pdisp);
} }
...@@ -32,7 +32,7 @@ gt200_disp = { ...@@ -32,7 +32,7 @@ gt200_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &gt200_disp_root_oclass, .root = &gt200_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 2, .new = g84_sor_new }, .sor = { .nr = 2, .new = g84_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -41,5 +41,5 @@ gt200_disp = { ...@@ -41,5 +41,5 @@ gt200_disp = {
int int
gt200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gt200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&gt200_disp, device, index, 2, pdisp); return nv50_disp_new_(&gt200_disp, device, index, pdisp);
} }
...@@ -32,7 +32,7 @@ gt215_disp = { ...@@ -32,7 +32,7 @@ gt215_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &gt215_disp_root_oclass, .root = &gt215_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = gt215_sor_new }, .sor = { .nr = 4, .new = gt215_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -41,5 +41,5 @@ gt215_disp = { ...@@ -41,5 +41,5 @@ gt215_disp = {
int int
gt215_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) gt215_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&gt215_disp, device, index, 2, pdisp); return nv50_disp_new_(&gt215_disp, device, index, pdisp);
} }
...@@ -52,6 +52,10 @@ void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); ...@@ -52,6 +52,10 @@ void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *);
#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) #define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a)
int nv04_head_new(struct nvkm_disp *, int id); int nv04_head_new(struct nvkm_disp *, int id);
int nv50_head_cnt(struct nvkm_disp *, unsigned long *);
int nv50_head_new(struct nvkm_disp *, int id); int nv50_head_new(struct nvkm_disp *, int id);
int gf119_head_cnt(struct nvkm_disp *, unsigned long *);
int gf119_head_new(struct nvkm_disp *, int id); int gf119_head_new(struct nvkm_disp *, int id);
#endif #endif
...@@ -92,8 +92,13 @@ gf119_head = { ...@@ -92,8 +92,13 @@ gf119_head = {
int int
gf119_head_new(struct nvkm_disp *disp, int id) gf119_head_new(struct nvkm_disp *disp, int id)
{ {
struct nvkm_device *device = disp->engine.subdev.device;
if (!(nvkm_rd32(device, 0x612004) & (0x00000001 << id)))
return 0;
return nvkm_head_new_(&gf119_head, disp, id); return nvkm_head_new_(&gf119_head, disp, id);
} }
int
gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask)
{
struct nvkm_device *device = disp->engine.subdev.device;
*pmask = nvkm_rd32(device, 0x612004) & 0x0000000f;
return nvkm_rd32(device, 0x022448);
}
...@@ -90,3 +90,10 @@ nv50_head_new(struct nvkm_disp *disp, int id) ...@@ -90,3 +90,10 @@ nv50_head_new(struct nvkm_disp *disp, int id)
{ {
return nvkm_head_new_(&nv50_head, disp, id); return nvkm_head_new_(&nv50_head, disp, id);
} }
int
nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask)
{
*pmask = 3;
return 2;
}
...@@ -30,7 +30,7 @@ mcp77_disp = { ...@@ -30,7 +30,7 @@ mcp77_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &g94_disp_root_oclass, .root = &g94_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = mcp77_sor_new }, .sor = { .nr = 4, .new = mcp77_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -39,5 +39,5 @@ mcp77_disp = { ...@@ -39,5 +39,5 @@ mcp77_disp = {
int int
mcp77_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) mcp77_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&mcp77_disp, device, index, 2, pdisp); return nv50_disp_new_(&mcp77_disp, device, index, pdisp);
} }
...@@ -30,7 +30,7 @@ mcp89_disp = { ...@@ -30,7 +30,7 @@ mcp89_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &gt215_disp_root_oclass, .root = &gt215_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = mcp89_sor_new }, .sor = { .nr = 4, .new = mcp89_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -39,5 +39,5 @@ mcp89_disp = { ...@@ -39,5 +39,5 @@ mcp89_disp = {
int int
mcp89_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) mcp89_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&mcp89_disp, device, index, 2, pdisp); return nv50_disp_new_(&mcp89_disp, device, index, pdisp);
} }
...@@ -64,9 +64,13 @@ nv50_disp_oneinit_(struct nvkm_disp *base) ...@@ -64,9 +64,13 @@ nv50_disp_oneinit_(struct nvkm_disp *base)
{ {
struct nv50_disp *disp = nv50_disp(base); struct nv50_disp *disp = nv50_disp(base);
const struct nv50_disp_func *func = disp->func; const struct nv50_disp_func *func = disp->func;
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
int ret, i; int ret, i;
for (i = 0; func->head.new && i < disp->head.nr; i++) { disp->head.nr = func->head.cnt(&disp->base, &disp->head.mask);
nvkm_debug(subdev, " Head(s): %d (%02lx)\n",
disp->head.nr, disp->head.mask);
for_each_set_bit(i, &disp->head.mask, disp->head.nr) {
ret = func->head.new(&disp->base, i); ret = func->head.new(&disp->base, i);
if (ret) if (ret)
return ret; return ret;
...@@ -103,7 +107,7 @@ nv50_disp_ = { ...@@ -103,7 +107,7 @@ nv50_disp_ = {
int int
nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
int index, int heads, struct nvkm_disp **pdisp) int index, struct nvkm_disp **pdisp)
{ {
struct nv50_disp *disp; struct nv50_disp *disp;
int ret; int ret;
...@@ -122,7 +126,6 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, ...@@ -122,7 +126,6 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
return -ENOMEM; return -ENOMEM;
INIT_WORK(&disp->supervisor, func->super); INIT_WORK(&disp->supervisor, func->super);
disp->head.nr = heads;
return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan),
&disp->uevent); &disp->uevent);
...@@ -633,7 +636,7 @@ nv50_disp = { ...@@ -633,7 +636,7 @@ nv50_disp = {
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super, .super = nv50_disp_super,
.root = &nv50_disp_root_oclass, .root = &nv50_disp_root_oclass,
.head.new = nv50_head_new, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
.dac = { .nr = 3, .new = nv50_dac_new }, .dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 2, .new = nv50_sor_new }, .sor = { .nr = 2, .new = nv50_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new }, .pior = { .nr = 3, .new = nv50_pior_new },
...@@ -642,5 +645,5 @@ nv50_disp = { ...@@ -642,5 +645,5 @@ nv50_disp = {
int int
nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{ {
return nv50_disp_new_(&nv50_disp, device, index, 2, pdisp); return nv50_disp_new_(&nv50_disp, device, index, pdisp);
} }
...@@ -16,6 +16,7 @@ struct nv50_disp { ...@@ -16,6 +16,7 @@ struct nv50_disp {
struct nvkm_event uevent; struct nvkm_event uevent;
struct { struct {
unsigned long mask;
int nr; int nr;
} head; } head;
...@@ -38,8 +39,6 @@ void nv50_disp_super_2_2(struct nv50_disp *, struct nvkm_head *); ...@@ -38,8 +39,6 @@ void nv50_disp_super_2_2(struct nv50_disp *, struct nvkm_head *);
void nv50_disp_super_3_0(struct nv50_disp *, struct nvkm_head *); void nv50_disp_super_3_0(struct nv50_disp *, struct nvkm_head *);
int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *,
int index, int heads, struct nvkm_disp **);
int gf119_disp_new_(const struct nv50_disp_func *, struct nvkm_device *,
int index, struct nvkm_disp **); int index, struct nvkm_disp **);
struct nv50_disp_func { struct nv50_disp_func {
...@@ -52,6 +51,7 @@ struct nv50_disp_func { ...@@ -52,6 +51,7 @@ struct nv50_disp_func {
const struct nvkm_disp_oclass *root; const struct nvkm_disp_oclass *root;
struct { struct {
int (*cnt)(struct nvkm_disp *, unsigned long *mask);
int (*new)(struct nvkm_disp *, int id); int (*new)(struct nvkm_disp *, int id);
} head; } head;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment