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