From 99145fe39cd039c79cecd13520bd7e53d2372874 Mon Sep 17 00:00:00 2001 From: Damien Diederen Date: Sat, 22 Mar 2014 18:55:00 +0100 Subject: [PATCH] [WIP,BROKEN] drm/nv50: Hack FORCE_DP_TRAIN method for DPMS power-on Display doesn't wake up properly, though. --- drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 27 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | 4 ++++ drivers/gpu/drm/nouveau/core/engine/disp/nv84.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/nva0.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c | 1 + drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c | 18 +++++++++++++++ drivers/gpu/drm/nouveau/core/include/core/class.h | 1 + drivers/gpu/drm/nouveau/nouveau_dp.c | 5 +--- 12 files changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 9ad722e..29be94f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -1130,6 +1130,32 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, bestVTUi << 8 | unk); } +void +nv50_force_dp_train(struct nv50_disp_priv *priv, int head) +{ + struct dcb_output outp; + u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + exec_clkcmp(priv, head, 0xff, pclk, &outp); + + if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { + u32 soff = (ffs(outp.or) - 1) * 0x08; + u32 ctrl = nv_rd32(priv, 0x610794 + soff); + u32 datarate; + + switch ((ctrl & 0x000f0000) >> 16) { + case 6: datarate = pclk * 30 / 8; break; + case 5: datarate = pclk * 24 / 8; break; + case 2: + default: + datarate = pclk * 18 / 8; + break; + } + + nouveau_dp_train(&priv->base, priv->sor.dp, + &outp, head, datarate); + } +} + static void nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) { @@ -1341,6 +1367,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->pior.power = nv50_pior_power; priv->pior.dp = &nv50_pior_dp_func; return 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index d31d426..262edae 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -30,6 +30,7 @@ struct nv50_disp_priv { struct { int nr; int (*power)(struct nv50_disp_priv *, int sor, u32 data); + int (*force_dp_train)(struct nv50_disp_priv *); int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32); int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); u32 lvdsconf; @@ -64,6 +65,9 @@ int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32); int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32); int nv50_sor_power(struct nv50_disp_priv *, int, u32); +int nv50_sor_force_dp_train(struct nv50_disp_priv *); + +void nv50_force_dp_train(struct nv50_disp_priv *, int); int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16, u32, struct dcb_output *); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index ef9ce30..0031979 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c @@ -85,6 +85,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hdmi = nv84_hdmi_ctrl; priv->pior.power = nv50_pior_power; priv->pior.dp = &nv50_pior_dp_func; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index a518543..9348836 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c @@ -85,6 +85,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hdmi = nv84_hdmi_ctrl; priv->sor.dp = &nv94_sor_dp_func; priv->pior.power = nv50_pior_power; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c index 6cf8eef..7bc433d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c @@ -71,6 +71,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hdmi = nv84_hdmi_ctrl; priv->pior.power = nv50_pior_power; priv->pior.dp = &nv50_pior_dp_func; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index 6ad6dce..601fb99 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c @@ -86,6 +86,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hda_eld = nva3_hda_eld; priv->sor.hdmi = nva3_hdmi_ctrl; priv->sor.dp = &nv94_sor_dp_func; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 1c5e4e8..513fc1b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -1029,6 +1029,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; priv->sor.dp = &nvd0_sor_dp_func; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index ab63f32..901345d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c @@ -71,6 +71,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; priv->sor.dp = &nvd0_sor_dp_func; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c index 05fee10..b994894 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c @@ -71,6 +71,7 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; + priv->sor.force_dp_train = nv50_sor_force_dp_train; priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; priv->sor.dp = &nvd0_sor_dp_func; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index 526b752..52d598c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs */ +#include + #include #include @@ -32,10 +34,23 @@ #include "nv50.h" int +nv50_sor_force_dp_train(struct nv50_disp_priv *priv) +{ + int head; + + for (head = 0; head < priv->head.nr; head++) { + nv50_force_dp_train(priv, head); + } + + return 0; +} + +int nv50_sor_power(struct nv50_disp_priv *priv, int or, u32 data) { const u32 stat = data & NV50_DISP_SOR_PWR_STATE; const u32 soff = (or * 0x800); + nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000); nv_mask(priv, 0x61c004 + soff, 0x80000001, 0x80000000 | stat); nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000); @@ -71,6 +86,9 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; ret = 0; break; + case NV50_DISP_SOR_FORCE_DP_TRAIN: + ret = priv->sor.force_dp_train(priv); + break; default: BUG_ON(1); } diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index e71a432..e1b93a4 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -293,6 +293,7 @@ struct nv04_display_scanoutpos { #define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f #define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 #define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff +#define NV50_DISP_SOR_FORCE_DP_TRAIN 0x00014000 #define NV50_DISP_DAC_MTHD 0x00020000 #define NV50_DISP_DAC_MTHD_TYPE 0x0000f000 diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 4c8c554..ec8b6cd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -114,9 +114,6 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, nv_wraux(auxch, DP_SET_POWER, &status, 1); - /* FIXME */ - /* if (mode == DRM_MODE_DPMS_ON) - nouveau_dp_train(...); - */ + nv_call(core, NV50_DISP_SOR_FORCE_DP_TRAIN, 0); } -- 1.9.1