Commit 9648da5a authored by Ben Skeggs's avatar Ben Skeggs

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6c22ea37
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include "dp.h" #include "dp.h"
#include "conn.h" #include "conn.h"
#include "head.h"
#include "ior.h" #include "ior.h"
#include <subdev/bios.h> #include <subdev/bios.h>
...@@ -419,19 +420,28 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps) ...@@ -419,19 +420,28 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps)
} }
int int
nvkm_output_dp_train(struct nvkm_outp *outp, u32 datakbps) nvkm_output_dp_train(struct nvkm_outp *outp, u32 unused)
{ {
struct nvkm_dp *dp = nvkm_dp(outp); struct nvkm_dp *dp = nvkm_dp(outp);
struct nvkm_ior *ior = dp->outp.ior; struct nvkm_ior *ior = dp->outp.ior;
struct nvkm_head *head;
bool retrain = true; bool retrain = true;
u32 linkKBps; u32 datakbps = 0;
u32 dataKBps; u32 dataKBps;
u32 linkKBps;
u8 stat[3]; u8 stat[3];
int ret, i; int ret, i;
mutex_lock(&dp->mutex); mutex_lock(&dp->mutex);
/* Check that link configuration meets current requirements. */ /* Check that link configuration meets current requirements. */
list_for_each_entry(head, &outp->disp->head, head) {
if (ior->asy.head & (1 << head->id)) {
u32 khz = (head->asy.hz >> ior->asy.rgdiv) / 1000;
datakbps += khz * head->asy.or.depth;
}
}
linkKBps = ior->dp.bw * 27000 * ior->dp.nr; linkKBps = ior->dp.bw * 27000 * ior->dp.nr;
dataKBps = DIV_ROUND_UP(datakbps, 8); dataKBps = DIV_ROUND_UP(datakbps, 8);
OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d", OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d",
......
...@@ -18,6 +18,12 @@ struct nvkm_head { ...@@ -18,6 +18,12 @@ struct nvkm_head {
u16 vsynce; u16 vsynce;
u16 vblanke; u16 vblanke;
u16 vblanks; u16 vblanks;
u32 hz;
/* Prior to GF119, these are set by the OR. */
struct {
u8 depth;
} or;
} arm, asy; } arm, asy;
}; };
......
...@@ -58,6 +58,19 @@ gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) ...@@ -58,6 +58,19 @@ gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state)
data = nvkm_rd32(device, 0x640420 + hoff); data = nvkm_rd32(device, 0x640420 + hoff);
state->vblanks = (data & 0xffff0000) >> 16; state->vblanks = (data & 0xffff0000) >> 16;
state->hblanks = (data & 0x0000ffff); state->hblanks = (data & 0x0000ffff);
state->hz = nvkm_rd32(device, 0x640450 + hoff);
data = nvkm_rd32(device, 0x640404 + hoff);
switch ((data & 0x000003c0) >> 6) {
case 6: state->or.depth = 30; break;
case 5: state->or.depth = 24; break;
case 2: state->or.depth = 18; break;
case 0: state->or.depth = 18; break; /*XXX: "default" */
default:
state->or.depth = 18;
WARN_ON(1);
break;
}
} }
static const struct nvkm_head_func static const struct nvkm_head_func
......
...@@ -66,6 +66,7 @@ nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) ...@@ -66,6 +66,7 @@ nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state)
data = nvkm_rd32(device, 0x610b00 + hoff); data = nvkm_rd32(device, 0x610b00 + hoff);
state->vsynce = (data & 0xffff0000) >> 16; state->vsynce = (data & 0xffff0000) >> 16;
state->hsynce = (data & 0x0000ffff); state->hsynce = (data & 0x0000ffff);
state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000;
} }
static const struct nvkm_head_func static const struct nvkm_head_func
......
...@@ -89,6 +89,8 @@ nv50_ior_base(struct nvkm_ior *ior) ...@@ -89,6 +89,8 @@ nv50_ior_base(struct nvkm_ior *ior)
void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool); void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool);
int nv50_dac_sense(struct nvkm_ior *, u32); int nv50_dac_sense(struct nvkm_ior *, u32);
void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl);
static inline u32 static inline u32
nv50_sor_link(struct nvkm_ior *ior) nv50_sor_link(struct nvkm_ior *ior)
{ {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "ior.h" #include "ior.h"
#include "head.h"
#include <subdev/i2c.h> #include <subdev/i2c.h>
#include <subdev/timer.h> #include <subdev/timer.h>
...@@ -60,6 +61,31 @@ nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, ...@@ -60,6 +61,31 @@ nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu,
nv50_pior_power_wait(device, poff); nv50_pior_power_wait(device, poff);
} }
void
nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl)
{
/* GF119 moves this information to per-head methods, which is
* a lot more convenient, and where our shared code expect it.
*/
if (state->head && state == &ior->asy) {
struct nvkm_head *head =
nvkm_head_find(ior->disp, __ffs(state->head));
if (!WARN_ON(!head)) {
struct nvkm_head_state *state = &head->asy;
switch ((ctrl & 0x000f0000) >> 16) {
case 6: state->or.depth = 30; break;
case 5: state->or.depth = 24; break;
case 2: state->or.depth = 18; break;
case 0: state->or.depth = 18; break; /*XXX*/
default:
state->or.depth = 18;
WARN_ON(1);
break;
}
}
}
}
static void static void
nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state)
{ {
...@@ -77,6 +103,7 @@ nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) ...@@ -77,6 +103,7 @@ nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state)
} }
state->head = ctrl & 0x00000003; state->head = ctrl & 0x00000003;
nv50_pior_depth(pior, state, ctrl);
} }
static const struct nvkm_ior_func static const struct nvkm_ior_func
......
...@@ -238,6 +238,7 @@ g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) ...@@ -238,6 +238,7 @@ g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
} }
state->head = ctrl & 0x00000003; state->head = ctrl & 0x00000003;
nv50_pior_depth(sor, state, ctrl);
} }
static const struct nvkm_ior_func static const struct nvkm_ior_func
......
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