提交 c21e6b30 编写于 作者: B Ben Skeggs

drm/gm204/disp: some magic that fixes bringup of uninitialised outputs

Probably missing something here, doesn't make a lot of sense to write
or+link data into a register whose offset is calculated by the same
or+link info..

This is the all I've witnessed the binary driver and vbios doing so
far, so it'll do.
Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 1f89b475
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <subdev/bios/init.h> #include <subdev/bios/init.h>
#include <subdev/i2c.h> #include <subdev/i2c.h>
#include <engine/disp.h> #include "nv50.h"
#include <nvif/class.h> #include <nvif/class.h>
...@@ -326,7 +326,7 @@ void ...@@ -326,7 +326,7 @@ void
nouveau_dp_train(struct work_struct *w) nouveau_dp_train(struct work_struct *w)
{ {
struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work); struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work);
struct nouveau_disp *disp = nouveau_disp(outp); struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
const struct dp_rates *cfg = nouveau_dp_rates; const struct dp_rates *cfg = nouveau_dp_rates;
struct dp_state _dp = { struct dp_state _dp = {
.outp = outp, .outp = outp,
...@@ -334,8 +334,11 @@ nouveau_dp_train(struct work_struct *w) ...@@ -334,8 +334,11 @@ nouveau_dp_train(struct work_struct *w)
u32 datarate = 0; u32 datarate = 0;
int ret; int ret;
if (!outp->base.info.location && priv->sor.magic)
priv->sor.magic(&outp->base);
/* bring capabilities within encoder limits */ /* bring capabilities within encoder limits */
if (nv_mclass(disp) < GF110_DISP) if (nv_mclass(priv) < GF110_DISP)
outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED; outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) { if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) {
outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT; outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
......
...@@ -85,6 +85,7 @@ gm204_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -85,6 +85,7 @@ gm204_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.power = nv50_sor_power; priv->sor.power = nv50_sor_power;
priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hda_eld = nvd0_hda_eld;
priv->sor.hdmi = nvd0_hdmi_ctrl; priv->sor.hdmi = nvd0_hdmi_ctrl;
priv->sor.magic = gm204_sor_magic;
return 0; return 0;
} }
......
...@@ -42,6 +42,7 @@ struct nv50_disp_priv { ...@@ -42,6 +42,7 @@ struct nv50_disp_priv {
int (*hda_eld)(NV50_DISP_MTHD_V1); int (*hda_eld)(NV50_DISP_MTHD_V1);
int (*hdmi)(NV50_DISP_MTHD_V1); int (*hdmi)(NV50_DISP_MTHD_V1);
u32 lvdsconf; u32 lvdsconf;
void (*magic)(struct nvkm_output *);
} sor; } sor;
struct { struct {
int nr; int nr;
...@@ -245,6 +246,7 @@ extern struct nvkm_output_dp_impl nvd0_sor_dp_impl; ...@@ -245,6 +246,7 @@ extern struct nvkm_output_dp_impl nvd0_sor_dp_impl;
int nvd0_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool); int nvd0_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
extern struct nouveau_oclass *nvd0_disp_outp_sclass[]; extern struct nouveau_oclass *nvd0_disp_outp_sclass[];
void gm204_sor_magic(struct nvkm_output *outp);
extern struct nvkm_output_dp_impl gm204_sor_dp_impl; extern struct nvkm_output_dp_impl gm204_sor_dp_impl;
#endif #endif
...@@ -1055,6 +1055,9 @@ nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head) ...@@ -1055,6 +1055,9 @@ nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head)
if (nvkm_output_dp_train(outp, pclk, true)) if (nvkm_output_dp_train(outp, pclk, true))
ERR("link not trained before attach\n"); ERR("link not trained before attach\n");
} else {
if (priv->sor.magic)
priv->sor.magic(outp);
} }
exec_clkcmp(priv, head, 0, pclk, &conf); exec_clkcmp(priv, head, 0, pclk, &conf);
......
...@@ -44,6 +44,18 @@ gm204_sor_loff(struct nvkm_output_dp *outp) ...@@ -44,6 +44,18 @@ gm204_sor_loff(struct nvkm_output_dp *outp)
return gm204_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80; return gm204_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
} }
void
gm204_sor_magic(struct nvkm_output *outp)
{
struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
const u32 soff = outp->or * 0x100;
const u32 data = outp->or + 1;
if (outp->info.sorconf.link & 1)
nv_mask(priv, 0x612308 + soff, 0x0000001f, 0x00000000 | data);
if (outp->info.sorconf.link & 2)
nv_mask(priv, 0x612388 + soff, 0x0000001f, 0x00000010 | data);
}
static inline u32 static inline u32
gm204_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) gm204_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册