ICS1562.c revision 7706df26
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tga/ICS1562.c,v 1.2 1998/07/25 16:55:56 dawes Exp $ */
2
3#ifdef HAVE_CONFIG_H
4#include "config.h"
5#endif
6
7#define BASE_FREQ 14.31818
8#define MAX_FREQ 230000
9
10#define	reorder(a)	( \
11	(a & 0x80) >> 7 | \
12	(a & 0x40) >> 5 | \
13	(a & 0x20) >> 3 | \
14	(a & 0x10) >> 1 | \
15	(a & 0x08) << 1 | \
16	(a & 0x04) << 3 | \
17	(a & 0x02) << 5 | \
18	(a & 0x01) << 7 )
19
20#define CHECK_MIN(m,a,r,n)  do { \
21      diff = f - (BASE_FREQ * 1e3 * (n)) / (r << p); \
22      if (diff < 0) diff = -diff; \
23      if (diff < min_diff) {  \
24	min_diff = diff; \
25	best_m = m; \
26	best_a = a; \
27	best_r = r; \
28      } \
29    } while(0)
30
31
32static void Set_1562_PLL(int f, int p, int m, int a, int r, unsigned char *bits)
33{
34  bits[0] = 0x80;  /* N1 = 4, not used for PLL */
35  bits[1] = reorder(p) >> 4;
36  bits[2] = 0x00;  /* N2 = 1 */
37  if (f <= 120000)
38    bits[3] = 0x20;  /* V = 100 */
39  else if (f <= 200000)
40    bits[3] = 0xa0;  /* V = 101 */
41  else
42    bits[3] = 0x60;  /* V = 110 */
43  bits[3] |= 0x05;   /* P = 10, phase detector on */
44  bits[4] = reorder(m);
45  bits[5] = reorder(a);
46  bits[6] = reorder(r);
47
48#ifdef DEBUG
49  {
50    int i;
51    for(i=0; i<7; i++)
52      ErrorF("%02x ", bits[i]);
53    ErrorF("\n");
54  }
55#endif
56}
57
58void ICS1562_CalcClockBits(long f, unsigned char *bits);
59
60void ICS1562_CalcClockBits(long f, unsigned char *bits)
61{
62  int n,r, a,m, p, r0,r1,n0,n1;
63  int best_m=34, best_a=1, best_r=30;
64  double diff, min_diff;
65  double ff, ffp;
66
67  if (f > MAX_FREQ)
68    f = MAX_FREQ;
69
70  if (f >= MAX_FREQ/2)
71    p=0;
72  else if (f >= MAX_FREQ/4)
73    p=1;
74  else
75    p=2;
76
77  ff  = f / 1e3 / BASE_FREQ;
78  ffp = ff * (1 << p);
79  min_diff = 999999999;
80
81  r0 = (int)(7/ffp);
82  if (r0 < 1) r0 = 1;
83  r1 = (int)(449/ffp);
84  if (r1 > 0x7f+1) r1 = 0x7f+1;
85  if (r1 < r0) r1 = r0;
86
87  for (r=r0; r<r1; r++) {
88    n0 = (int)(ffp * r);
89    if (n0 < 7) n0 = 7;
90    n1 = (int)(ffp * (r+1));
91    if (n1 > 448) n1 = 448;
92    for (n=n0; n<n1; n++) {
93      m = ((n+3)/7) - 1;
94      if (m   <= 0x3f) CHECK_MIN(m, 0, r, (m+1)*7);
95      if (++m <= 0x3f) CHECK_MIN(m, 0, r, (m+1)*7);
96      m = (n/6) - 1;
97      a = n - (m+1)*6;
98      if (m <= 0x3f && a > 0 && a<=7) CHECK_MIN(m, a, r, (m+1)*6+a);
99      m++;
100      a = n - (m+1)*6;
101      if (m <= 0x3f && a > 0 && a<=7) CHECK_MIN(m, a, r, (m+1)*6+a);
102    }
103  }
104
105  if (best_a) n = (best_m+1)*6+best_a;
106  else n = (best_m+1)*7;
107
108#ifdef DEBUG
109  ErrorF("%8.3f %f %f  p=%d m=%d a=%d r=%d  %d/%d\n"
110	 ,f/1e3
111	 ,min_diff,(BASE_FREQ * (n)) / (best_r << p)
112	 ,p ,best_m, best_a, best_r-1
113	 ,n,best_r
114	 );
115#endif
116
117  Set_1562_PLL(f, p, best_m, best_a, best_r-1, bits);
118}
119