diff options
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 435 |
1 files changed, 425 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 7914097b09c6..49404ce1666e 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * Copyright © 2007 Dave Airlie | 8 | * Copyright © 2007 Dave Airlie |
9 | * Copyright © 2007-2008 Intel Corporation | 9 | * Copyright © 2007-2008 Intel Corporation |
10 | * Jesse Barnes <jesse.barnes@intel.com> | 10 | * Jesse Barnes <jesse.barnes@intel.com> |
11 | * Copyright 2005-2006 Luc Verhaegen | ||
12 | * Copyright (c) 2001, Andy Ritger aritger@nvidia.com | ||
11 | * | 13 | * |
12 | * Permission is hereby granted, free of charge, to any person obtaining a | 14 | * Permission is hereby granted, free of charge, to any person obtaining a |
13 | * copy of this software and associated documentation files (the "Software"), | 15 | * copy of this software and associated documentation files (the "Software"), |
@@ -38,7 +40,6 @@ | |||
38 | #include "drm.h" | 40 | #include "drm.h" |
39 | #include "drm_crtc.h" | 41 | #include "drm_crtc.h" |
40 | 42 | ||
41 | #define DRM_MODESET_DEBUG "drm_mode" | ||
42 | /** | 43 | /** |
43 | * drm_mode_debug_printmodeline - debug print a mode | 44 | * drm_mode_debug_printmodeline - debug print a mode |
44 | * @dev: DRM device | 45 | * @dev: DRM device |
@@ -51,8 +52,8 @@ | |||
51 | */ | 52 | */ |
52 | void drm_mode_debug_printmodeline(struct drm_display_mode *mode) | 53 | void drm_mode_debug_printmodeline(struct drm_display_mode *mode) |
53 | { | 54 | { |
54 | DRM_DEBUG_MODE(DRM_MODESET_DEBUG, | 55 | DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d " |
55 | "Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", | 56 | "0x%x 0x%x\n", |
56 | mode->base.id, mode->name, mode->vrefresh, mode->clock, | 57 | mode->base.id, mode->name, mode->vrefresh, mode->clock, |
57 | mode->hdisplay, mode->hsync_start, | 58 | mode->hdisplay, mode->hsync_start, |
58 | mode->hsync_end, mode->htotal, | 59 | mode->hsync_end, mode->htotal, |
@@ -62,6 +63,420 @@ void drm_mode_debug_printmodeline(struct drm_display_mode *mode) | |||
62 | EXPORT_SYMBOL(drm_mode_debug_printmodeline); | 63 | EXPORT_SYMBOL(drm_mode_debug_printmodeline); |
63 | 64 | ||
64 | /** | 65 | /** |
66 | * drm_cvt_mode -create a modeline based on CVT algorithm | ||
67 | * @dev: DRM device | ||
68 | * @hdisplay: hdisplay size | ||
69 | * @vdisplay: vdisplay size | ||
70 | * @vrefresh : vrefresh rate | ||
71 | * @reduced : Whether the GTF calculation is simplified | ||
72 | * @interlaced:Whether the interlace is supported | ||
73 | * | ||
74 | * LOCKING: | ||
75 | * none. | ||
76 | * | ||
77 | * return the modeline based on CVT algorithm | ||
78 | * | ||
79 | * This function is called to generate the modeline based on CVT algorithm | ||
80 | * according to the hdisplay, vdisplay, vrefresh. | ||
81 | * It is based from the VESA(TM) Coordinated Video Timing Generator by | ||
82 | * Graham Loveridge April 9, 2003 available at | ||
83 | * http://www.vesa.org/public/CVT/CVTd6r1.xls | ||
84 | * | ||
85 | * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. | ||
86 | * What I have done is to translate it by using integer calculation. | ||
87 | */ | ||
88 | #define HV_FACTOR 1000 | ||
89 | struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, | ||
90 | int vdisplay, int vrefresh, | ||
91 | bool reduced, bool interlaced) | ||
92 | { | ||
93 | /* 1) top/bottom margin size (% of height) - default: 1.8, */ | ||
94 | #define CVT_MARGIN_PERCENTAGE 18 | ||
95 | /* 2) character cell horizontal granularity (pixels) - default 8 */ | ||
96 | #define CVT_H_GRANULARITY 8 | ||
97 | /* 3) Minimum vertical porch (lines) - default 3 */ | ||
98 | #define CVT_MIN_V_PORCH 3 | ||
99 | /* 4) Minimum number of vertical back porch lines - default 6 */ | ||
100 | #define CVT_MIN_V_BPORCH 6 | ||
101 | /* Pixel Clock step (kHz) */ | ||
102 | #define CVT_CLOCK_STEP 250 | ||
103 | struct drm_display_mode *drm_mode; | ||
104 | bool margins = false; | ||
105 | unsigned int vfieldrate, hperiod; | ||
106 | int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; | ||
107 | int interlace; | ||
108 | |||
109 | /* allocate the drm_display_mode structure. If failure, we will | ||
110 | * return directly | ||
111 | */ | ||
112 | drm_mode = drm_mode_create(dev); | ||
113 | if (!drm_mode) | ||
114 | return NULL; | ||
115 | |||
116 | /* the CVT default refresh rate is 60Hz */ | ||
117 | if (!vrefresh) | ||
118 | vrefresh = 60; | ||
119 | |||
120 | /* the required field fresh rate */ | ||
121 | if (interlaced) | ||
122 | vfieldrate = vrefresh * 2; | ||
123 | else | ||
124 | vfieldrate = vrefresh; | ||
125 | |||
126 | /* horizontal pixels */ | ||
127 | hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY); | ||
128 | |||
129 | /* determine the left&right borders */ | ||
130 | hmargin = 0; | ||
131 | if (margins) { | ||
132 | hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; | ||
133 | hmargin -= hmargin % CVT_H_GRANULARITY; | ||
134 | } | ||
135 | /* find the total active pixels */ | ||
136 | drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin; | ||
137 | |||
138 | /* find the number of lines per field */ | ||
139 | if (interlaced) | ||
140 | vdisplay_rnd = vdisplay / 2; | ||
141 | else | ||
142 | vdisplay_rnd = vdisplay; | ||
143 | |||
144 | /* find the top & bottom borders */ | ||
145 | vmargin = 0; | ||
146 | if (margins) | ||
147 | vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; | ||
148 | |||
149 | drm_mode->vdisplay = vdisplay + 2 * vmargin; | ||
150 | |||
151 | /* Interlaced */ | ||
152 | if (interlaced) | ||
153 | interlace = 1; | ||
154 | else | ||
155 | interlace = 0; | ||
156 | |||
157 | /* Determine VSync Width from aspect ratio */ | ||
158 | if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay)) | ||
159 | vsync = 4; | ||
160 | else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay)) | ||
161 | vsync = 5; | ||
162 | else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay)) | ||
163 | vsync = 6; | ||
164 | else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay)) | ||
165 | vsync = 7; | ||
166 | else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay)) | ||
167 | vsync = 7; | ||
168 | else /* custom */ | ||
169 | vsync = 10; | ||
170 | |||
171 | if (!reduced) { | ||
172 | /* simplify the GTF calculation */ | ||
173 | /* 4) Minimum time of vertical sync + back porch interval (µs) | ||
174 | * default 550.0 | ||
175 | */ | ||
176 | int tmp1, tmp2; | ||
177 | #define CVT_MIN_VSYNC_BP 550 | ||
178 | /* 3) Nominal HSync width (% of line period) - default 8 */ | ||
179 | #define CVT_HSYNC_PERCENTAGE 8 | ||
180 | unsigned int hblank_percentage; | ||
181 | int vsyncandback_porch, vback_porch, hblank; | ||
182 | |||
183 | /* estimated the horizontal period */ | ||
184 | tmp1 = HV_FACTOR * 1000000 - | ||
185 | CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate; | ||
186 | tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 + | ||
187 | interlace; | ||
188 | hperiod = tmp1 * 2 / (tmp2 * vfieldrate); | ||
189 | |||
190 | tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1; | ||
191 | /* 9. Find number of lines in sync + backporch */ | ||
192 | if (tmp1 < (vsync + CVT_MIN_V_PORCH)) | ||
193 | vsyncandback_porch = vsync + CVT_MIN_V_PORCH; | ||
194 | else | ||
195 | vsyncandback_porch = tmp1; | ||
196 | /* 10. Find number of lines in back porch */ | ||
197 | vback_porch = vsyncandback_porch - vsync; | ||
198 | drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + | ||
199 | vsyncandback_porch + CVT_MIN_V_PORCH; | ||
200 | /* 5) Definition of Horizontal blanking time limitation */ | ||
201 | /* Gradient (%/kHz) - default 600 */ | ||
202 | #define CVT_M_FACTOR 600 | ||
203 | /* Offset (%) - default 40 */ | ||
204 | #define CVT_C_FACTOR 40 | ||
205 | /* Blanking time scaling factor - default 128 */ | ||
206 | #define CVT_K_FACTOR 128 | ||
207 | /* Scaling factor weighting - default 20 */ | ||
208 | #define CVT_J_FACTOR 20 | ||
209 | #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256) | ||
210 | #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ | ||
211 | CVT_J_FACTOR) | ||
212 | /* 12. Find ideal blanking duty cycle from formula */ | ||
213 | hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME * | ||
214 | hperiod / 1000; | ||
215 | /* 13. Blanking time */ | ||
216 | if (hblank_percentage < 20 * HV_FACTOR) | ||
217 | hblank_percentage = 20 * HV_FACTOR; | ||
218 | hblank = drm_mode->hdisplay * hblank_percentage / | ||
219 | (100 * HV_FACTOR - hblank_percentage); | ||
220 | hblank -= hblank % (2 * CVT_H_GRANULARITY); | ||
221 | /* 14. find the total pixes per line */ | ||
222 | drm_mode->htotal = drm_mode->hdisplay + hblank; | ||
223 | drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2; | ||
224 | drm_mode->hsync_start = drm_mode->hsync_end - | ||
225 | (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100; | ||
226 | drm_mode->hsync_start += CVT_H_GRANULARITY - | ||
227 | drm_mode->hsync_start % CVT_H_GRANULARITY; | ||
228 | /* fill the Vsync values */ | ||
229 | drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH; | ||
230 | drm_mode->vsync_end = drm_mode->vsync_start + vsync; | ||
231 | } else { | ||
232 | /* Reduced blanking */ | ||
233 | /* Minimum vertical blanking interval time (µs)- default 460 */ | ||
234 | #define CVT_RB_MIN_VBLANK 460 | ||
235 | /* Fixed number of clocks for horizontal sync */ | ||
236 | #define CVT_RB_H_SYNC 32 | ||
237 | /* Fixed number of clocks for horizontal blanking */ | ||
238 | #define CVT_RB_H_BLANK 160 | ||
239 | /* Fixed number of lines for vertical front porch - default 3*/ | ||
240 | #define CVT_RB_VFPORCH 3 | ||
241 | int vbilines; | ||
242 | int tmp1, tmp2; | ||
243 | /* 8. Estimate Horizontal period. */ | ||
244 | tmp1 = HV_FACTOR * 1000000 - | ||
245 | CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate; | ||
246 | tmp2 = vdisplay_rnd + 2 * vmargin; | ||
247 | hperiod = tmp1 / (tmp2 * vfieldrate); | ||
248 | /* 9. Find number of lines in vertical blanking */ | ||
249 | vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1; | ||
250 | /* 10. Check if vertical blanking is sufficient */ | ||
251 | if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH)) | ||
252 | vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH; | ||
253 | /* 11. Find total number of lines in vertical field */ | ||
254 | drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines; | ||
255 | /* 12. Find total number of pixels in a line */ | ||
256 | drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK; | ||
257 | /* Fill in HSync values */ | ||
258 | drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2; | ||
259 | drm_mode->hsync_start = drm_mode->hsync_end = CVT_RB_H_SYNC; | ||
260 | } | ||
261 | /* 15/13. Find pixel clock frequency (kHz for xf86) */ | ||
262 | drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; | ||
263 | drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; | ||
264 | /* 18/16. Find actual vertical frame frequency */ | ||
265 | /* ignore - just set the mode flag for interlaced */ | ||
266 | if (interlaced) | ||
267 | drm_mode->vtotal *= 2; | ||
268 | /* Fill the mode line name */ | ||
269 | drm_mode_set_name(drm_mode); | ||
270 | if (reduced) | ||
271 | drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC | | ||
272 | DRM_MODE_FLAG_NVSYNC); | ||
273 | else | ||
274 | drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC | | ||
275 | DRM_MODE_FLAG_NHSYNC); | ||
276 | if (interlaced) | ||
277 | drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; | ||
278 | |||
279 | return drm_mode; | ||
280 | } | ||
281 | EXPORT_SYMBOL(drm_cvt_mode); | ||
282 | |||
283 | /** | ||
284 | * drm_gtf_mode - create the modeline based on GTF algorithm | ||
285 | * | ||
286 | * @dev :drm device | ||
287 | * @hdisplay :hdisplay size | ||
288 | * @vdisplay :vdisplay size | ||
289 | * @vrefresh :vrefresh rate. | ||
290 | * @interlaced :whether the interlace is supported | ||
291 | * @margins :whether the margin is supported | ||
292 | * | ||
293 | * LOCKING. | ||
294 | * none. | ||
295 | * | ||
296 | * return the modeline based on GTF algorithm | ||
297 | * | ||
298 | * This function is to create the modeline based on the GTF algorithm. | ||
299 | * Generalized Timing Formula is derived from: | ||
300 | * GTF Spreadsheet by Andy Morrish (1/5/97) | ||
301 | * available at http://www.vesa.org | ||
302 | * | ||
303 | * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c. | ||
304 | * What I have done is to translate it by using integer calculation. | ||
305 | * I also refer to the function of fb_get_mode in the file of | ||
306 | * drivers/video/fbmon.c | ||
307 | */ | ||
308 | struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, | ||
309 | int vdisplay, int vrefresh, | ||
310 | bool interlaced, int margins) | ||
311 | { | ||
312 | /* 1) top/bottom margin size (% of height) - default: 1.8, */ | ||
313 | #define GTF_MARGIN_PERCENTAGE 18 | ||
314 | /* 2) character cell horizontal granularity (pixels) - default 8 */ | ||
315 | #define GTF_CELL_GRAN 8 | ||
316 | /* 3) Minimum vertical porch (lines) - default 3 */ | ||
317 | #define GTF_MIN_V_PORCH 1 | ||
318 | /* width of vsync in lines */ | ||
319 | #define V_SYNC_RQD 3 | ||
320 | /* width of hsync as % of total line */ | ||
321 | #define H_SYNC_PERCENT 8 | ||
322 | /* min time of vsync + back porch (microsec) */ | ||
323 | #define MIN_VSYNC_PLUS_BP 550 | ||
324 | /* blanking formula gradient */ | ||
325 | #define GTF_M 600 | ||
326 | /* blanking formula offset */ | ||
327 | #define GTF_C 40 | ||
328 | /* blanking formula scaling factor */ | ||
329 | #define GTF_K 128 | ||
330 | /* blanking formula scaling factor */ | ||
331 | #define GTF_J 20 | ||
332 | /* C' and M' are part of the Blanking Duty Cycle computation */ | ||
333 | #define GTF_C_PRIME (((GTF_C - GTF_J) * GTF_K / 256) + GTF_J) | ||
334 | #define GTF_M_PRIME (GTF_K * GTF_M / 256) | ||
335 | struct drm_display_mode *drm_mode; | ||
336 | unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd; | ||
337 | int top_margin, bottom_margin; | ||
338 | int interlace; | ||
339 | unsigned int hfreq_est; | ||
340 | int vsync_plus_bp, vback_porch; | ||
341 | unsigned int vtotal_lines, vfieldrate_est, hperiod; | ||
342 | unsigned int vfield_rate, vframe_rate; | ||
343 | int left_margin, right_margin; | ||
344 | unsigned int total_active_pixels, ideal_duty_cycle; | ||
345 | unsigned int hblank, total_pixels, pixel_freq; | ||
346 | int hsync, hfront_porch, vodd_front_porch_lines; | ||
347 | unsigned int tmp1, tmp2; | ||
348 | |||
349 | drm_mode = drm_mode_create(dev); | ||
350 | if (!drm_mode) | ||
351 | return NULL; | ||
352 | |||
353 | /* 1. In order to give correct results, the number of horizontal | ||
354 | * pixels requested is first processed to ensure that it is divisible | ||
355 | * by the character size, by rounding it to the nearest character | ||
356 | * cell boundary: | ||
357 | */ | ||
358 | hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; | ||
359 | hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN; | ||
360 | |||
361 | /* 2. If interlace is requested, the number of vertical lines assumed | ||
362 | * by the calculation must be halved, as the computation calculates | ||
363 | * the number of vertical lines per field. | ||
364 | */ | ||
365 | if (interlaced) | ||
366 | vdisplay_rnd = vdisplay / 2; | ||
367 | else | ||
368 | vdisplay_rnd = vdisplay; | ||
369 | |||
370 | /* 3. Find the frame rate required: */ | ||
371 | if (interlaced) | ||
372 | vfieldrate_rqd = vrefresh * 2; | ||
373 | else | ||
374 | vfieldrate_rqd = vrefresh; | ||
375 | |||
376 | /* 4. Find number of lines in Top margin: */ | ||
377 | top_margin = 0; | ||
378 | if (margins) | ||
379 | top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / | ||
380 | 1000; | ||
381 | /* 5. Find number of lines in bottom margin: */ | ||
382 | bottom_margin = top_margin; | ||
383 | |||
384 | /* 6. If interlace is required, then set variable interlace: */ | ||
385 | if (interlaced) | ||
386 | interlace = 1; | ||
387 | else | ||
388 | interlace = 0; | ||
389 | |||
390 | /* 7. Estimate the Horizontal frequency */ | ||
391 | { | ||
392 | tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500; | ||
393 | tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) * | ||
394 | 2 + interlace; | ||
395 | hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1; | ||
396 | } | ||
397 | |||
398 | /* 8. Find the number of lines in V sync + back porch */ | ||
399 | /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */ | ||
400 | vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000; | ||
401 | vsync_plus_bp = (vsync_plus_bp + 500) / 1000; | ||
402 | /* 9. Find the number of lines in V back porch alone: */ | ||
403 | vback_porch = vsync_plus_bp - V_SYNC_RQD; | ||
404 | /* 10. Find the total number of lines in Vertical field period: */ | ||
405 | vtotal_lines = vdisplay_rnd + top_margin + bottom_margin + | ||
406 | vsync_plus_bp + GTF_MIN_V_PORCH; | ||
407 | /* 11. Estimate the Vertical field frequency: */ | ||
408 | vfieldrate_est = hfreq_est / vtotal_lines; | ||
409 | /* 12. Find the actual horizontal period: */ | ||
410 | hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines); | ||
411 | |||
412 | /* 13. Find the actual Vertical field frequency: */ | ||
413 | vfield_rate = hfreq_est / vtotal_lines; | ||
414 | /* 14. Find the Vertical frame frequency: */ | ||
415 | if (interlaced) | ||
416 | vframe_rate = vfield_rate / 2; | ||
417 | else | ||
418 | vframe_rate = vfield_rate; | ||
419 | /* 15. Find number of pixels in left margin: */ | ||
420 | if (margins) | ||
421 | left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / | ||
422 | 1000; | ||
423 | else | ||
424 | left_margin = 0; | ||
425 | |||
426 | /* 16.Find number of pixels in right margin: */ | ||
427 | right_margin = left_margin; | ||
428 | /* 17.Find total number of active pixels in image and left and right */ | ||
429 | total_active_pixels = hdisplay_rnd + left_margin + right_margin; | ||
430 | /* 18.Find the ideal blanking duty cycle from blanking duty cycle */ | ||
431 | ideal_duty_cycle = GTF_C_PRIME * 1000 - | ||
432 | (GTF_M_PRIME * 1000000 / hfreq_est); | ||
433 | /* 19.Find the number of pixels in the blanking time to the nearest | ||
434 | * double character cell: */ | ||
435 | hblank = total_active_pixels * ideal_duty_cycle / | ||
436 | (100000 - ideal_duty_cycle); | ||
437 | hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN); | ||
438 | hblank = hblank * 2 * GTF_CELL_GRAN; | ||
439 | /* 20.Find total number of pixels: */ | ||
440 | total_pixels = total_active_pixels + hblank; | ||
441 | /* 21.Find pixel clock frequency: */ | ||
442 | pixel_freq = total_pixels * hfreq_est / 1000; | ||
443 | /* Stage 1 computations are now complete; I should really pass | ||
444 | * the results to another function and do the Stage 2 computations, | ||
445 | * but I only need a few more values so I'll just append the | ||
446 | * computations here for now */ | ||
447 | /* 17. Find the number of pixels in the horizontal sync period: */ | ||
448 | hsync = H_SYNC_PERCENT * total_pixels / 100; | ||
449 | hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; | ||
450 | hsync = hsync * GTF_CELL_GRAN; | ||
451 | /* 18. Find the number of pixels in horizontal front porch period */ | ||
452 | hfront_porch = hblank / 2 - hsync; | ||
453 | /* 36. Find the number of lines in the odd front porch period: */ | ||
454 | vodd_front_porch_lines = GTF_MIN_V_PORCH ; | ||
455 | |||
456 | /* finally, pack the results in the mode struct */ | ||
457 | drm_mode->hdisplay = hdisplay_rnd; | ||
458 | drm_mode->hsync_start = hdisplay_rnd + hfront_porch; | ||
459 | drm_mode->hsync_end = drm_mode->hsync_start + hsync; | ||
460 | drm_mode->htotal = total_pixels; | ||
461 | drm_mode->vdisplay = vdisplay_rnd; | ||
462 | drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines; | ||
463 | drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD; | ||
464 | drm_mode->vtotal = vtotal_lines; | ||
465 | |||
466 | drm_mode->clock = pixel_freq; | ||
467 | |||
468 | drm_mode_set_name(drm_mode); | ||
469 | drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC; | ||
470 | |||
471 | if (interlaced) { | ||
472 | drm_mode->vtotal *= 2; | ||
473 | drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; | ||
474 | } | ||
475 | |||
476 | return drm_mode; | ||
477 | } | ||
478 | EXPORT_SYMBOL(drm_gtf_mode); | ||
479 | /** | ||
65 | * drm_mode_set_name - set the name on a mode | 480 | * drm_mode_set_name - set the name on a mode |
66 | * @mode: name will be set in this mode | 481 | * @mode: name will be set in this mode |
67 | * | 482 | * |
@@ -151,7 +566,9 @@ EXPORT_SYMBOL(drm_mode_height); | |||
151 | * FIXME: why is this needed? shouldn't vrefresh be set already? | 566 | * FIXME: why is this needed? shouldn't vrefresh be set already? |
152 | * | 567 | * |
153 | * RETURNS: | 568 | * RETURNS: |
154 | * Vertical refresh rate of @mode x 1000. For precision reasons. | 569 | * Vertical refresh rate. It will be the result of actual value plus 0.5. |
570 | * If it is 70.288, it will return 70Hz. | ||
571 | * If it is 59.6, it will return 60Hz. | ||
155 | */ | 572 | */ |
156 | int drm_mode_vrefresh(struct drm_display_mode *mode) | 573 | int drm_mode_vrefresh(struct drm_display_mode *mode) |
157 | { | 574 | { |
@@ -161,14 +578,13 @@ int drm_mode_vrefresh(struct drm_display_mode *mode) | |||
161 | if (mode->vrefresh > 0) | 578 | if (mode->vrefresh > 0) |
162 | refresh = mode->vrefresh; | 579 | refresh = mode->vrefresh; |
163 | else if (mode->htotal > 0 && mode->vtotal > 0) { | 580 | else if (mode->htotal > 0 && mode->vtotal > 0) { |
581 | int vtotal; | ||
582 | vtotal = mode->vtotal; | ||
164 | /* work out vrefresh the value will be x1000 */ | 583 | /* work out vrefresh the value will be x1000 */ |
165 | calc_val = (mode->clock * 1000); | 584 | calc_val = (mode->clock * 1000); |
166 | |||
167 | calc_val /= mode->htotal; | 585 | calc_val /= mode->htotal; |
168 | calc_val *= 1000; | 586 | refresh = (calc_val + vtotal / 2) / vtotal; |
169 | calc_val /= mode->vtotal; | ||
170 | 587 | ||
171 | refresh = calc_val; | ||
172 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) | 588 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
173 | refresh *= 2; | 589 | refresh *= 2; |
174 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 590 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
@@ -403,8 +819,7 @@ void drm_mode_prune_invalid(struct drm_device *dev, | |||
403 | list_del(&mode->head); | 819 | list_del(&mode->head); |
404 | if (verbose) { | 820 | if (verbose) { |
405 | drm_mode_debug_printmodeline(mode); | 821 | drm_mode_debug_printmodeline(mode); |
406 | DRM_DEBUG_MODE(DRM_MODESET_DEBUG, | 822 | DRM_DEBUG_KMS("Not using %s mode %d\n", |
407 | "Not using %s mode %d\n", | ||
408 | mode->name, mode->status); | 823 | mode->name, mode->status); |
409 | } | 824 | } |
410 | drm_mode_destroy(dev, mode); | 825 | drm_mode_destroy(dev, mode); |