📄 nv_hw.c
字号:
/***************************************************************************\|* *||* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *||* *||* NOTICE TO USER: The source code is copyrighted under U.S. and *||* international laws. Users and possessors of this source code are *||* hereby granted a nonexclusive, royalty-free copyright license to *||* use this code in individual and commercial software. *||* *||* Any use of this source code must include, in the user documenta- *||* tion and internal comments to the code, notices to the end user *||* as follows: *||* *||* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *||* *||* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *||* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *||* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *||* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *||* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *||* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *||* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *||* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *||* SULTING 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 SOURCE CODE. *||* *||* U.S. Government End Users. This source code is a "commercial *||* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *||* consisting of "commercial computer software" and "commercial *||* computer software documentation," as such terms are used in *||* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *||* ment only as a commercial end item. Consistent with 48 C.F.R. *||* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *||* all U.S. Government End Users acquire the source code with only *||* those rights set forth herein. *||* *| \***************************************************************************//* * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ * XFree86 'nv' driver, this source code is provided under MIT-style licensing * where the source code is provided "as is" without warranty of any kind. * The only usage restriction is for the copyright notices to be retained * whenever code is used. * * Antonino Daplas <adaplas@pol.net> 2005-03-11 *//* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */#include <linux/pci.h>#include "nv_type.h"#include "nv_local.h"#include "nv_proto.h"void NVLockUnlock(struct nvidia_par *par, int Lock){ u8 cr11; VGA_WR08(par->PCIO, 0x3D4, 0x1F); VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57); VGA_WR08(par->PCIO, 0x3D4, 0x11); cr11 = VGA_RD08(par->PCIO, 0x3D5); if (Lock) cr11 |= 0x80; else cr11 &= ~0x80; VGA_WR08(par->PCIO, 0x3D5, cr11);}int NVShowHideCursor(struct nvidia_par *par, int ShowHide){ int cur = par->CurrentState->cursor1; par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) | (ShowHide & 0x01); VGA_WR08(par->PCIO, 0x3D4, 0x31); VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1); if (par->Architecture == NV_ARCH_40) NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300)); return (cur & 0x01);}/****************************************************************************\* ** The video arbitration routines calculate some "magic" numbers. Fixes ** the snow seen when accessing the framebuffer without it. ** It just works (I hope). ** *\****************************************************************************/typedef struct { int graphics_lwm; int video_lwm; int graphics_burst_size; int video_burst_size; int valid;} nv4_fifo_info;typedef struct { int pclk_khz; int mclk_khz; int nvclk_khz; char mem_page_miss; char mem_latency; int memory_width; char enable_video; char gr_during_vid; char pix_bpp; char mem_aligned; char enable_mp;} nv4_sim_state;typedef struct { int graphics_lwm; int video_lwm; int graphics_burst_size; int video_burst_size; int valid;} nv10_fifo_info;typedef struct { int pclk_khz; int mclk_khz; int nvclk_khz; char mem_page_miss; char mem_latency; int memory_type; int memory_width; char enable_video; char gr_during_vid; char pix_bpp; char mem_aligned; char enable_mp;} nv10_sim_state;static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk, unsigned int *NVClk){ unsigned int pll, N, M, MB, NB, P; if (par->Architecture >= NV_ARCH_40) { pll = NV_RD32(par->PMC, 0x4020); P = (pll >> 16) & 0x07; pll = NV_RD32(par->PMC, 0x4024); M = pll & 0xFF; N = (pll >> 8) & 0xFF; if (((par->Chipset & 0xfff0) == 0x0290) || ((par->Chipset & 0xfff0) == 0x0390) || ((par->Chipset & 0xfff0) == 0x02E0)) { MB = 1; NB = 1; } else { MB = (pll >> 16) & 0xFF; NB = (pll >> 24) & 0xFF; } *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; pll = NV_RD32(par->PMC, 0x4000); P = (pll >> 16) & 0x03; pll = NV_RD32(par->PMC, 0x4004); M = pll & 0xFF; N = (pll >> 8) & 0xFF; MB = (pll >> 16) & 0xFF; NB = (pll >> 24) & 0xFF; *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; } else if (par->twoStagePLL) { pll = NV_RD32(par->PRAMDAC0, 0x0504); M = pll & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; pll = NV_RD32(par->PRAMDAC0, 0x0574); if (pll & 0x80000000) { MB = pll & 0xFF; NB = (pll >> 8) & 0xFF; } else { MB = 1; NB = 1; } *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; pll = NV_RD32(par->PRAMDAC0, 0x0500); M = pll & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; pll = NV_RD32(par->PRAMDAC0, 0x0570); if (pll & 0x80000000) { MB = pll & 0xFF; NB = (pll >> 8) & 0xFF; } else { MB = 1; NB = 1; } *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; } else if (((par->Chipset & 0x0ff0) == 0x0300) || ((par->Chipset & 0x0ff0) == 0x0330)) { pll = NV_RD32(par->PRAMDAC0, 0x0504); M = pll & 0x0F; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x07; if (pll & 0x00000080) { MB = (pll >> 4) & 0x07; NB = (pll >> 19) & 0x1f; } else { MB = 1; NB = 1; } *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; pll = NV_RD32(par->PRAMDAC0, 0x0500); M = pll & 0x0F; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x07; if (pll & 0x00000080) { MB = (pll >> 4) & 0x07; NB = (pll >> 19) & 0x1f; } else { MB = 1; NB = 1; } *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; } else { pll = NV_RD32(par->PRAMDAC0, 0x0504); M = pll & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; *MClk = (N * par->CrystalFreqKHz / M) >> P; pll = NV_RD32(par->PRAMDAC0, 0x0500); M = pll & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; *NVClk = (N * par->CrystalFreqKHz / M) >> P; }}static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb){ int data, pagemiss, cas, width, video_enable, bpp; int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; int found, mclk_extra, mclk_loop, cbs, m1, p1; int mclk_freq, pclk_freq, nvclk_freq, mp_enable; int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate; int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm; fifo->valid = 1; pclk_freq = arb->pclk_khz; mclk_freq = arb->mclk_khz; nvclk_freq = arb->nvclk_khz; pagemiss = arb->mem_page_miss; cas = arb->mem_latency; width = arb->memory_width >> 6; video_enable = arb->enable_video; bpp = arb->pix_bpp; mp_enable = arb->enable_mp; clwm = 0; vlwm = 0; cbs = 128; pclks = 2; nvclks = 2; nvclks += 2; nvclks += 1; mclks = 5; mclks += 3; mclks += 1; mclks += cas; mclks += 1; mclks += 1; mclks += 1; mclks += 1; mclk_extra = 3; nvclks += 2; nvclks += 1; nvclks += 1; nvclks += 1; if (mp_enable) mclks += 4; nvclks += 0; pclks += 0; found = 0; vbs = 0; while (found != 1) { fifo->valid = 1; found = 1; mclk_loop = mclks + mclk_extra; us_m = mclk_loop * 1000 * 1000 / mclk_freq; us_n = nvclks * 1000 * 1000 / nvclk_freq; us_p = nvclks * 1000 * 1000 / pclk_freq; if (video_enable) { video_drain_rate = pclk_freq * 2; crtc_drain_rate = pclk_freq * bpp / 8; vpagemiss = 2; vpagemiss += 1; crtpagemiss = 2; vpm_us = (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq; if (nvclk_freq * 2 > mclk_freq * width) video_fill_us = cbs * 1000 * 1000 / 16 / nvclk_freq; else video_fill_us = cbs * 1000 * 1000 / (8 * width) / mclk_freq; us_video = vpm_us + us_m + us_n + us_p + video_fill_us; vlwm = us_video * video_drain_rate / (1000 * 1000); vlwm++; vbs = 128; if (vlwm > 128) vbs = 64; if (vlwm > (256 - 64)) vbs = 32; if (nvclk_freq * 2 > mclk_freq * width) video_fill_us = vbs * 1000 * 1000 / 16 / nvclk_freq; else video_fill_us = vbs * 1000 * 1000 / (8 * width) / mclk_freq; cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; us_crt = us_video + video_fill_us + cpm_us + us_m + us_n + us_p; clwm = us_crt * crtc_drain_rate / (1000 * 1000); clwm++; } else { crtc_drain_rate = pclk_freq * bpp / 8; crtpagemiss = 2; crtpagemiss += 1; cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; us_crt = cpm_us + us_m + us_n + us_p; clwm = us_crt * crtc_drain_rate / (1000 * 1000); clwm++; } m1 = clwm + cbs - 512; p1 = m1 * pclk_freq / mclk_freq; p1 = p1 * bpp / 8; if ((p1 < m1) && (m1 > 0)) { fifo->valid = 0; found = 0; if (mclk_extra == 0) found = 1; mclk_extra--; } else if (video_enable) { if ((clwm > 511) || (vlwm > 255)) { fifo->valid = 0; found = 0; if (mclk_extra == 0) found = 1; mclk_extra--; } } else { if (clwm > 519) { fifo->valid = 0; found = 0; if (mclk_extra == 0) found = 1; mclk_extra--; } } if (clwm < 384) clwm = 384; if (vlwm < 128) vlwm = 128; data = (int)(clwm); fifo->graphics_lwm = data; fifo->graphics_burst_size = 128; data = (int)((vlwm + 15)); fifo->video_lwm = data; fifo->video_burst_size = vbs; }}static void nv4UpdateArbitrationSettings(unsigned VClk, unsigned pixelDepth, unsigned *burst, unsigned *lwm, struct nvidia_par *par){ nv4_fifo_info fifo_data; nv4_sim_state sim_data; unsigned int MClk, NVClk, cfg1; nvGetClocks(par, &MClk, &NVClk); cfg1 = NV_RD32(par->PFB, 0x00000204); sim_data.pix_bpp = (char)pixelDepth; sim_data.enable_video = 0; sim_data.enable_mp = 0; sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ? 128 : 64; sim_data.mem_latency = (char)cfg1 & 0x0F; sim_data.mem_aligned = 1; sim_data.mem_page_miss = (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01)); sim_data.gr_during_vid = 0; sim_data.pclk_khz = VClk; sim_data.mclk_khz = MClk; sim_data.nvclk_khz = NVClk; nv4CalcArbitration(&fifo_data, &sim_data); if (fifo_data.valid) { int b = fifo_data.graphics_burst_size >> 4; *burst = 0; while (b >>= 1) (*burst)++; *lwm = fifo_data.graphics_lwm >> 3; }}static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -