drm/nouveau/disp: add a method to fetch info needed by drm vblank timestamping
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
eb2e9686d6
commit
d2fa7d32ea
|
@ -31,9 +31,45 @@ struct nv04_disp_priv {
|
||||||
struct nouveau_disp base;
|
struct nouveau_disp base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
|
||||||
|
void *data, u32 size)
|
||||||
|
{
|
||||||
|
struct nv04_disp_priv *priv = (void *)object->engine;
|
||||||
|
struct nv04_display_scanoutpos *args = data;
|
||||||
|
const int head = (mthd & NV04_DISP_MTHD_HEAD);
|
||||||
|
u32 line;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 struct nouveau_omthds
|
||||||
|
nv04_disp_omthds[] = {
|
||||||
|
{ HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
nv04_disp_sclass[] = {
|
nv04_disp_sclass[] = {
|
||||||
{ NV04_DISP_CLASS, &nouveau_object_ofuncs },
|
{ NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -541,6 +541,35 @@ nv50_disp_curs_ofuncs = {
|
||||||
* Base display object
|
* Base display object
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
|
||||||
|
void *data, u32 size)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
|
nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
|
||||||
{
|
{
|
||||||
|
@ -675,6 +704,7 @@ nv50_disp_base_ofuncs = {
|
||||||
|
|
||||||
static struct nouveau_omthds
|
static struct nouveau_omthds
|
||||||
nv50_disp_base_omthds[] = {
|
nv50_disp_base_omthds[] = {
|
||||||
|
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||||
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
|
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
|
||||||
|
|
|
@ -43,6 +43,10 @@ struct nv50_disp_priv {
|
||||||
} pior;
|
} pior;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HEAD_MTHD(n) (n), (n) + 0x03
|
||||||
|
|
||||||
|
int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
|
||||||
|
|
||||||
#define DAC_MTHD(n) (n), (n) + 0x03
|
#define DAC_MTHD(n) (n), (n) + 0x03
|
||||||
|
|
||||||
int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
|
int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
|
||||||
|
@ -132,13 +136,12 @@ void nv50_disp_intr(struct nouveau_subdev *);
|
||||||
|
|
||||||
extern struct nouveau_omthds nv84_disp_base_omthds[];
|
extern struct nouveau_omthds nv84_disp_base_omthds[];
|
||||||
|
|
||||||
extern struct nouveau_omthds nva3_disp_base_omthds[];
|
|
||||||
|
|
||||||
extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
|
extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
|
||||||
extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
|
extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
|
||||||
extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
|
extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
|
||||||
extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
|
extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
|
||||||
extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
|
extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
|
||||||
|
extern struct nouveau_omthds nvd0_disp_base_omthds[];
|
||||||
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
|
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
|
||||||
extern struct nouveau_oclass nvd0_disp_cclass;
|
extern struct nouveau_oclass nvd0_disp_cclass;
|
||||||
void nvd0_disp_intr_supervisor(struct work_struct *);
|
void nvd0_disp_intr_supervisor(struct work_struct *);
|
||||||
|
|
|
@ -41,6 +41,7 @@ nv84_disp_sclass[] = {
|
||||||
|
|
||||||
struct nouveau_omthds
|
struct nouveau_omthds
|
||||||
nv84_disp_base_omthds[] = {
|
nv84_disp_base_omthds[] = {
|
||||||
|
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||||
|
|
|
@ -41,6 +41,7 @@ nv94_disp_sclass[] = {
|
||||||
|
|
||||||
static struct nouveau_omthds
|
static struct nouveau_omthds
|
||||||
nv94_disp_base_omthds[] = {
|
nv94_disp_base_omthds[] = {
|
||||||
|
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||||
|
|
|
@ -39,8 +39,9 @@ nva3_disp_sclass[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nouveau_omthds
|
static struct nouveau_omthds
|
||||||
nva3_disp_base_omthds[] = {
|
nva3_disp_base_omthds[] = {
|
||||||
|
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
|
||||||
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
|
{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||||
|
|
|
@ -440,6 +440,36 @@ nvd0_disp_curs_ofuncs = {
|
||||||
* Base display object
|
* Base display object
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
|
||||||
|
void *data, u32 size)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
|
nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
|
||||||
{
|
{
|
||||||
|
@ -573,9 +603,24 @@ nvd0_disp_base_ofuncs = {
|
||||||
.fini = nvd0_disp_base_fini,
|
.fini = nvd0_disp_base_fini,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nouveau_omthds
|
||||||
|
nvd0_disp_base_omthds[] = {
|
||||||
|
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
|
||||||
|
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||||
|
{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
|
||||||
|
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||||
|
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||||
|
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
|
||||||
|
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
|
||||||
|
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
|
||||||
|
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
|
||||||
|
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
nvd0_disp_base_oclass[] = {
|
nvd0_disp_base_oclass[] = {
|
||||||
{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
|
{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ nve0_disp_sclass[] = {
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
nve0_disp_base_oclass[] = {
|
nve0_disp_base_oclass[] = {
|
||||||
{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
|
{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ nvf0_disp_sclass[] = {
|
||||||
|
|
||||||
static struct nouveau_oclass
|
static struct nouveau_oclass
|
||||||
nvf0_disp_base_oclass[] = {
|
nvf0_disp_base_oclass[] = {
|
||||||
{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
|
{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -230,9 +230,26 @@ struct nve0_channel_ind_class {
|
||||||
|
|
||||||
#define NV04_DISP_CLASS 0x00000046
|
#define NV04_DISP_CLASS 0x00000046
|
||||||
|
|
||||||
|
#define NV04_DISP_MTHD 0x00000000
|
||||||
|
#define NV04_DISP_MTHD_HEAD 0x00000001
|
||||||
|
|
||||||
|
#define NV04_DISP_SCANOUTPOS 0x00000000
|
||||||
|
|
||||||
struct nv04_display_class {
|
struct nv04_display_class {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nv04_display_scanoutpos {
|
||||||
|
s64 time[2];
|
||||||
|
u32 vblanks;
|
||||||
|
u32 vblanke;
|
||||||
|
u32 vtotal;
|
||||||
|
u32 vline;
|
||||||
|
u32 hblanks;
|
||||||
|
u32 hblanke;
|
||||||
|
u32 htotal;
|
||||||
|
u32 hline;
|
||||||
|
};
|
||||||
|
|
||||||
/* 5070: NV50_DISP
|
/* 5070: NV50_DISP
|
||||||
* 8270: NV84_DISP
|
* 8270: NV84_DISP
|
||||||
* 8370: NVA0_DISP
|
* 8370: NVA0_DISP
|
||||||
|
@ -252,6 +269,11 @@ struct nv04_display_class {
|
||||||
#define NVE0_DISP_CLASS 0x00009170
|
#define NVE0_DISP_CLASS 0x00009170
|
||||||
#define NVF0_DISP_CLASS 0x00009270
|
#define NVF0_DISP_CLASS 0x00009270
|
||||||
|
|
||||||
|
#define NV50_DISP_MTHD 0x00000000
|
||||||
|
#define NV50_DISP_MTHD_HEAD 0x00000003
|
||||||
|
|
||||||
|
#define NV50_DISP_SCANOUTPOS 0x00000000
|
||||||
|
|
||||||
#define NV50_DISP_SOR_MTHD 0x00010000
|
#define NV50_DISP_SOR_MTHD 0x00010000
|
||||||
#define NV50_DISP_SOR_MTHD_TYPE 0x0000f000
|
#define NV50_DISP_SOR_MTHD_TYPE 0x0000f000
|
||||||
#define NV50_DISP_SOR_MTHD_HEAD 0x00000018
|
#define NV50_DISP_SOR_MTHD_HEAD 0x00000018
|
||||||
|
|
Loading…
Reference in a new issue