drm/g94-/disp: add method to power-off dp lanes
authorBen Skeggs <bskeggs@redhat.com>
Mon, 26 May 2014 02:09:06 +0000 (12:09 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 11 Jun 2014 06:10:57 +0000 (16:10 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
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/sornv50.c
drivers/gpu/drm/nouveau/core/include/core/class.h

index 240b69a89b7b8b386ae8c482d1fff83bd539627d..4f718a9f5aefbeb0b75d8a55de7c05f2f3d04793 100644 (file)
@@ -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_PWR)      , 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 },
index 705c6784fb68e5cf25a08388dae8f247cd8b0290..019124d4782bf5303733927ef4bc9c6861152cde 100644 (file)
@@ -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_PWR)      , 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 },
index 4eb16e9e7b59429d6ad30815cbfdb446a36e9f26..254a7a18c26dc5a8d07b1f3318f9642eac88bbce 100644 (file)
@@ -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_PWR)      , 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 },
index 526b75242899fb6e97e0abc3bd48cd228affe151..e1832778e8b67def8e1030fa47955acc42c3f204 100644 (file)
@@ -47,8 +47,12 @@ int
 nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
 {
        struct nv50_disp_priv *priv = (void *)object->engine;
+       const u8  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 nvkm_output *outp = NULL, *temp;
        u32 data;
        int ret = -EINVAL;
 
@@ -56,6 +60,13 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
                return -EINVAL;
        data = *(u32 *)args;
 
+       list_for_each_entry(temp, &priv->base.outp, head) {
+               if ((temp->info.hasht & 0xff) == type &&
+                   (temp->info.hashm & mask) == mask) {
+                       outp = temp;
+                       break;
+               }
+       }
 
        switch (mthd & ~0x3f) {
        case NV50_DISP_SOR_PWR:
@@ -71,6 +82,23 @@ 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_PWR:
+               if (outp) {
+                       struct nvkm_output_dp *outpdp = (void *)outp;
+                       switch (data) {
+                       case NV94_DISP_SOR_DP_PWR_STATE_OFF:
+                               ((struct nvkm_output_dp_impl *)nv_oclass(outp))
+                                       ->lnk_pwr(outpdp, 0);
+                               atomic_set(&outpdp->lt.done, 0);
+                               break;
+                       case NV94_DISP_SOR_DP_PWR_STATE_ON:
+                               nvkm_output_dp_train(&outpdp->base, 0, true);
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+               break;
        default:
                BUG_ON(1);
        }
index 9c0cd73462d953971159f94c0d643381662215bd..e0c812bc884f900f5171da05e35ad89e3072da67 100644 (file)
@@ -295,6 +295,10 @@ 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_PWR                                         0x00016000
+#define NV94_DISP_SOR_DP_PWR_STATE                                   0x00000001
+#define NV94_DISP_SOR_DP_PWR_STATE_OFF                               0x00000000
+#define NV94_DISP_SOR_DP_PWR_STATE_ON                                0x00000001
 
 #define NV50_DISP_DAC_MTHD                                           0x00020000
 #define NV50_DISP_DAC_MTHD_TYPE                                      0x0000f000