mirror of https://gitee.com/openkylin/linux.git
drm/nouveau/disp: common implementation of scanoutpos method in nvkm_head
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
14187b007e
commit
57b2d73be2
|
@ -32,7 +32,6 @@ g84_disp = {
|
|||
.super = nv50_disp_super,
|
||||
.root = &g84_disp_root_oclass,
|
||||
.head.new = nv50_head_new,
|
||||
.head.scanoutpos = nv50_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -32,7 +32,6 @@ g94_disp = {
|
|||
.super = nv50_disp_super,
|
||||
.root = &g94_disp_root_oclass,
|
||||
.head.new = nv50_head_new,
|
||||
.head.scanoutpos = nv50_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -501,7 +501,6 @@ gf119_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gf119_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -33,7 +33,6 @@ gk104_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gk104_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -33,7 +33,6 @@ gk110_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gk110_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -33,7 +33,6 @@ gm107_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gm107_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -33,7 +33,6 @@ gm200_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gm200_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -33,7 +33,6 @@ gp100_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gp100_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -59,7 +59,6 @@ gp102_disp = {
|
|||
.super = gf119_disp_super,
|
||||
.root = &gp102_disp_root_oclass,
|
||||
.head.new = gf119_head_new,
|
||||
.head.scanoutpos = gf119_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -32,7 +32,6 @@ gt200_disp = {
|
|||
.super = nv50_disp_super,
|
||||
.root = >200_disp_root_oclass,
|
||||
.head.new = nv50_head_new,
|
||||
.head.scanoutpos = nv50_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -32,7 +32,6 @@ gt215_disp = {
|
|||
.super = nv50_disp_super,
|
||||
.root = >215_disp_root_oclass,
|
||||
.head.new = nv50_head_new,
|
||||
.head.scanoutpos = nv50_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
*/
|
||||
#include "head.h"
|
||||
|
||||
#include <core/client.h>
|
||||
|
||||
#include <nvif/cl0046.h>
|
||||
#include <nvif/unpack.h>
|
||||
|
||||
struct nvkm_head *
|
||||
nvkm_head_find(struct nvkm_disp *disp, int id)
|
||||
{
|
||||
|
@ -34,6 +39,44 @@ nvkm_head_find(struct nvkm_disp *disp, int id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_head_mthd_scanoutpos(struct nvkm_object *object,
|
||||
struct nvkm_head *head, void *data, u32 size)
|
||||
{
|
||||
union {
|
||||
struct nv04_disp_scanoutpos_v0 v0;
|
||||
} *args = data;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
nvif_ioctl(object, "head scanoutpos size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||
nvif_ioctl(object, "head scanoutpos vers %d\n",
|
||||
args->v0.version);
|
||||
|
||||
head->func->state(head, &head->arm);
|
||||
args->v0.vtotal = head->arm.vtotal;
|
||||
args->v0.vblanks = head->arm.vblanks;
|
||||
args->v0.vblanke = head->arm.vblanke;
|
||||
args->v0.htotal = head->arm.htotal;
|
||||
args->v0.hblanks = head->arm.hblanks;
|
||||
args->v0.hblanke = head->arm.hblanke;
|
||||
|
||||
/* We don't support reading htotal/vtotal on pre-NV50 VGA,
|
||||
* 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());
|
||||
head->func->rgpos(head, &args->v0.hline, &args->v0.vline);
|
||||
args->v0.time[1] = ktime_to_ns(ktime_get());
|
||||
} else
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nvkm_head_del(struct nvkm_head **phead)
|
||||
{
|
||||
|
|
|
@ -8,17 +8,34 @@ struct nvkm_head {
|
|||
int id;
|
||||
|
||||
struct list_head head;
|
||||
|
||||
struct nvkm_head_state {
|
||||
u16 htotal;
|
||||
u16 hsynce;
|
||||
u16 hblanke;
|
||||
u16 hblanks;
|
||||
u16 vtotal;
|
||||
u16 vsynce;
|
||||
u16 vblanke;
|
||||
u16 vblanks;
|
||||
} arm, asy;
|
||||
};
|
||||
|
||||
int nvkm_head_new_(const struct nvkm_head_func *, struct nvkm_disp *, int id);
|
||||
void nvkm_head_del(struct nvkm_head **);
|
||||
int nvkm_head_mthd_scanoutpos(struct nvkm_object *,
|
||||
struct nvkm_head *, void *, u32);
|
||||
struct nvkm_head *nvkm_head_find(struct nvkm_disp *, int id);
|
||||
|
||||
struct nvkm_head_func {
|
||||
void (*state)(struct nvkm_head *, struct nvkm_head_state *);
|
||||
void (*rgpos)(struct nvkm_head *, u16 *hline, u16 *vline);
|
||||
void (*vblank_get)(struct nvkm_head *);
|
||||
void (*vblank_put)(struct nvkm_head *);
|
||||
};
|
||||
|
||||
void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *);
|
||||
|
||||
#define HEAD_MSG(h,l,f,a...) do { \
|
||||
struct nvkm_head *_h = (h); \
|
||||
nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \
|
||||
|
|
|
@ -39,8 +39,31 @@ gf119_head_vblank_get(struct nvkm_head *head)
|
|||
nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001);
|
||||
}
|
||||
|
||||
static void
|
||||
gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state)
|
||||
{
|
||||
struct nvkm_device *device = head->disp->engine.subdev.device;
|
||||
const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300;
|
||||
u32 data;
|
||||
|
||||
data = nvkm_rd32(device, 0x640414 + hoff);
|
||||
state->vtotal = (data & 0xffff0000) >> 16;
|
||||
state->htotal = (data & 0x0000ffff);
|
||||
data = nvkm_rd32(device, 0x640418 + hoff);
|
||||
state->vsynce = (data & 0xffff0000) >> 16;
|
||||
state->hsynce = (data & 0x0000ffff);
|
||||
data = nvkm_rd32(device, 0x64041c + hoff);
|
||||
state->vblanke = (data & 0xffff0000) >> 16;
|
||||
state->hblanke = (data & 0x0000ffff);
|
||||
data = nvkm_rd32(device, 0x640420 + hoff);
|
||||
state->vblanks = (data & 0xffff0000) >> 16;
|
||||
state->hblanks = (data & 0x0000ffff);
|
||||
}
|
||||
|
||||
static const struct nvkm_head_func
|
||||
gf119_head = {
|
||||
.state = gf119_head_state,
|
||||
.rgpos = nv50_head_rgpos,
|
||||
.vblank_get = gf119_head_vblank_get,
|
||||
.vblank_put = gf119_head_vblank_put,
|
||||
};
|
||||
|
|
|
@ -37,8 +37,32 @@ nv04_head_vblank_get(struct nvkm_head *head)
|
|||
nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001);
|
||||
}
|
||||
|
||||
static void
|
||||
nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline)
|
||||
{
|
||||
struct nvkm_device *device = head->disp->engine.subdev.device;
|
||||
u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000));
|
||||
*hline = (data & 0xffff0000) >> 16;
|
||||
*vline = (data & 0x0000ffff);
|
||||
}
|
||||
|
||||
static void
|
||||
nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state)
|
||||
{
|
||||
struct nvkm_device *device = head->disp->engine.subdev.device;
|
||||
const u32 hoff = head->id * 0x0200;
|
||||
state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff;
|
||||
state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff;
|
||||
state->vblanke = state->vtotal - 1;
|
||||
state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff;
|
||||
state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff;
|
||||
state->hblanke = state->htotal - 1;
|
||||
}
|
||||
|
||||
static const struct nvkm_head_func
|
||||
nv04_head = {
|
||||
.state = nv04_head_state,
|
||||
.rgpos = nv04_head_rgpos,
|
||||
.vblank_get = nv04_head_vblank_get,
|
||||
.vblank_put = nv04_head_vblank_put,
|
||||
};
|
||||
|
|
|
@ -37,8 +37,41 @@ nv50_head_vblank_get(struct nvkm_head *head)
|
|||
nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id));
|
||||
}
|
||||
|
||||
void
|
||||
nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline)
|
||||
{
|
||||
struct nvkm_device *device = head->disp->engine.subdev.device;
|
||||
const u32 hoff = head->id * 0x800;
|
||||
/* vline read locks hline. */
|
||||
*vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff;
|
||||
*hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state)
|
||||
{
|
||||
struct nvkm_device *device = head->disp->engine.subdev.device;
|
||||
const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4;
|
||||
u32 data;
|
||||
|
||||
data = nvkm_rd32(device, 0x610ae8 + hoff);
|
||||
state->vblanke = (data & 0xffff0000) >> 16;
|
||||
state->hblanke = (data & 0x0000ffff);
|
||||
data = nvkm_rd32(device, 0x610af0 + hoff);
|
||||
state->vblanks = (data & 0xffff0000) >> 16;
|
||||
state->hblanks = (data & 0x0000ffff);
|
||||
data = nvkm_rd32(device, 0x610af8 + hoff);
|
||||
state->vtotal = (data & 0xffff0000) >> 16;
|
||||
state->htotal = (data & 0x0000ffff);
|
||||
data = nvkm_rd32(device, 0x610b00 + hoff);
|
||||
state->vsynce = (data & 0xffff0000) >> 16;
|
||||
state->hsynce = (data & 0x0000ffff);
|
||||
}
|
||||
|
||||
static const struct nvkm_head_func
|
||||
nv50_head = {
|
||||
.state = nv50_head_state,
|
||||
.rgpos = nv50_head_rgpos,
|
||||
.vblank_get = nv50_head_vblank_get,
|
||||
.vblank_put = nv50_head_vblank_put,
|
||||
};
|
||||
|
|
|
@ -797,7 +797,6 @@ nv50_disp = {
|
|||
.super = nv50_disp_super,
|
||||
.root = &nv50_disp_root_oclass,
|
||||
.head.new = nv50_head_new,
|
||||
.head.scanoutpos = nv50_disp_root_scanoutpos,
|
||||
.outp.internal.crt = nv50_dac_output_new,
|
||||
.outp.internal.tmds = nv50_sor_output_new,
|
||||
.outp.internal.lvds = nv50_sor_output_new,
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#define NV50_DISP_MTHD_ struct nvkm_object *object, \
|
||||
struct nv50_disp *disp, void *data, u32 size
|
||||
#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
|
||||
#define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp
|
||||
|
||||
struct nv50_disp {
|
||||
|
@ -29,10 +28,6 @@ struct nv50_disp {
|
|||
struct nv50_disp_chan *chan[17];
|
||||
};
|
||||
|
||||
int nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0);
|
||||
|
||||
int gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0);
|
||||
|
||||
int nv50_dac_power(NV50_DISP_MTHD_V1);
|
||||
int nv50_dac_sense(NV50_DISP_MTHD_V1);
|
||||
|
||||
|
@ -76,7 +71,6 @@ struct nv50_disp_func {
|
|||
|
||||
struct {
|
||||
int (*new)(struct nvkm_disp *, int id);
|
||||
int (*scanoutpos)(NV50_DISP_MTHD_V0);
|
||||
} head;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -25,47 +25,10 @@
|
|||
#include "head.h"
|
||||
#include "dmacnv50.h"
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/ramht.h>
|
||||
#include <subdev/timer.h>
|
||||
|
||||
#include <nvif/class.h>
|
||||
#include <nvif/cl5070.h>
|
||||
#include <nvif/unpack.h>
|
||||
|
||||
int
|
||||
gf119_disp_root_scanoutpos(NV50_DISP_MTHD_V0)
|
||||
{
|
||||
struct nvkm_device *device = disp->base.engine.subdev.device;
|
||||
const u32 total = nvkm_rd32(device, 0x640414 + (head * 0x300));
|
||||
const u32 blanke = nvkm_rd32(device, 0x64041c + (head * 0x300));
|
||||
const u32 blanks = nvkm_rd32(device, 0x640420 + (head * 0x300));
|
||||
union {
|
||||
struct nv50_disp_scanoutpos_v0 v0;
|
||||
} *args = data;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
nvif_ioctl(object, "disp scanoutpos size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||
nvif_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 */
|
||||
nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff;
|
||||
args->v0.time[1] = ktime_to_ns(ktime_get());
|
||||
args->v0.hline =
|
||||
nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff;
|
||||
} else
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gf119_disp_root_fini(struct nv50_disp_root *root)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object)
|
||||
#include "priv.h"
|
||||
#include "head.h"
|
||||
|
||||
#include <core/client.h>
|
||||
|
||||
|
@ -35,50 +36,6 @@ struct nv04_disp_root {
|
|||
struct nvkm_disp *disp;
|
||||
};
|
||||
|
||||
static int
|
||||
nv04_disp_scanoutpos(struct nv04_disp_root *root,
|
||||
void *data, u32 size, int head)
|
||||
{
|
||||
struct nvkm_device *device = root->disp->engine.subdev.device;
|
||||
struct nvkm_object *object = &root->object;
|
||||
const u32 hoff = head * 0x2000;
|
||||
union {
|
||||
struct nv04_disp_scanoutpos_v0 v0;
|
||||
} *args = data;
|
||||
u32 line;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
nvif_ioctl(object, "disp scanoutpos size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||
nvif_ioctl(object, "disp scanoutpos vers %d\n",
|
||||
args->v0.version);
|
||||
args->v0.vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0xffff;
|
||||
args->v0.vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0xffff;
|
||||
args->v0.vblanke = args->v0.vtotal - 1;
|
||||
|
||||
args->v0.hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0xffff;
|
||||
args->v0.htotal = nvkm_rd32(device, 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 = nvkm_rd32(device, 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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
||||
{
|
||||
|
@ -86,23 +43,24 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
union {
|
||||
struct nv04_disp_mthd_v0 v0;
|
||||
} *args = data;
|
||||
int head, ret = -ENOSYS;
|
||||
struct nvkm_head *head;
|
||||
int id, ret = -ENOSYS;
|
||||
|
||||
nvif_ioctl(object, "disp mthd size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
|
||||
nvif_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;
|
||||
id = args->v0.head;
|
||||
} else
|
||||
return ret;
|
||||
|
||||
if (head < 0 || head >= 2)
|
||||
if (!(head = nvkm_head_find(root->disp, id)))
|
||||
return -ENXIO;
|
||||
|
||||
switch (mthd) {
|
||||
case NV04_DISP_SCANOUTPOS:
|
||||
return nv04_disp_scanoutpos(root, data, size, head);
|
||||
return nvkm_head_mthd_scanoutpos(object, head, data, size);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -33,40 +33,6 @@
|
|||
#include <nvif/cl5070.h>
|
||||
#include <nvif/unpack.h>
|
||||
|
||||
int
|
||||
nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0)
|
||||
{
|
||||
struct nvkm_device *device = disp->base.engine.subdev.device;
|
||||
const u32 blanke = nvkm_rd32(device, 0x610aec + (head * 0x540));
|
||||
const u32 blanks = nvkm_rd32(device, 0x610af4 + (head * 0x540));
|
||||
const u32 total = nvkm_rd32(device, 0x610afc + (head * 0x540));
|
||||
union {
|
||||
struct nv50_disp_scanoutpos_v0 v0;
|
||||
} *args = data;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
nvif_ioctl(object, "disp scanoutpos size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||
nvif_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 */
|
||||
nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff;
|
||||
args->v0.time[1] = ktime_to_ns(ktime_get());
|
||||
args->v0.hline =
|
||||
nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff;
|
||||
} else
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
||||
{
|
||||
|
@ -78,8 +44,9 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
struct nv50_disp *disp = root->disp;
|
||||
const struct nv50_disp_func *func = disp->func;
|
||||
struct nvkm_outp *temp, *outp = NULL;
|
||||
struct nvkm_head *head;
|
||||
u16 type, mask = 0;
|
||||
int head, ret = -ENOSYS;
|
||||
int hidx, ret = -ENOSYS;
|
||||
|
||||
if (mthd != NV50_DISP_MTHD)
|
||||
return -EINVAL;
|
||||
|
@ -89,7 +56,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
nvif_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;
|
||||
hidx = args->v0.head;
|
||||
} else
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) {
|
||||
nvif_ioctl(object, "disp mthd vers %d mthd %02x "
|
||||
|
@ -99,11 +66,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
mthd = args->v1.method;
|
||||
type = args->v1.hasht;
|
||||
mask = args->v1.hashm;
|
||||
head = ffs((mask >> 8) & 0x0f) - 1;
|
||||
hidx = ffs((mask >> 8) & 0x0f) - 1;
|
||||
} else
|
||||
return ret;
|
||||
|
||||
if (!nvkm_head_find(&disp->base, head))
|
||||
if (!(head = nvkm_head_find(&disp->base, hidx)))
|
||||
return -ENXIO;
|
||||
|
||||
if (mask) {
|
||||
|
@ -119,27 +86,28 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
}
|
||||
|
||||
switch (mthd) {
|
||||
case NV50_DISP_SCANOUTPOS:
|
||||
return func->head.scanoutpos(object, disp, data, size, head);
|
||||
case NV50_DISP_SCANOUTPOS: {
|
||||
return nvkm_head_mthd_scanoutpos(object, head, data, size);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mthd * !!outp) {
|
||||
case NV50_DISP_MTHD_V1_DAC_PWR:
|
||||
return func->dac.power(object, disp, data, size, head, outp);
|
||||
return func->dac.power(object, disp, data, size, hidx, outp);
|
||||
case NV50_DISP_MTHD_V1_DAC_LOAD:
|
||||
return func->dac.sense(object, disp, data, size, head, outp);
|
||||
return func->dac.sense(object, disp, data, size, hidx, outp);
|
||||
case NV50_DISP_MTHD_V1_SOR_PWR:
|
||||
return func->sor.power(object, disp, data, size, head, outp);
|
||||
return func->sor.power(object, disp, data, size, hidx, outp);
|
||||
case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
|
||||
if (!func->sor.hda_eld)
|
||||
return -ENODEV;
|
||||
return func->sor.hda_eld(object, disp, data, size, head, outp);
|
||||
return func->sor.hda_eld(object, disp, data, size, hidx, outp);
|
||||
case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
|
||||
if (!func->sor.hdmi)
|
||||
return -ENODEV;
|
||||
return func->sor.hdmi(object, disp, data, size, head, outp);
|
||||
return func->sor.hdmi(object, disp, data, size, hidx, outp);
|
||||
case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
|
||||
union {
|
||||
struct nv50_disp_sor_lvds_script_v0 v0;
|
||||
|
@ -215,7 +183,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
args->v0.aligned_pbn);
|
||||
if (!outpdp->func->vcpi)
|
||||
return -ENODEV;
|
||||
outpdp->func->vcpi(outpdp, head, args->v0.start_slot,
|
||||
outpdp->func->vcpi(outpdp, hidx, args->v0.start_slot,
|
||||
args->v0.num_slots, args->v0.pbn,
|
||||
args->v0.aligned_pbn);
|
||||
return 0;
|
||||
|
@ -226,7 +194,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|||
case NV50_DISP_MTHD_V1_PIOR_PWR:
|
||||
if (!func->pior.power)
|
||||
return -ENODEV;
|
||||
return func->pior.power(object, disp, data, size, head, outp);
|
||||
return func->pior.power(object, disp, data, size, hidx, outp);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue