vmodes.c revision 0b661123
1bdcaa8d0Smrg/*
2bdcaa8d0Smrg * file vmodes.c
3bdcaa8d0Smrg *
4bdcaa8d0Smrg * Routines that handle mode setting.
5bdcaa8d0Smrg */
6bdcaa8d0Smrg
7bdcaa8d0Smrg#ifdef HAVE_CONFIG_H
8bdcaa8d0Smrg#include "config.h"
9bdcaa8d0Smrg#endif
10bdcaa8d0Smrg
11bdcaa8d0Smrg/*
12bdcaa8d0Smrg * includes
13bdcaa8d0Smrg */
14bdcaa8d0Smrg
15bdcaa8d0Smrg#include "rendition.h"
16bdcaa8d0Smrg#include "vmodes.h"
17bdcaa8d0Smrg#include "vos.h"
18bdcaa8d0Smrg#include "vramdac.h"
19bdcaa8d0Smrg#include "v1krisc.h"
20bdcaa8d0Smrg#include "v1kregs.h"
21bdcaa8d0Smrg#include "v2kregs.h"
22bdcaa8d0Smrg
23bdcaa8d0Smrg
24bdcaa8d0Smrg#undef DEBUG
25bdcaa8d0Smrg
26bdcaa8d0Smrg
27bdcaa8d0Smrg/*
28bdcaa8d0Smrg * defines
29bdcaa8d0Smrg */
30bdcaa8d0Smrg
31bdcaa8d0Smrg#define combineNMP(N, M, P) \
32bdcaa8d0Smrg    (((vu32)(M-2)<<10) | ((vu32)P<<8) | (vu32)(N-2))
33bdcaa8d0Smrg
34bdcaa8d0Smrg#define v2kcombineNMP(N, M, P) (((vu32)N<<13) | ((vu32)P<<9) | (vu32)M)
35bdcaa8d0Smrg
36bdcaa8d0Smrg/* defines for doubled clock */
37bdcaa8d0Smrg#define CLK_DOUBLE		1
38bdcaa8d0Smrg#define NO_CLK_DOUBLE	0
39bdcaa8d0Smrg
40bdcaa8d0Smrg/* video FIFO is set to 64 or 128 entries based on req.d bandwidth in bytes/s */
41bdcaa8d0Smrg#define FIFOSIZE_THRESH 	100000000 	 /* set thresh to 100MB/s */
42bdcaa8d0Smrg
43bdcaa8d0Smrg/* compute desired video FIFO size given total bandwidth in bytes/s. */
44bdcaa8d0Smrg#define FIFOSIZE(vclk, Bpp) (((vclk * Bpp) > FIFOSIZE_THRESH)  ? 128 : 64)
45bdcaa8d0Smrg
46bdcaa8d0Smrg/* Bt485A RAMDAC control bits */
47bdcaa8d0Smrg#define PALETTEDISABLE		0x10
48bdcaa8d0Smrg
49bdcaa8d0Smrg/* Hold memory refresh cycles until video blank */
50bdcaa8d0Smrg#define HOLD_MEMREFRESHCYCLE 0x2000
51bdcaa8d0Smrg
52bdcaa8d0Smrg/* memCtl bits [16..23] */
53bdcaa8d0Smrg#define DEFAULT_WREFRESH	0x330000
54bdcaa8d0Smrg
55bdcaa8d0Smrg/* Disable memory refresh cycles */
56bdcaa8d0Smrg#define DISABLE_MEMREFRESHCYCLE		0x8000
57bdcaa8d0Smrg
58bdcaa8d0Smrg#define CTL(ldbl, hsynchi, vsynchi) \
59bdcaa8d0Smrg  (((ldbl) ? CRTCCTL_LINEDOUBLE : 0) \
60bdcaa8d0Smrg  |((hsynchi) ? CRTCCTL_HSYNCHI : 0) \
61bdcaa8d0Smrg  |((vsynchi) ? CRTCCTL_VSYNCHI : 0) \
62bdcaa8d0Smrg  |(CRTCCTL_VSYNCENABLE | CRTCCTL_HSYNCENABLE))
63bdcaa8d0Smrg
64bdcaa8d0Smrg#define HORZ(fp, sy, bp, ac) \
65bdcaa8d0Smrg  (((((vu32)(((fp)>>3)-1))&7)<<21)|((((vu32)(((sy)>>3)-1))&0x1F)<<16)|((((vu32)(((bp)>>3)-1))&0x3f)<<9)|((((vu32)(((ac)>>3)-1))&0xff)))
66bdcaa8d0Smrg
67bdcaa8d0Smrg#define VERT(fp, sy, bp, ac) \
68bdcaa8d0Smrg  (((((vu32)(fp-1))&0x3f)<<20)|((((vu32)(sy-1))&0x7)<<17)|((((vu32)(bp-1))&0x3f)<<11)|((((vu32)(ac-1))&0x7ff)))
69bdcaa8d0Smrg
70bdcaa8d0Smrg#define HORZAC(crtchorz) \
71bdcaa8d0Smrg  (((((vu32)crtchorz)&CRTCHORZ_ACTIVE_MASK)+1)<<3)
72bdcaa8d0Smrg
73bdcaa8d0Smrg#define HORZBP(crtchorz) \
74bdcaa8d0Smrg  ((((((vu32)crtchorz)&CRTCHORZ_BACKPORCH_MASK)>>9)+1)<<3)
75bdcaa8d0Smrg
76bdcaa8d0Smrg#define HORZSY(crtchorz) \
77bdcaa8d0Smrg  ((((((vu32)crtchorz)&CRTCHORZ_SYNC_MASK)>>16)+1)<<3)
78bdcaa8d0Smrg
79bdcaa8d0Smrg#define HORZFP(crtchorz) \
80bdcaa8d0Smrg  ((((((vu32)crtchorz)&CRTCHORZ_FRONTPORCH_MASK)>>21)+1)<<3)
81bdcaa8d0Smrg
82bdcaa8d0Smrg#define VERTAC(crtcvert) \
83bdcaa8d0Smrg  ((((vu32)crtcvert)&CRTCVERT_ACTIVE_MASK)+1)
84bdcaa8d0Smrg
85bdcaa8d0Smrg#define VERTBP(crtcvert) \
86bdcaa8d0Smrg  (((((vu32)crtcvert)&CRTCVERT_BACKPORCH_MASK)>>11)+1)
87bdcaa8d0Smrg
88bdcaa8d0Smrg#define VERTSY(crtcvert) \
89bdcaa8d0Smrg  (((((vu32)crtcvert)&CRTCVERT_SYNC_MASK)>>17)+1)
90bdcaa8d0Smrg
91bdcaa8d0Smrg#define VERTFP(crtcvert) \
92bdcaa8d0Smrg  (((((vu32)crtcvert)&CRTCVERT_FRONTPORCH_MASK)>>20)+1)
93bdcaa8d0Smrg
94bdcaa8d0Smrg#define PCLK(N, M, P) (N),(M),(P)
95bdcaa8d0Smrg
96bdcaa8d0Smrg#define TIMING_MASK	(CRTCCTL_VIDEOFIFOSIZE128|CRTCCTL_LINEDOUBLE|\
97bdcaa8d0Smrg			         CRTCCTL_VSYNCHI|CRTCCTL_HSYNCHI|CRTCCTL_VSYNCENABLE|\
98bdcaa8d0Smrg                     CRTCCTL_HSYNCENABLE)
99bdcaa8d0Smrg
100bdcaa8d0Smrg/* addr&7 == 5, 6, 7 are bad */
101bdcaa8d0Smrg#define BADADDR(x)	(((x)&(((x)<<1)|((x)<<2)))&0x4)
102bdcaa8d0Smrg
103bdcaa8d0Smrg#define V1_MIN_VCO_FREQ  25
104bdcaa8d0Smrg#define V1_MAX_VCO_FREQ  135
105bdcaa8d0Smrg#define V1_REF_FREQ      14.318
106bdcaa8d0Smrg#define V1_MIN_PCF_FREQ  0.2
107bdcaa8d0Smrg#define V1_MAX_PCF_FREQ  5
108bdcaa8d0Smrg
109bdcaa8d0Smrg#define V2_MIN_VCO_FREQ  125
110bdcaa8d0Smrg#define V2_MAX_VCO_FREQ  250
111bdcaa8d0Smrg#define V2_REF_FREQ      14.31818 /* Eh, is this right? */
112bdcaa8d0Smrg#define V2_MIN_PCF_FREQ  1
113bdcaa8d0Smrg#define V2_MAX_PCF_FREQ  3
114bdcaa8d0Smrg
115bdcaa8d0Smrg
116bdcaa8d0Smrg
117bdcaa8d0Smrg/*
118bdcaa8d0Smrg * global data
119bdcaa8d0Smrg */
120bdcaa8d0Smrg
121bdcaa8d0Smrgstatic struct width_to_stride_t {
122bdcaa8d0Smrg    vu32 width8bpp;
123bdcaa8d0Smrg    vu8 stride0;
124bdcaa8d0Smrg    vu8 stride1;
125bdcaa8d0Smrg    vu16 chip;
126bdcaa8d0Smrg} width_to_stride_table[]={
127bdcaa8d0Smrg/*  {    0, 0, 0, V1000_DEVICE }, */
128bdcaa8d0Smrg    {    4, 4, 0, V1000_DEVICE },
129bdcaa8d0Smrg    {   16, 0, 1, V1000_DEVICE },
130bdcaa8d0Smrg    {   20, 4, 1, V1000_DEVICE },
131bdcaa8d0Smrg    {   32, 0, 2, V1000_DEVICE },
132bdcaa8d0Smrg    {   36, 4, 2, V1000_DEVICE },
133bdcaa8d0Smrg    {   64, 0, 3, V1000_DEVICE },
134bdcaa8d0Smrg    {   68, 4, 3, V1000_DEVICE },
135bdcaa8d0Smrg    {  128, 0, 4, V1000_DEVICE },
136bdcaa8d0Smrg    {  132, 4, 4, V1000_DEVICE },
137bdcaa8d0Smrg    {  256, 1, 0, V1000_DEVICE },
138bdcaa8d0Smrg    {  272, 1, 1, V1000_DEVICE },
139bdcaa8d0Smrg    {  288, 1, 2, V1000_DEVICE },
140bdcaa8d0Smrg    {  320, 1, 3, V1000_DEVICE },
141bdcaa8d0Smrg    {  384, 1, 4, V1000_DEVICE },
142bdcaa8d0Smrg    {  512, 2, 0, V1000_DEVICE },
143bdcaa8d0Smrg    {  528, 2, 1, V1000_DEVICE },
144bdcaa8d0Smrg    {  544, 2, 2, V1000_DEVICE },
145bdcaa8d0Smrg    {  576, 2, 3, V1000_DEVICE },
146bdcaa8d0Smrg    {  592, 6, 1, V2000_DEVICE },
147bdcaa8d0Smrg    {  608, 6, 2, V2000_DEVICE },
148bdcaa8d0Smrg    {  640, 2, 4, V1000_DEVICE },
149bdcaa8d0Smrg    {  704, 6, 4, V2000_DEVICE },
150bdcaa8d0Smrg    {  768, 5, 0, V2000_DEVICE },
151bdcaa8d0Smrg    {  784, 5, 1, V2000_DEVICE },
152bdcaa8d0Smrg    {  800, 5, 2, V2000_DEVICE },
153bdcaa8d0Smrg    {  832, 5, 3, V2000_DEVICE },
154bdcaa8d0Smrg    {  896, 5, 4, V2000_DEVICE },
155bdcaa8d0Smrg    { 1024, 3, 0, V1000_DEVICE },
156bdcaa8d0Smrg    { 1028, 4, 5, V1000_DEVICE },
157bdcaa8d0Smrg    { 1040, 3, 1, V1000_DEVICE },
158bdcaa8d0Smrg    { 1056, 3, 2, V1000_DEVICE },
159bdcaa8d0Smrg    { 1088, 3, 3, V1000_DEVICE },
160bdcaa8d0Smrg    { 1152, 3, 4, V1000_DEVICE },
161bdcaa8d0Smrg    { 1168, 7, 1, V2000_DEVICE },
162bdcaa8d0Smrg    { 1184, 7, 2, V2000_DEVICE },
163bdcaa8d0Smrg    { 1216, 7, 3, V2000_DEVICE },
164bdcaa8d0Smrg    { 1280, 1, 5, V1000_DEVICE },
165bdcaa8d0Smrg    { 1536, 2, 5, V1000_DEVICE },
166bdcaa8d0Smrg    { 1600, 6, 5, V2000_DEVICE },
167bdcaa8d0Smrg    { 1792, 5, 5, V2000_DEVICE },
168bdcaa8d0Smrg    { 2048, 0, 6, V1000_DEVICE },
169bdcaa8d0Smrg    { 2052, 4, 6, V1000_DEVICE },
170bdcaa8d0Smrg    { 2176, 7, 5, V2000_DEVICE },
171bdcaa8d0Smrg    { 2304, 1, 6, V1000_DEVICE },
172bdcaa8d0Smrg    { 2560, 2, 6, V1000_DEVICE },
173bdcaa8d0Smrg    { 2624, 6, 6, V2000_DEVICE },
174bdcaa8d0Smrg    { 2816, 5, 6, V2000_DEVICE },
175bdcaa8d0Smrg    { 3072, 3, 6, V1000_DEVICE },
176bdcaa8d0Smrg    { 3200, 7, 6, V2000_DEVICE },
177bdcaa8d0Smrg    { 4096, 0, 7, V1000_DEVICE },
178bdcaa8d0Smrg    { 4100, 4, 7, V1000_DEVICE },
179bdcaa8d0Smrg    { 4352, 1, 7, V1000_DEVICE },
180bdcaa8d0Smrg    { 4608, 2, 7, V1000_DEVICE },
181bdcaa8d0Smrg    { 4672, 6, 7, V2000_DEVICE },
182bdcaa8d0Smrg    { 4864, 5, 7, V2000_DEVICE },
183bdcaa8d0Smrg    { 5120, 3, 7, V1000_DEVICE },
184bdcaa8d0Smrg    { 5248, 7, 7, V2000_DEVICE },
185bdcaa8d0Smrg    {    0, 0, 0, 0 }
186bdcaa8d0Smrg};
187bdcaa8d0Smrg
188bdcaa8d0Smrgstruct V1000ClocksStr {
189bdcaa8d0Smrg    int h_size;
190bdcaa8d0Smrg    int pll_val;
191bdcaa8d0Smrg} V1000Clocks [] = {
192bdcaa8d0Smrg    { 72, 0x40000 }, /* For Textmode */
193bdcaa8d0Smrg    { 640, 0x2408 },   /*  31500  MHz */
194bdcaa8d0Smrg    { 800, 0x1583D },  /*  40000  MHz */
195bdcaa8d0Smrg    { 1024, 0x14823 }, /*  65000  MHz */
196bdcaa8d0Smrg    { 1280, 0x14414 }, /*  108000 MHz */
197bdcaa8d0Smrg    { 0, 0 }
198bdcaa8d0Smrg};
199bdcaa8d0Smrg
200bdcaa8d0Smrg/*
201bdcaa8d0Smrg * local function prototypes
202bdcaa8d0Smrg */
203bdcaa8d0Smrg
204bdcaa8d0Smrgstatic void set_PLL(IOADDRESS iob, vu32 value);
205bdcaa8d0Smrgstatic double V1000CalcClock(double target, int *M, int *N, int *P);
206bdcaa8d0Smrgstatic double V2200CalcClock(double target, int *m, int *n, int *p);
207bdcaa8d0Smrg
208bdcaa8d0Smrg
209bdcaa8d0Smrg
210bdcaa8d0Smrg/*
211bdcaa8d0Smrg * functions
212bdcaa8d0Smrg */
213bdcaa8d0Smrg
214bdcaa8d0Smrgint
215bdcaa8d0Smrgverite_setmode(ScrnInfoPtr pScreenInfo, struct verite_modeinfo_t *mode)
216bdcaa8d0Smrg{
217bdcaa8d0Smrg    renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
218bdcaa8d0Smrg
219bdcaa8d0Smrg    int tmp;
220bdcaa8d0Smrg    int doubleclock=0;
221bdcaa8d0Smrg    int M, N, P;
222bdcaa8d0Smrg    int iob=pRendition->board.io_base;
223bdcaa8d0Smrg
224bdcaa8d0Smrg#ifdef DEBUG
225bdcaa8d0Smrg    ErrorF ("Rendition: Debug verite_setmode called\n");
226bdcaa8d0Smrg#endif
227bdcaa8d0Smrg
228bdcaa8d0Smrg    /* switching to native mode */
229bdcaa8d0Smrg    verite_out8(iob+MODEREG, NATIVE_MODE|VESA_MODE);
230bdcaa8d0Smrg
231bdcaa8d0Smrg    /* flipping some bytes */
232bdcaa8d0Smrg    /* Must be something better to do than this -- FIX */
233bdcaa8d0Smrg    switch (mode->bitsperpixel) {
234bdcaa8d0Smrg    case 32:
235bdcaa8d0Smrg      verite_out8(iob+MEMENDIAN, MEMENDIAN_NO);
236bdcaa8d0Smrg      break;
237bdcaa8d0Smrg    case 16:
238bdcaa8d0Smrg      verite_out8(iob+MEMENDIAN, MEMENDIAN_HW);
239bdcaa8d0Smrg      break;
240bdcaa8d0Smrg    case 8:
241bdcaa8d0Smrg      verite_out8(iob+MEMENDIAN, MEMENDIAN_END);
242bdcaa8d0Smrg      break;
243bdcaa8d0Smrg    }
244bdcaa8d0Smrg
245bdcaa8d0Smrg    if (pRendition->board.chip != V1000_DEVICE) {
246bdcaa8d0Smrg      if(!pRendition->board.overclock_mem){
247bdcaa8d0Smrg	verite_out32(iob+SCLKPLL, 0xa484d);  /* mclk=110 sclk=50 */
248bdcaa8d0Smrg                                        /* M/N/P/P = 77/5/2/4 */
249bdcaa8d0Smrg      }
250bdcaa8d0Smrg      else{
251bdcaa8d0Smrg	xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
252bdcaa8d0Smrg		   (" *** OVERCLOCKING MEM/CLK mclk=125 sclk=60 ***\n"));
253bdcaa8d0Smrg	/* increase Mem/Sys clock on request */
254bdcaa8d0Smrg	verite_out32(iob+SCLKPLL, 0xa4854);  /* mclk=125 sclk=60 */
255bdcaa8d0Smrg                                        /* M/N/P/P = 84/5/2/4 */
256bdcaa8d0Smrg      }
257bdcaa8d0Smrg      usleep(500);
258bdcaa8d0Smrg    }
259bdcaa8d0Smrg
260bdcaa8d0Smrg    /* this has something to do with memory */
261bdcaa8d0Smrg    tmp=verite_in32(iob+DRAMCTL)&0xdfff;              /* reset bit 13 */
262bdcaa8d0Smrg    verite_out32(iob+DRAMCTL, tmp|0x330000);
263bdcaa8d0Smrg
264bdcaa8d0Smrg    /* program pixel clock */
265bdcaa8d0Smrg    if (pRendition->board.chip == V1000_DEVICE) {
266bdcaa8d0Smrg        if (110.0 < V1000CalcClock(mode->clock/1000.0, &M, &N, &P)) {
267bdcaa8d0Smrg            P++;
268bdcaa8d0Smrg            doubleclock=1;
269bdcaa8d0Smrg        }
270bdcaa8d0Smrg        set_PLL(iob, combineNMP(N, M, P));
271bdcaa8d0Smrg    }
272bdcaa8d0Smrg    else {
273bdcaa8d0Smrg	tmp = (~0x1800) & verite_in32(iob+DRAMCTL);
274bdcaa8d0Smrg        verite_out32(iob+DRAMCTL, tmp);
275bdcaa8d0Smrg        V2200CalcClock(mode->clock/1000.0, &M, &N, &P);
276bdcaa8d0Smrg        verite_out32(iob+PCLKPLL, v2kcombineNMP(N, M, P));
277bdcaa8d0Smrg    }
278bdcaa8d0Smrg    usleep(500);
279bdcaa8d0Smrg
280bdcaa8d0Smrg    /* init the ramdac */
281bdcaa8d0Smrg    verite_initdac(pScreenInfo, mode->bitsperpixel, doubleclock);
282bdcaa8d0Smrg
283bdcaa8d0Smrg    verite_out32(iob+CRTCHORZ, HORZ(mode->hsyncstart - mode->hdisplay,
284bdcaa8d0Smrg                               mode->hsyncend - mode->hsyncstart,
285bdcaa8d0Smrg                               mode->htotal - mode->hsyncend,
286bdcaa8d0Smrg                               mode->hdisplay));
287bdcaa8d0Smrg    verite_out32(iob+CRTCVERT, VERT(mode->vsyncstart-mode->vdisplay,
288bdcaa8d0Smrg                               mode->vsyncend-mode->vsyncstart,
289bdcaa8d0Smrg                               mode->vtotal-mode->vsyncend,
290bdcaa8d0Smrg                               mode->vdisplay));
291bdcaa8d0Smrg
292bdcaa8d0Smrg    /* fill in the mode parameters */
293bdcaa8d0Smrg    memcpy(&(pRendition->board.mode), mode, sizeof(struct verite_modeinfo_t));
294bdcaa8d0Smrg    pRendition->board.mode.fifosize=128;
295bdcaa8d0Smrg    pRendition->board.mode.pll_m=M;
296bdcaa8d0Smrg    pRendition->board.mode.pll_n=N;
297bdcaa8d0Smrg    pRendition->board.mode.pll_p=P;
298bdcaa8d0Smrg    pRendition->board.mode.doubleclock=doubleclock;
299bdcaa8d0Smrg    if (0 == pRendition->board.mode.virtualwidth)
300bdcaa8d0Smrg        pRendition->board.mode.virtualwidth=pRendition->board.mode.screenwidth;
301bdcaa8d0Smrg
302bdcaa8d0Smrg    pRendition->board.init=1;
303bdcaa8d0Smrg    (*pScreenInfo->AdjustFrame)(pScreenInfo->scrnIndex,
304bdcaa8d0Smrg        pScreenInfo->frameX0, pScreenInfo->frameY0, 0);
305bdcaa8d0Smrg
306bdcaa8d0Smrg    /* Need to fix up syncs */
307bdcaa8d0Smrg
308bdcaa8d0Smrg    /* enable the display */
309bdcaa8d0Smrg    verite_out32(iob+CRTCCTL, CTL(0, mode->hsynchi, mode->vsynchi)
310bdcaa8d0Smrg                        |mode->pixelformat
311bdcaa8d0Smrg                        |CRTCCTL_VIDEOFIFOSIZE128
312bdcaa8d0Smrg                        |CRTCCTL_HSYNCENABLE
313bdcaa8d0Smrg                        |CRTCCTL_VSYNCENABLE
314bdcaa8d0Smrg                        |CRTCCTL_VIDEOENABLE);
315bdcaa8d0Smrg
316bdcaa8d0Smrg#ifdef DEBUG
317bdcaa8d0Smrg    ErrorF ("Interlace mode -> %d\n", mode->flags);
318bdcaa8d0Smrg    xf86sleep(10);ErrorF ("...Exit SetMode...\n");
319bdcaa8d0Smrg#endif
320bdcaa8d0Smrg
321bdcaa8d0Smrg   return 0;
322bdcaa8d0Smrg}
323bdcaa8d0Smrg
324bdcaa8d0Smrgstatic double
325bdcaa8d0Smrgverite_findtextclock(int width)
326bdcaa8d0Smrg{
327bdcaa8d0Smrg    int i = 0, val;
328bdcaa8d0Smrg    while ((val = V1000Clocks[i].h_size) > 0) {
329bdcaa8d0Smrg	if (val > width)
330bdcaa8d0Smrg	    break;
331bdcaa8d0Smrg	else
332bdcaa8d0Smrg	    i++;
333bdcaa8d0Smrg    }
334bdcaa8d0Smrg    if (i > 0) i--;
335bdcaa8d0Smrg    return V1000Clocks[i].pll_val;
336bdcaa8d0Smrg}
337bdcaa8d0Smrg
338bdcaa8d0Smrgvoid
339bdcaa8d0Smrgverite_save(ScrnInfoPtr pScreenInfo)
340bdcaa8d0Smrg{
341bdcaa8d0Smrg    renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
342bdcaa8d0Smrg    int iob=pRendition->board.io_base;
343bdcaa8d0Smrg    RenditionRegPtr reg = &pRendition->saveRegs;
344bdcaa8d0Smrg
345bdcaa8d0Smrg    reg->memendian = verite_in8(iob+MEMENDIAN);
346bdcaa8d0Smrg    reg->mode = verite_in8(iob+MODEREG);
347bdcaa8d0Smrg    reg->sclkpll = verite_in32(iob+SCLKPLL);
348bdcaa8d0Smrg    reg->dramctl = verite_in32(iob+DRAMCTL);
349bdcaa8d0Smrg    reg->crtch = verite_in32(iob+CRTCHORZ);
350bdcaa8d0Smrg    reg->crtcv = verite_in32(iob+CRTCVERT);
351bdcaa8d0Smrg    /* clock */
352bdcaa8d0Smrg    if (V1000_DEVICE ==pRendition->board.chip) {
353bdcaa8d0Smrg	int width;
354bdcaa8d0Smrg	/*
355bdcaa8d0Smrg	 * I have no idea how to read back the clock from
356bdcaa8d0Smrg	 * V1000. Therefore we pick a VESA Mode clock from
357bdcaa8d0Smrg	 * a list for the width found.
358bdcaa8d0Smrg	 */
359bdcaa8d0Smrg	width = ((reg->crtch & 0xff) + 1) << 3;
360bdcaa8d0Smrg        reg->pclkpll = verite_findtextclock(width);
361bdcaa8d0Smrg	reg->plldev= verite_in8(iob+PLLDEV);
362bdcaa8d0Smrg    } else {
363bdcaa8d0Smrg	reg->pclkpll = verite_in32(iob+PCLKPLL);
364bdcaa8d0Smrg    }
365bdcaa8d0Smrg    /* initdac */
366bdcaa8d0Smrg    verite_out8(iob+MODEREG,NATIVE_MODE);
367bdcaa8d0Smrg    verite_savedac(pScreenInfo);
368bdcaa8d0Smrg    verite_out8(iob+MODEREG,reg->mode);
369bdcaa8d0Smrg
370bdcaa8d0Smrg    reg->vbasea = verite_in32(iob+FRAMEBASEA);
371bdcaa8d0Smrg    reg->crtcoff = verite_in32(iob+CRTCOFFSET);
372bdcaa8d0Smrg    reg->crtcctl = verite_in32(iob+CRTCCTL);
373bdcaa8d0Smrg}
374bdcaa8d0Smrg
375bdcaa8d0Smrgvoid
376bdcaa8d0Smrgverite_restore(ScrnInfoPtr pScreenInfo, RenditionRegPtr reg)
377bdcaa8d0Smrg{
378bdcaa8d0Smrg    renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
379bdcaa8d0Smrg    int iob=pRendition->board.io_base;
380bdcaa8d0Smrg
381bdcaa8d0Smrg    verite_restoredac (pScreenInfo, reg);
382bdcaa8d0Smrg    /*
383bdcaa8d0Smrg     * If this is a Verite 1000, restore the MODEREG
384bdcaa8d0Smrg     * register now.  The MODEREG gets restored later
385bdcaa8d0Smrg     * for the Verite 2x00 because restoring it here
386bdcaa8d0Smrg     * has been confirmed to cause intermittent
387bdcaa8d0Smrg     * system locks.
388bdcaa8d0Smrg     */
389bdcaa8d0Smrg    if (pRendition->board.chip == V1000_DEVICE) {
390bdcaa8d0Smrg	verite_out32(iob+MODEREG,reg->mode);
391bdcaa8d0Smrg    }
392bdcaa8d0Smrg    verite_out8(iob+MEMENDIAN,reg->memendian);
393bdcaa8d0Smrg    verite_out32(iob+DRAMCTL,reg->dramctl);
394bdcaa8d0Smrg    verite_out32(iob+SCLKPLL,reg->sclkpll);
395bdcaa8d0Smrg    if (pRendition->board.chip == V1000_DEVICE) {
396bdcaa8d0Smrg	/* fixme */
397bdcaa8d0Smrg        set_PLL(iob, reg->pclkpll);
3980b661123Smrg	usleep(10000);
399bdcaa8d0Smrg    } else {
400bdcaa8d0Smrg	verite_out32(iob+PCLKPLL,reg->pclkpll);
401bdcaa8d0Smrg	/*
402bdcaa8d0Smrg	 * Need to wait 200uS for PLL to stabilize --
403bdcaa8d0Smrg	 * let's play it safe with 500
404bdcaa8d0Smrg	 */
4050b661123Smrg	usleep(10000);
406bdcaa8d0Smrg	/* wait until VBLANK */
407bdcaa8d0Smrg	while ((verite_in32(iob+CRTCSTATUS)&CRTCSTATUS_VERT_MASK) !=
408bdcaa8d0Smrg	       CRTCSTATUS_VERT_ACTIVE);
409bdcaa8d0Smrg	while ((verite_in32(iob+CRTCSTATUS)&CRTCSTATUS_VERT_MASK) ==
410bdcaa8d0Smrg	       CRTCSTATUS_VERT_ACTIVE);
411bdcaa8d0Smrg    }
412bdcaa8d0Smrg
413bdcaa8d0Smrg    /*
414bdcaa8d0Smrg     * If this is a Verite 2x00, restore the MODEREG
415bdcaa8d0Smrg     * register now.  The MODEREG register is restored
416bdcaa8d0Smrg     * earlier for the Verite 1000, but is restored
417bdcaa8d0Smrg     * here for the Verite 2x00 to prevent system
418bdcaa8d0Smrg     * locks.
419bdcaa8d0Smrg     */
420bdcaa8d0Smrg    if (pRendition->board.chip != V1000_DEVICE) {
421bdcaa8d0Smrg	verite_out32(iob+MODEREG,reg->mode);
422bdcaa8d0Smrg    }
423bdcaa8d0Smrg
424bdcaa8d0Smrg    verite_out32(iob+CRTCHORZ,reg->crtch);
425bdcaa8d0Smrg    verite_out32(iob+CRTCVERT,reg->crtcv);
426bdcaa8d0Smrg    verite_out32(iob+FRAMEBASEA, reg->vbasea);
427bdcaa8d0Smrg    verite_out32(iob+CRTCOFFSET,reg->crtcoff);
428bdcaa8d0Smrg    verite_out32(iob+CRTCCTL,reg->crtcctl);
429bdcaa8d0Smrg}
430bdcaa8d0Smrg
431bdcaa8d0Smrgvoid
432bdcaa8d0Smrgverite_setframebase(ScrnInfoPtr pScreenInfo, vu32 framebase)
433bdcaa8d0Smrg{
434bdcaa8d0Smrg    renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
435bdcaa8d0Smrg
436bdcaa8d0Smrg    vu32 offset;
437bdcaa8d0Smrg
438bdcaa8d0Smrg    int iob=pRendition->board.io_base;
439bdcaa8d0Smrg    int swidth=pRendition->board.mode.screenwidth;
440bdcaa8d0Smrg    int vwidth=  pRendition->board.mode.virtualwidth;
441bdcaa8d0Smrg    int bytespp=pRendition->board.mode.bitsperpixel>>3;
442bdcaa8d0Smrg    int fifo_size=pRendition->board.mode.fifosize;
443bdcaa8d0Smrg
444bdcaa8d0Smrg#ifdef DEBUG
445bdcaa8d0Smrg    ErrorF( "Rendition: Debug verite_setframebase w=%d v=%d b=%d f=%d\n",
446bdcaa8d0Smrg        swidth, vwidth, bytespp, fifo_size);
447bdcaa8d0Smrg#endif
448bdcaa8d0Smrg
449bdcaa8d0Smrg    /* CRTCOFFSET */
450bdcaa8d0Smrg    offset=vwidth*bytespp               /* virtual width in bytes */
451bdcaa8d0Smrg          -swidth*bytespp               /* screen width in bytes */
452bdcaa8d0Smrg          +((swidth*bytespp)%fifo_size) /* width in bytes modulo fifo size */
453bdcaa8d0Smrg        ;
454bdcaa8d0Smrg
455bdcaa8d0Smrg    if (!(   framebase&7            /* framebase multiple of 8? */
456bdcaa8d0Smrg          || (swidth*bytespp)%128)) /* screenwidth multiple of fifo size */
457bdcaa8d0Smrg      offset+=fifo_size;            /* increment offset by fifosize */
458bdcaa8d0Smrg
459bdcaa8d0Smrg    /* wait for vertical retrace */
460bdcaa8d0Smrg#ifndef DEBUG
461bdcaa8d0Smrg    if (!pRendition->board.init) {
462bdcaa8d0Smrg        while ((verite_in32(iob+CRTCSTATUS) & CRTCSTATUS_VERT_MASK) !=
463bdcaa8d0Smrg               CRTCSTATUS_VERT_ACTIVE) ;
464bdcaa8d0Smrg        while ((verite_in32(iob+CRTCSTATUS) & CRTCSTATUS_VERT_MASK) ==
465bdcaa8d0Smrg               CRTCSTATUS_VERT_ACTIVE) ;
466bdcaa8d0Smrg    }
467bdcaa8d0Smrg    else
468bdcaa8d0Smrg        pRendition->board.init=0;
469bdcaa8d0Smrg#endif
470bdcaa8d0Smrg
471bdcaa8d0Smrg    /* framebase */
472bdcaa8d0Smrg    verite_out32(iob+FRAMEBASEA, framebase);
473bdcaa8d0Smrg
474bdcaa8d0Smrg    /* crtc offset */
475bdcaa8d0Smrg    verite_out32(iob+CRTCOFFSET, offset&0xffff);
476bdcaa8d0Smrg}
477bdcaa8d0Smrg
478bdcaa8d0Smrgint
479bdcaa8d0Smrgverite_getstride(ScrnInfoPtr pScreenInfo, int *width,
480bdcaa8d0Smrg		 vu16 *stride0, vu16 *stride1)
481bdcaa8d0Smrg{
482bdcaa8d0Smrg    renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
483bdcaa8d0Smrg    int bytesperline;
484bdcaa8d0Smrg    int c = 0;
485bdcaa8d0Smrg
486bdcaa8d0Smrg    bytesperline
487bdcaa8d0Smrg	= pRendition->board.mode.virtualwidth
488bdcaa8d0Smrg	* (pRendition->board.mode.bitsperpixel >> 3);
489bdcaa8d0Smrg#ifdef DEBUG
490bdcaa8d0Smrg    ErrorF("RENDITION: %d bytes per line\n", bytesperline);
491bdcaa8d0Smrg#endif
492bdcaa8d0Smrg
493bdcaa8d0Smrg    /* for now, I implemented a linear search only, should be fixed <ml> */
494bdcaa8d0Smrg    while (0 != width_to_stride_table[c].width8bpp) {
495bdcaa8d0Smrg	if (width_to_stride_table[c].width8bpp == bytesperline
496bdcaa8d0Smrg	    && ((width_to_stride_table[c].chip == pRendition->board.chip)
497bdcaa8d0Smrg		|| (V2000_DEVICE == pRendition->board.chip))) {
498bdcaa8d0Smrg            *stride0 = width_to_stride_table[c].stride0;
499bdcaa8d0Smrg            *stride1 = width_to_stride_table[c].stride1;
500bdcaa8d0Smrg            return 1;
501bdcaa8d0Smrg        }
502bdcaa8d0Smrg        c++;
503bdcaa8d0Smrg    }
504bdcaa8d0Smrg    return 0;
505bdcaa8d0Smrg}
506bdcaa8d0Smrg
507bdcaa8d0Smrg/*
508bdcaa8d0Smrg * local functions
509bdcaa8d0Smrg */
510bdcaa8d0Smrg
511bdcaa8d0Smrg/*
512bdcaa8d0Smrg * void set_PLL(IOADDRESS iob, vu32 value)
513bdcaa8d0Smrg *
514bdcaa8d0Smrg * Set PLL clock to desired frequency for the V1000.
515bdcaa8d0Smrg */
516bdcaa8d0Smrg
517bdcaa8d0Smrgvoid
518bdcaa8d0Smrgset_PLL(IOADDRESS iob, vu32 value)
519bdcaa8d0Smrg{
520bdcaa8d0Smrg    vu32 ulD;
521bdcaa8d0Smrg    int b;
522bdcaa8d0Smrg
523bdcaa8d0Smrg    /* shift out the 20 serial bits */
524bdcaa8d0Smrg    for (b=19; b>=0; b--) {
525bdcaa8d0Smrg        ulD=(value>>b)&1;
526bdcaa8d0Smrg        verite_out8(iob+PLLDEV, (vu8)ulD);
527bdcaa8d0Smrg    }
528bdcaa8d0Smrg
529bdcaa8d0Smrg    /* read PLL device so the latch is filled with the previously
530bdcaa8d0Smrg     * written value */
531bdcaa8d0Smrg    (void)verite_in8(iob+PLLDEV);
532bdcaa8d0Smrg}
533bdcaa8d0Smrg
534bdcaa8d0Smrg
535bdcaa8d0Smrg
536bdcaa8d0Smrg/* Vxx00CalcClock -- finds PLL parameters to match target
537bdcaa8d0Smrg *                   frequency (in megahertz)
538bdcaa8d0Smrg *
539bdcaa8d0Smrg *                   Brute force, but takes less than a tenth
540bdcaa8d0Smrg *                   of a second and the function is only called
541bdcaa8d0Smrg *                   O(1) times during program execution.
542bdcaa8d0Smrg */
543bdcaa8d0Smrgstatic double
544bdcaa8d0SmrgV1000CalcClock(double target, int *M, int *N, int *P)
545bdcaa8d0Smrg{
546bdcaa8d0Smrg    double mindiff = 1e10;
547bdcaa8d0Smrg    double vco, pcf, diff, freq;
548bdcaa8d0Smrg    int mm, nn, pp;
549bdcaa8d0Smrg
550bdcaa8d0Smrg    for (pp=0; pp<4; pp++)
551bdcaa8d0Smrg        for (nn=1; nn<=129; nn++)
552bdcaa8d0Smrg            for (mm=1; mm<=129; mm++) {
553bdcaa8d0Smrg                vco=V1_REF_FREQ*2.0*mm/nn;
554bdcaa8d0Smrg                if ((vco<V1_MIN_VCO_FREQ) || (vco>V1_MAX_VCO_FREQ))
555bdcaa8d0Smrg                    continue;
556bdcaa8d0Smrg            	pcf = V1_REF_FREQ/nn;
557bdcaa8d0Smrg            	if ((pcf<V1_MIN_PCF_FREQ) || (pcf>V1_MAX_PCF_FREQ))
558bdcaa8d0Smrg                    continue;
559bdcaa8d0Smrg            	freq=vco/(1<<pp);
560bdcaa8d0Smrg            	diff=fabs(target-freq);
561bdcaa8d0Smrg            	if (diff < mindiff) {
562bdcaa8d0Smrg                    *M=mm;
563bdcaa8d0Smrg                    *N=nn;
564bdcaa8d0Smrg                    *P=pp;
565bdcaa8d0Smrg                    mindiff=diff;
566bdcaa8d0Smrg                }
567bdcaa8d0Smrg            }
568bdcaa8d0Smrg
569bdcaa8d0Smrg    vco=V1_REF_FREQ*2*(*M)/(*N);
570bdcaa8d0Smrg    pcf=V1_REF_FREQ/(*N);
571bdcaa8d0Smrg    freq=vco/(1<<(*P));
572bdcaa8d0Smrg
573bdcaa8d0Smrg#ifdef DEBUG
574bdcaa8d0Smrg    ErrorF(
575bdcaa8d0Smrg        "RENDITION: target=%f freq=%f vco=%f pcf=%f n=%d m=%d p=%d\n",
576bdcaa8d0Smrg        target, freq, vco, pcf, *N, *M, *P);
577bdcaa8d0Smrg#endif
578bdcaa8d0Smrg
579bdcaa8d0Smrg    return freq;
580bdcaa8d0Smrg}
581bdcaa8d0Smrg
582bdcaa8d0Smrg
583bdcaa8d0Smrg
584bdcaa8d0Smrgstatic double
585bdcaa8d0SmrgV2200CalcClock(double target, int *m, int *n, int *p)
586bdcaa8d0Smrg{
587bdcaa8d0Smrg    double mindiff = 1e10;
588bdcaa8d0Smrg    double vco, pcf, diff, freq;
589bdcaa8d0Smrg    int mm, nn, pp;
590bdcaa8d0Smrg
591bdcaa8d0Smrg    for (pp=1; pp<=0x0f; pp++)
592bdcaa8d0Smrg        for (nn=1; nn<=0x3f; nn++)
593bdcaa8d0Smrg            for (mm=1; mm<=0xff; mm++) {
594bdcaa8d0Smrg                vco = V2_REF_FREQ*mm/nn;
595bdcaa8d0Smrg                if ((vco < V2_MIN_VCO_FREQ) || (vco > V2_MAX_VCO_FREQ))
596bdcaa8d0Smrg                    continue;
597bdcaa8d0Smrg            	pcf = V2_REF_FREQ*mm/nn;
598bdcaa8d0Smrg                if ((vco < V2_MIN_VCO_FREQ) || (vco > V2_MAX_VCO_FREQ))
599bdcaa8d0Smrg                    continue;
600bdcaa8d0Smrg            	pcf = V2_REF_FREQ/nn;
601bdcaa8d0Smrg            	if ((pcf < V2_MIN_PCF_FREQ) || (pcf > V2_MAX_PCF_FREQ))
602bdcaa8d0Smrg                    continue;
603bdcaa8d0Smrg            	freq = vco/pp;
604bdcaa8d0Smrg            	diff = fabs(target-freq);
605bdcaa8d0Smrg            	if (diff < mindiff) {
606bdcaa8d0Smrg                    *m = mm; *n = nn; *p = pp;
607bdcaa8d0Smrg                    mindiff = diff;
608bdcaa8d0Smrg                }
609bdcaa8d0Smrg            }
610bdcaa8d0Smrg
611bdcaa8d0Smrg    vco = V2_REF_FREQ * *m / *n;
612bdcaa8d0Smrg    pcf = V2_REF_FREQ / *n;
613bdcaa8d0Smrg    freq = vco / *p;
614bdcaa8d0Smrg
615bdcaa8d0Smrg#ifdef DEBUG
616bdcaa8d0Smrg    ErrorF(
617bdcaa8d0Smrg        "RENDITION: target=%f freq=%f vco=%f pcf=%f n=%d m=%d p=%d\n",
618bdcaa8d0Smrg        target, freq, vco, pcf, *n, *m, *p);
619bdcaa8d0Smrg#endif
620bdcaa8d0Smrg
621bdcaa8d0Smrg    return freq;
622bdcaa8d0Smrg}
623bdcaa8d0Smrg
624bdcaa8d0Smrg
625bdcaa8d0Smrg/*
626bdcaa8d0Smrg * end of file vmodes.c
627bdcaa8d0Smrg */
628bdcaa8d0Smrg
629