Skip to content

Commit d83ef85

Browse files
author
Ben Skeggs
committed
drm/nouveau: implement hooks for needed for drm vblank timestamping support
Signed-off-by: Ben Skeggs <[email protected]>
1 parent d2fa7d3 commit d83ef85

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

drivers/gpu/drm/nouveau/nouveau_display.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,86 @@ nouveau_display_vblank_disable(struct drm_device *dev, int head)
6868
nouveau_event_put(disp->vblank[head]);
6969
}
7070

71+
static inline int
72+
calc(int blanks, int blanke, int total, int line)
73+
{
74+
if (blanke >= blanks) {
75+
if (line >= blanks)
76+
line -= total;
77+
} else {
78+
if (line >= blanks)
79+
line -= total;
80+
line -= blanke + 1;
81+
}
82+
return line;
83+
}
84+
85+
int
86+
nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
87+
ktime_t *stime, ktime_t *etime)
88+
{
89+
const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
90+
struct nouveau_display *disp = nouveau_display(crtc->dev);
91+
struct nv04_display_scanoutpos args;
92+
int ret, retry = 1;
93+
94+
do {
95+
ret = nv_exec(disp->core, mthd, &args, sizeof(args));
96+
if (ret != 0)
97+
return 0;
98+
99+
if (args.vline) {
100+
ret |= DRM_SCANOUTPOS_ACCURATE;
101+
ret |= DRM_SCANOUTPOS_VALID;
102+
break;
103+
}
104+
105+
if (retry) ndelay(crtc->linedur_ns);
106+
} while (retry--);
107+
108+
*hpos = calc(args.hblanks, args.hblanke, args.htotal, args.hline);
109+
*vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
110+
if (stime) *stime = ns_to_ktime(args.time[0]);
111+
if (etime) *etime = ns_to_ktime(args.time[1]);
112+
113+
if (*vpos < 0)
114+
ret |= DRM_SCANOUTPOS_INVBL;
115+
return ret;
116+
}
117+
118+
int
119+
nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
120+
int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
121+
{
122+
struct drm_crtc *crtc;
123+
124+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
125+
if (nouveau_crtc(crtc)->index == head) {
126+
return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
127+
stime, etime);
128+
}
129+
}
130+
131+
return 0;
132+
}
133+
134+
int
135+
nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
136+
struct timeval *time, unsigned flags)
137+
{
138+
struct drm_crtc *crtc;
139+
140+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
141+
if (nouveau_crtc(crtc)->index == head) {
142+
return drm_calc_vbltimestamp_from_scanoutpos(dev,
143+
head, max_error, time, flags, crtc,
144+
&crtc->hwmode);
145+
}
146+
}
147+
148+
return -EINVAL;
149+
}
150+
71151
static void
72152
nouveau_display_vblank_fini(struct drm_device *dev)
73153
{

drivers/gpu/drm/nouveau/nouveau_display.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ void nouveau_display_repin(struct drm_device *dev);
6464
void nouveau_display_resume(struct drm_device *dev);
6565
int nouveau_display_vblank_enable(struct drm_device *, int);
6666
void nouveau_display_vblank_disable(struct drm_device *, int);
67+
int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int,
68+
int *, int *, ktime_t *, ktime_t *);
69+
int nouveau_display_vblstamp(struct drm_device *, int, int *,
70+
struct timeval *, unsigned);
6771

6872
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
6973
struct drm_pending_vblank_event *event,

drivers/gpu/drm/nouveau/nouveau_drm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,8 @@ driver = {
798798
.get_vblank_counter = drm_vblank_count,
799799
.enable_vblank = nouveau_display_vblank_enable,
800800
.disable_vblank = nouveau_display_vblank_disable,
801+
.get_scanout_position = nouveau_display_scanoutpos,
802+
.get_vblank_timestamp = nouveau_display_vblstamp,
801803

802804
.ioctls = nouveau_ioctls,
803805
.num_ioctls = ARRAY_SIZE(nouveau_ioctls),

0 commit comments

Comments
 (0)