mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
drm/nouveau: implement hooks for needed for drm vblank timestamping support
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
d2fa7d32ea
commit
d83ef85395
@ -68,6 +68,86 @@ nouveau_display_vblank_disable(struct drm_device *dev, int head)
|
||||
nouveau_event_put(disp->vblank[head]);
|
||||
}
|
||||
|
||||
static inline int
|
||||
calc(int blanks, int blanke, int total, int line)
|
||||
{
|
||||
if (blanke >= blanks) {
|
||||
if (line >= blanks)
|
||||
line -= total;
|
||||
} else {
|
||||
if (line >= blanks)
|
||||
line -= total;
|
||||
line -= blanke + 1;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
|
||||
ktime_t *stime, ktime_t *etime)
|
||||
{
|
||||
const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
|
||||
struct nouveau_display *disp = nouveau_display(crtc->dev);
|
||||
struct nv04_display_scanoutpos args;
|
||||
int ret, retry = 1;
|
||||
|
||||
do {
|
||||
ret = nv_exec(disp->core, mthd, &args, sizeof(args));
|
||||
if (ret != 0)
|
||||
return 0;
|
||||
|
||||
if (args.vline) {
|
||||
ret |= DRM_SCANOUTPOS_ACCURATE;
|
||||
ret |= DRM_SCANOUTPOS_VALID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (retry) ndelay(crtc->linedur_ns);
|
||||
} while (retry--);
|
||||
|
||||
*hpos = calc(args.hblanks, args.hblanke, args.htotal, args.hline);
|
||||
*vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
|
||||
if (stime) *stime = ns_to_ktime(args.time[0]);
|
||||
if (etime) *etime = ns_to_ktime(args.time[1]);
|
||||
|
||||
if (*vpos < 0)
|
||||
ret |= DRM_SCANOUTPOS_INVBL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
|
||||
int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (nouveau_crtc(crtc)->index == head) {
|
||||
return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
|
||||
stime, etime);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
|
||||
struct timeval *time, unsigned flags)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (nouveau_crtc(crtc)->index == head) {
|
||||
return drm_calc_vbltimestamp_from_scanoutpos(dev,
|
||||
head, max_error, time, flags, crtc,
|
||||
&crtc->hwmode);
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_display_vblank_fini(struct drm_device *dev)
|
||||
{
|
||||
|
@ -64,6 +64,10 @@ void nouveau_display_repin(struct drm_device *dev);
|
||||
void nouveau_display_resume(struct drm_device *dev);
|
||||
int nouveau_display_vblank_enable(struct drm_device *, int);
|
||||
void nouveau_display_vblank_disable(struct drm_device *, int);
|
||||
int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int,
|
||||
int *, int *, ktime_t *, ktime_t *);
|
||||
int nouveau_display_vblstamp(struct drm_device *, int, int *,
|
||||
struct timeval *, unsigned);
|
||||
|
||||
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
|
@ -798,6 +798,8 @@ driver = {
|
||||
.get_vblank_counter = drm_vblank_count,
|
||||
.enable_vblank = nouveau_display_vblank_enable,
|
||||
.disable_vblank = nouveau_display_vblank_disable,
|
||||
.get_scanout_position = nouveau_display_scanoutpos,
|
||||
.get_vblank_timestamp = nouveau_display_vblstamp,
|
||||
|
||||
.ioctls = nouveau_ioctls,
|
||||
.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
|
||||
|
Loading…
Reference in New Issue
Block a user