diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2017-05-19 09:59:35 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2017-06-16 00:04:58 -0400 |
commit | 9648da5a71c25e17d14feb0d7dc9ee73319e8a24 (patch) | |
tree | a1697de0d6eb9b8ad6e7b307545d11c73acc9c48 | |
parent | 6c22ea3747fd36409ce4a1e1a0cbac40f93e1e71 (diff) |
drm/nouveau/disp/dp: determine link bandwidth requirements from head state
Training/Untraining will be hooked up to the routing logic, which
doesn't allow us to pass in a data rate.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c | 1 |
7 files changed, 62 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 0f1c223cc7a8..4ad31302aaf4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | #include "dp.h" | 24 | #include "dp.h" |
25 | #include "conn.h" | 25 | #include "conn.h" |
26 | #include "head.h" | ||
26 | #include "ior.h" | 27 | #include "ior.h" |
27 | 28 | ||
28 | #include <subdev/bios.h> | 29 | #include <subdev/bios.h> |
@@ -419,19 +420,28 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps) | |||
419 | } | 420 | } |
420 | 421 | ||
421 | int | 422 | int |
422 | nvkm_output_dp_train(struct nvkm_outp *outp, u32 datakbps) | 423 | nvkm_output_dp_train(struct nvkm_outp *outp, u32 unused) |
423 | { | 424 | { |
424 | struct nvkm_dp *dp = nvkm_dp(outp); | 425 | struct nvkm_dp *dp = nvkm_dp(outp); |
425 | struct nvkm_ior *ior = dp->outp.ior; | 426 | struct nvkm_ior *ior = dp->outp.ior; |
427 | struct nvkm_head *head; | ||
426 | bool retrain = true; | 428 | bool retrain = true; |
427 | u32 linkKBps; | 429 | u32 datakbps = 0; |
428 | u32 dataKBps; | 430 | u32 dataKBps; |
431 | u32 linkKBps; | ||
429 | u8 stat[3]; | 432 | u8 stat[3]; |
430 | int ret, i; | 433 | int ret, i; |
431 | 434 | ||
432 | mutex_lock(&dp->mutex); | 435 | mutex_lock(&dp->mutex); |
433 | 436 | ||
434 | /* Check that link configuration meets current requirements. */ | 437 | /* Check that link configuration meets current requirements. */ |
438 | list_for_each_entry(head, &outp->disp->head, head) { | ||
439 | if (ior->asy.head & (1 << head->id)) { | ||
440 | u32 khz = (head->asy.hz >> ior->asy.rgdiv) / 1000; | ||
441 | datakbps += khz * head->asy.or.depth; | ||
442 | } | ||
443 | } | ||
444 | |||
435 | linkKBps = ior->dp.bw * 27000 * ior->dp.nr; | 445 | linkKBps = ior->dp.bw * 27000 * ior->dp.nr; |
436 | dataKBps = DIV_ROUND_UP(datakbps, 8); | 446 | dataKBps = DIV_ROUND_UP(datakbps, 8); |
437 | OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d", | 447 | OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d", |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index 94f5cb7596a0..829a0a8cfb2e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h | |||
@@ -18,6 +18,12 @@ struct nvkm_head { | |||
18 | u16 vsynce; | 18 | u16 vsynce; |
19 | u16 vblanke; | 19 | u16 vblanke; |
20 | u16 vblanks; | 20 | u16 vblanks; |
21 | u32 hz; | ||
22 | |||
23 | /* Prior to GF119, these are set by the OR. */ | ||
24 | struct { | ||
25 | u8 depth; | ||
26 | } or; | ||
21 | } arm, asy; | 27 | } arm, asy; |
22 | }; | 28 | }; |
23 | 29 | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c index 8e7acc57d31d..d2bd6bb4a621 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c | |||
@@ -58,6 +58,19 @@ gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) | |||
58 | data = nvkm_rd32(device, 0x640420 + hoff); | 58 | data = nvkm_rd32(device, 0x640420 + hoff); |
59 | state->vblanks = (data & 0xffff0000) >> 16; | 59 | state->vblanks = (data & 0xffff0000) >> 16; |
60 | state->hblanks = (data & 0x0000ffff); | 60 | state->hblanks = (data & 0x0000ffff); |
61 | state->hz = nvkm_rd32(device, 0x640450 + hoff); | ||
62 | |||
63 | data = nvkm_rd32(device, 0x640404 + hoff); | ||
64 | switch ((data & 0x000003c0) >> 6) { | ||
65 | case 6: state->or.depth = 30; break; | ||
66 | case 5: state->or.depth = 24; break; | ||
67 | case 2: state->or.depth = 18; break; | ||
68 | case 0: state->or.depth = 18; break; /*XXX: "default" */ | ||
69 | default: | ||
70 | state->or.depth = 18; | ||
71 | WARN_ON(1); | ||
72 | break; | ||
73 | } | ||
61 | } | 74 | } |
62 | 75 | ||
63 | static const struct nvkm_head_func | 76 | static const struct nvkm_head_func |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c index 3cccda2cb09e..d4a9879f0d0a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c | |||
@@ -66,6 +66,7 @@ nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) | |||
66 | data = nvkm_rd32(device, 0x610b00 + hoff); | 66 | data = nvkm_rd32(device, 0x610b00 + hoff); |
67 | state->vsynce = (data & 0xffff0000) >> 16; | 67 | state->vsynce = (data & 0xffff0000) >> 16; |
68 | state->hsynce = (data & 0x0000ffff); | 68 | state->hsynce = (data & 0x0000ffff); |
69 | state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; | ||
69 | } | 70 | } |
70 | 71 | ||
71 | static const struct nvkm_head_func | 72 | static const struct nvkm_head_func |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index a2e38d4780b1..3a6e01f5a0e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h | |||
@@ -89,6 +89,8 @@ nv50_ior_base(struct nvkm_ior *ior) | |||
89 | void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool); | 89 | void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool); |
90 | int nv50_dac_sense(struct nvkm_ior *, u32); | 90 | int nv50_dac_sense(struct nvkm_ior *, u32); |
91 | 91 | ||
92 | void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); | ||
93 | |||
92 | static inline u32 | 94 | static inline u32 |
93 | nv50_sor_link(struct nvkm_ior *ior) | 95 | nv50_sor_link(struct nvkm_ior *ior) |
94 | { | 96 | { |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c index f66beda1ae11..dc59c319377e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c | |||
@@ -22,6 +22,7 @@ | |||
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | #include "ior.h" | 24 | #include "ior.h" |
25 | #include "head.h" | ||
25 | 26 | ||
26 | #include <subdev/i2c.h> | 27 | #include <subdev/i2c.h> |
27 | #include <subdev/timer.h> | 28 | #include <subdev/timer.h> |
@@ -60,6 +61,31 @@ nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, | |||
60 | nv50_pior_power_wait(device, poff); | 61 | nv50_pior_power_wait(device, poff); |
61 | } | 62 | } |
62 | 63 | ||
64 | void | ||
65 | nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) | ||
66 | { | ||
67 | /* GF119 moves this information to per-head methods, which is | ||
68 | * a lot more convenient, and where our shared code expect it. | ||
69 | */ | ||
70 | if (state->head && state == &ior->asy) { | ||
71 | struct nvkm_head *head = | ||
72 | nvkm_head_find(ior->disp, __ffs(state->head)); | ||
73 | if (!WARN_ON(!head)) { | ||
74 | struct nvkm_head_state *state = &head->asy; | ||
75 | switch ((ctrl & 0x000f0000) >> 16) { | ||
76 | case 6: state->or.depth = 30; break; | ||
77 | case 5: state->or.depth = 24; break; | ||
78 | case 2: state->or.depth = 18; break; | ||
79 | case 0: state->or.depth = 18; break; /*XXX*/ | ||
80 | default: | ||
81 | state->or.depth = 18; | ||
82 | WARN_ON(1); | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
63 | static void | 89 | static void |
64 | nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) | 90 | nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) |
65 | { | 91 | { |
@@ -77,6 +103,7 @@ nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) | |||
77 | } | 103 | } |
78 | 104 | ||
79 | state->head = ctrl & 0x00000003; | 105 | state->head = ctrl & 0x00000003; |
106 | nv50_pior_depth(pior, state, ctrl); | ||
80 | } | 107 | } |
81 | 108 | ||
82 | static const struct nvkm_ior_func | 109 | static const struct nvkm_ior_func |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c index bfc7b0e053a4..5abf563b0e84 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c | |||
@@ -238,6 +238,7 @@ g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) | |||
238 | } | 238 | } |
239 | 239 | ||
240 | state->head = ctrl & 0x00000003; | 240 | state->head = ctrl & 0x00000003; |
241 | nv50_pior_depth(sor, state, ctrl); | ||
241 | } | 242 | } |
242 | 243 | ||
243 | static const struct nvkm_ior_func | 244 | static const struct nvkm_ior_func |