forked from Minki/linux
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]);
|
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
|
static void
|
||||||
nouveau_display_vblank_fini(struct drm_device *dev)
|
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);
|
void nouveau_display_resume(struct drm_device *dev);
|
||||||
int nouveau_display_vblank_enable(struct drm_device *, int);
|
int nouveau_display_vblank_enable(struct drm_device *, int);
|
||||||
void nouveau_display_vblank_disable(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,
|
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||||
struct drm_pending_vblank_event *event,
|
struct drm_pending_vblank_event *event,
|
||||||
|
@ -798,6 +798,8 @@ driver = {
|
|||||||
.get_vblank_counter = drm_vblank_count,
|
.get_vblank_counter = drm_vblank_count,
|
||||||
.enable_vblank = nouveau_display_vblank_enable,
|
.enable_vblank = nouveau_display_vblank_enable,
|
||||||
.disable_vblank = nouveau_display_vblank_disable,
|
.disable_vblank = nouveau_display_vblank_disable,
|
||||||
|
.get_scanout_position = nouveau_display_scanoutpos,
|
||||||
|
.get_vblank_timestamp = nouveau_display_vblstamp,
|
||||||
|
|
||||||
.ioctls = nouveau_ioctls,
|
.ioctls = nouveau_ioctls,
|
||||||
.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
|
.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
|
||||||
|
Loading…
Reference in New Issue
Block a user