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 + -
显示快捷键?