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

📄 nv_hw.c

📁 nvidia 的LCD 驱动代码
💻 C
📖 第 1 页 / 共 4 页
字号:
{	int data, pagemiss, width, video_enable, bpp;	int nvclks, mclks, pclks, vpagemiss, crtpagemiss;	int nvclk_fill;	int found, mclk_extra, mclk_loop, cbs, m1;	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;	int us_m, us_m_min, us_n, us_p, crtc_drain_rate;	int vus_m;	int vpm_us, us_video, cpm_us, us_crt, clwm;	int clwm_rnd_down;	int m2us, us_pipe_min, p1clk, p2;	int min_mclk_extra;	int us_min_mclk_extra;	fifo->valid = 1;	pclk_freq = arb->pclk_khz;	/* freq in KHz */	mclk_freq = arb->mclk_khz;	nvclk_freq = arb->nvclk_khz;	pagemiss = arb->mem_page_miss;	width = arb->memory_width / 64;	video_enable = arb->enable_video;	bpp = arb->pix_bpp;	mp_enable = arb->enable_mp;	clwm = 0;	cbs = 512;	pclks = 4;	/* lwm detect. */	nvclks = 3;	/* lwm -> sync. */	nvclks += 2;	/* fbi bus cycles (1 req + 1 busy) */	/* 2 edge sync.  may be very close to edge so just put one. */	mclks = 1;	mclks += 1;	/* arb_hp_req */	mclks += 5;	/* ap_hp_req   tiling pipeline */	mclks += 2;	/* tc_req     latency fifo */	mclks += 2;	/* fb_cas_n_  memory request to fbio block */	mclks += 7;	/* sm_d_rdv   data returned from fbio block */	/* fb.rd.d.Put_gc   need to accumulate 256 bits for read */	if (arb->memory_type == 0)		if (arb->memory_width == 64)	/* 64 bit bus */			mclks += 4;		else			mclks += 2;	else if (arb->memory_width == 64)	/* 64 bit bus */		mclks += 2;	else		mclks += 1;	if ((!video_enable) && (arb->memory_width == 128)) {		mclk_extra = (bpp == 32) ? 31 : 42;	/* Margin of error */		min_mclk_extra = 17;	} else {		mclk_extra = (bpp == 32) ? 8 : 4;	/* Margin of error */		/* mclk_extra = 4; *//* Margin of error */		min_mclk_extra = 18;	}	/* 2 edge sync.  may be very close to edge so just put one. */	nvclks += 1;	nvclks += 1;		/* fbi_d_rdv_n */	nvclks += 1;		/* Fbi_d_rdata */	nvclks += 1;		/* crtfifo load */	if (mp_enable)		mclks += 4;	/* Mp can get in with a burst of 8. */	/* Extra clocks determined by heuristics */	nvclks += 0;	pclks += 0;	found = 0;	while (found != 1) {		fifo->valid = 1;		found = 1;		mclk_loop = mclks + mclk_extra;		/* Mclk latency in us */		us_m = mclk_loop * 1000 * 1000 / mclk_freq;		/* Minimum Mclk latency in us */		us_m_min = mclks * 1000 * 1000 / mclk_freq;		us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;		/* nvclk latency in us */		us_n = nvclks * 1000 * 1000 / nvclk_freq;		/* nvclk latency in us */		us_p = pclks * 1000 * 1000 / pclk_freq;		us_pipe_min = us_m_min + us_n + us_p;		/* Mclk latency in us */		vus_m = mclk_loop * 1000 * 1000 / mclk_freq;		if (video_enable) {			crtc_drain_rate = pclk_freq * bpp / 8;	/* MB/s */			vpagemiss = 1;	/* self generating page miss */			vpagemiss += 1;	/* One higher priority before */			crtpagemiss = 2;	/* self generating page miss */			if (mp_enable)				crtpagemiss += 1;	/* if MA0 conflict */			vpm_us =			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;			/* Video has separate read return path */			us_video = vpm_us + vus_m;			cpm_us =			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;			/* Wait for video */			us_crt = us_video			    + cpm_us	/* CRT Page miss */			    + us_m + us_n + us_p	/* other latency */			    ;			clwm = us_crt * crtc_drain_rate / (1000 * 1000);			/* fixed point <= float_point - 1.  Fixes that */			clwm++;		} else {		    /* bpp * pclk/8 */			crtc_drain_rate = pclk_freq * bpp / 8;			crtpagemiss = 1;	/* self generating page miss */			crtpagemiss += 1;	/* MA0 page miss */			if (mp_enable)				crtpagemiss += 1;	/* if MA0 conflict */			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);			/* fixed point <= float_point - 1.  Fixes that */			clwm++;			/* Finally, a heuristic check when width == 64 bits */			if (width == 1) {				nvclk_fill = nvclk_freq * 8;				if (crtc_drain_rate * 100 >= nvclk_fill * 102)					/*Large number to fail */					clwm = 0xfff;				else if (crtc_drain_rate * 100 >=					 nvclk_fill * 98) {					clwm = 1024;					cbs = 512;				}			}		}		/*		   Overfill check:		 */		clwm_rnd_down = ((int)clwm / 8) * 8;		if (clwm_rnd_down < clwm)			clwm += 8;		m1 = clwm + cbs - 1024;	/* Amount of overfill */		m2us = us_pipe_min + us_min_mclk_extra;		/* pclk cycles to drain */		p1clk = m2us * pclk_freq / (1000 * 1000);		p2 = p1clk * bpp / 8;	/* bytes drained. */		if ((p2 < m1) && (m1 > 0)) {			fifo->valid = 0;			found = 0;			if (min_mclk_extra == 0) {				if (cbs <= 32) {					/* Can't adjust anymore! */					found = 1;				} else {					/* reduce the burst size */					cbs = cbs / 2;				}			} else {				min_mclk_extra--;			}		} else {			if (clwm > 1023) {	/* Have some margin */				fifo->valid = 0;				found = 0;				if (min_mclk_extra == 0)					/* Can't adjust anymore! */					found = 1;				else					min_mclk_extra--;			}		}		if (clwm < (1024 - cbs + 8))			clwm = 1024 - cbs + 8;		data = (int)(clwm);		/*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n",		    clwm, data ); */		fifo->graphics_lwm = data;		fifo->graphics_burst_size = cbs;		fifo->video_lwm = 1024;		fifo->video_burst_size = 512;	}}static void nv10UpdateArbitrationSettings(unsigned VClk,					  unsigned pixelDepth,					  unsigned *burst,					  unsigned *lwm,					  struct nvidia_par *par){	nv10_fifo_info fifo_data;	nv10_sim_state sim_data;	unsigned int MClk, NVClk, cfg1;	nvGetClocks(par, &MClk, &NVClk);	cfg1 = NV_RD32(par->PFB, 0x0204);	sim_data.pix_bpp = (char)pixelDepth;	sim_data.enable_video = 1;	sim_data.enable_mp = 0;	sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 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;	nv10CalcArbitration(&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 nv30UpdateArbitrationSettings (    struct nvidia_par *par,    unsigned int      *burst,    unsigned int      *lwm){    unsigned int MClk, NVClk;    unsigned int fifo_size, burst_size, graphics_lwm;    fifo_size = 2048;    burst_size = 512;    graphics_lwm = fifo_size - burst_size;    nvGetClocks(par, &MClk, &NVClk);    *burst = 0;    burst_size >>= 5;    while(burst_size >>= 1) (*burst)++;    *lwm = graphics_lwm >> 3;}static void nForceUpdateArbitrationSettings(unsigned VClk,					    unsigned pixelDepth,					    unsigned *burst,					    unsigned *lwm,					    struct nvidia_par *par){	nv10_fifo_info fifo_data;	nv10_sim_state sim_data;	unsigned int M, N, P, pll, MClk, NVClk, memctrl;	struct pci_dev *dev;	if ((par->Chipset & 0x0FF0) == 0x01A0) {		unsigned int uMClkPostDiv;		dev = pci_get_bus_and_slot(0, 3);		pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);		uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;		if (!uMClkPostDiv)			uMClkPostDiv = 4;		MClk = 400000 / uMClkPostDiv;	} else {		dev = pci_get_bus_and_slot(0, 5);		pci_read_config_dword(dev, 0x4c, &MClk);		MClk /= 1000;	}	pci_dev_put(dev);	pll = NV_RD32(par->PRAMDAC0, 0x0500);	M = (pll >> 0) & 0xFF;	N = (pll >> 8) & 0xFF;	P = (pll >> 16) & 0x0F;	NVClk = (N * par->CrystalFreqKHz / M) >> P;	sim_data.pix_bpp = (char)pixelDepth;	sim_data.enable_video = 0;	sim_data.enable_mp = 0;	dev = pci_get_bus_and_slot(0, 1);	pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);	pci_dev_put(dev);	sim_data.memory_type = (sim_data.memory_type >> 12) & 1;	sim_data.memory_width = 64;	dev = pci_get_bus_and_slot(0, 3);	pci_read_config_dword(dev, 0, &memctrl);	pci_dev_put(dev);	memctrl >>= 16;	if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {		int dimm[3];		dev = pci_get_bus_and_slot(0, 2);		pci_read_config_dword(dev, 0x40, &dimm[0]);		dimm[0] = (dimm[0] >> 8) & 0x4f;		pci_read_config_dword(dev, 0x44, &dimm[1]);		dimm[1] = (dimm[1] >> 8) & 0x4f;		pci_read_config_dword(dev, 0x48, &dimm[2]);		dimm[2] = (dimm[2] >> 8) & 0x4f;		if ((dimm[0] + dimm[1]) != dimm[2]) {			printk("nvidiafb: your nForce DIMMs are not arranged "			       "in optimal banks!\n");		}		pci_dev_put(dev);	}	sim_data.mem_latency = 3;	sim_data.mem_aligned = 1;	sim_data.mem_page_miss = 10;	sim_data.gr_during_vid = 0;	sim_data.pclk_khz = VClk;	sim_data.mclk_khz = MClk;	sim_data.nvclk_khz = NVClk;	nv10CalcArbitration(&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;	}}/****************************************************************************\*                                                                            **                          RIVA Mode State Routines                          **                                                                            *\****************************************************************************//* * Calculate the Video Clock parameters for the PLL. */static void CalcVClock(int clockIn,		       int *clockOut, u32 * pllOut, struct nvidia_par *par){	unsigned lowM, highM;	unsigned DeltaNew, DeltaOld;	unsigned VClk, Freq;	unsigned M, N, P;	DeltaOld = 0xFFFFFFFF;	VClk = (unsigned)clockIn;	if (par->CrystalFreqKHz == 13500) {		lowM = 7;		highM = 13;	} else {		lowM = 8;		highM = 14;	}	for (P = 0; P <= 4; P++) {		Freq = VClk << P;		if ((Freq >= 128000) && (Freq <= 350000)) {			for (M = lowM; M <= highM; M++) {				N = ((VClk << P) * M) / par->CrystalFreqKHz;				if (N <= 255) {					Freq =					    ((par->CrystalFreqKHz * N) /					     M) >> P;					if (Freq > VClk)						DeltaNew = Freq - VClk;					else						DeltaNew = VClk - Freq;					if (DeltaNew < DeltaOld) {						*pllOut =						    (P << 16) | (N << 8) | M;						*clockOut = Freq;						DeltaOld = DeltaNew;					}				}			}		}	}}static void CalcVClock2Stage(int clockIn,			     int *clockOut,			     u32 * pllOut,			     u32 * pllBOut, struct nvidia_par *par){	unsigned DeltaNew, DeltaOld;	unsigned VClk, Freq;	unsigned M, N, P;	DeltaOld = 0xFFFFFFFF;	*pllBOut = 0x80000401;	/* fixed at x4 for now */	VClk = (unsigned)clockIn;	for (P = 0; P <= 6; P++) {		Freq = VClk << P;		if ((Freq >= 400000) && (Freq <= 1000000)) {			for (M = 1; M <= 13; M++) {				N = ((VClk << P) * M) /				    (par->CrystalFreqKHz << 2);				if ((N >= 5) && (N <= 255)) {

⌨️ 快捷键说明

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