*/
#include "dp.h"
#include "conn.h"
+#include "head.h"
#include "ior.h"
#include <subdev/bios.h>
}
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_ior *ior = dp->outp.ior;
+ struct nvkm_head *head;
bool retrain = true;
- u32 linkKBps;
+ u32 datakbps = 0;
u32 dataKBps;
+ u32 linkKBps;
u8 stat[3];
int ret, i;
mutex_lock(&dp->mutex);
/* 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;
dataKBps = DIV_ROUND_UP(datakbps, 8);
OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d",
u16 vsynce;
u16 vblanke;
u16 vblanks;
+ u32 hz;
+
+ /* Prior to GF119, these are set by the OR. */
+ struct {
+ u8 depth;
+ } or;
} arm, asy;
};
data = nvkm_rd32(device, 0x640420 + hoff);
state->vblanks = (data & 0xffff0000) >> 16;
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
data = nvkm_rd32(device, 0x610b00 + hoff);
state->vsynce = (data & 0xffff0000) >> 16;
state->hsynce = (data & 0x0000ffff);
+ state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000;
}
static const struct nvkm_head_func
void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool);
int nv50_dac_sense(struct nvkm_ior *, u32);
+void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl);
+
static inline u32
nv50_sor_link(struct nvkm_ior *ior)
{
* Authors: Ben Skeggs
*/
#include "ior.h"
+#include "head.h"
#include <subdev/i2c.h>
#include <subdev/timer.h>
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
nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state)
{
}
state->head = ctrl & 0x00000003;
+ nv50_pior_depth(pior, state, ctrl);
}
static const struct nvkm_ior_func
}
state->head = ctrl & 0x00000003;
+ nv50_pior_depth(sor, state, ctrl);
}
static const struct nvkm_ior_func