xf86gtf.c (13275B)
1 /* 2 * gtf.c Generate mode timings using the GTF Timing Standard 3 * 4 * gcc gtf.c -o gtf -lm -Wall 5 * 6 * Copyright (c) 2001, Andy Ritger aritger@nvidia.com 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * o Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * o Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer 17 * in the documentation and/or other materials provided with the 18 * distribution. 19 * o Neither the name of NVIDIA nor the names of its contributors 20 * may be used to endorse or promote products derived from this 21 * software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 25 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 26 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 * 36 * This program is based on the Generalized Timing Formula(GTF TM) 37 * Standard Version: 1.0, Revision: 1.0 38 * 39 * The GTF Document contains the following Copyright information: 40 * 41 * Copyright (c) 1994, 1995, 1996 - Video Electronics Standards 42 * Association. Duplication of this document within VESA member 43 * companies for review purposes is permitted. All other rights 44 * reserved. 45 * 46 * While every precaution has been taken in the preparation 47 * of this standard, the Video Electronics Standards Association and 48 * its contributors assume no responsibility for errors or omissions, 49 * and make no warranties, expressed or implied, of functionality 50 * of suitability for any purpose. The sample code contained within 51 * this standard may be used without restriction. 52 * 53 * 54 * 55 * The GTF EXCEL(TM) SPREADSHEET, a sample (and the definitive) 56 * implementation of the GTF Timing Standard, is available at: 57 * 58 * ftp://ftp.vesa.org/pub/GTF/GTF_V1R1.xls 59 */ 60 61 /* Ruthlessly converted to server code by Adam Jackson <ajax@redhat.com> */ 62 63 #ifdef HAVE_XORG_CONFIG_H 64 #include <xorg-config.h> 65 #endif 66 67 #include "xf86.h" 68 #include "xf86Modes.h" 69 #include <string.h> 70 71 #define MARGIN_PERCENT 1.8 /* % of active vertical image */ 72 #define CELL_GRAN 8.0 /* assumed character cell granularity */ 73 #define MIN_PORCH 1 /* minimum front porch */ 74 #define V_SYNC_RQD 3 /* width of vsync in lines */ 75 #define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */ 76 #define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */ 77 #define M 600.0 /* blanking formula gradient */ 78 #define C 40.0 /* blanking formula offset */ 79 #define K 128.0 /* blanking formula scaling factor */ 80 #define J 20.0 /* blanking formula scaling factor */ 81 82 /* C' and M' are part of the Blanking Duty Cycle computation */ 83 84 #define C_PRIME (((C - J) * K/256.0) + J) 85 #define M_PRIME (K/256.0 * M) 86 87 /* 88 * xf86GTFMode() - as defined by the GTF Timing Standard, compute the 89 * Stage 1 Parameters using the vertical refresh frequency. In other 90 * words: input a desired resolution and desired refresh rate, and 91 * output the GTF mode timings. 92 * 93 * XXX All the code is in place to compute interlaced modes, but I don't 94 * feel like testing it right now. 95 * 96 * XXX margin computations are implemented but not tested (nor used by 97 * XServer of fbset mode descriptions, from what I can tell). 98 */ 99 100 DisplayModePtr 101 xf86GTFMode(int h_pixels, int v_lines, float freq, int interlaced, int margins) 102 { 103 DisplayModeRec *mode = xnfcalloc(1, sizeof(DisplayModeRec)); 104 105 float h_pixels_rnd; 106 float v_lines_rnd; 107 float v_field_rate_rqd; 108 float top_margin; 109 float bottom_margin; 110 float interlace; 111 float h_period_est; 112 float vsync_plus_bp; 113 float v_back_porch; 114 float total_v_lines; 115 float v_field_rate_est; 116 float h_period; 117 float v_field_rate; 118 float v_frame_rate; 119 float left_margin; 120 float right_margin; 121 float total_active_pixels; 122 float ideal_duty_cycle; 123 float h_blank; 124 float total_pixels; 125 float pixel_freq; 126 float h_freq; 127 128 float h_sync; 129 float h_front_porch; 130 float v_odd_front_porch_lines; 131 132 /* 1. In order to give correct results, the number of horizontal 133 * pixels requested is first processed to ensure that it is divisible 134 * by the character size, by rounding it to the nearest character 135 * cell boundary: 136 * 137 * [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND]) 138 */ 139 140 h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN; 141 142 /* 2. If interlace is requested, the number of vertical lines assumed 143 * by the calculation must be halved, as the computation calculates 144 * the number of vertical lines per field. In either case, the 145 * number of lines is rounded to the nearest integer. 146 * 147 * [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0), 148 * ROUND([V LINES],0)) 149 */ 150 151 v_lines_rnd = interlaced ? 152 rint((float) v_lines) / 2.0 : rint((float) v_lines); 153 154 /* 3. Find the frame rate required: 155 * 156 * [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2, 157 * [I/P FREQ RQD]) 158 */ 159 160 v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq); 161 162 /* 4. Find number of lines in Top margin: 163 * 164 * [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y", 165 * ROUND(([MARGIN%]/100*[V LINES RND]),0), 166 * 0) 167 */ 168 169 top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0); 170 171 /* 5. Find number of lines in Bottom margin: 172 * 173 * [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y", 174 * ROUND(([MARGIN%]/100*[V LINES RND]),0), 175 * 0) 176 */ 177 178 bottom_margin = 179 margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0); 180 181 /* 6. If interlace is required, then set variable [INTERLACE]=0.5: 182 * 183 * [INTERLACE]=(IF([INT RQD?]="y",0.5,0)) 184 */ 185 186 interlace = interlaced ? 0.5 : 0.0; 187 188 /* 7. Estimate the Horizontal period 189 * 190 * [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) / 191 * ([V LINES RND] + (2*[TOP MARGIN (LINES)]) + 192 * [MIN PORCH RND]+[INTERLACE]) * 1000000 193 */ 194 195 h_period_est = (((1.0 / v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP / 1000000.0)) 196 / (v_lines_rnd + (2 * top_margin) + MIN_PORCH + interlace) 197 * 1000000.0); 198 199 /* 8. Find the number of lines in V sync + back porch: 200 * 201 * [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0) 202 */ 203 204 vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP / h_period_est); 205 206 /* 9. Find the number of lines in V back porch alone: 207 * 208 * [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND] 209 * 210 * XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]? 211 */ 212 213 v_back_porch = vsync_plus_bp - V_SYNC_RQD; 214 (void) v_back_porch; 215 216 /* 10. Find the total number of lines in Vertical field period: 217 * 218 * [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] + 219 * [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] + 220 * [MIN PORCH RND] 221 */ 222 223 total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp + 224 interlace + MIN_PORCH; 225 226 /* 11. Estimate the Vertical field frequency: 227 * 228 * [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000 229 */ 230 231 v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0; 232 233 /* 12. Find the actual horizontal period: 234 * 235 * [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST]) 236 */ 237 238 h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est); 239 240 /* 13. Find the actual Vertical field frequency: 241 * 242 * [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000 243 */ 244 245 v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0; 246 247 /* 14. Find the Vertical frame frequency: 248 * 249 * [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE])) 250 */ 251 252 v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate; 253 (void) v_frame_rate; 254 255 /* 15. Find number of pixels in left margin: 256 * 257 * [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", 258 * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / 259 * [CELL GRAN RND]),0)) * [CELL GRAN RND], 260 * 0)) 261 */ 262 263 left_margin = margins ? 264 rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : 265 0.0; 266 267 /* 16. Find number of pixels in right margin: 268 * 269 * [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", 270 * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / 271 * [CELL GRAN RND]),0)) * [CELL GRAN RND], 272 * 0)) 273 */ 274 275 right_margin = margins ? 276 rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : 277 0.0; 278 279 /* 17. Find total number of active pixels in image and left and right 280 * margins: 281 * 282 * [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] + 283 * [RIGHT MARGIN (PIXELS)] 284 */ 285 286 total_active_pixels = h_pixels_rnd + left_margin + right_margin; 287 288 /* 18. Find the ideal blanking duty cycle from the blanking duty cycle 289 * equation: 290 * 291 * [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000) 292 */ 293 294 ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0); 295 296 /* 19. Find the number of pixels in the blanking time to the nearest 297 * double character cell: 298 * 299 * [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] * 300 * [IDEAL DUTY CYCLE] / 301 * (100-[IDEAL DUTY CYCLE]) / 302 * (2*[CELL GRAN RND])), 0)) 303 * * (2*[CELL GRAN RND]) 304 */ 305 306 h_blank = rint(total_active_pixels * 307 ideal_duty_cycle / 308 (100.0 - ideal_duty_cycle) / 309 (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN); 310 311 /* 20. Find total number of pixels: 312 * 313 * [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)] 314 */ 315 316 total_pixels = total_active_pixels + h_blank; 317 318 /* 21. Find pixel clock frequency: 319 * 320 * [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD] 321 */ 322 323 pixel_freq = total_pixels / h_period; 324 325 /* 22. Find horizontal frequency: 326 * 327 * [H FREQ] = 1000 / [H PERIOD] 328 */ 329 330 h_freq = 1000.0 / h_period; 331 332 /* Stage 1 computations are now complete; I should really pass 333 the results to another function and do the Stage 2 334 computations, but I only need a few more values so I'll just 335 append the computations here for now */ 336 337 /* 17. Find the number of pixels in the horizontal sync period: 338 * 339 * [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] / 340 * [CELL GRAN RND]),0))*[CELL GRAN RND] 341 */ 342 343 h_sync = 344 rint(H_SYNC_PERCENT / 100.0 * total_pixels / CELL_GRAN) * CELL_GRAN; 345 346 /* 18. Find the number of pixels in the horizontal front porch period: 347 * 348 * [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)] 349 */ 350 351 h_front_porch = (h_blank / 2.0) - h_sync; 352 353 /* 36. Find the number of lines in the odd front porch period: 354 * 355 * [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE]) 356 */ 357 358 v_odd_front_porch_lines = MIN_PORCH + interlace; 359 360 /* finally, pack the results in the mode struct */ 361 362 mode->HDisplay = (int) (h_pixels_rnd); 363 mode->HSyncStart = (int) (h_pixels_rnd + h_front_porch); 364 mode->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync); 365 mode->HTotal = (int) (total_pixels); 366 mode->VDisplay = (int) (v_lines_rnd); 367 mode->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines); 368 mode->VSyncEnd = (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD); 369 mode->VTotal = (int) (total_v_lines); 370 371 mode->Clock = (int) (pixel_freq * 1000.0); 372 mode->HSync = h_freq; 373 mode->VRefresh = freq; 374 375 xf86SetModeDefaultName(mode); 376 377 mode->Flags = V_NHSYNC | V_PVSYNC; 378 if (interlaced) { 379 mode->VTotal *= 2; 380 mode->Flags |= V_INTERLACE; 381 } 382 383 return mode; 384 }