Commit 4874322e authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/dp: fix support for dpms

SOR_PWR has no effect to power-off DP links, unlike other SOR protocols.

Instead, on the source side, we cut power to the lanes after having put
the sink into D3.  Link training takes care of everything required to
bring it back again.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 8894f491
......@@ -76,7 +76,8 @@ find_encoder(struct drm_connector *connector, int type)
continue;
nv_encoder = nouveau_encoder(obj_to_encoder(obj));
if (type == DCB_OUTPUT_ANY || nv_encoder->dcb->type == type)
if (type == DCB_OUTPUT_ANY ||
(nv_encoder->dcb && nv_encoder->dcb->type == type))
return nv_encoder;
}
......@@ -914,6 +915,40 @@ nouveau_connector_funcs_lvds = {
.force = nouveau_connector_force
};
static void
nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
{
struct nouveau_encoder *nv_encoder = NULL;
if (connector->encoder)
nv_encoder = nouveau_encoder(connector->encoder);
if (nv_encoder && nv_encoder->dcb &&
nv_encoder->dcb->type == DCB_OUTPUT_DP) {
if (mode == DRM_MODE_DPMS_ON) {
u8 data = DP_SET_POWER_D0;
nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1);
usleep_range(1000, 2000);
} else {
u8 data = DP_SET_POWER_D3;
nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1);
}
}
drm_helper_connector_dpms(connector, mode);
}
static const struct drm_connector_funcs
nouveau_connector_funcs_dp = {
.dpms = nouveau_connector_dp_dpms,
.save = NULL,
.restore = NULL,
.detect = nouveau_connector_detect,
.destroy = nouveau_connector_destroy,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = nouveau_connector_set_property,
.force = nouveau_connector_force
};
static void
nouveau_connector_hotplug_work(struct work_struct *work)
{
......@@ -1122,7 +1157,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
return ERR_PTR(ret);
}
funcs = &nouveau_connector_funcs;
funcs = &nouveau_connector_funcs_dp;
break;
default:
funcs = &nouveau_connector_funcs;
......
......@@ -26,6 +26,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_dp_helper.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
......@@ -1722,7 +1723,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
struct drm_device *dev = encoder->dev;
struct nv50_disp *disp = nv50_disp(dev);
struct drm_encoder *partner;
int or = nv_encoder->or;
u32 mthd;
nv_encoder->last_dpms = mode;
......@@ -1740,7 +1741,17 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
}
}
nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
mthd = (ffs(nv_encoder->dcb->sorconf.link) - 1) << 2;
mthd |= nv_encoder->or;
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
nv_call(disp->core, NV50_DISP_SOR_PWR | mthd, 1);
mthd |= NV94_DISP_SOR_DP_PWR;
} else {
mthd |= NV50_DISP_SOR_PWR;
}
nv_call(disp->core, mthd, (mode == DRM_MODE_DPMS_ON));
}
static bool
......
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