attdac.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 344 行
C
344 行
/* $XFree86: xc/programs/Xserver/hw/xfree86/common_hw/ATTDac.c,v 3.5 1996/12/23 06:44:00 dawes Exp $ *//* * Copyright 1994 by David Wexelblat <dwex@goblin.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of David Wexelblat not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. David Wexelblat makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * *//* $XConsortium: ATTDac.c /main/9 1996/05/07 17:12:54 kaleb $ */#include "Xfuncproto.h"#include "compiler.h"#define NO_OSLIB_PROTOTYPES#include "xf86_OSlib.h"#include "misc.h"/* #include "xf86_HWlib.h" */#define ATT409_CC 0x06#define ATT409_CR0 0x01void xf86dactopel(){ outb(0x3C8,0); return;}unsigned char xf86dactocomm(){ (void)inb(0x3C6); (void)inb(0x3C6); (void)inb(0x3C6); return(inb(0x3C6));}unsigned charxf86getdaccomm(){ unsigned char ret; xf86dactopel(); (void)xf86dactocomm(); ret = inb(0x3C6); xf86dactopel();#ifdef EXTENDED_DEBUG ErrorF("Old CR0 0x%x\n",ret);#endif return(ret);}voidxf86setdaccomm(comm)unsigned char comm;{ xf86dactopel(); (void)xf86dactocomm(); outb(0x3C6, comm); xf86dactopel();#ifdef EXTENDED_DEBUG ErrorF("New CR0 0x%x\n",comm);#endif return;}voidxf86setdaccommbit(bits)unsigned char bits;{ unsigned char tmp; tmp = xf86getdaccomm() | bits; xf86setdaccomm(tmp); return;}voidxf86clrdaccommbit(bits)unsigned char bits;{ unsigned char tmp; tmp = xf86getdaccomm() & ~bits; xf86setdaccomm(tmp); return;}unsigned charxf86getdacregindexed(idx)unsigned char idx;{ unsigned char ret; /* * first check if we are in indexed mode */ if( !xf86testdacindexed() ) { ret = xf86getdaccomm(); ErrorF("Yieck! CR0 = 0x%x which is not indexed mode\n",ret); } outb(0x3C8,idx); ret = inb(0x3C6);#ifdef EXTENDED_DEBUG ErrorF("Index 0x%x is 0x%x\n",idx,ret);#endif return(ret);}voidxf86setdacregindexed(idx,val)unsigned char idx;unsigned char val;{ unsigned char tmp; /* * first check if we are in indexed mode */ if( !xf86testdacindexed() ) { tmp = xf86getdaccomm(); ErrorF("Yieck! CR0 = 0x%x which is not indexed mode\n",tmp); }#ifdef EXTENDED_DEBUG outb(0x3C8,idx); tmp = inb(0x3C6);#endif outb(0x3C8,idx); outb(0x3C6,val);#ifdef EXTENDED_DEBUG ErrorF("Index 0x%x set to 0x%x (was 0x%x)\n",idx,val,tmp);#endif return;}intxf86testdacindexed(){ /* * figure out whether we are in indexed addressing mode */ outb(0x3C8,0); /* reset state machine, if we are non-index */ (void) inb(0x3C6); (void) inb(0x3C6); (void) inb(0x3C6); (void) inb(0x3C6); (void) inb(0x3C6); if( (inb(0x3C6) != 0x84) || ((inb(0x3C6) & 0xf) != 9) ) return TRUE; else return FALSE;}staticvoidAtt409UseClock(clk)int clk;{ unsigned char tmp; /* * this function should only be called when the chip is in indexed * addressing mode (CR0[0] = 1) !! */ tmp = xf86getdacregindexed(ATT409_CC); if( clk <= 3 ) { /* * this sets the PCLK (Clock A) by setting CC[5:4] */ xf86setdacregindexed(ATT409_CC, (tmp & 0xCF) | 0x80 | clk << 4); } else { /* * this sets the MCLK (Clock B) by setting CC[1:0] */ xf86setdacregindexed(ATT409_CC, (tmp & 0xFC) | 0x08 | (clk & 3)); }#ifdef EXTENDED_DEBUG ErrorF("CC set to 0x%x (was 0x%x)\n", xf86getdacregindexed(ATT409_CC),tmp);#endif return;}#define BASE_FREQ 14.31818#define FREQ_MIN (120000.0 / 8.0) /* p = 3 */#define FREQ_MAX (240000.0 / 1.0) /* p = 0 */staticvoidAtt409CalcMNP(freq,m,n,p)long freq;unsigned char *m,*n,*p;{ double ffreq, ffreq_min, ffreq_max; double div, diff, best_diff; unsigned int mm,nn; int pp; /* let's make that signed so the loop is easier to phrase */ unsigned char best_n=5+2, best_p=2, best_m=125+2; ffreq = freq / 1000.0 / BASE_FREQ; ffreq_min = FREQ_MIN / 1000.0 / BASE_FREQ; ffreq_max = FREQ_MAX / 1000.0 / BASE_FREQ; best_diff = ffreq; for (pp=3; pp >= 0; pp--) { for (nn = 0+2; nn <= 63+2; nn++) { mm = (int)(ffreq * nn * (1<<pp) + 0.5) ; if (mm < 1+2 || mm > 255+2) continue; div = (double)(mm) / (double)(nn); if ((div >= ffreq_min) && (div <= ffreq_max)) { diff = ffreq - div / (1<<pp); if (diff < 0.0) diff = -diff; if (diff < best_diff) { best_diff = diff; best_m = mm; best_n = nn; best_p = pp; } if (diff < ffreq * 0.005) { /* * 0.5% is close enough */ break; } } } } *m = best_m - 2; *n = best_n - 2; *p = best_p;} staticvoidAtt409SetFreq(clk,freq)int clk;long freq;{ unsigned char m,n,p,reg_m,reg_n;#ifdef EXTENDED_DEBUG unsigned char tmp,m_old,n_old;#endif /* * this function should only be called when the chip is in indexed * addressing mode (CR0[0] = 1) !! */ /* * This function does not try to program the Loop Filter Control Bits * or the Ibias Control (as we have no idea what to put there...) */ reg_m = 0x40 + 4*clk + ((clk >= 4) ? 0x10 : 0x0); reg_n = 0x41 + 4*clk + ((clk >= 4) ? 0x10 : 0x0); Att409CalcMNP(freq,&m,&n,&p); n = (n & 0x3f) | ((p & 0x3) << 6); /* combine n and p into 8 bit */#ifdef EXTENDED_DEBUG ErrorF("setting Clk %d to %1.6f MHz (m %d, n %d, p %d)\n", clk, ((double)(m+2)/(double)((n&0x3f)+2)/(1<<p))*BASE_FREQ, m,(n&0x3f),p); m_old = xf86getdacregindexed(reg_m); n_old = xf86getdacregindexed(reg_n); ErrorF("setting Index 0x%x to 0x%x (was 0x%x)\n", reg_m, m, m_old); ErrorF("setting Index 0x%x to 0x%x (was 0x%x)\n", reg_n, n, n_old);#endif /* * now set the corresponding registers * * 0x48/0x49 for PCLK C (clk == 2) * 0x4c/0x4d for PCLK D (clk == 3) * 0x6c/0x6d for MCLK D (clk == 7) */ xf86setdacregindexed(reg_m,m); xf86setdacregindexed(reg_n,n); return;}intAtt409SetClock(freq, clk)long freq;int clk;{ unsigned char tmp; /* * we accept clocks 2 and 3 (these are the programmable PCLKs C and D) * and clock 7 (this we interpret as programmable MCLK D) */ if( (clk != 2) && (clk != 3) && (clk != 7) ) { ErrorF("-------- Illegal Clock for ATT20C409: %d\n", clk); return(FALSE); } /* * enable indexed addressing and power down the chip for programming * the clocks without corrupting the pixel color RAM */ xf86setdaccommbit(0x09); usleep(300); /* PLL settling time */ Att409SetFreq(clk,freq);#if NOT_NEEDED Att409UseClock(clk);#endif usleep(300); /* * turn off indexed addressing and power up RAMDAC */ tmp = xf86getdacregindexed(ATT409_CR0); xf86setdacregindexed(ATT409_CR0,tmp & ~0x09); return(TRUE);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?