@@ -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+
71151static void
72152nouveau_display_vblank_fini (struct drm_device * dev )
73153{
0 commit comments