unichrome_vid.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 982 行 · 第 1/2 页
C
982 行
/* * VIDIX driver for VIA CLE266/Unichrome chipsets. * Copyright (C) 2004 Timothy Lee * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPlayer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MPlayer; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Thanks to Gilles Frattini for bugfixes * * Changes: * 2004-03-10 * Initial version * 2004-10-09 * Added Doxygen documentation (Benjamin Zores <ben@geexbox.org>) * 2004-11-08 * Added h/w revision detection (Timothy Lee <timothy.lee@siriushk.com>) */#include <errno.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <inttypes.h>#include <mplaylib.h>#include "vidix.h"#include "vidixlib.h"#include "fourcc.h"#include "dha.h"#include "pci_ids.h"#include "pci_names.h"#include "config.h"#include "unichrome_regs.h"#undef memcpy#define memcpy uc_memcpy/** * @brief Information on PCI device. */static pciinfo_t pci_info;/** * @brief Unichrome driver colorkey settings. */static vidix_grkey_t uc_grkey;static int frames[VID_PLAY_MAXFRAMES];static uint8_t *vio;static uint8_t *uc_mem;static uint8_t mclk_save[3];static uint8_t hwrev;#define VIA_OUT(hwregs, reg, val) *(volatile uint32_t *)((hwregs) + (reg)) = (val)#define VIA_IN(hwregs, reg) *(volatile uint32_t *)((hwregs) + (reg))#define VGA_OUT8(hwregs, reg, val) *(volatile uint8_t *)((hwregs) + (reg) + 0x8000) = (val)#define VGA_IN8(hwregs, reg) *(volatile uint8_t *)((hwregs) + (reg) + 0x8000)#define VIDEO_OUT(hwregs, reg, val) VIA_OUT((hwregs)+0x200, reg, val)#define VIDEO_IN(hwregs, reg) VIA_IN((hwregs)+0x200, reg)#define outb(val,reg) OUTPORT8(reg,val)#define inb(reg) INPORT8(reg)#define ALIGN_TO(v, n) (((v) + (n-1)) & ~(n-1))#define UC_MAP_V1_FIFO_CONTROL(depth, pre_thr, thr) \ (((depth)-1) | ((thr) << 8) | ((pre_thr) << 24))#define VIDEOMEMORY_SIZE (8 * 1024 * 1024)#define FRAMEBUFFER_SIZE 0x200000#define FRAMEBUFFER_START (VIDEOMEMORY_SIZE - FRAMEBUFFER_SIZE)#ifdef DEBUG_LOGFILEstatic FILE *logfile = 0;#define LOGWRITE(x) {if(logfile) fprintf(logfile,x);}#else#define LOGWRITE(x)#endif/** * @brief Unichrome driver vidix capabilities. */static vidix_capability_t uc_cap = { "VIA CLE266 Unichrome driver", "Timothy Lee <timothy@siriushk.com>", TYPE_OUTPUT, {0, 0, 0, 0}, 4096, 4096, 4, 4, -1, FLAG_UPSCALER | FLAG_DOWNSCALER, VENDOR_VIA2, -1, {0, 0, 0, 0}};/** * @brief list of card IDs compliant with the Unichrome driver . */static unsigned short uc_card_ids[] = { DEVICE_VIA2_VT8623_APOLLO_CLE266, DEVICE_VIA2_VT8378_S3_UNICHROME};/** * @brief Find chip index in Unichrome compliant devices list. * * @param chip_id PCI device ID. * * @returns index position in uc_card_ids if successful. * -1 if chip_id is not a compliant chipset ID. */static intfind_chip (unsigned chip_id){ unsigned i; for (i = 0; i < sizeof (uc_card_ids) / sizeof (unsigned short); i++) { if (chip_id == uc_card_ids[i]) return i; } return -1;}/** * @brief Map hardware settings for vertical scaling. * * @param sh source height. * @param dh destination height. * @param zoom will hold vertical setting of zoom register. * @param mini will hold vertical setting of mini register. * * @returns 1 if successful. * 0 if the zooming factor is too large or small. * * @note Derived from VIA's V4L driver. * See ddover.c, DDOVER_HQVCalcZoomHeight() */static intuc_ovl_map_vzoom (uint32_t sh, uint32_t dh, uint32_t * zoom, uint32_t * mini){ uint32_t sh1, tmp, d; int zoom_ok = 1; if (sh == dh) /* No zoom */ { /* Do nothing */ } else if (sh < dh) /* Zoom in */ { tmp = (sh * 0x0400) / dh; zoom_ok = !(tmp > 0x3ff); *zoom |= (tmp & 0x3ff) | V1_Y_ZOOM_ENABLE; *mini |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY; } else /* sw > dh - Zoom out */ { /* Find a suitable divider (1 << d) = {2, 4, 8 or 16} */ sh1 = sh; for (d = 1; d < 5; d++) { sh1 >>= 1; if (sh1 <= dh) break; } if (d == 5) /* too small */ { d = 4; zoom_ok = 0; } *mini |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */ /* Add scaling */ if (sh1 < dh) { tmp = (sh1 * 0x400) / dh; *zoom |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE); *mini |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY; } } return zoom_ok;}/** * @brief Map hardware settings for horizontal scaling. * * @param sw source width. * @param dw destination width. * @param zoom will hold horizontal setting of zoom register. * @param mini will hold horizontal setting of mini register. * @param falign will hold fetch aligment. * @param dcount will hold display count. * * @returns 1 if successful. * 0 if the zooming factor is too large or small. * * @note Derived from VIA's V4L driver. * See ddover.c, DDOVER_HQVCalcZoomWidth() and DDOver_GetDisplayCount() */static intuc_ovl_map_hzoom (uint32_t sw, uint32_t dw, uint32_t * zoom, uint32_t * mini, int *falign, int *dcount){ uint32_t tmp, sw1, d; int md; /* Minify-divider */ int zoom_ok = 1; md = 1; *falign = 0; if (sw == dw) /* no zoom */ { /* Do nothing */ } else if (sw < dw) /* zoom in */ { tmp = (sw * 0x0800) / dw; zoom_ok = !(tmp > 0x7ff); *zoom |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE; *mini |= V1_X_INTERPOLY; } else /* sw > dw - Zoom out */ { /* Find a suitable divider (1 << d) = {2, 4, 8 or 16} */ sw1 = sw; for (d = 1; d < 5; d++) { sw1 >>= 1; if (sw1 <= dw) break; } if (d == 5) /* too small */ { d = 4; zoom_ok = 0; } md = 1 << d; /* <= {2,4,8,16} */ *falign = ((md << 1) - 1) & 0xf; /* <= {3,7,15,15} */ *mini |= V1_X_INTERPOLY; *mini |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */ /* Add scaling */ if (sw1 < dw) { /* CLE bug */ /* tmp = sw1*0x0800 / dw; */ tmp = (sw1 - 2) * 0x0800 / dw; *zoom |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE; } } *dcount = sw - md; return zoom_ok;}/** * @brief qword fetch register setting. * * @param format overlay pixel format. * @param sw source width. * * @return qword fetch register setting * * @note Derived from VIA's V4L driver. See ddover.c, DDOver_GetFetch() * @note Only call after uc_ovl_map_hzoom() */static uint32_tuc_ovl_map_qwfetch (uint32_t format, int sw){ uint32_t fetch = 0; switch (format) { case IMGFMT_YV12: case IMGFMT_I420: fetch = ALIGN_TO (sw, 32) >> 4; break; case IMGFMT_UYVY: case IMGFMT_YVYU: case IMGFMT_YUY2: fetch = (ALIGN_TO (sw << 1, 16) >> 4) + 1; break; case IMGFMT_BGR15: case IMGFMT_BGR16: fetch = (ALIGN_TO (sw << 1, 16) >> 4) + 1; break; case IMGFMT_BGR32: fetch = (ALIGN_TO (sw << 2, 16) >> 4) + 1; break; default: printf ("[unichrome] Unexpected pixelformat!"); break; } if (fetch < 4) fetch = 4; return fetch;}/** * @brief Map pixel format. * * @param format pixel format. * * @return the mapped pixel format. * * @note Derived from VIA's V4L driver. See ddover.c, DDOver_GetV1Format() */static uint32_tuc_ovl_map_format (uint32_t format){ switch (format) { case IMGFMT_UYVY: case IMGFMT_YVYU: case IMGFMT_YUY2: return V1_COLORSPACE_SIGN | V1_YUV422; case IMGFMT_IYUV: return V1_COLORSPACE_SIGN | V1_YCbCr420 | V1_SWAP_SW; case IMGFMT_YV12: case IMGFMT_I420: return V1_COLORSPACE_SIGN | V1_YCbCr420; case IMGFMT_BGR15: return V1_RGB15; case IMGFMT_BGR16: return V1_RGB16; case IMGFMT_BGR32: return V1_RGB32; default: printf ("[unichrome] Unexpected pixelformat!"); return V1_YUV422; }}/** * @brief Calculate V1 control and fifo-control register values. * * @param format pixel format. * @param sw source width. * @param hwrev CLE266 hardware revision. * @param extfifo_on set this 1 if the extended FIFO is enabled. * @param control will hold value for V1_CONTROL. * @param fifo will hold value for V1_FIFO_CONTROL. */static voiduc_ovl_map_v1_control (uint32_t format, int sw, int hwrev, int extfifo_on, uint32_t * control, uint32_t * fifo){ *control = V1_BOB_ENABLE | uc_ovl_map_format (format); if (hwrev == 0x10) { *control |= V1_EXPIRE_NUM_F; } else { if (extfifo_on) { *control |= V1_EXPIRE_NUM_A | V1_FIFO_EXTENDED; } else { *control |= V1_EXPIRE_NUM; } } if ((format == IMGFMT_YV12) || (format == IMGFMT_I420)) { /* Minified video will be skewed without this workaround. */ if (sw <= 80) /* Fetch count <= 5 */ { *fifo = UC_MAP_V1_FIFO_CONTROL (16, 0, 0); } else { if (hwrev == 0x10) *fifo = UC_MAP_V1_FIFO_CONTROL (64, 56, 56); else *fifo = UC_MAP_V1_FIFO_CONTROL (16, 12, 8); } } else { if (hwrev == 0x10) { *fifo = UC_MAP_V1_FIFO_CONTROL (64, 56, 56); /* Default rev 0x10 */ } else { if (extfifo_on) *fifo = UC_MAP_V1_FIFO_CONTROL (48, 40, 40); else *fifo = UC_MAP_V1_FIFO_CONTROL (32, 29, 16); /* Default */ } }}/** * @brief Setup extended FIFO. * * @param extfifo_on pointer determining if extended fifo is enable or not. * @param dst_w destination width. */static voiduc_ovl_setup_fifo (int *extfifo_on, int dst_w){ if (dst_w <= 1024) /* Disable extended FIFO */ { outb (0x16, 0x3c4); outb (mclk_save[0], 0x3c5); outb (0x17, 0x3c4); outb (mclk_save[1], 0x3c5); outb (0x18, 0x3c4); outb (mclk_save[2], 0x3c5); *extfifo_on = 0; } else /* Enable extended FIFO */ { outb (0x17, 0x3c4); outb (0x2f, 0x3c5); outb (0x16, 0x3c4); outb ((mclk_save[0] & 0xf0) | 0x14, 0x3c5); outb (0x18, 0x3c4); outb (0x56, 0x3c5); *extfifo_on = 1; }}static voiduc_ovl_vcmd_wait (volatile uint8_t * vio){ while ((VIDEO_IN (vio, V_COMPOSE_MODE) & (V1_COMMAND_FIRE | V3_COMMAND_FIRE)));}/** * @brief Probe hardware to find some useable chipset. * * @param verbose specifies verbose level. * @param force specifies force mode : driver should ignore * device_id (danger but useful for new devices) * * @returns 0 if it can handle something in PC. * a negative error code otherwise. */static intunichrome_probe (int verbose, int force){ pciinfo_t lst[MAX_PCI_DEVICES]; unsigned i, num_pci; int err; err = pci_scan (lst, &num_pci); if (err) { printf ("[unichrome] Error occurred during pci scan: %s\n", strerror (err)); return err; } else { err = ENXIO; for (i = 0; i < num_pci; i++) { if (lst[i].vendor == VENDOR_VIA2) { int idx; const char *dname; idx = find_chip (lst[i].device); if (idx == -1) continue; dname = pci_device_name (VENDOR_VIA2, lst[i].device);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?