aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
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:07 -0400
commitbf0eb89859439f016a1fab4cdf737c95f36dbb2e (patch)
tree59709bbd702fe904e63a2237d200162f90d820b4 /drivers/gpu
parent2c04ae01df38f95dd3e553c85cdac670a80110f5 (diff)
drm/nv50-/disp: audit and version DAC_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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c34
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c73
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h10
-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.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outp.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outp.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c7
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvif/class.h43
13 files changed, 171 insertions, 41 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
index a66b27c0fcab..9fb1a8438b56 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
@@ -22,8 +22,10 @@
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 <core/class.h>
27#include <nvif/unpack.h>
28#include <nvif/class.h>
27 29
28#include <subdev/bios.h> 30#include <subdev/bios.h>
29#include <subdev/bios/dcb.h> 31#include <subdev/bios/dcb.h>
@@ -32,13 +34,28 @@
32#include "nv50.h" 34#include "nv50.h"
33 35
34int 36int
35nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data) 37nv50_dac_power(NV50_DISP_MTHD_V1)
36{ 38{
37 const u32 stat = (data & NV50_DISP_DAC_PWR_HSYNC) | 39 const u32 doff = outp->or * 0x800;
38 (data & NV50_DISP_DAC_PWR_VSYNC) | 40 union {
39 (data & NV50_DISP_DAC_PWR_DATA) | 41 struct nv50_disp_dac_pwr_v0 v0;
40 (data & NV50_DISP_DAC_PWR_STATE); 42 } *args = data;
41 const u32 doff = (or * 0x800); 43 u32 stat;
44 int ret;
45
46 nv_ioctl(object, "disp dac pwr size %d\n", size);
47 if (nvif_unpack(args->v0, 0, 0, false)) {
48 nv_ioctl(object, "disp dac pwr vers %d state %d data %d "
49 "vsync %d hsync %d\n",
50 args->v0.version, args->v0.state, args->v0.data,
51 args->v0.vsync, args->v0.hsync);
52 stat = 0x00000040 * !args->v0.state;
53 stat |= 0x00000010 * !args->v0.data;
54 stat |= 0x00000004 * !args->v0.vsync;
55 stat |= 0x00000001 * !args->v0.hsync;
56 } else
57 return ret;
58
42 nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); 59 nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
43 nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat); 60 nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat);
44 nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); 61 nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@@ -80,9 +97,6 @@ nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
80 return -EINVAL; 97 return -EINVAL;
81 98
82 switch (mthd & ~0x3f) { 99 switch (mthd & ~0x3f) {
83 case NV50_DISP_DAC_PWR:
84 ret = priv->dac.power(priv, or, data[0]);
85 break;
86 case NV50_DISP_DAC_LOAD: 100 case NV50_DISP_DAC_LOAD:
87 ret = priv->dac.sense(priv, or, data[0]); 101 ret = priv->dac.sense(priv, or, data[0]);
88 if (ret >= 0) { 102 if (ret >= 0) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 4f1ed8928c82..00d1e34cb2a6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -23,10 +23,13 @@
23 */ 23 */
24 24
25#include <core/object.h> 25#include <core/object.h>
26#include <core/client.h>
26#include <core/parent.h> 27#include <core/parent.h>
27#include <core/handle.h> 28#include <core/handle.h>
28#include <core/class.h>
29#include <core/enum.h> 29#include <core/enum.h>
30#include <core/class.h>
31#include <nvif/unpack.h>
32#include <nvif/class.h>
30 33
31#include <subdev/bios.h> 34#include <subdev/bios.h>
32#include <subdev/bios/dcb.h> 35#include <subdev/bios/dcb.h>
@@ -840,6 +843,72 @@ nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
840} 843}
841 844
842int 845int
846nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
847 void *data, u32 size)
848{
849 union {
850 struct nv50_disp_mthd_v0 v0;
851 struct nv50_disp_mthd_v1 v1;
852 } *args = data;
853 struct nv50_disp_priv *priv = (void *)object->engine;
854 struct nvkm_output *outp = NULL;
855 struct nvkm_output *temp;
856 u16 type, mask = 0;
857 int head, ret;
858
859 if (mthd != NV50_DISP_MTHD)
860 return -EINVAL;
861
862 nv_ioctl(object, "disp mthd size %d\n", size);
863 if (nvif_unpack(args->v0, 0, 0, true)) {
864 nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
865 args->v0.version, args->v0.method, args->v0.head);
866 mthd = args->v0.method;
867 head = args->v0.head;
868 } else
869 if (nvif_unpack(args->v1, 1, 1, true)) {
870 nv_ioctl(object, "disp mthd vers %d mthd %02x "
871 "type %04x mask %04x\n",
872 args->v1.version, args->v1.method,
873 args->v1.hasht, args->v1.hashm);
874 mthd = args->v1.method;
875 type = args->v1.hasht;
876 mask = args->v1.hashm;
877 head = ffs((mask >> 8) & 0x0f) - 1;
878 } else
879 return ret;
880
881 if (head < 0 || head >= priv->head.nr)
882 return -ENXIO;
883
884 if (mask) {
885 list_for_each_entry(temp, &priv->base.outp, head) {
886 if ((temp->info.hasht == type) &&
887 (temp->info.hashm & mask) == mask) {
888 outp = temp;
889 break;
890 }
891 }
892 if (outp == NULL)
893 return -ENXIO;
894 }
895
896 switch (mthd) {
897 default:
898 break;
899 }
900
901 switch (mthd * !!outp) {
902 case NV50_DISP_MTHD_V1_DAC_PWR:
903 return priv->dac.power(object, priv, data, size, head, outp);
904 default:
905 break;
906 }
907
908 return -EINVAL;
909}
910
911int
843nv50_disp_base_ctor(struct nouveau_object *parent, 912nv50_disp_base_ctor(struct nouveau_object *parent,
844 struct nouveau_object *engine, 913 struct nouveau_object *engine,
845 struct nouveau_oclass *oclass, void *data, u32 size, 914 struct nouveau_oclass *oclass, void *data, u32 size,
@@ -954,6 +1023,7 @@ nv50_disp_base_ofuncs = {
954 .dtor = nv50_disp_base_dtor, 1023 .dtor = nv50_disp_base_dtor,
955 .init = nv50_disp_base_init, 1024 .init = nv50_disp_base_init,
956 .fini = nv50_disp_base_fini, 1025 .fini = nv50_disp_base_fini,
1026 .mthd = nv50_disp_base_mthd,
957}; 1027};
958 1028
959static struct nouveau_omthds 1029static struct nouveau_omthds
@@ -961,7 +1031,6 @@ nv50_disp_base_omthds[] = {
961 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, 1031 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
962 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 1032 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
963 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 1033 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
964 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
965 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 1034 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
966 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 1035 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
967 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 1036 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index a1ec6a556187..4a874d776368 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -24,6 +24,11 @@ struct nv50_disp_impl {
24 } mthd; 24 } mthd;
25}; 25};
26 26
27#define NV50_DISP_MTHD_ struct nouveau_object *object, \
28 struct nv50_disp_priv *priv, void *data, u32 size
29#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
30#define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp
31
27struct nv50_disp_priv { 32struct nv50_disp_priv {
28 struct nouveau_disp base; 33 struct nouveau_disp base;
29 struct nouveau_oclass *sclass; 34 struct nouveau_oclass *sclass;
@@ -36,7 +41,7 @@ struct nv50_disp_priv {
36 } head; 41 } head;
37 struct { 42 struct {
38 int nr; 43 int nr;
39 int (*power)(struct nv50_disp_priv *, int dac, u32 data); 44 int (*power)(NV50_DISP_MTHD_V1);
40 int (*sense)(struct nv50_disp_priv *, int dac, u32 load); 45 int (*sense)(struct nv50_disp_priv *, int dac, u32 load);
41 } dac; 46 } dac;
42 struct { 47 struct {
@@ -56,11 +61,12 @@ struct nv50_disp_priv {
56#define HEAD_MTHD(n) (n), (n) + 0x03 61#define HEAD_MTHD(n) (n), (n) + 0x03
57 62
58int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32); 63int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
64int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
59 65
60#define DAC_MTHD(n) (n), (n) + 0x03 66#define DAC_MTHD(n) (n), (n) + 0x03
61 67
62int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); 68int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
63int nv50_dac_power(struct nv50_disp_priv *, int, u32); 69int nv50_dac_power(NV50_DISP_MTHD_V1);
64int nv50_dac_sense(struct nv50_disp_priv *, int, u32); 70int nv50_dac_sense(struct nv50_disp_priv *, int, u32);
65 71
66#define SOR_MTHD(n) (n), (n) + 0x3f 72#define SOR_MTHD(n) (n), (n) + 0x3f
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index 43ef1fab52f1..f2414a4bc000 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -218,7 +218,6 @@ nv84_disp_base_omthds[] = {
218 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 218 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
219 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 219 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
220 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 220 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
221 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
222 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 221 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
223 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 222 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
224 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 223 { 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 2e38a79b19ca..7ae79cfbdbf4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -78,7 +78,6 @@ nv94_disp_base_omthds[] = {
78 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 78 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
79 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 79 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
80 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 80 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
81 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
82 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 81 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
83 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 82 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
84 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 83 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_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 4b601c87c318..31cdf7a612c4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -51,7 +51,6 @@ nva3_disp_base_omthds[] = {
51 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 51 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
52 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 52 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
53 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 53 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
54 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
55 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 54 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
56 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 55 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
57 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 56 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_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 57d6cb3ed0f7..66959cde0403 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -706,6 +706,7 @@ nvd0_disp_base_ofuncs = {
706 .dtor = nv50_disp_base_dtor, 706 .dtor = nv50_disp_base_dtor,
707 .init = nvd0_disp_base_init, 707 .init = nvd0_disp_base_init,
708 .fini = nvd0_disp_base_fini, 708 .fini = nvd0_disp_base_fini,
709 .mthd = nv50_disp_base_mthd,
709}; 710};
710 711
711struct nouveau_omthds 712struct nouveau_omthds
@@ -716,7 +717,6 @@ nvd0_disp_base_omthds[] = {
716 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 717 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
717 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 718 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
718 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 719 { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
719 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
720 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 720 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
721 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 721 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
722 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 722 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
index ad9ba7ccec7f..a5ff00a9cedc 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
@@ -78,6 +78,7 @@ nvkm_output_create_(struct nouveau_object *parent,
78 78
79 outp->info = *dcbE; 79 outp->info = *dcbE;
80 outp->index = index; 80 outp->index = index;
81 outp->or = ffs(outp->info.or) - 1;
81 82
82 DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n", 83 DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n",
83 dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ? 84 dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ?
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
index bc76fbf85710..187f435ad0e2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
@@ -9,6 +9,7 @@ struct nvkm_output {
9 9
10 struct dcb_output info; 10 struct dcb_output info;
11 int index; 11 int index;
12 int or;
12 13
13 struct nouveau_i2c_port *port; 14 struct nouveau_i2c_port *port;
14 struct nouveau_i2c_port *edid; 15 struct nouveau_i2c_port *edid;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index d3180e51ce62..026b123d1422 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -49,7 +49,6 @@ struct nv04_display_scanoutpos {
49#define NVF0_DISP_CLASS 0x00009270 49#define NVF0_DISP_CLASS 0x00009270
50#define GM107_DISP_CLASS 0x00009470 50#define GM107_DISP_CLASS 0x00009470
51 51
52#define NV50_DISP_MTHD 0x00000000
53#define NV50_DISP_MTHD_HEAD 0x00000003 52#define NV50_DISP_MTHD_HEAD 0x00000003
54 53
55#define NV50_DISP_SCANOUTPOS 0x00000000 54#define NV50_DISP_SCANOUTPOS 0x00000000
@@ -82,19 +81,6 @@ struct nv04_display_scanoutpos {
82#define NV50_DISP_DAC_MTHD_TYPE 0x0000f000 81#define NV50_DISP_DAC_MTHD_TYPE 0x0000f000
83#define NV50_DISP_DAC_MTHD_OR 0x00000003 82#define NV50_DISP_DAC_MTHD_OR 0x00000003
84 83
85#define NV50_DISP_DAC_PWR 0x00020000
86#define NV50_DISP_DAC_PWR_HSYNC 0x00000001
87#define NV50_DISP_DAC_PWR_HSYNC_ON 0x00000000
88#define NV50_DISP_DAC_PWR_HSYNC_LO 0x00000001
89#define NV50_DISP_DAC_PWR_VSYNC 0x00000004
90#define NV50_DISP_DAC_PWR_VSYNC_ON 0x00000000
91#define NV50_DISP_DAC_PWR_VSYNC_LO 0x00000004
92#define NV50_DISP_DAC_PWR_DATA 0x00000010
93#define NV50_DISP_DAC_PWR_DATA_ON 0x00000000
94#define NV50_DISP_DAC_PWR_DATA_LO 0x00000010
95#define NV50_DISP_DAC_PWR_STATE 0x00000040
96#define NV50_DISP_DAC_PWR_STATE_ON 0x00000000
97#define NV50_DISP_DAC_PWR_STATE_OFF 0x00000040
98#define NV50_DISP_DAC_LOAD 0x00020100 84#define NV50_DISP_DAC_LOAD 0x00020100
99#define NV50_DISP_DAC_LOAD_VALUE 0x00000007 85#define NV50_DISP_DAC_LOAD_VALUE 0x00000007
100 86
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index ffdf85f7814e..dae2c96deef8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -1397,6 +1397,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1397 uint32_t conn, uint32_t conf, struct dcb_output *entry) 1397 uint32_t conn, uint32_t conf, struct dcb_output *entry)
1398{ 1398{
1399 struct nouveau_drm *drm = nouveau_drm(dev); 1399 struct nouveau_drm *drm = nouveau_drm(dev);
1400 int link = 0;
1400 1401
1401 entry->type = conn & 0xf; 1402 entry->type = conn & 0xf;
1402 entry->i2c_index = (conn >> 4) & 0xf; 1403 entry->i2c_index = (conn >> 4) & 0xf;
@@ -1442,6 +1443,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1442 if (conf & 0x4) 1443 if (conf & 0x4)
1443 entry->lvdsconf.use_power_scripts = true; 1444 entry->lvdsconf.use_power_scripts = true;
1444 entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4; 1445 entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4;
1446 link = entry->lvdsconf.sor.link;
1445 } 1447 }
1446 if (conf & mask) { 1448 if (conf & mask) {
1447 /* 1449 /*
@@ -1490,17 +1492,18 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1490 entry->dpconf.link_nr = 1; 1492 entry->dpconf.link_nr = 1;
1491 break; 1493 break;
1492 } 1494 }
1495 link = entry->dpconf.sor.link;
1493 break; 1496 break;
1494 case DCB_OUTPUT_TMDS: 1497 case DCB_OUTPUT_TMDS:
1495 if (dcb->version >= 0x40) { 1498 if (dcb->version >= 0x40) {
1496 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; 1499 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
1497 entry->extdev = (conf & 0x0000ff00) >> 8; 1500 entry->extdev = (conf & 0x0000ff00) >> 8;
1501 link = entry->tmdsconf.sor.link;
1498 } 1502 }
1499 else if (dcb->version >= 0x30) 1503 else if (dcb->version >= 0x30)
1500 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; 1504 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
1501 else if (dcb->version >= 0x22) 1505 else if (dcb->version >= 0x22)
1502 entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; 1506 entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;
1503
1504 break; 1507 break;
1505 case DCB_OUTPUT_EOL: 1508 case DCB_OUTPUT_EOL:
1506 /* weird g80 mobile type that "nv" treats as a terminator */ 1509 /* weird g80 mobile type that "nv" treats as a terminator */
@@ -1524,6 +1527,8 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1524 if (conf & 0x100000) 1527 if (conf & 0x100000)
1525 entry->i2c_upper_default = true; 1528 entry->i2c_upper_default = true;
1526 1529
1530 entry->hasht = (entry->location << 4) | entry->type;
1531 entry->hashm = (entry->heads << 8) | (link << 6) | entry->or;
1527 return true; 1532 return true;
1528} 1533}
1529 1534
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 2d9a02c4b87e..d3e6bd33670e 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1466,16 +1466,24 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
1466{ 1466{
1467 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1467 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1468 struct nv50_disp *disp = nv50_disp(encoder->dev); 1468 struct nv50_disp *disp = nv50_disp(encoder->dev);
1469 int or = nv_encoder->or; 1469 struct {
1470 u32 dpms_ctrl; 1470 struct nv50_disp_mthd_v1 base;
1471 struct nv50_disp_dac_pwr_v0 pwr;
1472 } args = {
1473 .base.version = 1,
1474 .base.method = NV50_DISP_MTHD_V1_DAC_PWR,
1475 .base.hasht = nv_encoder->dcb->hasht,
1476 .base.hashm = nv_encoder->dcb->hashm,
1477 .pwr.state = 1,
1478 .pwr.data = 1,
1479 .pwr.vsync = (mode != DRM_MODE_DPMS_SUSPEND &&
1480 mode != DRM_MODE_DPMS_OFF),
1481 .pwr.hsync = (mode != DRM_MODE_DPMS_STANDBY &&
1482 mode != DRM_MODE_DPMS_OFF),
1483 };
1471 1484
1472 dpms_ctrl = 0x00000000;
1473 if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
1474 dpms_ctrl |= 0x00000001;
1475 if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
1476 dpms_ctrl |= 0x00000004;
1477 1485
1478 nvif_exec(disp->disp, NV50_DISP_DAC_PWR + or, &dpms_ctrl, sizeof(dpms_ctrl)); 1486 nvif_mthd(disp->disp, 0, &args, sizeof(args));
1479} 1487}
1480 1488
1481static bool 1489static bool
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h
index 50c5413ff523..9681a102970d 100644
--- a/drivers/gpu/drm/nouveau/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/nvif/class.h
@@ -290,4 +290,47 @@ struct kepler_channel_gpfifo_a_v0 {
290 __u64 ioffset; 290 __u64 ioffset;
291}; 291};
292 292
293/*******************************************************************************
294 * legacy display
295 ******************************************************************************/
296
297
298/*******************************************************************************
299 * display
300 ******************************************************************************/
301
302#define NV50_DISP_MTHD 0x00
303
304struct nv50_disp_mthd_v0 {
305 __u8 version;
306 __u8 method;
307 __u8 head;
308 __u8 pad03[5];
309};
310
311struct nv50_disp_mthd_v1 {
312 __u8 version;
313#define NV50_DISP_MTHD_V1_DAC_PWR 0x10
314#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11
315#define NV50_DISP_MTHD_V1_SOR_PWR 0x20
316#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21
317#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
318#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
319#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24
320#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30
321 __u8 method;
322 __u16 hasht;
323 __u16 hashm;
324 __u8 pad06[2];
325};
326
327struct nv50_disp_dac_pwr_v0 {
328 __u8 version;
329 __u8 state;
330 __u8 data;
331 __u8 vsync;
332 __u8 hsync;
333 __u8 pad05[3];
334};
335
293#endif 336#endif