The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/videomode/vesagtf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: vesagtf.c,v 1.2 2013/09/15 15:56:07 martin Exp $ */
    2 /* $FreeBSD$ */
    3 
    4 /*-
    5  * Copyright (c) 2006 Itronix Inc.
    6  * All rights reserved.
    7  *
    8  * Written by Garrett D'Amore for Itronix Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. The name of Itronix Inc. may not be used to endorse
   19  *    or promote products derived from this software without specific
   20  *    prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
   23  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   28  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33  */ 
   34 
   35 /*
   36  * This was derived from a userland GTF program supplied by NVIDIA.
   37  * NVIDIA's original boilerplate follows. 
   38  *
   39  * Note that I have heavily modified the program for use in the EDID
   40  * kernel code for NetBSD, including removing the use of floating
   41  * point operations and making significant adjustments to minimize
   42  * error propagation while operating with integer only math.
   43  *
   44  * This has required the use of 64-bit integers in a few places, but
   45  * the upshot is that for a calculation of 1920x1200x85 (as an
   46  * example), the error deviates by only ~.004% relative to the
   47  * floating point version.  This error is *well* within VESA
   48  * tolerances.
   49  */
   50 
   51 /*
   52  * Copyright (c) 2001, Andy Ritger  aritger@nvidia.com
   53  * All rights reserved.
   54  * 
   55  * Redistribution and use in source and binary forms, with or without
   56  * modification, are permitted provided that the following conditions
   57  * are met:
   58  * 
   59  * o Redistributions of source code must retain the above copyright
   60  *   notice, this list of conditions and the following disclaimer.
   61  * o Redistributions in binary form must reproduce the above copyright
   62  *   notice, this list of conditions and the following disclaimer
   63  *   in the documentation and/or other materials provided with the
   64  *   distribution.
   65  * o Neither the name of NVIDIA nor the names of its contributors
   66  *   may be used to endorse or promote products derived from this
   67  *   software without specific prior written permission.
   68  *
   69  *
   70  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   71  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
   72  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   73  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   74  * THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   75  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   76  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   77  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   78  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   79  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   80  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   81  * POSSIBILITY OF SUCH DAMAGE.
   82  *
   83  * 
   84  *
   85  * This program is based on the Generalized Timing Formula(GTF TM)
   86  * Standard Version: 1.0, Revision: 1.0
   87  *
   88  * The GTF Document contains the following Copyright information:
   89  *
   90  * Copyright (c) 1994, 1995, 1996 - Video Electronics Standards
   91  * Association. Duplication of this document within VESA member
   92  * companies for review purposes is permitted. All other rights
   93  * reserved.
   94  *
   95  * While every precaution has been taken in the preparation
   96  * of this standard, the Video Electronics Standards Association and
   97  * its contributors assume no responsibility for errors or omissions,
   98  * and make no warranties, expressed or implied, of functionality
   99  * of suitability for any purpose. The sample code contained within
  100  * this standard may be used without restriction.
  101  *
  102  * 
  103  *
  104  * The GTF EXCEL(TM) SPREADSHEET, a sample (and the definitive)
  105  * implementation of the GTF Timing Standard, is available at:
  106  *
  107  * ftp://ftp.vesa.org/pub/GTF/GTF_V1R1.xls
  108  *
  109  *
  110  *
  111  * This program takes a desired resolution and vertical refresh rate,
  112  * and computes mode timings according to the GTF Timing Standard.
  113  * These mode timings can then be formatted as an XFree86 modeline
  114  * or a mode description for use by fbset(8).
  115  *
  116  *
  117  *
  118  * NOTES:
  119  *
  120  * The GTF allows for computation of "margins" (the visible border
  121  * surrounding the addressable video); on most non-overscan type
  122  * systems, the margin period is zero.  I've implemented the margin
  123  * computations but not enabled it because 1) I don't really have
  124  * any experience with this, and 2) neither XFree86 modelines nor
  125  * fbset fb.modes provide an obvious way for margin timings to be
  126  * included in their mode descriptions (needs more investigation).
  127  * 
  128  * The GTF provides for computation of interlaced mode timings;
  129  * I've implemented the computations but not enabled them, yet.
  130  * I should probably enable and test this at some point.
  131  *
  132  * 
  133  *
  134  * TODO:
  135  *
  136  * o Add support for interlaced modes.
  137  *
  138  * o Implement the other portions of the GTF: compute mode timings
  139  *   given either the desired pixel clock or the desired horizontal
  140  *   frequency.
  141  *
  142  * o It would be nice if this were more general purpose to do things
  143  *   outside the scope of the GTF: like generate double scan mode
  144  *   timings, for example.
  145  *   
  146  * o Printing digits to the right of the decimal point when the
  147  *   digits are 0 annoys me.
  148  *
  149  * o Error checking.
  150  *
  151  */
  152 
  153 #ifdef  _KERNEL
  154 #include <sys/cdefs.h>
  155 
  156 __FBSDID("$FreeBSD$");
  157 #include <sys/types.h>
  158 #include <sys/param.h>
  159 #include <sys/systm.h>
  160 #include <dev/videomode/videomode.h>
  161 #include <dev/videomode/vesagtf.h>
  162 #else
  163 #include <stdio.h>
  164 #include <stdlib.h>
  165 #include <sys/types.h>
  166 #include "videomode.h"
  167 #include "vesagtf.h"
  168 
  169 void print_xf86_mode(struct videomode *m);
  170 #endif
  171 
  172 #define CELL_GRAN         8     /* assumed character cell granularity        */
  173 
  174 /* C' and M' are part of the Blanking Duty Cycle computation */
  175 /*
  176  * #define C_PRIME           (((C - J) * K/256.0) + J)
  177  * #define M_PRIME           (K/256.0 * M)
  178  */
  179 
  180 /*
  181  * C' and M' multiplied by 256 to give integer math.  Make sure to
  182  * scale results using these back down, appropriately.
  183  */
  184 #define C_PRIME256(p)     (((p->C - p->J) * p->K) + (p->J * 256))
  185 #define M_PRIME256(p)     (p->K * p->M)
  186 
  187 #define DIVIDE(x,y)     (((x) + ((y) / 2)) / (y))
  188 
  189 /*
  190  * print_value() - print the result of the named computation; this is
  191  * useful when comparing against the GTF EXCEL spreadsheet.
  192  */
  193 
  194 #ifdef GTFDEBUG
  195 
  196 static void
  197 print_value(int n, const char *name, unsigned val)
  198 {
  199         printf("%2d: %-27s: %u\n", n, name, val);
  200 }
  201 #else
  202 #define print_value(n, name, val)
  203 #endif
  204 
  205 /*
  206  * vert_refresh() - as defined by the GTF Timing Standard, compute the
  207  * Stage 1 Parameters using the vertical refresh frequency.  In other
  208  * words: input a desired resolution and desired refresh rate, and
  209  * output the GTF mode timings.
  210  *
  211  * XXX All the code is in place to compute interlaced modes, but I don't
  212  * feel like testing it right now.
  213  *
  214  * XXX margin computations are implemented but not tested (nor used by
  215  * XFree86 of fbset mode descriptions, from what I can tell).
  216  */
  217 
  218 void
  219 vesagtf_mode_params(unsigned h_pixels, unsigned v_lines, unsigned freq,
  220     struct vesagtf_params *params, int flags, struct videomode *vmp)
  221 {
  222     unsigned v_field_rqd;
  223     unsigned top_margin;
  224     unsigned bottom_margin;
  225     unsigned interlace;
  226     uint64_t h_period_est;
  227     unsigned vsync_plus_bp;
  228     unsigned v_back_porch __unused;
  229     unsigned total_v_lines;
  230     uint64_t v_field_est;
  231     uint64_t h_period;
  232     unsigned v_field_rate;
  233     unsigned v_frame_rate __unused;
  234     unsigned left_margin;
  235     unsigned right_margin;
  236     unsigned total_active_pixels;
  237     uint64_t ideal_duty_cycle;
  238     unsigned h_blank;
  239     unsigned total_pixels;
  240     unsigned pixel_freq;
  241 
  242     unsigned h_sync;
  243     unsigned h_front_porch;
  244     unsigned v_odd_front_porch_lines;
  245 
  246 #ifdef  GTFDEBUG
  247     unsigned h_freq;
  248 #endif
  249     
  250     /*  1. In order to give correct results, the number of horizontal
  251      *  pixels requested is first processed to ensure that it is divisible
  252      *  by the character size, by rounding it to the nearest character
  253      *  cell boundary:
  254      *
  255      *  [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND])
  256      */
  257     
  258     h_pixels = DIVIDE(h_pixels, CELL_GRAN) * CELL_GRAN;
  259     
  260     print_value(1, "[H PIXELS RND]", h_pixels);
  261 
  262     
  263     /*  2. If interlace is requested, the number of vertical lines assumed
  264      *  by the calculation must be halved, as the computation calculates
  265      *  the number of vertical lines per field. In either case, the
  266      *  number of lines is rounded to the nearest integer.
  267      *   
  268      *  [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0),
  269      *                                     ROUND([V LINES],0))
  270      */
  271 
  272     v_lines = (flags & VESAGTF_FLAG_ILACE) ? DIVIDE(v_lines, 2) : v_lines;
  273     
  274     print_value(2, "[V LINES RND]", v_lines);
  275     
  276     
  277     /*  3. Find the frame rate required:
  278      *
  279      *  [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2,
  280      *                                          [I/P FREQ RQD])
  281      */
  282 
  283     v_field_rqd = (flags & VESAGTF_FLAG_ILACE) ? (freq * 2) : (freq);
  284 
  285     print_value(3, "[V FIELD RATE RQD]", v_field_rqd);
  286     
  287 
  288     /*  4. Find number of lines in Top margin:
  289      *  5. Find number of lines in Bottom margin:
  290      *
  291      *  [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y",
  292      *          ROUND(([MARGIN%]/100*[V LINES RND]),0),
  293      *          0)
  294      *
  295      *  Ditto for bottom margin.  Note that instead of %, we use PPT, which
  296      *  is parts per thousand.  This helps us with integer math.
  297      */
  298 
  299     top_margin = bottom_margin = (flags & VESAGTF_FLAG_MARGINS) ?
  300         DIVIDE(v_lines * params->margin_ppt, 1000) : 0;
  301 
  302     print_value(4, "[TOP MARGIN (LINES)]", top_margin);
  303     print_value(5, "[BOT MARGIN (LINES)]", bottom_margin);
  304 
  305     
  306     /*  6. If interlace is required, then set variable [INTERLACE]=0.5:
  307      *   
  308      *  [INTERLACE]=(IF([INT RQD?]="y",0.5,0))
  309      *
  310      *  To make this integer friendly, we use some special hacks in step
  311      *  7 below.  Please read those comments to understand why I am using
  312      *  a whole number of 1.0 instead of 0.5 here.
  313      */
  314     interlace = (flags & VESAGTF_FLAG_ILACE) ? 1 : 0;
  315 
  316     print_value(6, "[2*INTERLACE]", interlace);
  317     
  318 
  319     /*  7. Estimate the Horizontal period
  320      *
  321      *  [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) /
  322      *                    ([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
  323      *                     [MIN PORCH RND]+[INTERLACE]) * 1000000
  324      *
  325      *  To make it integer friendly, we pre-multiply the 1000000 to get to
  326      *  usec.  This gives us:
  327      *
  328      *  [H PERIOD EST] = ((1000000/[V FIELD RATE RQD]) - [MIN VSYNC+BP]) /
  329      *                  ([V LINES RND] + (2 * [TOP MARGIN (LINES)]) +
  330      *                   [MIN PORCH RND]+[INTERLACE])
  331      *
  332      *  The other problem is that the interlace value is wrong.  To get
  333      *  the interlace to a whole number, we multiply both the numerator and
  334      *  divisor by 2, so we can use a value of either 1 or 0 for the interlace
  335      *  factor.
  336      *
  337      * This gives us:
  338      *
  339      * [H PERIOD EST] = ((2*((1000000/[V FIELD RATE RQD]) - [MIN VSYNC+BP])) /
  340      *                   (2*([V LINES RND] + (2*[TOP MARGIN (LINES)]) +
  341      *                    [MIN PORCH RND]) + [2*INTERLACE]))
  342      *
  343      * Finally we multiply by another 1000, to get value in picosec.
  344      * Why picosec?  To minimize rounding errors.  Gotta love integer
  345      * math and error propagation.
  346      */
  347 
  348     h_period_est = DIVIDE(((DIVIDE(2000000000000ULL, v_field_rqd)) -
  349                               (2000000 * params->min_vsbp)),
  350         ((2 * (v_lines + (2 * top_margin) + params->min_porch)) + interlace));
  351 
  352     print_value(7, "[H PERIOD EST (ps)]", h_period_est);
  353     
  354 
  355     /*  8. Find the number of lines in V sync + back porch:
  356      *
  357      *  [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0)
  358      *
  359      *  But recall that h_period_est is in psec. So multiply by 1000000.
  360      */
  361 
  362     vsync_plus_bp = DIVIDE(params->min_vsbp * 1000000, h_period_est);
  363 
  364     print_value(8, "[V SYNC+BP]", vsync_plus_bp);
  365     
  366     
  367     /*  9. Find the number of lines in V back porch alone:
  368      *
  369      *  [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND]
  370      *
  371      *  XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]?
  372      */
  373     
  374     v_back_porch = vsync_plus_bp - params->vsync_rqd;
  375     
  376     print_value(9, "[V BACK PORCH]", v_back_porch);
  377     
  378 
  379     /*  10. Find the total number of lines in Vertical field period:
  380      *
  381      *  [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] +
  382      *                    [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] +
  383      *                    [MIN PORCH RND]
  384      */
  385 
  386     total_v_lines = v_lines + top_margin + bottom_margin + vsync_plus_bp +
  387         interlace + params->min_porch;
  388     
  389     print_value(10, "[TOTAL V LINES]", total_v_lines);
  390     
  391 
  392     /*  11. Estimate the Vertical field frequency:
  393      *
  394      *  [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000
  395      *
  396      *  Again, we want to pre multiply by 10^9 to convert for nsec, thereby
  397      *  making it usable in integer math.
  398      *
  399      *  So we get:
  400      *
  401      *  [V FIELD RATE EST] = 1000000000 / [H PERIOD EST] / [TOTAL V LINES]
  402      *
  403      *  This is all scaled to get the result in uHz.  Again, we're trying to
  404      *  minimize error propagation.
  405      */
  406     v_field_est = DIVIDE(DIVIDE(1000000000000000ULL, h_period_est),
  407         total_v_lines);
  408     
  409     print_value(11, "[V FIELD RATE EST(uHz)]", v_field_est);
  410     
  411 
  412     /*  12. Find the actual horizontal period:
  413      *
  414      *  [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST])
  415      */
  416 
  417     h_period = DIVIDE(h_period_est * v_field_est, v_field_rqd * 1000);
  418     
  419     print_value(12, "[H PERIOD(ps)]", h_period);
  420     
  421 
  422     /*  13. Find the actual Vertical field frequency:
  423      *
  424      *  [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000
  425      *
  426      *  And again, we convert to nsec ahead of time, giving us:
  427      *
  428      *  [V FIELD RATE] = 1000000 / [H PERIOD] / [TOTAL V LINES]
  429      *
  430      *  And another rescaling back to mHz.  Gotta love it.
  431      */
  432 
  433     v_field_rate = DIVIDE(1000000000000ULL, h_period * total_v_lines);
  434 
  435     print_value(13, "[V FIELD RATE]", v_field_rate);
  436     
  437 
  438     /*  14. Find the Vertical frame frequency:
  439      *
  440      *  [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE]))
  441      *
  442      *  N.B. that the result here is in mHz.
  443      */
  444 
  445     v_frame_rate = (flags & VESAGTF_FLAG_ILACE) ?
  446         v_field_rate / 2 : v_field_rate;
  447 
  448     print_value(14, "[V FRAME RATE]", v_frame_rate);
  449     
  450 
  451     /*  15. Find number of pixels in left margin:
  452      *  16. Find number of pixels in right margin:
  453      *
  454      *  [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y",
  455      *          (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 /
  456      *                   [CELL GRAN RND]),0)) * [CELL GRAN RND],
  457      *          0))
  458      *
  459      *  Again, we deal with margin percentages as PPT (parts per thousand).
  460      *  And the calculations for left and right are the same.
  461      */
  462 
  463     left_margin = right_margin = (flags & VESAGTF_FLAG_MARGINS) ?
  464         DIVIDE(DIVIDE(h_pixels * params->margin_ppt, 1000),
  465             CELL_GRAN) * CELL_GRAN : 0;
  466 
  467     print_value(15, "[LEFT MARGIN (PIXELS)]", left_margin);
  468     print_value(16, "[RIGHT MARGIN (PIXELS)]", right_margin);
  469     
  470 
  471     /*  17. Find total number of active pixels in image and left and right
  472      *  margins:
  473      *
  474      *  [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] +
  475      *                          [RIGHT MARGIN (PIXELS)]
  476      */
  477 
  478     total_active_pixels = h_pixels + left_margin + right_margin;
  479     
  480     print_value(17, "[TOTAL ACTIVE PIXELS]", total_active_pixels);
  481     
  482     
  483     /*  18. Find the ideal blanking duty cycle from the blanking duty cycle
  484      *  equation:
  485      *
  486      *  [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000)
  487      *
  488      *  However, we have modified values for [C'] as [256*C'] and
  489      *  [M'] as [256*M'].  Again the idea here is to get good scaling.
  490      *  We use 256 as the factor to make the math fast.
  491      *
  492      *  Note that this means that we have to scale it appropriately in
  493      *  later calculations.
  494      *
  495      *  The ending result is that our ideal_duty_cycle is 256000x larger
  496      *  than the duty cycle used by VESA.  But again, this reduces error
  497      *  propagation.
  498      */
  499 
  500     ideal_duty_cycle =
  501         ((C_PRIME256(params) * 1000) -
  502             (M_PRIME256(params) * h_period / 1000000));
  503     
  504     print_value(18, "[IDEAL DUTY CYCLE]", ideal_duty_cycle);
  505     
  506 
  507     /*  19. Find the number of pixels in the blanking time to the nearest
  508      *  double character cell:
  509      *
  510      *  [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] *
  511      *                               [IDEAL DUTY CYCLE] /
  512      *                               (100-[IDEAL DUTY CYCLE]) /
  513      *                               (2*[CELL GRAN RND])), 0))
  514      *                       * (2*[CELL GRAN RND])
  515      *
  516      *  Of course, we adjust to make this rounding work in integer math.
  517      */
  518 
  519     h_blank = DIVIDE(DIVIDE(total_active_pixels * ideal_duty_cycle,
  520                          (256000 * 100ULL) - ideal_duty_cycle),
  521         2 * CELL_GRAN) * (2 * CELL_GRAN);
  522 
  523     print_value(19, "[H BLANK (PIXELS)]", h_blank);
  524     
  525 
  526     /*  20. Find total number of pixels:
  527      *
  528      *  [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)]
  529      */
  530 
  531     total_pixels = total_active_pixels + h_blank;
  532     
  533     print_value(20, "[TOTAL PIXELS]", total_pixels);
  534     
  535 
  536     /*  21. Find pixel clock frequency:
  537      *
  538      *  [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD]
  539      *
  540      *  We calculate this in Hz rather than MHz, to get a value that
  541      *  is usable with integer math.  Recall that the [H PERIOD] is in
  542      *  nsec.
  543      */
  544     
  545     pixel_freq = DIVIDE(total_pixels * 1000000, DIVIDE(h_period, 1000));
  546     
  547     print_value(21, "[PIXEL FREQ]", pixel_freq);
  548     
  549 
  550     /*  22. Find horizontal frequency:
  551      *
  552      *  [H FREQ] = 1000 / [H PERIOD]
  553      *
  554      *  I've ifdef'd this out, because we don't need it for any of
  555      *  our calculations.
  556      *  We calculate this in Hz rather than kHz, to avoid rounding
  557      *  errors.  Recall that the [H PERIOD] is in usec.
  558      */
  559 
  560 #ifdef  GTFDEBUG
  561     h_freq = 1000000000 / h_period;
  562     
  563     print_value(22, "[H FREQ]", h_freq);
  564 #endif
  565     
  566 
  567     /* Stage 1 computations are now complete; I should really pass
  568        the results to another function and do the Stage 2
  569        computations, but I only need a few more values so I'll just
  570        append the computations here for now */
  571 
  572     
  573 
  574     /*  17. Find the number of pixels in the horizontal sync period:
  575      *
  576      *  [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] /
  577      *                             [CELL GRAN RND]),0))*[CELL GRAN RND]
  578      *
  579      *  Rewriting for integer math:
  580      *
  581      *  [H SYNC (PIXELS)]=(ROUND((H SYNC%] * [TOTAL PIXELS] / 100 /
  582      *                             [CELL GRAN RND),0))*[CELL GRAN RND]
  583      */
  584 
  585     h_sync = DIVIDE(((params->hsync_pct * total_pixels) / 100), CELL_GRAN) *
  586         CELL_GRAN;
  587 
  588     print_value(17, "[H SYNC (PIXELS)]", h_sync);
  589     
  590 
  591     /*  18. Find the number of pixels in the horizontal front porch period:
  592      *
  593      *  [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)]
  594      *
  595      *  Note that h_blank is always an even number of characters (i.e.
  596      *  h_blank % (CELL_GRAN * 2) == 0)
  597      */
  598 
  599     h_front_porch = (h_blank / 2) - h_sync;
  600 
  601     print_value(18, "[H FRONT PORCH (PIXELS)]", h_front_porch);
  602     
  603     
  604     /*  36. Find the number of lines in the odd front porch period:
  605      *
  606      *  [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE])
  607      *
  608      *  Adjusting for the fact that the interlace is scaled:
  609      *
  610      *  [V ODD FRONT PORCH(LINES)]=(([MIN PORCH RND] * 2) + [2*INTERLACE]) / 2
  611      */
  612     
  613     v_odd_front_porch_lines = ((2 * params->min_porch) + interlace) / 2;
  614     
  615     print_value(36, "[V ODD FRONT PORCH(LINES)]", v_odd_front_porch_lines);
  616     
  617 
  618     /* finally, pack the results in the mode struct */
  619 
  620     vmp->hsync_start = h_pixels + h_front_porch;
  621     vmp->hsync_end = vmp->hsync_start + h_sync;
  622     vmp->htotal = total_pixels;
  623     vmp->hdisplay = h_pixels;
  624 
  625     vmp->vsync_start = v_lines + v_odd_front_porch_lines;
  626     vmp->vsync_end = vmp->vsync_start + params->vsync_rqd;
  627     vmp->vtotal = total_v_lines;
  628     vmp->vdisplay = v_lines;
  629 
  630     vmp->dot_clock = pixel_freq;
  631     
  632 }
  633 
  634 void
  635 vesagtf_mode(unsigned x, unsigned y, unsigned refresh, struct videomode *vmp)
  636 {
  637         struct vesagtf_params   params;
  638 
  639         params.margin_ppt = VESAGTF_MARGIN_PPT;
  640         params.min_porch = VESAGTF_MIN_PORCH;
  641         params.vsync_rqd = VESAGTF_VSYNC_RQD;
  642         params.hsync_pct = VESAGTF_HSYNC_PCT;
  643         params.min_vsbp = VESAGTF_MIN_VSBP;
  644         params.M = VESAGTF_M;
  645         params.C = VESAGTF_C;
  646         params.K = VESAGTF_K;
  647         params.J = VESAGTF_J;
  648 
  649         vesagtf_mode_params(x, y, refresh, &params, 0, vmp);
  650 }
  651 
  652 /*
  653  * The tidbit here is so that you can compile this file as a
  654  * standalone user program to generate X11 modelines using VESA GTF.
  655  * This also allows for testing of the code itself, without
  656  * necessitating a full kernel recompile.
  657  */
  658 
  659 /* print_xf86_mode() - print the XFree86 modeline, given mode timings. */
  660 
  661 #ifndef _KERNEL
  662 void
  663 print_xf86_mode (struct videomode *vmp)
  664 {
  665         float   vf, hf;
  666 
  667         hf = 1000.0 * vmp->dot_clock / vmp->htotal;
  668         vf = 1.0 * hf / vmp->vtotal;
  669 
  670     printf("\n");
  671     printf("  # %dx%d @ %.2f Hz (GTF) hsync: %.2f kHz; pclk: %.2f MHz\n",
  672         vmp->hdisplay, vmp->vdisplay, vf, hf, vmp->dot_clock / 1000.0);
  673     
  674     printf("  Modeline \"%dx%d_%.2f\"  %.2f"
  675         "  %d %d %d %d"
  676         "  %d %d %d %d"
  677         "  -HSync +Vsync\n\n",
  678         vmp->hdisplay, vmp->vdisplay, vf, (vmp->dot_clock / 1000.0),
  679         vmp->hdisplay, vmp->hsync_start, vmp->hsync_end, vmp->htotal,
  680         vmp->vdisplay, vmp->vsync_start, vmp->vsync_end, vmp->vtotal);
  681 }
  682 
  683 int
  684 main (int argc, char *argv[])
  685 {
  686         struct videomode m;
  687 
  688         if (argc != 4) {
  689                 printf("usage: %s x y refresh\n", argv[0]);
  690                 exit(1);
  691         }
  692     
  693         vesagtf_mode(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), &m);
  694 
  695         print_xf86_mode(&m);
  696     
  697         return 0;
  698     
  699 }
  700 #endif

Cache object: 7397f293cba42a34f15c249d88db9853


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.