From 74b6685089591fa275929109f7b839bf386890a0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 8 Nov 2012 12:01:39 +1000 Subject: drm/nvd0/disp: call into core to handle sor power state changes Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index eada7bc..ce490a1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -21,6 +21,7 @@ struct nv50_disp_priv { } dac; struct { int nr; + int (*power)(struct nv50_disp_priv *, int sor, u32 data); int (*dp_train)(struct nv50_disp_priv *, int sor, int link, u16 type, u16 mask, u32 data, struct dcb_output *); @@ -38,6 +39,7 @@ extern struct nouveau_omthds nva3_disp_base_omthds[]; #define SOR_MTHD(n) (n), (n) + 0x3f int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32); +int nv50_sor_power(struct nv50_disp_priv *, int, u32); int nvd0_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32, struct dcb_output *); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index ec0ac5b..f1d8e5a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c @@ -41,6 +41,7 @@ nva3_disp_sclass[] = { struct nouveau_omthds nva3_disp_base_omthds[] = { + { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index f5ebbac..29f65dc 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -896,6 +896,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->head.nr = nv_rd32(priv, 0x022448); priv->dac.nr = 3; priv->sor.nr = 4; + priv->sor.power = nv50_sor_power; priv->sor.dp_train = nvd0_sor_dp_train; priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index ed5ab9b..6c21929 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c @@ -66,6 +66,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->head.nr = nv_rd32(priv, 0x022448); priv->dac.nr = 3; priv->sor.nr = 4; + priv->sor.power = nv50_sor_power; priv->sor.dp_train = nvd0_sor_dp_train; priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index 1ebf2bd..fc7944f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -27,10 +27,23 @@ #include #include +#include #include "nv50.h" 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); + nv_wait(priv, 0x61c030 + soff, 0x10000000, 0x00000000); + return 0; +} + +int nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) { struct nv50_disp_priv *priv = (void *)object->engine; @@ -72,6 +85,9 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) data = *(u32 *)args; switch (mthd & ~0x3f) { + case NV50_DISP_SOR_PWR: + ret = priv->sor.power(priv, or, data); + break; case NV94_DISP_SOR_DP_TRAIN: ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); break; diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 0445b0f..7c95ca6 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -177,6 +177,10 @@ struct nve0_channel_ind_class { #define NV50_DISP_SOR_MTHD_LINK 0x00000004 #define NV50_DISP_SOR_MTHD_OR 0x00000003 +#define NV50_DISP_SOR_PWR 0x00010000 +#define NV50_DISP_SOR_PWR_STATE 0x00000001 +#define NV50_DISP_SOR_PWR_STATE_ON 0x00000001 +#define NV50_DISP_SOR_PWR_STATE_OFF 0x00000000 #define NV94_DISP_SOR_DP_TRAIN 0x00016000 #define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003 #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000 diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 39ceff2..ea1ae0d 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1434,10 +1434,9 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; - struct nouveau_device *device = nouveau_dev(dev); + struct nvd0_disp *disp = nvd0_disp(dev); struct drm_encoder *partner; int or = nv_encoder->or; - u32 dpms_ctrl; nv_encoder->last_dpms = mode; @@ -1455,13 +1454,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) } } - dpms_ctrl = (mode == DRM_MODE_DPMS_ON); - dpms_ctrl |= 0x80000000; - - nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); - nv_mask(device, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); - nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); - nv_wait(device, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); + nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { struct dp_train_func func = { -- cgit v0.10.2