~ubuntu-branches/ubuntu/trusty/xorg-server-lts-utopic/trusty-proposed

« back to all changes in this revision

Viewing changes to hw/xwayland/xwayland-cvt.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2015-01-22 10:01:57 UTC
  • Revision ID: package-import@ubuntu.com-20150122100157-3zdz5pof8z66kbmp
Tags: upstream-1.16.0
Import upstream version 1.16.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and
 
2
 * changed to generate an RRMode */
 
3
 
 
4
/*
 
5
 * Copyright 2005-2006 Luc Verhaegen.
 
6
 *
 
7
 * Permission is hereby granted, free of charge, to any person obtaining a
 
8
 * copy of this software and associated documentation files (the "Software"),
 
9
 * to deal in the Software without restriction, including without limitation
 
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
11
 * and/or sell copies of the Software, and to permit persons to whom the
 
12
 * Software is furnished to do so, subject to the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice shall be included in
 
15
 * all copies or substantial portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
20
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
23
 * OTHER DEALINGS IN THE SOFTWARE.
 
24
 */
 
25
 
 
26
/*
 
27
 * The reason for having this function in a file of its own is
 
28
 * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
 
29
 * code is shared directly.
 
30
 */
 
31
 
 
32
#ifdef HAVE_DIX_CONFIG_H
 
33
#include <dix-config.h>
 
34
#endif
 
35
 
 
36
#include <string.h>
 
37
#include <randrstr.h>
 
38
#include "xwayland.h"
 
39
 
 
40
/*
 
41
 * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
 
42
 *
 
43
 * These calculations are stolen from the CVT calculation spreadsheet written
 
44
 * by Graham Loveridge. He seems to be claiming no copyright and there seems to
 
45
 * be no license attached to this. He apparently just wants to see his name
 
46
 * mentioned.
 
47
 *
 
48
 * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
 
49
 *
 
50
 * Comments and structure corresponds to the comments and structure of the xls.
 
51
 * This should ease importing of future changes to the standard (not very
 
52
 * likely though).
 
53
 *
 
54
 * About margins; i'm sure that they are to be the bit between HDisplay and
 
55
 * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
 
56
 * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
 
57
 * outside sync "margin" for some reason. Since we prefer seeing proper
 
58
 * blanking instead of the overscan colour, and since the Crtc* values will
 
59
 * probably get altered after us, we will disable margins altogether. With
 
60
 * these calculations, Margins will plainly expand H/VDisplay, and we don't
 
61
 * want that. -- libv
 
62
 *
 
63
 */
 
64
RRModePtr
 
65
xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
 
66
             Bool Interlaced)
 
