aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-11-13 22:37:48 -0500
committerBen Skeggs <bskeggs@redhat.com>2014-01-29 17:18:36 -0500
commitd2fa7d32ea7b54d910637e50df4972e3540722d4 (patch)
tree075f4af98aca095896f07a87e4a5eddc980226e7
parenteb2e9686d6bc94559dc7f25ed1e67ebbf0a9a41b (diff)
drm/nouveau/disp: add a method to fetch info needed by drm vblank timestamping
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv04.c38
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h7
-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.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c47
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h22
10 files changed, 146 insertions, 7 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index a0bc8a89b699..7cf8b1348632 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -31,9 +31,45 @@ struct nv04_disp_priv {
31 struct nouveau_disp base; 31 struct nouveau_disp base;
32}; 32};
33 33
34static int
35nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
36 void *data, u32 size)
37{
38 struct nv04_disp_priv *priv = (void *)object->engine;
39 struct nv04_display_scanoutpos *args = data;
40 const int head = (mthd & NV04_DISP_MTHD_HEAD);
41 u32 line;
42
43 if (size < sizeof(*args))
44 return -EINVAL;
45
46 args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
47 args->vtotal = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
48 args->vblanke = args->vtotal - 1;
49
50 args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
51 args->htotal = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
52 args->hblanke = args->htotal - 1;
53
54 args->time[0] = ktime_to_ns(ktime_get());
55 line = nv_rd32(priv, 0x600868 + (head * 0x2000));
56 args->time[1] = ktime_to_ns(ktime_get());
57 args->hline = (line & 0xffff0000) >> 16;
58 args->vline = (line & 0x0000ffff);
59 return 0;
60}
61
62#define HEAD_MTHD(n) (n), (n) + 0x01
63
64static struct nouveau_omthds
65nv04_disp_omthds[] = {
66 { HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
67 {}
68};
69
34static struct nouveau_oclass 70static struct nouveau_oclass
35nv04_disp_sclass[] = { 71nv04_disp_sclass[] = {
36 { NV04_DISP_CLASS, &nouveau_object_ofuncs }, 72 { NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
37 {}, 73 {},
38}; 74};
39 75
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index c168ae3eaa97..940eaa5d8b9a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -541,6 +541,35 @@ nv50_disp_curs_ofuncs = {
541 * Base display object 541 * Base display object
542 ******************************************************************************/ 542 ******************************************************************************/
543 543
544int
545nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
546 void *data, u32 size)
547{
548 struct nv50_disp_priv *priv = (void *)object->engine;
549 struct nv04_display_scanoutpos *args = data;
550 const int head = (mthd & NV50_DISP_MTHD_HEAD);
551 u32 blanke, blanks, total;
552
553 if (size < sizeof(*args) || head >= priv->head.nr)
554 return -EINVAL;
555 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
556 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
557 total = nv_rd32(priv, 0x610afc + (head * 0x540));
558
559 args->vblanke = (blanke & 0xffff0000) >> 16;
560 args->hblanke = (blanke & 0x0000ffff);
561 args->vblanks = (blanks & 0xffff0000) >> 16;
562 args->hblanks = (blanks & 0x0000ffff);
563 args->vtotal = ( total & 0xffff0000) >> 16;
564 args->htotal = ( total & 0x0000ffff);
565
566 args->time[0] = ktime_to_ns(ktime_get());
567 args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
568 args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
569 args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
570 return 0;
571}
572
544static void 573static void
545nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) 574nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
546{ 575{
@@ -675,6 +704,7 @@ nv50_disp_base_ofuncs = {
675 704
676static struct nouveau_omthds 705static struct nouveau_omthds
677nv50_disp_base_omthds[] = { 706nv50_disp_base_omthds[] = {
707 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
678 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 708 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
679 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 709 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
680 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 710 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 1ae6ceb56704..d31d426ea1f6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -43,6 +43,10 @@ struct nv50_disp_priv {
43 } pior; 43 } pior;
44}; 44};
45 45
46#define HEAD_MTHD(n) (n), (n) + 0x03
47
48int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
49
46#define DAC_MTHD(n) (n), (n) + 0x03 50#define DAC_MTHD(n) (n), (n) + 0x03
47 51
48int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); 52int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
@@ -132,13 +136,12 @@ void nv50_disp_intr(struct nouveau_subdev *);
132 136
133extern struct nouveau_omthds nv84_disp_base_omthds[]; 137extern struct nouveau_omthds nv84_disp_base_omthds[];
134 138
135extern struct nouveau_omthds nva3_disp_base_omthds[];
136
137extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs; 139extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
138extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs; 140extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
139extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs; 141extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
140extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs; 142extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
141extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; 143extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
144extern struct nouveau_omthds nvd0_disp_base_omthds[];
142extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; 145extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
143extern struct nouveau_oclass nvd0_disp_cclass; 146extern struct nouveau_oclass nvd0_disp_cclass;
144void nvd0_disp_intr_supervisor(struct work_struct *); 147void 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 d8c74c0883a1..ef9ce300a496 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -41,6 +41,7 @@ nv84_disp_sclass[] = {
41 41
42struct nouveau_omthds 42struct nouveau_omthds
43nv84_disp_base_omthds[] = { 43nv84_disp_base_omthds[] = {
44 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
44 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 45 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
45 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 46 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 47 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index a66f949c1f84..a518543c00ab 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -41,6 +41,7 @@ nv94_disp_sclass[] = {
41 41
42static struct nouveau_omthds 42static struct nouveau_omthds
43nv94_disp_base_omthds[] = { 43nv94_disp_base_omthds[] = {
44 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
44 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 45 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
45 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 46 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 47 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index b75413169eae..6ad6dcece43b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -39,8 +39,9 @@ nva3_disp_sclass[] = {
39 {} 39 {}
40}; 40};
41 41
42struct nouveau_omthds 42static struct nouveau_omthds
43nva3_disp_base_omthds[] = { 43nva3_disp_base_omthds[] = {
44 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
44 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 45 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
45 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, 46 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
46 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 47 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index d52c0f50a1a9..1c5e4e8b2c82 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -440,6 +440,36 @@ nvd0_disp_curs_ofuncs = {
440 * Base display object 440 * Base display object
441 ******************************************************************************/ 441 ******************************************************************************/
442 442
443static int
444nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
445 void *data, u32 size)
446{
447 struct nv50_disp_priv *priv = (void *)object->engine;
448 struct nv04_display_scanoutpos *args = data;
449 const int head = (mthd & NV50_DISP_MTHD_HEAD);
450 u32 blanke, blanks, total;
451
452 if (size < sizeof(*args) || head >= priv->head.nr)
453 return -EINVAL;
454
455 total = nv_rd32(priv, 0x640414 + (head * 0x300));
456 blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
457 blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
458
459 args->vblanke = (blanke & 0xffff0000) >> 16;
460 args->hblanke = (blanke & 0x0000ffff);
461 args->vblanks = (blanks & 0xffff0000) >> 16;
462 args->hblanks = (blanks & 0x0000ffff);
463 args->vtotal = ( total & 0xffff0000) >> 16;
464 args->htotal = ( total & 0x0000ffff);
465
466 args->time[0] = ktime_to_ns(ktime_get());
467 args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
468 args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
469 args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
470 return 0;
471}
472
443static void 473static void
444nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head) 474nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
445{ 475{
@@ -573,9 +603,24 @@ nvd0_disp_base_ofuncs = {
573 .fini = nvd0_disp_base_fini, 603 .fini = nvd0_disp_base_fini,
574}; 604};
575 605
606struct nouveau_omthds
607nvd0_disp_base_omthds[] = {
608 { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
609 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
610 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
611 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
612 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
613 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
614 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
615 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
616 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
617 { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
618 {},
619};
620
576static struct nouveau_oclass 621static struct nouveau_oclass
577nvd0_disp_base_oclass[] = { 622nvd0_disp_base_oclass[] = {
578 { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, 623 { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
579 {} 624 {}
580}; 625};
581 626
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 20725b363d58..ab63f32c00b2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -41,7 +41,7 @@ nve0_disp_sclass[] = {
41 41
42static struct nouveau_oclass 42static struct nouveau_oclass
43nve0_disp_base_oclass[] = { 43nve0_disp_base_oclass[] = {
44 { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, 44 { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
45 {} 45 {}
46}; 46};
47 47
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
index a488c36e40f9..05fee10e0c97 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -41,7 +41,7 @@ nvf0_disp_sclass[] = {
41 41
42static struct nouveau_oclass 42static struct nouveau_oclass
43nvf0_disp_base_oclass[] = { 43nvf0_disp_base_oclass[] = {
44 { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, 44 { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
45 {} 45 {}
46}; 46};
47 47
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index 560c3593dae7..e71a4325e670 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -230,9 +230,26 @@ struct nve0_channel_ind_class {
230 230
231#define NV04_DISP_CLASS 0x00000046 231#define NV04_DISP_CLASS 0x00000046
232 232
233#define NV04_DISP_MTHD 0x00000000
234#define NV04_DISP_MTHD_HEAD 0x00000001
235
236#define NV04_DISP_SCANOUTPOS 0x00000000
237
233struct nv04_display_class { 238struct nv04_display_class {
234}; 239};
235 240
241struct nv04_display_scanoutpos {
242 s64 time[2];
243 u32 vblanks;
244 u32 vblanke;
245 u32 vtotal;
246 u32 vline;
247 u32 hblanks;
248 u32 hblanke;
249 u32 htotal;
250 u32 hline;
251};
252
236/* 5070: NV50_DISP 253/* 5070: NV50_DISP
237 * 8270: NV84_DISP 254 * 8270: NV84_DISP
238 * 8370: NVA0_DISP 255 * 8370: NVA0_DISP
@@ -252,6 +269,11 @@ struct nv04_display_class {
252#define NVE0_DISP_CLASS 0x00009170 269#define NVE0_DISP_CLASS 0x00009170
253#define NVF0_DISP_CLASS 0x00009270 270#define NVF0_DISP_CLASS 0x00009270
254 271
272#define NV50_DISP_MTHD 0x00000000
273#define NV50_DISP_MTHD_HEAD 0x00000003
274
275#define NV50_DISP_SCANOUTPOS 0x00000000
276
255#define NV50_DISP_SOR_MTHD 0x00010000 277#define NV50_DISP_SOR_MTHD 0x00010000
256#define NV50_DISP_SOR_MTHD_TYPE 0x0000f000 278#define NV50_DISP_SOR_MTHD_TYPE 0x0000f000
257#define NV50_DISP_SOR_MTHD_HEAD 0x00000018 279#define NV50_DISP_SOR_MTHD_HEAD 0x00000018