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