mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-11 20:36:45 +07:00
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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
8894f4919b
commit
4874322e78
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user