diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2014-08-09 14:10:26 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-09 15:28:07 -0400 |
| commit | bf0eb89859439f016a1fab4cdf737c95f36dbb2e (patch) | |
| tree | 59709bbd702fe904e63a2237d200162f90d820b4 /drivers/gpu | |
| parent | 2c04ae01df38f95dd3e553c85cdac670a80110f5 (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.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 73 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv84.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv94.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/outp.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/outp.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/include/core/class.h | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvif/class.h | 43 |
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 | ||
| 34 | int | 36 | int |
| 35 | nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data) | 37 | nv50_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 | ||
| 842 | int | 845 | int |
| 846 | nv50_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 | |||
| 911 | int | ||
| 843 | nv50_disp_base_ctor(struct nouveau_object *parent, | 912 | nv50_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 | ||
| 959 | static struct nouveau_omthds | 1029 | static 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 | |||
| 27 | struct nv50_disp_priv { | 32 | struct 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 | ||
| 58 | int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32); | 63 | int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32); |
| 64 | int 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 | ||
| 62 | int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); | 68 | int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); |
| 63 | int nv50_dac_power(struct nv50_disp_priv *, int, u32); | 69 | int nv50_dac_power(NV50_DISP_MTHD_V1); |
| 64 | int nv50_dac_sense(struct nv50_disp_priv *, int, u32); | 70 | int 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 | ||
| 711 | struct nouveau_omthds | 712 | struct 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 | ||
| 1481 | static bool | 1489 | static 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 | |||
| 304 | struct nv50_disp_mthd_v0 { | ||
| 305 | __u8 version; | ||
| 306 | __u8 method; | ||
| 307 | __u8 head; | ||
| 308 | __u8 pad03[5]; | ||
| 309 | }; | ||
| 310 | |||
| 311 | struct 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 | |||
| 327 | struct 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 |
