nvidia_vid.c

来自「linux下的MPEG1」· C语言 代码 · 共 977 行 · 第 1/3 页

C
977
字号
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	       */	unsigned long 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;//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 (chip->PFB[0x00000000] & 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) >> 20) & 0x000000FF) * 1024 * 1024;}//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){	VID_WR08 (chip->PCIO, 0x3C4, 0x06);	VID_WR08 (chip->PCIO, 0x3C5, LockUnlock ? 0x99 : 0x57);	VID_WR08 (chip->PCIO, 0x3D4, 0x1F);	VID_WR08 (chip->PCIO, 0x3D5, 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:        /* 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:		/* 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);	VID_WR08 (info->chip.PCIO, 0x3D4, 0x0D);	pan = VID_RD08 (info->chip.PCIO, 0x3D5);	VID_WR08 (info->chip.PCIO, 0x3D4, 0x0C);	pan |= VID_RD08 (info->chip.PCIO, 0x3D5) << 8;	VID_WR08 (info->chip.PCIO, 0x3D4, 0x19);	pan |= (VID_RD08 (info->chip.PCIO, 0x3D5) & 0x1F) << 16;	VID_WR08 (info->chip.PCIO, 0x3D4, 0x2D);	pan |= (VID_RD08 (info->chip.PCIO, 0x3D5) & 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:        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;  info->chip.lock(&info->chip, 0);  /*get screen depth*/  VID_WR08(info->chip.PCIO, 0x03D4,0x28);  bpp = VID_RD08(info->chip.PCIO,0x03D5)&0x3;  if(bpp==3)bpp=4;  if((bpp == 2) && (info->chip.PVIDEO[0x00000600/4] & 0x00001000) == 0x0)info->depth=15;             else info->depth = bpp*8;  /*get screen width*/  VID_WR08(info->chip.PCIO, 0x03D4, 0x1);  info->screen_x = (1 + VID_RD08(info->chip.PCIO, 0x3D5)) * 8;  /*get screen height*/  /* get first 8 bits in VT_DISPLAY_END*/  VID_WR08(info->chip.PCIO, 0x03D4, 0x12);  info->screen_y = VID_RD08(info->chip.PCIO,0x03D5);  VID_WR08(info->chip.PCIO,0x03D4,0x07);  /* get 9th bit in CRTC_OVERFLOW*/  info->screen_y |= (VID_RD08(info->chip.PCIO,0x03D5) &0x02)<<7;  /* and the 10th in CRTC_OVERFLOW*/  info->screen_y |=(VID_RD08(info->chip.PCIO,0x03D5) &0x40)<<3;  ++info->screen_y;}/* 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?info->wx:8, y=info->wy?info->wy:8;	int lwidth=info->d_width, lheight=info->d_height;	int bps;	int i;    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){//        bps = info->screen_x * ((info->depth+1)/8);    	/* get pan offset of the physical screen */     	pan = rivatv_overlay_pan (info);    	/* adjust window position depending on the pan offset */        bps = 0;	info->chip.lock (&info->chip, 0);	for (i = 0; (i < 1024) && (bps == 0); i++)	{		if (info->chip.arch != NV_ARCH_03)			bps = info->chip.PGRAPH[0x00000670/4];		else			bps = info->chip.PGRAPH[0x00000650/4];	}	if (bps == 0)	{		fprintf(stderr, "[nvidia_vid] reading bps returned 0!!!\n");		if (info->bps != 0)			bps = info->bps;	}	else	{		info->bps = bps;	}    	if (bps != 0)	{	x = info->wx - (pan % bps) * 8 / info->depth;    	y = info->wy - (pan / bps);	}    }    	    /* 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:		/* 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);

⌨️ 快捷键说明

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