⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3dacs.c

📁 linux 下svgalib编的一个界面程序示例
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * s3dacs.c: *  * RAMDAC definitions for the S3-SDAC (86C716), S3-GENDAC, and Trio64. * * These contain S3-specific code. */#include <stdio.h>#include "libvga.h"#include "timing.h"#include "vgaregs.h"#include "driver.h"		/* for __svgalib_driver_report */#include "ramdac.h"/* SDAC/GENDAC registers */#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC)#define SDAC_COMMAND		0	/* Register offsets into state. */#define GENDAC_COMMAND		0#define SDAC_PLL_WRITEINDEX	1#define SDAC_PLL_READINDEX	2#define SDAC_PLL_M		3	/* f2 programmed clock */#define SDAC_PLL_N1_N2		4#define SDAC_PLL_CONTROL	5#define SDAC_STATESIZE 6	/* 6 registers. */#define GENDAC_STATESIZE 6#endif#if defined(INCLUDE_S3_SDAC_DAC_TEST) || defined(INCLUDE_S3_GENDAC_DAC_TEST)static int GENDAC_SDAC_probe(void){/* Taken from XFree86, accel/s3.c. *//* Return 1 if GENDAC found, 2 if SDAC, 0 otherwise. */    /* probe for S3 GENDAC or SDAC */    /*     * S3 GENDAC and SDAC have two fixed read only PLL clocks     *     CLK0 f0: 25.255MHz   M-byte 0x28  N-byte 0x61     *     CLK0 f1: 28.311MHz   M-byte 0x3d  N-byte 0x62     * which can be used to detect GENDAC and SDAC since there is no chip-id     * for the GENDAC.     *     * NOTE: for the GENDAC on a MIRO 10SD (805+GENDAC) reading PLL values     * for CLK0 f0 and f1 always returns 0x7f (but is documented "read only")     */    unsigned char saveCR55, savelut[6];    int i;    long clock01, clock23;    saveCR55 = __svgalib_inCR(0x55);    __svgalib_outbCR(0x55, saveCR55 & ~1);    outb(0x3c7, 0);    for (i = 0; i < 2 * 3; i++)	/* save first two LUT entries */	savelut[i] = inb(0x3c9);    outb(0x3c8, 0);    for (i = 0; i < 2 * 3; i++)	/* set first two LUT entries to zero */	outb(0x3c9, 0);    __svgalib_outbCR(0x55, saveCR55 | 1);    outb(0x3c7, 0);    for (i = clock01 = 0; i < 4; i++)	clock01 = (clock01 << 8) | (inb(0x3c9) & 0xff);    for (i = clock23 = 0; i < 4; i++)	clock23 = (clock23 << 8) | (inb(0x3c9) & 0xff);    __svgalib_outbCR(0x55, saveCR55 & ~1);    outb(0x3c8, 0);    for (i = 0; i < 2 * 3; i++)	/* restore first two LUT entries */	outb(0x3c9, savelut[i]);    __svgalib_outbCR(0x55, saveCR55);    if (clock01 == 0x28613d62 ||	(clock01 == 0x7f7f7f7f && clock23 != 0x7f7f7f7f)) {	inb(0x3c8);		/* dactopel */	inb(0x3c6);	inb(0x3c6);	inb(0x3c6);	/* the forth read will show the SDAC chip ID and revision */	if (((i = inb(0x3c6)) & 0xf0) == 0x70) {	    return 2;		/* SDAC found. */	} else {	    return 1;		/* GENDAC found. */	}	inb(0x3c8);		/* dactopel */    }    return 0;}#endif#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC)static void GENDAC_SDAC_init(void){    unsigned char val;    int m, n, n1, n2, MCLK;    val = __svgalib_inCR(0x55);    __svgalib_outbCR(0x55, val | 0x01);    outb(0x3C7, 10);		/* Read MCLK. */    m = inb(0x3C9);    n = inb(0x3C9);    __svgalib_outbCR(0x55, val);		/* Restore CR55. */    m &= 0x7f;    n1 = n & 0x1f;    n2 = (n >> 5) & 0x03;    /* Calculate MCLK in kHz. */    MCLK = 14318 * (m + 2) / (n1 + 2) / (1 << n2);    if (__svgalib_driver_report)	printf("svgalib: S3-GENDAC/SDAC: MCLK = %d.%03d MHz\n",	       MCLK / 1000, MCLK % 1000);}#endif#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) || defined(INCLUDE_S3_TRIO64_DAC)/* * From XFree86 common_hw/S3gendac.c and S3gendac.h. *  * Progaming of the S3 gendac programable clocks, from the S3 Gendac * programing documentation by S3 Inc.  * Jon Tombs <jon@esix2.us.es> *  * Returns nonzero if success, 0 if failure. */#define BASE_FREQ	     14.31818	/* MHz */#define DEBUG_FINDCLOCK 0static int S3dacsFindClock(int freq_in, int min_n2, int freq_min, int freq_max,		     int *best_m_out, int *best_n1_out, int *best_n2_out){    double ffreq_in, ffreq_min, ffreq_max;    double ffreq_out, diff, best_diff;    unsigned int m;    unsigned char n1, n2;    unsigned char best_n1 = 16 + 2, best_n2 = 2, best_m = 125 + 2;#if DEBUG_FINDCLOCK    printf("S3dacsFindClock: Trying to match clock of %0.3f MHz\n", freq_in / 1000.0);#endif        ffreq_in = freq_in / 1000.0 / BASE_FREQ;    ffreq_min = freq_min / 1000.0 / BASE_FREQ;    ffreq_max = freq_max / 1000.0 / BASE_FREQ;    /* Check if getting freq_in is possible at all */    if (freq_in < freq_min / 8) {#if DEBUG_FINDCLOCK	printf("S3dacsFindClock: %0.3f MHz is too low (lowest is %0.3f MHz)\n",	       freq_in / 1000.0, freq_min / 1000.0 / 8);#endif	return 0;    }      if (freq_in > freq_max / (1 << min_n2)) {#if DEBUG_FINDCLOCK	printf("S3dacsFindClock: %0.3f MHz is too high (highest is %0.3f MHz)\n",	       freq_in / 1000.0, freq_max / 1000.0 / (1 << min_n2));#endif	return 0;    }    /* work out suitable timings */    best_diff = ffreq_in;    for (n2 = min_n2; n2 <= 3; n2++) {	for (n1 = 1 + 2; n1 <= 31 + 2; n1++) {	    m = (int) (ffreq_in * n1 * (1 << n2) + 0.5);	    if (m < 1 + 2 || m > 127 + 2)		continue;	    ffreq_out = (double) (m) / (double) (n1);	    if ((ffreq_out >= ffreq_min) && (ffreq_out <= ffreq_max)) {		diff = ffreq_in - ffreq_out / (1 << n2);		if (diff < 0.0)		    diff = -diff;		if (diff < best_diff) {		    best_diff = diff;		    best_m = m;		    best_n1 = n1;		    best_n2 = n2;		}	    }	}    }#if DEBUG_FINDCLOCK    printf("S3dacsFindClock: clock wanted %1.6f MHz, found %1.6f MHz (m %d, n1 %d, n2 %d)\n",	   freq_in / 1000.0,	   best_m / ((double) best_n1 * (1 << best_n2)) * BASE_FREQ,	   best_m, best_n1, best_n2);#endif        *best_m_out = best_m;    *best_n1_out = best_n1;    *best_n2_out = best_n2;        return 1;}#endif#if defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC)static int GENDAC_SDAC_match_programmable_clock(int desiredclock){    int min_m, min_n1, n2;        /* Note: For ICS5342, min_n2 parameter should be one. */    if (!S3dacsFindClock(desiredclock, 0, 100000, 250000, &min_m, &min_n1, &n2))	return 0;    return ((float) (min_m) / (float) (min_n1) / (1 << n2)) * BASE_FREQ * 1000;}#if 0				/* Retained for reference. */static void setdacpll(reg, data1, data2)int reg;unsigned char data1;unsigned char data2;{    unsigned char tmp, tmp1;    int vgaCRIndex = vgaIOBase + 4;    int vgaCRReg = vgaIOBase + 5;    /* set RS2 via CR55, yuck */    tmp = __svgalib_inCR(0x55) & 0xFC;    __svgalib_outCR(tmp | 0x01);    tmp1 = inb(GENDAC_INDEX);    outb(GENDAC_INDEX, reg);    outb(GENDAC_DATA, data1);    outb(GENDAC_DATA, data2);    /* Now clean up our mess */    outb(GENDAC_INDEX, tmp1);    __svgalib_outbCR(0x55, tmp);}#endifstatic void GENDAC_SDAC_initialize_clock_state(unsigned char *regs, int freq){    int min_m, min_n1, n2;    int n, m;    if (!S3dacsFindClock(freq, 0, 100000, 250000, &min_m, &min_n1, &n2)) {	printf("Bad dot clock %0.3f MHz.\n", freq / 1000.0);	return;    }        n = (min_n1 - 2) | (n2 << 5);    m = min_m - 2;    regs[SDAC_PLL_M] = m;    regs[SDAC_PLL_N1_N2] = n;    if (__svgalib_driver_report)	printf("Initializing DAC PLL values; 0x%02X, 0x%02X.\n", m, n);}static void GENDAC_SDAC_savestate(unsigned char *regs){    unsigned char tmp;    tmp = __svgalib_inCR(0x55);    __svgalib_outbCR(0x55, tmp | 1);    regs[SDAC_COMMAND] = inb(0x3c6);    regs[SDAC_PLL_WRITEINDEX] = inb(0x3c8);	/* PLL write index */    regs[SDAC_PLL_READINDEX] = inb(0x3c7);	/* PLL read index */    outb(0x3c7, 2);		/* index to f2 reg */    regs[SDAC_PLL_M] = inb(0x3c9);	/* f2 PLL M divider */    regs[SDAC_PLL_N1_N2] = inb(0x3c9);	/* f2 PLL N1/N2 divider */    outb(0x3c7, 0x0e);		/* index to PLL control */    regs[SDAC_PLL_CONTROL] = inb(0x3c9);	/* PLL control */    __svgalib_outbCR(0x55, tmp & ~1);}static void GENDAC_SDAC_restorestate(const unsigned char *regs){    unsigned char tmp;    /* set RS2 via CR55, yuck */    tmp = __svgalib_inCR(0x55) & 0xFC;    __svgalib_outbCR(0x55, tmp | 0x01);#ifdef DEBUG    do {	int m, n1, n2, clk;	m = regs[SDAC_PLL_M] & 0x7f;	n1 = regs[SDAC_PLL_N1_N2] & 0x1f;	n2 = (regs[SDAC_PLL_N1_N2] & 0x60) >> 5;	clk = 14318 * (m + 2) / (n1 + 2) / (1 << n2);	printf("SDAC.restorestate, setting clock 0x%02X 0x%02X (%d.%3dMHz)\n",	       regs[SDAC_PLL_M],	       regs[SDAC_PLL_N1_N2], clk / 1000, clk % 1000);    } while (0);#endif    outb(0x3c6, regs[SDAC_COMMAND]);    outb(0x3c8, 2);		/* index to f2 reg */    outb(0x3c9, regs[SDAC_PLL_M]);	/* f2 PLL M divider */    outb(0x3c9, regs[SDAC_PLL_N1_N2]);	/* f2 PLL N1/N2 divider */    outb(0x3c8, 0x0e);		/* index to PLL control */    outb(0x3c9, regs[SDAC_PLL_CONTROL]);	/* PLL control */    outb(0x3c8, regs[SDAC_PLL_WRITEINDEX]);	/* PLL write index */    outb(0x3c7, regs[SDAC_PLL_READINDEX]);	/* PLL read index */    __svgalib_outbCR(0x55, tmp);}#endif				/* defined(INCLUDE_S3_SDAC_DAC) || defined(INCLUDE_S3_GENDAC_DAC) *//* * SDAC: 16-bit DAC, 110 MHz raw clock limit. * * The 135 MHz version supports pixel multiplexing in 8bpp modes with a * halved raw clock. (SL: at least mine doesn't.) */#ifdef INCLUDE_S3_SDAC_DAC_TESTstatic int SDAC_probe(void){    return GENDAC_SDAC_probe() == 2;}#else#define SDAC_probe 0#endif#ifdef INCLUDE_S3_SDAC_DACstatic int SDAC_map_clock(int bpp, int pixelclock){    switch (bpp) {    case 4:    case 8:#ifdef SDAC_8BPP_PIXMUX		/* SL: AFAIK it doesn't work */	if (pixelclock >= 67500)	    /* Use pixel multiplexing. */	    return pixelclock / 2;#endif	break;    case 24:	return pixelclock * 3 / 2;    case 32:	return pixelclock * 2;    }    return pixelclock;}static int SDAC_map_horizontal_crtc(int bpp, int pixelclock, int htiming){    switch (bpp) {    case 16:	return htiming * 2;    case 24:	return htiming * 3;    case 32:	return htiming * 4;    }    return htiming;}static void SDAC_initializestate(unsigned char *regs, int bpp, int colormode,				 int pixelclock){    int pixmux;			/* SDAC command register. */    pixmux = 0;    switch (colormode) {    case CLUT8_6:#ifdef SDAC_8BPP_PIXMUX	if (pixelclock >= 67500)	    pixmux = 0x10;#endif	break;    case RGB16_555:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -