aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-09 14:10:26 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-08-09 15:28:09 -0400
commite00f2235386484cc1920dd99d17beac2a8dc4a95 (patch)
treefe61b4a6bd6c44ba668dcb3687b6a7e6049c7bae
parent120b0c39c75688864e4a25e71cf3ed40e8e18651 (diff)
drm/nv50-/disp: audit and version SOR_HDMI_PWR method
The full object interfaces are about to be exposed to userspace, so we need to check for any security-related issues and version the structs to make it easier to handle any changes we may need in the future. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c33
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h6
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c39
-rw-r--r--drivers/gpu/drm/nouveau/nvif/class.h8
13 files changed, 121 insertions, 45 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
index 7fdade6e604d..fa276dede9cd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
@@ -22,17 +22,38 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/os.h> 25#include <core/client.h>
26#include <core/class.h> 26#include <nvif/unpack.h>
27#include <nvif/class.h>
27 28
28#include "nv50.h" 29#include "nv50.h"
29 30
30int 31int
31nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data) 32nv84_hdmi_ctrl(NV50_DISP_MTHD_V1)
32{ 33{
33 const u32 hoff = (head * 0x800); 34 const u32 hoff = (head * 0x800);
35 union {
36 struct nv50_disp_sor_hdmi_pwr_v0 v0;
37 } *args = data;
38 u32 ctrl;
39 int ret;
34 40
35 if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) { 41 nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
42 if (nvif_unpack(args->v0, 0, 0, false)) {
43 nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
44 "max_ac_packet %d rekey %d\n",
45 args->v0.version, args->v0.state,
46 args->v0.max_ac_packet, args->v0.rekey);
47 if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
48 return -EINVAL;
49 ctrl = 0x40000000 * !!args->v0.state;
50 ctrl |= args->v0.max_ac_packet << 16;
51 ctrl |= args->v0.rekey;
52 ctrl |= 0x1f000000; /* ??? */
53 } else
54 return ret;
55
56 if (!(ctrl & 0x40000000)) {
36 nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000); 57 nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000);
37 nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000); 58 nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000);
38 nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000); 59 nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
65 nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ 86 nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
66 87
67 /* HDMI_CTRL */ 88 /* HDMI_CTRL */
68 nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, data | 0x1f000000 /* ??? */); 89 nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
69 return 0; 90 return 0;
70} 91}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
index db8c6fd46278..57eeed1d1942 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
@@ -22,17 +22,38 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/os.h> 25#include <core/client.h>
26#include <core/class.h> 26#include <nvif/unpack.h>
27#include <nvif/class.h>
27 28
28#include "nv50.h" 29#include "nv50.h"
29 30
30int 31int
31nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data) 32nva3_hdmi_ctrl(NV50_DISP_MTHD_V1)
32{ 33{
33 const u32 soff = (or * 0x800); 34 const u32 soff = outp->or * 0x800;
35 union {
36 struct nv50_disp_sor_hdmi_pwr_v0 v0;
37 } *args = data;
38 u32 ctrl;
39 int ret;
34 40
35 if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) { 41 nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
42 if (nvif_unpack(args->v0, 0, 0, false)) {
43 nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
44 "max_ac_packet %d rekey %d\n",
45 args->v0.version, args->v0.state,
46 args->v0.max_ac_packet, args->v0.rekey);
47 if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
48 return -EINVAL;
49 ctrl = 0x40000000 * !!args->v0.state;
50 ctrl |= args->v0.max_ac_packet << 16;
51 ctrl |= args->v0.rekey;
52 ctrl |= 0x1f000000; /* ??? */
53 } else
54 return ret;
55
56 if (!(ctrl & 0x40000000)) {
36 nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000); 57 nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000);
37 nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000); 58 nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000);
38 nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000); 59 nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
65 nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ 86 nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
66 87
67 /* HDMI_CTRL */ 88 /* HDMI_CTRL */
68 nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, data | 0x1f000000 /* ??? */); 89 nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, ctrl);
69 return 0; 90 return 0;
70} 91}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
index 5151bb261832..3106d295b48d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
@@ -22,17 +22,37 @@
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24 24
25#include <core/os.h> 25#include <core/client.h>
26#include <core/class.h> 26#include <nvif/unpack.h>
27#include <nvif/class.h>
27 28
28#include "nv50.h" 29#include "nv50.h"
29 30
30int 31int
31nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data) 32nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1)
32{ 33{
33 const u32 hoff = (head * 0x800); 34 const u32 hoff = (head * 0x800);
35 union {
36 struct nv50_disp_sor_hdmi_pwr_v0 v0;
37 } *args = data;
38 u32 ctrl;
39 int ret;
34 40
35 if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) { 41 nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
42 if (nvif_unpack(args->v0, 0, 0, false)) {
43 nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
44 "max_ac_packet %d rekey %d\n",
45 args->v0.version, args->v0.state,
46 args->v0.max_ac_packet, args->v0.rekey);
47 if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
48 return -EINVAL;
49 ctrl = 0x40000000 * !!args->v0.state;
50 ctrl |= args->v0.max_ac_packet << 16;
51 ctrl |= args->v0.rekey;
52 } else
53 return ret;
54
55 if (!(ctrl & 0x40000000)) {
36 nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000); 56 nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000);
37 nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000); 57 nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000);
38 nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000); 58 nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000);
@@ -54,7 +74,7 @@ nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
54 nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001); 74 nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001);
55 75
56 /* HDMI_CTRL */ 76 /* HDMI_CTRL */
57 nv_mask(priv, 0x616798 + hoff, 0x401f007f, data); 77 nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl);
58 78
59 /* NFI, audio doesn't work without it though.. */ 79 /* NFI, audio doesn't work without it though.. */
60 nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000); 80 nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 9381b161f309..bb5caa7e2176 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -909,6 +909,10 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
909 if (!priv->sor.hda_eld) 909 if (!priv->sor.hda_eld)
910 return -ENODEV; 910 return -ENODEV;
911 return priv->sor.hda_eld(object, priv, data, size, head, outp); 911 return priv->sor.hda_eld(object, priv, data, size, head, outp);
912 case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
913 if (!priv->sor.hdmi)
914 return -ENODEV;
915 return priv->sor.hdmi(object, priv, data, size, head, outp);
912 default: 916 default:
913 break; 917 break;
914 } 918 }
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index a09875fedcf8..a9c8e19d0e2b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -48,7 +48,7 @@ struct nv50_disp_priv {
48 int nr; 48 int nr;
49 int (*power)(NV50_DISP_MTHD_V1); 49 int (*power)(NV50_DISP_MTHD_V1);
50 int (*hda_eld)(NV50_DISP_MTHD_V1); 50 int (*hda_eld)(NV50_DISP_MTHD_V1);
51 int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); 51 int (*hdmi)(NV50_DISP_MTHD_V1);
52 u32 lvdsconf; 52 u32 lvdsconf;
53 } sor; 53 } sor;
54 struct { 54 struct {
@@ -73,9 +73,9 @@ int nv50_dac_sense(NV50_DISP_MTHD_V1);
73int nva3_hda_eld(NV50_DISP_MTHD_V1); 73int nva3_hda_eld(NV50_DISP_MTHD_V1);
74int nvd0_hda_eld(NV50_DISP_MTHD_V1); 74int nvd0_hda_eld(NV50_DISP_MTHD_V1);
75 75
76int nv84_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32); 76int nv84_hdmi_ctrl(NV50_DISP_MTHD_V1);
77int nva3_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32); 77int nva3_hdmi_ctrl(NV50_DISP_MTHD_V1);
78int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32); 78int nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1);
79 79
80int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32); 80int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
81int nv50_sor_power(NV50_DISP_MTHD_V1); 81int nv50_sor_power(NV50_DISP_MTHD_V1);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index 81a0e8d6c848..49cbecf981e6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -215,7 +215,6 @@ nv84_disp_sclass[] = {
215struct nouveau_omthds 215struct nouveau_omthds
216nv84_disp_base_omthds[] = { 216nv84_disp_base_omthds[] = {
217 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, 217 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
218 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
219 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 218 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
220 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 219 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
221 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 220 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index ca8bab4844c1..7234237f4031 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -74,7 +74,6 @@ nv94_disp_sclass[] = {
74static struct nouveau_omthds 74static struct nouveau_omthds
75nv94_disp_base_omthds[] = { 75nv94_disp_base_omthds[] = {
76 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, 76 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
77 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
78 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 77 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
79 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 78 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
80 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 79 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index ca42d7913f4e..488623386cba 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -46,7 +46,6 @@ nva3_disp_sclass[] = {
46static struct nouveau_omthds 46static struct nouveau_omthds
47nva3_disp_base_omthds[] = { 47nva3_disp_base_omthds[] = {
48 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, 48 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
49 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
50 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 49 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
51 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 50 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
52 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 51 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 77fe8cc633c7..7f035f33f25e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -712,7 +712,6 @@ nvd0_disp_base_ofuncs = {
712struct nouveau_omthds 712struct nouveau_omthds
713nvd0_disp_base_omthds[] = { 713nvd0_disp_base_omthds[] = {
714 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos }, 714 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
715 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
716 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 715 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
717 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 716 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
718 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 717 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
index be7e235e9553..5f2d71c3f71e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
@@ -84,9 +84,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
84 } 84 }
85 85
86 switch (mthd & ~0x3f) { 86 switch (mthd & ~0x3f) {
87 case NV84_DISP_SOR_HDMI_PWR:
88 ret = priv->sor.hdmi(priv, head, or, data);
89 break;
90 case NV50_DISP_SOR_LVDS_SCRIPT: 87 case NV50_DISP_SOR_LVDS_SCRIPT:
91 priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; 88 priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
92 ret = 0; 89 ret = 0;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index 234e1175f038..e54d9cc54887 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -59,12 +59,6 @@ struct nv04_display_scanoutpos {
59#define NV50_DISP_SOR_MTHD_LINK 0x00000004 59#define NV50_DISP_SOR_MTHD_LINK 0x00000004
60#define NV50_DISP_SOR_MTHD_OR 0x00000003 60#define NV50_DISP_SOR_MTHD_OR 0x00000003
61 61
62#define NV84_DISP_SOR_HDMI_PWR 0x00012000
63#define NV84_DISP_SOR_HDMI_PWR_STATE 0x40000000
64#define NV84_DISP_SOR_HDMI_PWR_STATE_OFF 0x00000000
65#define NV84_DISP_SOR_HDMI_PWR_STATE_ON 0x40000000
66#define NV84_DISP_SOR_HDMI_PWR_MAX_AC_PACKET 0x001f0000
67#define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f
68#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 62#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000
69#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff 63#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff
70#define NV94_DISP_SOR_DP_PWR 0x00016000 64#define NV94_DISP_SOR_DP_PWR 0x00016000
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 543ddb96feef..e83ed52da239 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1717,25 +1717,32 @@ nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
1717{ 1717{
1718 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1718 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1719 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 1719 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
1720 struct nouveau_connector *nv_connector;
1721 struct nv50_disp *disp = nv50_disp(encoder->dev); 1720 struct nv50_disp *disp = nv50_disp(encoder->dev);
1722 const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; 1721 struct {
1723 u32 rekey = 56; /* binary driver, and tegra constant */ 1722 struct nv50_disp_mthd_v1 base;
1723 struct nv50_disp_sor_hdmi_pwr_v0 pwr;
1724 } args = {
1725 .base.version = 1,
1726 .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
1727 .base.hasht = nv_encoder->dcb->hasht,
1728 .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
1729 (0x0100 << nv_crtc->index),
1730 .pwr.state = 1,
1731 .pwr.rekey = 56, /* binary driver, and tegra, constant */
1732 };
1733 struct nouveau_connector *nv_connector;
1724 u32 max_ac_packet; 1734 u32 max_ac_packet;
1725 u32 data;
1726 1735
1727 nv_connector = nouveau_encoder_connector_get(nv_encoder); 1736 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1728 if (!drm_detect_hdmi_monitor(nv_connector->edid)) 1737 if (!drm_detect_hdmi_monitor(nv_connector->edid))
1729 return; 1738 return;
1730 1739
1731 max_ac_packet = mode->htotal - mode->hdisplay; 1740 max_ac_packet = mode->htotal - mode->hdisplay;
1732 max_ac_packet -= rekey; 1741 max_ac_packet -= args.pwr.rekey;
1733 max_ac_packet -= 18; /* constant from tegra */ 1742 max_ac_packet -= 18; /* constant from tegra */
1734 max_ac_packet /= 32; 1743 args.pwr.max_ac_packet = max_ac_packet / 32;
1735
1736 data = NV84_DISP_SOR_HDMI_PWR_STATE_ON | (max_ac_packet << 16) | rekey;
1737 nvif_exec(disp->disp, NV84_DISP_SOR_HDMI_PWR + moff, &data, sizeof(data));
1738 1744
1745 nvif_mthd(disp->disp, 0, &args, sizeof(args));
1739 nv50_audio_mode_set(encoder, mode); 1746 nv50_audio_mode_set(encoder, mode);
1740} 1747}
1741 1748
@@ -1744,12 +1751,20 @@ nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
1744{ 1751{
1745 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1752 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1746 struct nv50_disp *disp = nv50_disp(encoder->dev); 1753 struct nv50_disp *disp = nv50_disp(encoder->dev);
1747 const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; 1754 struct {
1748 u32 data = 0; 1755 struct nv50_disp_mthd_v1 base;
1756 struct nv50_disp_sor_hdmi_pwr_v0 pwr;
1757 } args = {
1758 .base.version = 1,
1759 .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
1760 .base.hasht = nv_encoder->dcb->hasht,
1761 .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
1762 (0x0100 << nv_crtc->index),
1763 };
1749 1764
1750 nv50_audio_disconnect(encoder); 1765 nv50_audio_disconnect(encoder);
1751 1766
1752 nvif_exec(disp->disp, NV84_DISP_SOR_HDMI_PWR + moff, &data, sizeof(data)); 1767 nvif_mthd(disp->disp, 0, &args, sizeof(args));
1753} 1768}
1754 1769
1755/****************************************************************************** 1770/******************************************************************************
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h
index 84d2926dd069..abc6efab5dc6 100644
--- a/drivers/gpu/drm/nouveau/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/nvif/class.h
@@ -352,4 +352,12 @@ struct nv50_disp_sor_hda_eld_v0 {
352 __u8 data[]; 352 __u8 data[];
353}; 353};
354 354
355struct nv50_disp_sor_hdmi_pwr_v0 {
356 __u8 version;
357 __u8 state;
358 __u8 max_ac_packet;
359 __u8 rekey;
360 __u8 pad04[4];
361};
362
355#endif 363#endif