2
* Id: sisclock.c,v 1.1 1999/11/02 08:17:24 keithp Exp $
4
* Copyright � 1999 Keith Packard
6
* Permission to use, copy, modify, distribute, and sell this software and its
7
* documentation for any purpose is hereby granted without fee, provided that
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the name of Keith Packard not be used in
11
* advertising or publicity pertaining to distribution of the software without
12
* specific, written prior permission. Keith Packard makes no
13
* representations about the suitability of this software for any purpose. It
14
* is provided "as is" without express or implied warranty.
16
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
* PERFORMANCE OF THIS SOFTWARE.
24
/* $XFree86: xc/programs/Xserver/hw/kdrive/sis530/sisclock.c,v 1.2 2000/02/23 20:30:07 dawes Exp $ */
31
#define MAX_VCO 230000000
32
#define MAX_PSN 0 /* no pre scaler for this chip */
33
#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */
37
* Compute clock values given target frequency
40
sisGetClock (unsigned long clock, SisCrtc *crtc)
42
unsigned char reg7, reg13, reg2a, reg2b;
45
int bestM, bestN, bestP, bestPSN, bestVLD;
46
double bestError, abest = 42.0, bestFout;
51
double target = (double) clock;
61
* fd = fref*(Numerator/Denumerator)*(Divider/PostScaler)
63
* M = Numerator [1:128]
64
* N = DeNumerator [1:32]
65
* VLD = Divider (Vco Loop Divider) : divide by 1, 2
66
* P = Post Scaler : divide by 1, 2, 3, 4
67
* PSN = Pre Scaler (Reference Divisor Select)
73
if (target < MAX_VCO / 2)
75
if (target < MAX_VCO / 3)
77
if (target < MAX_VCO / 4)
79
if (target < MAX_VCO / 6)
81
if (target < MAX_VCO / 8)
86
for (N = low_N; N <= high_N; N++)
88
double M_desired = Fvco / FREF * N;
90
if (M_desired > M_max * max_VLD)
93
if ( M_desired > M_max )
95
M = (int)(M_desired / 2 + 0.5);
100
M = (int)(M_desired + 0.5);
104
Fout = (double)FREF * (M * VLD)/(N * P);
105
error = (target - Fout) / target;
106
aerror = (error < 0) ? -error : error;
120
crtc->vclk_numerator = bestM - 1;
121
crtc->vclk_divide_by_2 = bestVLD == 2;
123
crtc->vclk_denominator = bestN - 1;
126
crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_1;
127
crtc->vclk_post_scale_2 = 0;
130
crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_2;
131
crtc->vclk_post_scale_2 = 0;
134
crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_3;
135
crtc->vclk_post_scale_2 = 0;
138
crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_4;
139
crtc->vclk_post_scale_2 = 0;
142
crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_3;
143
crtc->vclk_post_scale_2 = 1;
146
crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_4;
147
crtc->vclk_post_scale_2 = 1;
151
crtc->vclk_vco_gain = 1;
154
* Don't know how to set mclk for local frame buffer; for
155
* shared frame buffer, mclk is hardwired to bus speed (100MHz)?
159
sisCalcMclk (SisCrtc *crtc)
161
int mclk, Numer, DeNumer;
162
double Divider, Scalar;
164
Numer = crtc->mclk_numerator;
165
DeNumer = crtc->mclk_denominator;
166
Divider = crtc->mclk_divide_by_2 ? 2.0 : 1.0;
168
if (crtc->mclk_post_scale_2)
170
switch (crtc->mclk_post_scale) {
181
switch (crtc->mclk_post_scale) {
197
mclk = (int)(FREF*((double)(Numer+1)/(double)(DeNumer+1))*(Divider/Scalar));
202
#define UMA_FACTOR 60
203
#define LFB_FACTOR 30 // Only if local frame buffer
204
#define SIS_SAYS_SO 0x1F // But how is the performance??
205
#define CRT_ENG_THRESH 0x0F // But how is the performance??
207
#define DFP_BUS_WIDTH 32 // rumour has it for digital flat panel ??
208
#define MEGAHZ (1<<20)
211
sisEngThresh (SisCrtc *crtc, unsigned long vclk, int bpp)
215
mclk = sisCalcMclk(crtc) / 1000000;
216
vclk = vclk / 1000000;
217
threshlow = ((((UMA_FACTOR*vclk*bpp)/
218
(mclk*BUS_WIDTH))+1)/2)+4;
220
crtc->crt_cpu_threshold_low_0_3 = threshlow;
221
crtc->crt_cpu_threshold_low_4 = threshlow >> 4;
223
crtc->crt_cpu_threshold_high_0_3 = (SIS_SAYS_SO & 0xf);
224
crtc->crt_cpu_threshold_high_4 = 0;
226
crtc->crt_engine_threshold_high_0_3 = CRT_ENG_THRESH;
227
crtc->crt_engine_threshold_high_4 = 1;
229
crtc->ascii_attribute_threshold_0_2 = (SIS_SAYS_SO >> 4);
231
crtc->crt_threshold_full_control = SIS_CRT_64_STAGE_THRESHOLD;