aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/engine/disp
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-10 04:10:27 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-08-10 05:28:10 +1000
commit4952b4d339033c2019bbd00f28f422b6fc340408 (patch)
tree10b610a3ca4d2b7e60e6795fc33e784e809bf2e8 /drivers/gpu/drm/nouveau/core/engine/disp
parentdrm/nv50-/disp: audit and version PIOR_PWR method (diff)
downloadlinux-dev-4952b4d339033c2019bbd00f28f422b6fc340408.tar.xz
linux-dev-4952b4d339033c2019bbd00f28f422b6fc340408.zip
drm/nouveau/disp: audit and version SCANOUTPOS 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/drm/nouveau/core/engine/disp')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/gm107.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv04.c110
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c61
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h33
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c66
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c3
11 files changed, 167 insertions, 142 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
index f93d76e040fe..6a25f38d7fbf 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
@@ -45,7 +45,7 @@ gm107_disp_sclass[] = {
static struct nouveau_oclass
gm107_disp_base_oclass[] = {
- { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs },
{}
};
@@ -99,4 +99,5 @@ gm107_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index f1f3bd15a5c0..6dba53df35fc 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -24,60 +24,100 @@
#include "priv.h"
+#include <core/client.h>
#include <core/event.h>
#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
struct nv04_disp_priv {
struct nouveau_disp base;
};
static int
-nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nv04_disp_scanoutpos(struct nouveau_object *object, struct nv04_disp_priv *priv,
+ void *data, u32 size, int head)
{
- struct nv04_disp_priv *priv = (void *)object->engine;
- struct nv04_display_scanoutpos *args = data;
- const int head = (mthd & NV04_DISP_MTHD_HEAD);
+ const u32 hoff = head * 0x2000;
+ union {
+ struct nv04_disp_scanoutpos_v0 v0;
+ } *args = data;
u32 line;
+ int ret;
+
+ nv_ioctl(object, "disp scanoutpos size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+ args->v0.vblanks = nv_rd32(priv, 0x680800 + hoff) & 0xffff;
+ args->v0.vtotal = nv_rd32(priv, 0x680804 + hoff) & 0xffff;
+ args->v0.vblanke = args->v0.vtotal - 1;
+
+ args->v0.hblanks = nv_rd32(priv, 0x680820 + hoff) & 0xffff;
+ args->v0.htotal = nv_rd32(priv, 0x680824 + hoff) & 0xffff;
+ args->v0.hblanke = args->v0.htotal - 1;
+
+ /*
+ * If output is vga instead of digital then vtotal/htotal is
+ * invalid so we have to give up and trigger the timestamping
+ * fallback in the drm core.
+ */
+ if (!args->v0.vtotal || !args->v0.htotal)
+ return -ENOTSUPP;
+
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ line = nv_rd32(priv, 0x600868 + hoff);
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ args->v0.hline = (line & 0xffff0000) >> 16;
+ args->v0.vline = (line & 0x0000ffff);
+ } else
+ return ret;
- if (size < sizeof(*args))
- return -EINVAL;
-
- args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
- args->vtotal = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
- args->vblanke = args->vtotal - 1;
-
- args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
- args->htotal = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
- args->hblanke = args->htotal - 1;
-
- /*
- * If output is vga instead of digital then vtotal/htotal is invalid
- * so we have to give up and trigger the timestamping fallback in the
- * drm core.
- */
- if (!args->vtotal || !args->htotal)
- return -ENOTSUPP;
-
- args->time[0] = ktime_to_ns(ktime_get());
- line = nv_rd32(priv, 0x600868 + (head * 0x2000));
- args->time[1] = ktime_to_ns(ktime_get());
- args->hline = (line & 0xffff0000) >> 16;
- args->vline = (line & 0x0000ffff);
return 0;
}
-#define HEAD_MTHD(n) (n), (n) + 0x01
+static int
+nv04_disp_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
+{
+ union {
+ struct nv04_disp_mthd_v0 v0;
+ } *args = data;
+ struct nv04_disp_priv *priv = (void *)object->engine;
+ int head, ret;
+
+ nv_ioctl(object, "disp mthd size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
+ args->v0.version, args->v0.method, args->v0.head);
+ mthd = args->v0.method;
+ head = args->v0.head;
+ } else
+ return ret;
+
+ if (head < 0 || head >= 2)
+ return -ENXIO;
+
+ switch (mthd) {
+ case NV04_DISP_SCANOUTPOS:
+ return nv04_disp_scanoutpos(object, priv, data, size, head);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
-static struct nouveau_omthds
-nv04_disp_omthds[] = {
- { HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
- {}
+static struct nouveau_ofuncs
+nv04_disp_ofuncs = {
+ .ctor = _nouveau_object_ctor,
+ .dtor = nouveau_object_destroy,
+ .init = nouveau_object_init,
+ .fini = nouveau_object_fini,
+ .mthd = nv04_disp_mthd,
};
static struct nouveau_oclass
nv04_disp_sclass[] = {
- { NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
+ { NV04_DISP_CLASS, &nv04_disp_ofuncs },
{},
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index d83d3efe8253..7e60c11d7d36 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -814,31 +814,34 @@ nv50_disp_curs_ofuncs = {
******************************************************************************/
int
-nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
{
- struct nv50_disp_priv *priv = (void *)object->engine;
- struct nv04_display_scanoutpos *args = data;
- const int head = (mthd & NV50_DISP_MTHD_HEAD);
- u32 blanke, blanks, total;
+ const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
+ const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
+ const u32 total = nv_rd32(priv, 0x610afc + (head * 0x540));
+ union {
+ struct nv04_disp_scanoutpos_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "disp scanoutpos size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+ args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+ args->v0.hblanke = (blanke & 0x0000ffff);
+ args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+ args->v0.hblanks = (blanks & 0x0000ffff);
+ args->v0.vtotal = ( total & 0xffff0000) >> 16;
+ args->v0.htotal = ( total & 0x0000ffff);
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ args->v0.vline = /* vline read locks hline */
+ nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ args->v0.hline =
+ nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ } else
+ return ret;
- if (size < sizeof(*args) || head >= priv->head.nr)
- return -EINVAL;
- blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
- blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
- total = nv_rd32(priv, 0x610afc + (head * 0x540));
-
- args->vblanke = (blanke & 0xffff0000) >> 16;
- args->hblanke = (blanke & 0x0000ffff);
- args->vblanks = (blanks & 0xffff0000) >> 16;
- args->hblanks = (blanks & 0x0000ffff);
- args->vtotal = ( total & 0xffff0000) >> 16;
- args->htotal = ( total & 0x0000ffff);
-
- args->time[0] = ktime_to_ns(ktime_get());
- args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
- args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
- args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
return 0;
}
@@ -846,6 +849,7 @@ int
nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
{
+ const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
union {
struct nv50_disp_mthd_v0 v0;
struct nv50_disp_mthd_v1 v1;
@@ -894,6 +898,8 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
}
switch (mthd) {
+ case NV50_DISP_SCANOUTPOS:
+ return impl->head.scanoutpos(object, priv, data, size, head);
default:
break;
}
@@ -1081,15 +1087,9 @@ nv50_disp_base_ofuncs = {
.mthd = nv50_disp_base_mthd,
};
-static struct nouveau_omthds
-nv50_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- {},
-};
-
static struct nouveau_oclass
nv50_disp_base_oclass[] = {
- { NV50_DISP_CLASS, &nv50_disp_base_ofuncs, nv50_disp_base_omthds },
+ { NV50_DISP_CLASS, &nv50_disp_base_ofuncs },
{}
};
@@ -1859,4 +1859,5 @@ nv50_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nv50_disp_sync_mthd_chan,
.mthd.ovly = &nv50_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 62a38b5f0024..81bf80fd8dcd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -14,16 +14,6 @@
#include "outp.h"
#include "outpdp.h"
-struct nv50_disp_impl {
- struct nouveau_disp_impl base;
- struct {
- const struct nv50_disp_mthd_chan *core;
- const struct nv50_disp_mthd_chan *base;
- const struct nv50_disp_mthd_chan *ovly;
- int prev;
- } mthd;
-};
-
#define NV50_DISP_MTHD_ struct nouveau_object *object, \
struct nv50_disp_priv *priv, void *data, u32 size
#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
@@ -58,18 +48,27 @@ struct nv50_disp_priv {
} pior;
};
-#define HEAD_MTHD(n) (n), (n) + 0x03
+struct nv50_disp_impl {
+ struct nouveau_disp_impl base;
+ struct {
+ const struct nv50_disp_mthd_chan *core;
+ const struct nv50_disp_mthd_chan *base;
+ const struct nv50_disp_mthd_chan *ovly;
+ int prev;
+ } mthd;
+ struct {
+ int (*scanoutpos)(NV50_DISP_MTHD_V0);
+ } head;
+};
-int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
+int nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
-#define DAC_MTHD(n) (n), (n) + 0x03
+int nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
int nv50_dac_power(NV50_DISP_MTHD_V1);
int nv50_dac_sense(NV50_DISP_MTHD_V1);
-#define SOR_MTHD(n) (n), (n) + 0x3f
-
int nva3_hda_eld(NV50_DISP_MTHD_V1);
int nvd0_hda_eld(NV50_DISP_MTHD_V1);
@@ -97,8 +96,6 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
struct dcb_output *);
-#define PIOR_MTHD(n) (n), (n) + 0x03
-
int nv50_pior_power(NV50_DISP_MTHD_V1);
struct nv50_disp_base {
@@ -203,7 +200,6 @@ extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
-extern struct nouveau_omthds nv84_disp_base_omthds[];
extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
@@ -217,7 +213,6 @@ extern struct nv50_disp_chan_impl nvd0_disp_ovly_ofuncs;
extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
extern struct nv50_disp_chan_impl nvd0_disp_oimm_ofuncs;
extern struct nv50_disp_chan_impl nvd0_disp_curs_ofuncs;
-extern struct nouveau_omthds nvd0_disp_base_omthds[];
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
extern struct nouveau_oclass nvd0_disp_cclass;
void nvd0_disp_intr_supervisor(struct work_struct *);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index c0012d8a450a..8746644d9ded 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -212,15 +212,9 @@ nv84_disp_sclass[] = {
{}
};
-struct nouveau_omthds
-nv84_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- {},
-};
-
static struct nouveau_oclass
nv84_disp_base_oclass[] = {
- { NV84_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+ { NV84_DISP_CLASS, &nv50_disp_base_ofuncs },
{}
};
@@ -274,4 +268,5 @@ nv84_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index 192c8085a1dc..11cd16abcee2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -71,15 +71,9 @@ nv94_disp_sclass[] = {
{}
};
-static struct nouveau_omthds
-nv94_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- {},
-};
-
static struct nouveau_oclass
nv94_disp_base_oclass[] = {
- { NV94_DISP_CLASS, &nv50_disp_base_ofuncs, nv94_disp_base_omthds },
+ { NV94_DISP_CLASS, &nv50_disp_base_ofuncs },
{}
};
@@ -140,4 +134,5 @@ nv94_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index bfd5cf14b0e4..381957586f03 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -90,7 +90,7 @@ nva0_disp_sclass[] = {
static struct nouveau_oclass
nva0_disp_base_oclass[] = {
- { NVA0_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+ { NVA0_DISP_CLASS, &nv50_disp_base_ofuncs },
{}
};
@@ -144,4 +144,5 @@ nva0_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nva0_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index 38a79a0e358f..25df6b93c93a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -43,15 +43,9 @@ nva3_disp_sclass[] = {
{}
};
-static struct nouveau_omthds
-nva3_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- {},
-};
-
static struct nouveau_oclass
nva3_disp_base_oclass[] = {
- { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs, nva3_disp_base_omthds },
+ { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs },
{}
};
@@ -106,4 +100,5 @@ nva3_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 5aa44eca8056..deddd05e7c76 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -23,9 +23,12 @@
*/
#include <core/object.h>
+#include <core/client.h>
#include <core/parent.h>
#include <core/handle.h>
#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <engine/disp.h>
@@ -589,33 +592,35 @@ nvd0_disp_curs_ofuncs = {
* Base display object
******************************************************************************/
-static int
-nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+int
+nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
{
- struct nv50_disp_priv *priv = (void *)object->engine;
- struct nv04_display_scanoutpos *args = data;
- const int head = (mthd & NV50_DISP_MTHD_HEAD);
- u32 blanke, blanks, total;
-
- if (size < sizeof(*args) || head >= priv->head.nr)
- return -EINVAL;
-
- total = nv_rd32(priv, 0x640414 + (head * 0x300));
- blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
- blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
-
- args->vblanke = (blanke & 0xffff0000) >> 16;
- args->hblanke = (blanke & 0x0000ffff);
- args->vblanks = (blanks & 0xffff0000) >> 16;
- args->hblanks = (blanks & 0x0000ffff);
- args->vtotal = ( total & 0xffff0000) >> 16;
- args->htotal = ( total & 0x0000ffff);
-
- args->time[0] = ktime_to_ns(ktime_get());
- args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
- args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
- args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ const u32 total = nv_rd32(priv, 0x640414 + (head * 0x300));
+ const u32 blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
+ const u32 blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
+ union {
+ struct nv04_disp_scanoutpos_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "disp scanoutpos size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+ args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+ args->v0.hblanke = (blanke & 0x0000ffff);
+ args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+ args->v0.hblanks = (blanks & 0x0000ffff);
+ args->v0.vtotal = ( total & 0xffff0000) >> 16;
+ args->v0.htotal = ( total & 0x0000ffff);
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ args->v0.vline = /* vline read locks hline */
+ nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ args->v0.hline =
+ nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ } else
+ return ret;
+
return 0;
}
@@ -709,15 +714,9 @@ nvd0_disp_base_ofuncs = {
.mthd = nv50_disp_base_mthd,
};
-struct nouveau_omthds
-nvd0_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
- {},
-};
-
static struct nouveau_oclass
nvd0_disp_base_oclass[] = {
- { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs },
{}
};
@@ -1242,4 +1241,5 @@ nvd0_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nvd0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 49ab742faae9..58b0ac101f16 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -210,7 +210,7 @@ nve0_disp_sclass[] = {
static struct nouveau_oclass
nve0_disp_base_oclass[] = {
- { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs },
{}
};
@@ -264,4 +264,5 @@ nve0_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
index 448dc912d0ce..b6b01463eb6c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -45,7 +45,7 @@ nvf0_disp_sclass[] = {
static struct nouveau_oclass
nvf0_disp_base_oclass[] = {
- { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs },
{}
};
@@ -99,4 +99,5 @@ nvf0_disp_oclass = &(struct nv50_disp_impl) {
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;