diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c index 03a5bace661bc6da545b3000f2a4768f8b1f2632..546fb6c99ab154db858d6e29b4569a8050957111 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c @@ -21,8 +21,27 @@ */ #include "ior.h" +static void +gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640180 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + static const struct nvkm_ior_func gf119_dac = { + .state = gf119_dac_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c index 5e2dbd5de5113438ec9fd29980a4af60a35677f6..6598252888eed95f2abfb01f7604cb02694cf974 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c @@ -126,8 +126,27 @@ nv50_dac_power(NV50_DISP_MTHD_V1) return 0; } +static void +nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; +} + static const struct nvkm_ior_func nv50_dac = { + .state = nv50_dac_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index 2ffbb995f13424869e601e4fc9266e59e6a0ab25..a030a2820709156acce710359b8aec23bafbd3e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -362,6 +362,7 @@ gf119_disp_super(struct work_struct *work) if (disp->super & 0x00000001) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); + nv50_disp_super_1(disp); list_for_each_entry(head, &disp->base.head, head) { if (!(mask[head->id] & 0x00001000)) continue; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index fd33eed68a2e7b05fe2b2b590866831ec87c5244..ef9d23a3b77b845636e5595f866f9338c794f754 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -16,6 +16,8 @@ struct nvkm_ior { struct list_head head; struct nvkm_ior_state { + unsigned rgdiv; + unsigned proto_evo:4; enum nvkm_ior_proto { CRT, TMDS, @@ -23,6 +25,8 @@ struct nvkm_ior { DP, UNKNOWN } proto:3; + unsigned link:2; + unsigned head:4; } arm, asy; /* Armed DP state. */ @@ -35,6 +39,7 @@ struct nvkm_ior { }; struct nvkm_ior_func { + void (*state)(struct nvkm_ior *, struct nvkm_ior_state *); }; int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *, @@ -42,6 +47,10 @@ int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *, void nvkm_ior_del(struct nvkm_ior **); struct nvkm_ior *nvkm_ior_find(struct nvkm_disp *, enum nvkm_ior_type, int id); +void nv50_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +void gf119_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); + #define IOR_MSG(i,l,f,a...) do { \ struct nvkm_ior *_ior = (i); \ nvkm_##l(&_ior->disp->engine.subdev, "%s: "f, _ior->name, ##a); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 21bdf301d37e701720a082310b4e73050e1f1acf..99a94a65b1a368cffc4cbb8616649b25fff9a232 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -678,6 +678,23 @@ nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head) exec_script(disp, head, 1); } +void +nv50_disp_super_1(struct nv50_disp *disp) +{ + struct nvkm_head *head; + struct nvkm_ior *ior; + + list_for_each_entry(head, &disp->base.head, head) { + head->func->state(head, &head->arm); + head->func->state(head, &head->asy); + } + + list_for_each_entry(ior, &disp->base.ior, head) { + ior->func->state(ior, &ior->arm); + ior->func->state(ior, &ior->asy); + } +} + void nv50_disp_super(struct work_struct *work) { @@ -692,6 +709,7 @@ nv50_disp_super(struct work_struct *work) if (disp->super & 0x00000010) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); + nv50_disp_super_1(disp); list_for_each_entry(head, &disp->base.head, head) { if (!(super & (0x00000020 << head->id))) continue; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index fe7ef0abef6ef1ab47edd7bebbb3e12aca9f8797..0b1ea0b9394d9519755d6c2e938934721485c05c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -29,6 +29,8 @@ struct nv50_disp { struct nv50_disp_chan *chan[17]; }; +void nv50_disp_super_1(struct nv50_disp *); + int nv50_dac_power(NV50_DISP_MTHD_V1); int nv50_dac_sense(NV50_DISP_MTHD_V1); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c index f81ba52c8c19105755f2e71072006720fb02aa4b..73ec6d4ae55453a19d6263dfff5256e96eb5bef2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c @@ -121,8 +121,28 @@ nv50_pior_power(NV50_DISP_MTHD_V1) return 0; } +static void +nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + state->rgdiv = 1; + switch (state->proto_evo) { + case 0: state->proto = TMDS; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; +} + static const struct nvkm_ior_func nv50_pior = { + .state = nv50_pior_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c index 427e04c602e8b9656bdec10ba61ebdfc454ab862..5b467f0ca36cfc9c778c3afc0bca736a370e0050 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c @@ -23,6 +23,7 @@ static const struct nvkm_ior_func g84_sor = { + .state = nv50_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c index 87b097327e294f66530a489a3954b8cf32fea5cf..89dd16590470f3d4e5a3b774d2b923fd0a16398c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c @@ -278,8 +278,32 @@ nv50_disp_dptmds_war_2(struct nv50_disp *disp, struct dcb_output *outp) } } +void +g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610794 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; +} + static const struct nvkm_ior_func g94_sor = { + .state = g94_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c index 6ad8af038eaef56742ac436bdc52e97965d3e093..56ff9d92b14e9c5dae3ea07d9d9f1c8388025778 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c @@ -130,8 +130,32 @@ gf119_sor_dp_new(struct nvkm_disp *disp, int index, return nvkm_output_dp_new_(&gf119_sor_dp_func, disp, index, dcbE, poutp); } +void +gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640200 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + static const struct nvkm_ior_func gf119_sor = { + .state = gf119_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c index a1946eca85edd81dac6c4589ea7d8f2955826db8..e1d1fd25720ba6019a650cd070de6d58601078c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c @@ -23,6 +23,7 @@ static const struct nvkm_ior_func gk104_sor = { + .state = gf119_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c index 590d66002c589e8d3c2440329b402b0c125d95b9..96317c461b3c3d6b7f8bad5411c492f1fc63e1ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c @@ -55,6 +55,7 @@ gm107_sor_dp_new(struct nvkm_disp *disp, int index, static const struct nvkm_ior_func gm107_sor = { + .state = gf119_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c index df3917cb1cb944933acaf22f605ebbe1118a0441..cc4bea30bb9b678e460dce1f67b432b653466692 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c @@ -132,6 +132,7 @@ gm200_sor_magic(struct nvkm_output *outp) static const struct nvkm_ior_func gm200_sor = { + .state = gf119_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c index dc209826156e071387a630dd39f6179a2deb10e5..87d1c9ce4e7f9ca6c4d9140c7c73d2e9cf92d4f1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c @@ -23,6 +23,7 @@ static const struct nvkm_ior_func gt215_sor = { + .state = g94_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c index 09d42240510a732e4295fb23306f2335e909f14b..78ddffab7a93bf1d4acb6865ca226bd87f689a96 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c @@ -23,6 +23,7 @@ static const struct nvkm_ior_func mcp77_sor = { + .state = g94_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c index f8fba6caad339040dcab98a31f27e5b54c76a07a..97433c17db717494a26c88d84fbb3002d7c30e55 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c @@ -23,6 +23,7 @@ static const struct nvkm_ior_func mcp89_sor = { + .state = g94_sor_state, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c index fb43307466cd46b7ff0ba6395819cdf7649e6384..a1327e8fead1782c079284aa7573695b2a0adea8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c @@ -79,8 +79,30 @@ nv50_sor_power(NV50_DISP_MTHD_V1) return 0; } +void +nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; +} + static const struct nvkm_ior_func nv50_sor = { + .state = nv50_sor_state, }; int