67
{
 
68
    /* 1) top/bottom margin size (% of height) - default: 1.8 */
 
69
#define CVT_MARGIN_PERCENTAGE 1.8
 
70
 
 
71
    /* 2) character cell horizontal granularity (pixels) - default 8 */
 
72
#define CVT_H_GRANULARITY 8
 
73
 
 
74
    /* 4) Minimum vertical porch (lines) - default 3 */
 
75
#define CVT_MIN_V_PORCH 3
 
76
 
 
77
    /* 4) Minimum number of vertical back porch lines - default 6 */
 
78
#define CVT_MIN_V_BPORCH 6
 
79
 
 
80
    /* Pixel Clock step (kHz) */
 
81
#define CVT_CLOCK_STEP 250
 
82
 
 
83
    Bool Margins = FALSE;
 
84
    float VFieldRate, HPeriod;
 
85
    int HDisplayRnd, HMargin;
 
86
    int VDisplayRnd, VMargin, VSync;
 
87
    float Interlace;            /* Please rename this */
 
88
    char name[128];
 
89
    xRRModeInfo modeinfo;
 
90
 
 
91
    memset(&modeinfo, 0, sizeof modeinfo);
 
92
 
 
93
    /* CVT default is 60.0Hz */
 
94
    if (!VRefresh)
 
95
        VRefresh = 60.0;
 
96
 
 
97
    /* 1. Required field rate */
 
98
    if (Interlaced)
 
99
        VFieldRate = VRefresh * 2;
 
100
    else
 
101
        VFieldRate = VRefresh;
 
102
 
 
103
    /* 2. Horizontal pixels */
 
104
    HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
 
105
 
 
106
    /* 3. Determine left and right borders */
 
107
    if (Margins) {
 
108
        /* right margin is actually exactly the same as left */
 
109
        HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
 
110
        HMargin -= HMargin % CVT_H_GRANULARITY;
 
111
    }
 
112
    else
 
113
        HMargin = 0;
 
114
 
 
115
    /* 4. Find total active pixels */
 
116
    modeinfo.width = HDisplayRnd + 2 * HMargin;
 
117
 
 
118
    /* 5. Find number of lines per field */
 
119
    if (Interlaced)
 
120
        VDisplayRnd = VDisplay / 2;
 
121
    else
 
122
        VDisplayRnd = VDisplay;
 
123
 
 
124
    /* 6. Find top and bottom margins */
 
125
    /* nope. */
 
126
    if (Margins)
 
127
        /* top and bottom margins are equal again. */
 
128
        VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
 
129
    else
 
130
        VMargin = 0;
 
131
 
 
132
    modeinfo.height = VDisplay + 2 * VMargin;
 
133
 
 
134
    /* 7. Interlace */
 
135
    if (Interlaced)
 
136
        Interlace = 0.5;
 
137
    else
 
138
        Interlace = 0.0;
 
139
 
 
140
    /* Determine VSync Width from aspect ratio */
 
141
    if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
 
142
        VSync = 4;
 
143
    else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
 
144
        VSync = 5;
 
145
    else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
 
146
        VSync = 6;
 
147
    else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
 
148
        VSync = 7;
 
149
    else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
 
150
        VSync = 7;
 
151
    else                        /* Custom */
 
152
        VSync = 10;
 
153
 
 
154
    if (!Reduced) {             /* simplified GTF calculation */
 
155
 
 
156
        /* 4) Minimum time of vertical sync + back porch interval (µs)
 
157
         * default 550.0 */
 
158
#define CVT_MIN_VSYNC_BP 550.0
 
159
 
 
160
        /* 3) Nominal HSync width (% of line period) - default 8 */
 
161
#define CVT_HSYNC_PERCENTAGE 8
 
162
 
 
163
        float HBlankPercentage;
 
164
        int VSyncAndBackPorch, VBackPorch;
 
165
        int HBlank;
 
166
 
 
167
        /* 8. Estimated Horizontal period */
 
168
        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
 
169
            (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
 
170
 
 
171
        /* 9. Find number of lines in sync + backporch */
 
172
        if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) <
 
173
            (VSync + CVT_MIN_V_PORCH))
 
174
            VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
 
175
        else
 
176
            VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1;
 
177
 
 
178
        /* 10. Find number of lines in back porch */
 
179
        VBackPorch = VSyncAndBackPorch - VSync;
 
180
        (void) VBackPorch;
 
181
 
 
182
        /* 11. Find total number of lines in vertical field */
 
183
        modeinfo.vTotal =
 
184
            VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace +
 
185
            CVT_MIN_V_PORCH;
 
186
 
 
187
        /* 5) Definition of Horizontal blanking time limitation */
 
188
        /* Gradient (%/kHz) - default 600 */
 
189
#define CVT_M_FACTOR 600
 
190
 
 
191
        /* Offset (%) - default 40 */
 
192
#define CVT_C_FACTOR 40
 
193
 
 
194
        /* Blanking time scaling factor - default 128 */
 
195
#define CVT_K_FACTOR 128
 
196
 
 
197
        /* Scaling factor weighting - default 20 */
 
198
#define CVT_J_FACTOR 20
 
199
 
 
200
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
 
201
#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
 
202
        CVT_J_FACTOR
 
203
 
 
204
        /* 12. Find ideal blanking duty cycle from formula */
 
205
        HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
 
206
 
 
207
        /* 13. Blanking time */
 
208
        if (HBlankPercentage < 20)
 
209
            HBlankPercentage = 20;
 
210
 
 
211
        HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage);
 
