nvidia_vid.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,156 行 · 第 1/3 页

C
1,156
字号
#define VID_WR32(p,i,val) ({ MEM_BARRIER(); ((uint32_t *)(p))[(i)/4]=val; })#undef	VID_RD32#define VID_RD32(p,i)     ({ MEM_BARRIER(); ((uint32_t *)(p))[(i)/4]; })#define VID_AND32(p,i,val) VID_WR32(p,i,VID_RD32(p,i)&(val))#define VID_OR32(p,i,val)  VID_WR32(p,i,VID_RD32(p,i)|(val))#define VID_XOR32(p,i,val) VID_WR32(p,i,VID_RD32(p,i)^(val))struct rivatv_chip {	volatile uint32_t *PMC;	   /* general control			*/	volatile uint32_t *PME;	   /* multimedia port			*/	volatile uint32_t *PFB;	   /* framebuffer control		*/	volatile uint32_t *PVIDEO; /* overlay control			*/	volatile uint8_t *PCIO;	   /* SVGA (CRTC, ATTR) registers	*/	volatile uint8_t *PVIO;	   /* SVGA (MISC, GRAPH, SEQ) registers */	volatile uint32_t *PRAMIN; /* instance memory			*/	volatile uint32_t *PRAMHT; /* hash table			*/	volatile uint32_t *PRAMFC; /* fifo context table		*/	volatile uint32_t *PRAMRO; /* fifo runout table			*/	volatile uint32_t *PFIFO;  /* fifo control region		*/	volatile uint32_t *FIFO;   /* fifo channels (USER)		*/	volatile uint32_t *PGRAPH; /* graphics engine                   */	unsigned long fbsize;		   /* framebuffer size		   */	int arch;		   /* compatible NV_ARCH_XX define */	int realarch;		   /* real architecture		   */	void (* lock) (struct rivatv_chip *, int);};typedef struct rivatv_chip rivatv_chip;struct rivatv_info {    unsigned int use_colorkey;        unsigned int colorkey; /* saved xv colorkey*/    unsigned int vidixcolorkey; /*currently used colorkey*/    unsigned int depth;     unsigned int format;    unsigned int pitch;    unsigned int width,height;    unsigned int d_width,d_height;  /*scaled width && height*/    unsigned int wx,wy;                /*window x && y*/    unsigned int screen_x;            /*screen width*/    unsigned int screen_y;            /*screen height*/	unsigned long buffer_size;		 /* size of the image buffer	       */	struct rivatv_chip chip;	 /* NV architecture structure		       */	void* video_base;		 /* virtual address of control region	       */	void* control_base;		 /* virtual address of fb region	       */	void* picture_base;		 /* direct pointer to video picture	       */	unsigned long picture_offset;	 /* offset of video picture in frame buffer    *///	struct rivatv_dma dma;           /* DMA structure                              */    unsigned int cur_frame;	unsigned int num_frames;             /* number of buffers                          */	int bps;			/* bytes per line */};typedef struct rivatv_info rivatv_info;uint8_t nvReadVGA (struct rivatv_chip *chip, int index) {	VID_WR08 (chip->PCIO, 0x3D4, index);	return VID_RD08 (chip->PCIO, 0x3D5);}void nvWriteVGA (struct rivatv_chip *chip, int index, int data) {	VID_WR08 (chip->PCIO, 0x3D4, index);	VID_WR08 (chip->PCIO, 0x3D5, data);}//framebuffer size funcsstatic unsigned long rivatv_fbsize_nv03 (struct rivatv_chip *chip){	if (VID_RD32 (chip->PFB, 0) & 0x00000020) {		if (((VID_RD32 (chip->PMC, 0) & 0xF0) == 0x20)		    && ((VID_RD32 (chip->PMC, 0) & 0x0F) >= 0x02)) {			/* SDRAM 128 ZX. */			return ((1 << (VID_RD32 (chip->PFB, 0) & 0x03)) * 1024 * 1024);		}		else {			return 1024 * 1024 * 8;		}	}	else {		/* SGRAM 128. */		switch (VID_RD32(chip->PFB, 0) & 0x00000003) {		case 0:			return 1024 * 1024 * 8;			break;		case 2:			return 1024 * 1024 * 4;			break;		default:			return 1024 * 1024 * 2;			break;		}	}}static unsigned long rivatv_fbsize_nv04 (struct rivatv_chip *chip){	if (VID_RD32 (chip->PFB, 0) & 0x00000100) {		return ((VID_RD32 (chip->PFB, 0) >> 12) & 0x0F) * 1024 * 1024 * 2			+ 1024 * 1024 * 2;	} else {		switch (VID_RD32 (chip->PFB, 0) & 0x00000003) {		case 0:			return 1024 * 1024 * 32;			break;		case 1:			return 1024 * 1024 * 4;			break;		case 2:			return 1024 * 1024 * 8;			break;		case 3:		default:			return 1024 * 1024 * 16;			break;		}	}}static unsigned long rivatv_fbsize_nv10 (struct rivatv_chip *chip){	return VID_RD32 (chip->PFB, 0x20C) & 0xFFF00000;}//lock funcsstatic void rivatv_lock_nv03 (struct rivatv_chip *chip, int LockUnlock){	VID_WR08 (chip->PVIO, 0x3C4, 0x06);	VID_WR08 (chip->PVIO, 0x3C5, LockUnlock ? 0x99 : 0x57);}static void rivatv_lock_nv04 (struct rivatv_chip *chip, int LockUnlock){	rivatv_lock_nv03 (chip, LockUnlock);	nvWriteVGA (chip, 0x1F, LockUnlock ? 0x99 : 0x57);}/* Enable PFB (Framebuffer), PVIDEO (Overlay unit) and PME (Mediaport) if neccessary. */static void  rivatv_enable_PMEDIA (struct rivatv_info *info){	uint32_t reg;	/* switch off interrupts once for a while *///	VID_WR32 (info->chip.PME, 0x200140, 0x00);//	VID_WR32 (info->chip.PMC, 0x000140, 0x00);	reg = VID_RD32 (info->chip.PMC, 0x000200);	/* NV3 (0x10100010): NV03_PMC_ENABLE_PMEDIA, NV03_PMC_ENABLE_PFB, NV03_PMC_ENABLE_PVIDEO */	if ((reg & 0x10100010) != 0x10100010) {		printf("PVIDEO and PFB disabled, enabling...\n");		VID_OR32 (info->chip.PMC, 0x000200, 0x10100010);	}	/* save the current colorkey */    switch (info->chip.arch ) {	  case NV_ARCH_10:	  case NV_ARCH_20:      case NV_ARCH_30:      case NV_ARCH_40:        /* NV_PVIDEO_COLOR_KEY */	    info->colorkey = VID_RD32 (info->chip.PVIDEO, 0xB00);        break;      case NV_ARCH_03:	  case NV_ARCH_04:        /* NV_PVIDEO_KEY */	    info->colorkey = VID_RD32 (info->chip.PVIDEO, 0x240);        break;    }           	/* re-enable interrupts again *///	VID_WR32 (info->chip.PMC, 0x000140, 0x01);//	VID_WR32 (info->chip.PME, 0x200140, 0x01);}/* Stop overlay video. */static void rivatv_overlay_stop (struct rivatv_info *info) {	switch (info->chip.arch ) {	case NV_ARCH_10:	case NV_ARCH_20:        case NV_ARCH_30:        case NV_ARCH_40:		/* NV_PVIDEO_COLOR_KEY */		/* Xv-Extension-Hack: Restore previously saved value. */		VID_WR32 (info->chip.PVIDEO, 0xB00, info->colorkey);		/* NV_PVIDEO_STOP */		VID_OR32 (info->chip.PVIDEO, 0x704, 0x11);		/* NV_PVIDEO_BUFFER */		VID_AND32 (info->chip.PVIDEO, 0x700, ~0x11);		/* NV_PVIDEO_INTR_EN_BUFFER *///		VID_AND32 (info->chip.PVIDEO, 0x140, ~0x11);		break;	case NV_ARCH_03:	case NV_ARCH_04:		/* NV_PVIDEO_KEY */		VID_WR32 (info->chip.PVIDEO, 0x240, info->colorkey);		/* NV_PVIDEO_OVERLAY_VIDEO_OFF */		VID_AND32 (info->chip.PVIDEO, 0x244, ~0x01);		/* NV_PVIDEO_INTR_EN_0_NOTIFY *///		VID_AND32 (info->chip.PVIDEO, 0x140, ~0x01);		/* NV_PVIDEO_OE_STATE */		VID_WR32 (info->chip.PVIDEO, 0x224, 0);		/* NV_PVIDEO_SU_STATE */		VID_WR32 (info->chip.PVIDEO, 0x228, 0);		/* NV_PVIDEO_RM_STATE */		VID_WR32 (info->chip.PVIDEO, 0x22C, 0);		break;	}}/* Get pan offset of the physical screen. */static uint32_t rivatv_overlay_pan (struct rivatv_info *info){	uint32_t pan;	info->chip.lock (&info->chip, 0);	pan  =  nvReadVGA (&info->chip, 0x0D);	pan |=  nvReadVGA (&info->chip, 0x0C) << 8;	pan |= (nvReadVGA (&info->chip, 0x19) & 0x1F) << 16;	pan |= (nvReadVGA (&info->chip, 0x2D) & 0x60) << 16;	return pan << 2;}/* Compute and set colorkey depending on the colour depth. */static void rivatv_overlay_colorkey (rivatv_info* info, unsigned int chromakey){	uint32_t r, g, b, key = 0;	r = (chromakey & 0x00FF0000) >> 16;	g = (chromakey & 0x0000FF00) >> 8;	b = chromakey & 0x000000FF;	switch (info->depth) {	case 15:		key = ((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3));#ifndef WIN32        key = key | 0x00008000;#endif       		break;	case 16: // XXX unchecked		key = ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3));#ifndef WIN32        key = key | 0x00008000;#endif       		break;	case 24: // XXX unchecked, maybe swap order of masking - FIXME Can the card be in 24 bit mode anyway?		key = (chromakey & 0x00FFFFFF) | 0x00800000;		break;	case 32:		key = chromakey;#ifndef WIN32        key = key | 0x80000000;#endif       		break;	}	//printf("[nvidia_vid] depth=%d %08X \n", info->depth, chromakey);    switch (info->chip.arch) {	  case NV_ARCH_10:	  case NV_ARCH_20:      case NV_ARCH_30:      case NV_ARCH_40:        VID_WR32 (info->chip.PVIDEO, 0xB00, key);        break;   	  case NV_ARCH_03:	  case NV_ARCH_04:        VID_WR32 (info->chip.PVIDEO, 0x240, key);        break;    }}static void nv_getscreenproperties(struct rivatv_info *info){  uint32_t bpp=0,x;  info->chip.lock(&info->chip, 0);  /*get screen depth*/  bpp = nvReadVGA (&info->chip, 0x28) & 0x3;  if((bpp == 2) && (VID_RD32(info->chip.PVIDEO,0x600) & 0x00001000) == 0x0)info->depth=15;  else info->depth = 0x04 << bpp;  /*get screen width*/  info->screen_x = nvReadVGA (&info->chip, 0x1);  /* NV_PCRTC_HORIZ_EXTRA_DISPLAY_END_8 */  info->screen_x |= (nvReadVGA (&info->chip, 0x2D) & 0x02) << 7;  info->screen_x = (info->screen_x + 1) << 3;  /*get screen height*/  /* get first 8 bits in VT_DISPLAY_END*/  info->screen_y = nvReadVGA (&info->chip, 0x12);  /* get 9th bit in CRTC_OVERFLOW*/  info->screen_y |= (nvReadVGA (&info->chip, 0x07) & 0x02) << 7;  /* and the 10th in CRTC_OVERFLOW*/  info->screen_y |= (nvReadVGA (&info->chip, 0x07) & 0x40) << 3;  ++info->screen_y;  if(info->chip.arch >= NV_ARCH_10){    /* NV_PCRTC_EXTRA_VERT_DISPLAY_END_10 */    info->screen_y |= (nvReadVGA (&info->chip, 0x25) & 0x02) << 9;    /* NV_PCRTC_???_VERT_DISPLAY_END_11 */    info->screen_y |= (nvReadVGA (&info->chip, 0x41) & 0x04) << 9;  }  /* NV_PCRTC_OFFSET */  x  =  nvReadVGA (&info->chip, 0x13);  /* NV_PCRTC_REPAINT0_OFFSET_10_8 */  x |= (nvReadVGA (&info->chip, 0x19) & 0xE0) << 3;  /* NV_PCRTC_EXTRA_OFFSET_11 */  x |= (nvReadVGA (&info->chip, 0x25) & 0x20) << 6; x <<= 3;  info->bps = x * bpp;}/* Start overlay video. */static void rivatv_overlay_start (struct rivatv_info *info,int bufno){    uint32_t base, size, offset, xscale, yscale, pan;    uint32_t value;	int x=info->wx, y=info->wy;	int lwidth=info->d_width, lheight=info->d_height;    size = info->buffer_size;	base = info->picture_offset;	offset = bufno*size;    /*update depth & dimensions here because it may change with vo vesa or vo fbdev*/    nv_getscreenproperties(info);    if(info->depth){    	/* get pan offset of the physical screen */     	pan = rivatv_overlay_pan (info);    	/* adjust window position depending on the pan offset */    	if (info->bps != 0)	{	  x = info->wx - (pan % info->bps) * 8 / info->depth;    	  y = info->wy - (pan / info->bps);	}    } else {            // we can't adjust the window position correctly in textmode            // setting y to 8 seems to work ok, though            if(info->chip.arch < NV_ARCH_10 && y < 8) y = 8;    }    	    /* adjust negative output window variables */	    if (x < 0) {		  lwidth = info->d_width + x;		  offset += (-x * info->width / info->d_width) << 1;//		offset += (-window->x * port->vld_width / window->width) << 1;		  x = 0;	    }	    if (y < 0) {		  lheight = info->d_height + y;		  offset += (-y * info->height / info->d_height * info->width) << 1;//		offset += (-window->y * port->vld_height / window->height * port->org_width) << 1;	      y = 0;	    }	switch (info->chip.arch) {	case NV_ARCH_10:	case NV_ARCH_20:	case NV_ARCH_30:        case NV_ARCH_40:		/* NV_PVIDEO_BASE */		VID_WR32 (info->chip.PVIDEO, 0x900 + 0, base + offset);		//VID_WR32 (info->chip.PVIDEO, 0x900 + 4, base);		/* NV_PVIDEO_LIMIT */		VID_WR32 (info->chip.PVIDEO, 0x908 + 0, base + offset + size - 1);		//VID_WR32 (info->chip.PVIDEO, 0x908 + 4, base + size - 1);		/* extra code for NV20 && NV30 architectures */		if (info->chip.arch == NV_ARCH_20 || info->chip.arch == NV_ARCH_30 || info->chip.arch == NV_ARCH_40) {			VID_WR32 (info->chip.PVIDEO, 0x800 + 0, base + offset);			//VID_WR32 (info->chip.PVIDEO, 0x800 + 4, base);			VID_WR32 (info->chip.PVIDEO, 0x808 + 0, base + offset + size - 1);			//VID_WR32 (info->chip.PVIDEO, 0x808 + 4, base + size - 1);		}		/* NV_PVIDEO_LUMINANCE */		VID_WR32 (info->chip.PVIDEO, 0x910 + 0, eq.lum);		//VID_WR32 (info->chip.PVIDEO, 0x910 + 4, 0x00001000);		/* NV_PVIDEO_CHROMINANCE */		VID_WR32 (info->chip.PVIDEO, 0x918 + 0, eq.chrom);		//VID_WR32 (info->chip.PVIDEO, 0x918 + 4, 0x00001000);		/* NV_PVIDEO_OFFSET */		VID_WR32 (info->chip.PVIDEO, 0x920 + 0, 0x0);		//VID_WR32 (info->chip.PVIDEO, 0x920 + 4, offset + pitch);		/* NV_PVIDEO_SIZE_IN */		VID_WR32 (info->chip.PVIDEO, 0x928 + 0, ((info->height) << 16) | info->width);		//VID_WR32 (info->chip.PVIDEO, 0x928 + 4, ((port->org_height/2) << 16) | port->org_width);		/* NV_PVIDEO_POINT_IN */

⌨️ 快捷键说明

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