On 5 May 2014 01:43, Ben Skeggs <[email protected]> wrote: > On Mon, May 5, 2014 at 4:48 AM, Sergei Antonov <[email protected]> wrote: >> The following commit from about a year ago removed nouveau_dp_dpms() which >> did steps required to suspend and resume a monitor connected via DisplayPort. >> >> commit 0a0afd282fd715dd63d64b243299a64da14f8e8d >> Author: Ben Skeggs <[email protected]> >> Date: Mon Feb 18 23:17:53 2013 -0500 >> drm/nv50-/disp: move DP link training to core and train from supervisor >> >> My computer with NVIDIA GeForce GT 640M did not blank the screen after a >> period >> of inactivity, the screen was always on. When in framebuffer console mode >> the system switched to blank mode internally but continued to show picture >> on the screen which produced ugly artifacts as new lines were output. >> >> This patch resurrects some of the removed code to restore the lost >> functionality. Some of the resurrected code was removed by the aforementioned >> commit, some by a later cleanup done by >> 9a7046d55f319b2dde5d2536cc2adb01ebdbe09e >> >> The code was updated to make it compatible with the current state of the >> driver. >> Here is how it now works. If the connection is DCB_OUTPUT_DP, call >> nouveau_dp_dpms() which does DP_SET_POWER and, if we are resuming, initiates >> DP link training by sending NV94_DISP_SOR_DP_TRAIN to have nv50_sor_mthd() >> call nouveau_dp_train(). > Thank you. This, as you've seen, would appear to solve the issue. > There's a little more to the power-down to be done however (such as > shutting down the lanes at the SOR, which, yes, we never did before > either), and potential races between the supervisor running link > training and a dpms on.
I'm curious about these races. The old code in nouveau_dp.c contained this: - /* some sinks toggle hotplug in response to some of the actions - * we take during link training (DP_SET_POWER is one), we need - * to ignore them for the moment to avoid races. - */ I wonder how DP_SET_POWER is taken during link training. > I'm about to (as in, this week) start some work which will address > this and some other DP issues as they've become more urgent here too. > > Thanks again, > Ben. > >> >> Cc: Ben Skeggs <[email protected]> >> Cc: Dave Airlie <[email protected]> >> Signed-off-by: Sergei Antonov <[email protected]> >> --- >> drivers/gpu/drm/nouveau/core/engine/disp/nv94.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/sornv50.c | 12 +++++++++++ >> drivers/gpu/drm/nouveau/core/include/core/class.h | 1 + >> drivers/gpu/drm/nouveau/nouveau_dp.c | 24 >> ++++++++++++++++++++++ >> drivers/gpu/drm/nouveau/nv50_display.c | 7 +++++-- >> 7 files changed, 45 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c >> b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c >> index 6844061..1f24b10 100644 >> --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c >> +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c >> @@ -77,6 +77,7 @@ nv94_disp_base_omthds[] = { >> { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, >> { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, >> { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, >> + { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, >> { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, >> { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, >> { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, >> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c >> b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c >> index 46cb2ce..59054ff6 100644 >> --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c >> +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c >> @@ -50,6 +50,7 @@ nva3_disp_base_omthds[] = { >> { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, >> { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, >> { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, >> + { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, >> { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, >> { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, >> { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, >> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c >> b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c >> index 7762665..8790c4c 100644 >> --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c >> +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c >> @@ -887,6 +887,7 @@ nvd0_disp_base_omthds[] = { >> { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, >> { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, >> { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, >> + { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, >> { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, >> { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, >> { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, >> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c >> b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c >> index 526b752..5238e65 100644 >> --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c >> +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c >> @@ -47,8 +47,14 @@ int >> nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) >> { >> struct nv50_disp_priv *priv = (void *)object->engine; >> + struct nouveau_bios *bios = nouveau_bios(priv); >> + const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12; >> const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; >> + const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2; >> const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); >> + const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << >> or); >> + struct dcb_output outp; >> + u8 ver, hdr; >> u32 data; >> int ret = -EINVAL; >> >> @@ -56,6 +62,8 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, >> void *args, u32 size) >> return -EINVAL; >> data = *(u32 *)args; >> >> + if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp)) >> + return -ENODEV; >> >> switch (mthd & ~0x3f) { >> case NV50_DISP_SOR_PWR: >> @@ -71,6 +79,10 @@ 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 NV94_DISP_SOR_DP_TRAIN: >> + ret = nouveau_dp_train(&priv->base, priv->sor.dp, &outp, >> + head, data); >> + 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 9c0cd73..a32f515 100644 >> --- a/drivers/gpu/drm/nouveau/core/include/core/class.h >> +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h >> @@ -295,6 +295,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 NV94_DISP_SOR_DP_TRAIN >> 0x00016000 >> >> #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 36fd225..ee1bc27 100644 >> --- a/drivers/gpu/drm/nouveau/nouveau_dp.c >> +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c >> @@ -35,6 +35,30 @@ >> #include <subdev/gpio.h> >> #include <subdev/i2c.h> >> >> +void >> +nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, >> + struct nouveau_object *core) >> +{ >> + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); >> + struct nouveau_i2c_port *auxch; >> + int or = nv_encoder->or; >> + u8 status; >> + >> + auxch = nv_encoder->i2c; >> + if (!auxch) >> + return; >> + >> + if (mode == DRM_MODE_DPMS_ON) >> + status = DP_SET_POWER_D0; >> + else >> + status = DP_SET_POWER_D3; >> + >> + nv_wraux(auxch, DP_SET_POWER, &status, 1); >> + >> + if (mode == DRM_MODE_DPMS_ON) >> + nv_call(core, NV94_DISP_SOR_DP_TRAIN + or, datarate); >> +} >> + >> static void >> nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, >> u8 *dpcd) >> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c >> b/drivers/gpu/drm/nouveau/nv50_display.c >> index 58af547..98fd94d 100644 >> --- a/drivers/gpu/drm/nouveau/nv50_display.c >> +++ b/drivers/gpu/drm/nouveau/nv50_display.c >> @@ -1720,7 +1720,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) >> { >> struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); >> struct drm_device *dev = encoder->dev; >> - struct nv50_disp *disp = nv50_disp(dev); >> + struct nouveau_object *core = nv50_disp(dev)->core; >> struct drm_encoder *partner; >> int or = nv_encoder->or; >> >> @@ -1740,7 +1740,10 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) >> } >> } >> >> - nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == >> DRM_MODE_DPMS_ON)); >> + nv_call(core, NV50_DISP_SOR_PWR + or, mode == DRM_MODE_DPMS_ON); >> + >> + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) >> + nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, >> core); >> } >> >> static bool >> -- >> 1.9.0 >> >> _______________________________________________ >> Nouveau mailing list >> [email protected] >> http://lists.freedesktop.org/mailman/listinfo/nouveau _______________________________________________ Nouveau mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/nouveau