212
        HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
 
213
 
 
214
        /* 14. Find total number of pixels in a line. */
 
215
        modeinfo.hTotal = modeinfo.width + HBlank;
 
216
 
 
217
        /* Fill in HSync values */
 
218
        modeinfo.hSyncEnd = modeinfo.width + HBlank / 2;
 
219
 
 
220
        modeinfo.hSyncStart = modeinfo.hSyncEnd -
 
221
            (modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100;
 
222
        modeinfo.hSyncStart += CVT_H_GRANULARITY -
 
223
            modeinfo.hSyncStart % CVT_H_GRANULARITY;
 
224
 
 
225
        /* Fill in VSync values */
 
226
        modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH;
 
227
        modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
 
228
 
 
229
    }
 
230
    else {                      /* Reduced blanking */
 
231
        /* Minimum vertical blanking interval time (µs) - default 460 */
 
232
#define CVT_RB_MIN_VBLANK 460.0
 
233
 
 
234
        /* Fixed number of clocks for horizontal sync */
 
235
#define CVT_RB_H_SYNC 32.0
 
236
 
 
237
        /* Fixed number of clocks for horizontal blanking */
 
238
#define CVT_RB_H_BLANK 160.0
 
239
 
 
240
        /* Fixed number of lines for vertical front porch - default 3 */
 
241
#define CVT_RB_VFPORCH 3
 
242
 
 
243
        int VBILines;
 
244
 
 
245
        /* 8. Estimate Horizontal period. */
 
246
        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
 
247
            (VDisplayRnd + 2 * VMargin);
 
248
 
 
249
        /* 9. Find number of lines in vertical blanking */
 
250
        VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
 
251
 
 
252
        /* 10. Check if vertical blanking is sufficient */
 
253
        if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
 
254
            VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
 
255
 
 
256
        /* 11. Find total number of lines in vertical field */
 
257
        modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
 
258
 
 
259
        /* 12. Find total number of pixels in a line */
 
260
        modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK;
 
261
 
 
262
        /* Fill in HSync values */
 
263
        modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2;
 
264
        modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC;
 
265
 
 
266
        /* Fill in VSync values */
 
267
        modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH;
 
268
        modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
 
269
    }
 
270
 
 
271
    /* 15/13. Find pixel clock frequency (kHz for xf86) */
 
272
    modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod;
 
273
    modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP;
 
274
    modeinfo.dotClock *= 1000.0;
 
275
#if 0
 
276
    /* 16/14. Find actual Horizontal Frequency (kHz) */
 
277
    modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal);
 
278
#endif
 
279
 
 
280
#if 0
 
281
    /* 17/15. Find actual Field rate */
 
282
    modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) /
 
283
        ((float) (modeinfo.hTotal * modeinfo.vTotal));
 
284
#endif
 
285
 
 
286
    /* 18/16. Find actual vertical frame frequency */
 
287
    /* ignore - just set the mode flag for interlaced */
 
288
    if (Interlaced)
 
289
        modeinfo.vTotal *= 2;
 
290
 
 
291
    if (Reduced)
 
292
        modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative;
 
293
    else
 
294
        modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive;
 
295
 
 
296
    if (Interlaced)
 
297
        modeinfo.modeFlags |= RR_Interlace;
 
298
 
 
299
    snprintf(name, sizeof name, "%dx%d@%.1fHz",
 
300
             modeinfo.width, modeinfo.height, VRefresh);
 
301
    modeinfo.nameLength = strlen(name);
 
302
 
 
303
    return RRModeGet(&modeinfo, name);
 
304
}