drm/nvd0/disp: call into core to handle sor power state changes
authorBen Skeggs <bskeggs@redhat.com>
Thu, 8 Nov 2012 02:01:39 +0000 (12:01 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 28 Nov 2012 23:57:46 +0000 (09:57 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
drivers/gpu/drm/nouveau/core/include/core/class.h
drivers/gpu/drm/nouveau/nvd0_display.c

index eada7bc408beaacf4a4ae0e46f595ad2c8344029..ce490a148ece326b5d1dbeb50122c1b1f859e19d 100644 (file)
@@ -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 *);
index ec0ac5bc874e77d3371dbb35cbdd2668995c69c3..f1d8e5a65591d54883336646721ba1737448528d 100644 (file)
@@ -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 },
index f5ebbac8712921a08af61304e0385c45a0669e82..29f65dcdc1a9847e6bf1db8fc2705a05fb2dca3d 100644 (file)
@@ -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;
index ed5ab9baa8eb2dc4bafe25fdb374054bc865ce36..6c21929d8e24fd98348100b851b54b9fcfc9a266 100644 (file)
@@ -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;
index 1ebf2bd372f18af67fb35bf78e3ad8f7782aaba7..fc7944f06268337ec834562a87de7d648617be9e 100644 (file)
 
 #include <subdev/bios.h>
 #include <subdev/bios/dcb.h>
+#include <subdev/timer.h>
 
 #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)
 {
@@ -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;
index 0445b0fdd2f079db04cca332b004f29cb19701fc..7c95ca6a44cc508a323fc68a1a3f50f64d431f8a 100644 (file)
@@ -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
index 39ceff274db847a82980d666392c874939d21738..ea1ae0da71d0cf9544d560c1748a57b90a5ffb13 100644 (file)
@@ -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 = {